Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
80 / 80
SavePlugin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
12 / 12
18
100.00% covered (success)
100.00%
80 / 80
 getUseClassNameList
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getDependantPluginList
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
0 / 0
 generate
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
4 / 4
 generateSaveMethod
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
13 / 13
 generateCycleDetection
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
9 / 9
 generateReferenceSave
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
8 / 8
 generateEntitySave
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
9 / 9
 generateCollectionSave
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
8 / 8
 generateCollectionManySave
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 generateCreateSPCall
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
13 / 13
 createPrimaryKeyLookup
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
 getQuoteCallList
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
7 / 7
<?php
declare(strict_types = 1);
namespace Siesta\GeneratorPlugin\Entity;
use Siesta\CodeGenerator\CodeGenerator;
use Siesta\CodeGenerator\MethodGenerator;
use Siesta\Database\StoredProcedureNaming;
use Siesta\GeneratorPlugin\BasePlugin;
use Siesta\Model\Entity;
use Siesta\Model\PHPType;
/**
 * @author Gregor Müller
 */
class SavePlugin extends BasePlugin
{
    const METHOD_CREATE_SP_CALL_STATEMENT = "createSaveStoredProcedureCall";
    const METHOD_SAVE = "save";
    /**
     * @param Entity $entity
     *
     * @return string[]
     */
    public function getUseClassNameList(Entity $entity) : array
    {
        return [
            'Siesta\Database\Escaper',
            'Siesta\Database\ConnectionFactory',
            'Siesta\Util\DefaultCycleDetector',
            'Siesta\Contract\CycleDetector'
        ];
    }
    /**
     * @return string[]
     */
    public function getDependantPluginList() : array
    {
        return [];
    }
    /**
     * @param Entity $entity
     * @param CodeGenerator $codeGenerator
     */
    public function generate(Entity $entity, CodeGenerator $codeGenerator)
    {
        $this->setup($entity, $codeGenerator);
        $this->generateCreateSPCall();
        $this->generateSaveMethod();
    }
    /**
     *
     */
    protected function generateSaveMethod()
    {
        $method = $this->codeGenerator->newPublicMethod(self::METHOD_SAVE);
        $method->addParameter(PHPType::BOOL, 'cascade', 'false');
        $method->addParameter('CycleDetector', 'cycleDetector', 'null');
        $method->addConnectionNameParameter();
        $method->addConnectionLookup();
        $method->newLine();
        $this->generateCycleDetection($method);
        $this->generateReferenceSave($method);
        $this->generateEntitySave($method);
        $this->generateCollectionSave($method);
        $this->generateCollectionManySave($method);
        $method->end();
    }
    /**
     * @param MethodGenerator $method
     */
    protected function generateCycleDetection(MethodGenerator $method)
    {
        $method->addIfStart('$cycleDetector === null');
        $method->addLine('$cycleDetector = new DefaultCycleDetector();');
        $method->addIfEnd();
        $method->newLine();
        // canProceed
        $method->addIfStart('!$cycleDetector->canProceed(self::TABLE_NAME, $this)');
        $method->addLine('return;');
        $method->addIfEnd();
        $method->newLine();
    }
    /**
     * @param MethodGenerator $method
     */
    protected function generateReferenceSave(MethodGenerator $method)
    {
        foreach ($this->entity->getReferenceList() as $reference) {
            $name = $reference->getName();
            $memberName = '$this->' . $reference->getName();
            $method->addIfStart('$cascade && ' . $memberName . ' !== null');
            $method->addLine($memberName . '->' . self::METHOD_SAVE . '($cascade, $cycleDetector, $connectionName);');
            $method->addIfEnd();
            $method->newLine();
        }
    }
    /**
     * @param MethodGenerator $method
     */
    protected function generateEntitySave(MethodGenerator $method)
    {
        $method->addLine('$call = $this->' . self::METHOD_CREATE_SP_CALL_STATEMENT . '($connectionName);');
        $method->addLine('$connection->execute($call);');
        $method->addLine('$this->_existing = true;');
        $method->newLine();
        $method->addIfStart('!$cascade');
        $method->addLine('return;');
        $method->addIfEnd();
        $method->newLine();
    }
    /**
     * @param MethodGenerator $method
     */
    protected function generateCollectionSave(MethodGenerator $method)
    {
        foreach ($this->entity->getCollectionList() as $collection) {
            $method->addIfStart('$this->' . $collection->getName() . ' !== null');
            $method->addForeachStart('$this->' . $collection->getName() . ' as $entity');
            $method->addLine('$entity->save($cascade, $cycleDetector, $connectionName);');
            $method->addForeachEnd();
            $method->addIfEnd();
            $method->newLine();
        }
    }
    /**
     * @param MethodGenerator $method
     */
    protected function generateCollectionManySave(MethodGenerator $method)
    {
        foreach ($this->entity->getCollectionManyList() as $collectionMany) {
            $method->addForeachStart('$this->' . $collectionMany->getName() . 'Mapping as $mapping');
            $method->addLine('$mapping->save($cascade, $cycleDetector, $connectionName);');
            $method->addForeachEnd();
        }
    }
    /**
     *
     */
    protected function generateCreateSPCall()
    {
        $method = $this->codeGenerator->newPublicMethod(self::METHOD_CREATE_SP_CALL_STATEMENT);
        $method->addConnectionNameParameter();
        $method->setReturnType(PHPType::STRING);
        // choose stored procedure
        $insertName = StoredProcedureNaming::getSPInsertName($this->entity);
        $updateName = StoredProcedureNaming::getUpdateName($this->entity);
        $method->addLine('$spCall = ($this->_existing) ? "CALL ' . $updateName . '(" : "CALL ' . $insertName . '(";');
        $method->addConnectionLookup();
        $this->createPrimaryKeyLookup($method);
        $escapeList = $this->getQuoteCallList($method);
        $line = 'return $spCall . ' . implode(" . ',' . ", $escapeList) . " . ');';";
        $method->addLine($line);
        $method->end();
    }
    /**
     * @param MethodGenerator $method
     */
    protected function createPrimaryKeyLookup(MethodGenerator $method)
    {
        foreach ($this->entity->getPrimaryKeyAttributeList() as $attribute) {
            $method->addLine('$this->get' . $attribute->getMethodName() . '(true, $connectionName);');
        }
    }
    /**
     * @return string[]
     */
    protected function getQuoteCallList(MethodGenerator $method) : array
    {
        $list = [];
        foreach ($this->entity->getAttributeList() as $attribute) {
            if ($attribute->getIsTransient()) {
                continue;
            }
            $memberName = '$this->' . $attribute->getPhpName();
            $list[] = $method->getQuoteCall($attribute->getPhpType(), $attribute->getDbType(), $memberName, $attribute->getIsObject());
        }
        return $list;
    }
}