Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
50.00% covered (warning)
50.00%
1 / 2
80.95% covered (success)
80.95%
17 / 21
CRAP
78.26% covered (success)
78.26%
54 / 69
StoredProcedureNaming
0.00% covered (danger)
0.00%
0 / 1
80.00% covered (success)
80.00%
16 / 20
42.28
77.27% covered (success)
77.27%
51 / 66
 getInstance
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
 getSPInsertName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getUpdateName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getSelectByPrimaryKeyName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getSelectByPrimaryKeyDelimitName
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
 getSelectByReferenceName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getSelectByCollectionManyName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
 getDeleteByPrimaryKeyName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getDeleteByReferenceName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getDeleteByCollectionManyName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
 getDeleteCollectionManyAssignmentName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
 getCopyToMemoryTable
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getCollectorFilterName
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getUniqueName
0.00% covered (danger)
0.00%
0 / 1
4.05
85.71% covered (success)
85.71%
6 / 7
 getMappedName
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
4 / 4
 isUnique
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
4 / 4
 createUniqueShortName
0.00% covered (danger)
0.00%
0 / 1
20
0.00% covered (danger)
0.00%
0 / 11
 isShortEnough
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 addName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
NameMapping
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
<?php
declare(strict_types = 1);
namespace Siesta\Database;
use Siesta\Model\CollectionMany;
use Siesta\Model\Entity;
use Siesta\Model\Reference;
/**
 * @author Gregor Müller
 */
class StoredProcedureNaming
{
    const SELECT_BY_PRIMARY_KEY = "%s_SB_PK";
    const SELECT_BY_PRIMARY_KEY_DELIMIT = "_SB_PK_D";
    const SELECT_BY_REFERENCE = "%s_SB_R_%s";
    const FIND_BY_COLLECTOR = "_FB_C_";
    const DELETE_BY_REFERENCE = "_DB_R_";
    const DELETE_BY_PRIMARY_KEY = "_DB_PK";
    const UPDATE_SUFFIX = "_U";
    const INSERT_SUFFIX = "_I";
    const COPY_TO_MEMORY_SUFFIX = "_COPY";
    /**
     * @var StoredProcedureNaming
     */
    private static $instance;
    /**
     * @return StoredProcedureNaming
     */
    public static function getInstance() : StoredProcedureNaming
    {
        if (!self::$instance) {
            self::$instance = new StoredProcedureNaming();
        }
        return self::$instance;
    }
    /**
     * @param Entity $entity
     *
     * @return string
     */
    public static function getSPInsertName(Entity $entity) : string
    {
        $name = $entity->getTableName() . self::INSERT_SUFFIX;
        return self::getInstance()->getUniqueName($name);
    }
    /**
     * @param Entity $entity
     *
     * @return string
     */
    public static function getUpdateName(Entity $entity) : string
    {
        $name = $entity->getTableName() . self::UPDATE_SUFFIX;
        return self::getInstance()->getUniqueName($name);
    }
    /**
     * @param Entity $entity
     *
     * @return string
     */
    public static function getSelectByPrimaryKeyName(Entity $entity) : string
    {
        $name = sprintf(self::SELECT_BY_PRIMARY_KEY, $entity->getTableName());
        return self::getInstance()->getUniqueName($name);
    }
    /**
     * @param Entity $entity
     *
     * @return string
     */
    public static function getSelectByPrimaryKeyDelimitName(Entity $entity) : string
    {
        $name = $entity->getTableName() . self::SELECT_BY_PRIMARY_KEY_DELIMIT;
        return self::getInstance()->getUniqueName($name);
    }
    /**
     * @param Entity $entity
     * @param Reference $reference
     *
     * @return string
     */
    public static function getSelectByReferenceName(Entity $entity, Reference $reference) : string
    {
        $name = sprintf(self::SELECT_BY_REFERENCE, $entity->getTableName(), $reference->getName());
        return self::getInstance()->getUniqueName($name);
    }
    /**
     * @param CollectionMany $collectionMany
     *
     * @return string
     */
    public static function getSelectByCollectionManyName(CollectionMany $collectionMany) : string
    {
        $name = $collectionMany->getName();
        $foreignEntity = $collectionMany->getForeignEntity();
        $mappingEntity = $collectionMany->getMappingEntity();
        $spName = $foreignEntity->getTableName() . '_S_JOIN_' . $mappingEntity->getTableName() . '_' . $name;
        return self::getInstance()->getUniqueName($spName);
    }
    /**
     * @param Entity $entity
     *
     * @return string
     */
    public static function getDeleteByPrimaryKeyName(Entity $entity) : string
    {
        $name = $entity->getTableName() . self::DELETE_BY_PRIMARY_KEY;
        return self::getInstance()->getUniqueName($name);
    }
    /**
     * @param Entity $entity
     * @param Reference $reference
     *
     * @return string
     */
    public static function getDeleteByReferenceName(Entity $entity, Reference $reference) : string
    {
        $name = $entity->getTableName() . self::DELETE_BY_REFERENCE . $reference->getName();
        return self::getInstance()->getUniqueName($name);
    }
    /**
     * @param CollectionMany $collectionMany
     *
     * @return string
     */
    public static function getDeleteByCollectionManyName(CollectionMany $collectionMany) : string
    {
        $name = $collectionMany->getName();
        $foreignEntity = $collectionMany->getForeignEntity();
        $mappingEntity = $collectionMany->getMappingEntity();
        $spName = $foreignEntity->getTableName() . '_D_JOIN_' . $mappingEntity->getTableName() . '_' . $name;
        return self::getInstance()->getUniqueName($spName);
    }
    /**
     * @param CollectionMany $collectionMany
     *
     * @return string
     */
    public static function getDeleteCollectionManyAssignmentName(CollectionMany $collectionMany) : string
    {
        $name = $collectionMany->getName();
        $entity = $collectionMany->getEntity();
        $mappingEntity = $collectionMany->getMappingEntity();
        $spName = $mappingEntity->getTableName() . '_D_A_' . $entity->getTableName() . '_' . $name;
        return self::getInstance()->getUniqueName($spName);
    }
    /**
     * @param Entity $entity
     *
     * @return string
     */
    public static function getCopyToMemoryTable(Entity $entity) : string
    {
        $name = $entity->getTableName() . self::COPY_TO_MEMORY_SUFFIX;
        return self::getInstance()->getUniqueName($name);
    }
    /**
     * @param string $tableName
     * @param string $referenceName
     * @param string $filerName
     *
     * @return string
     */
    public static function getCollectorFilterName($tableName, $referenceName, $filerName)
    {
        return self::getInstance()->getUniqueName($tableName . self::FIND_BY_COLLECTOR . $referenceName . $filerName);
    }
    /**
     * @var NameMapping[]
     */
    protected $mappingList;
    /**
     *
     */
    private function __construct()
    {
        $this->mappingList = [];
    }
    /**
     * @param string $original
     *
     * @return string
     */
    public function getUniqueName($original)
    {
        // check if the name is already available
        $mappedName = $this->getMappedName($original);
        if ($mappedName !== null) {
            return $mappedName;
        }
        // check if it is unique and short enough
        if ($this->isUnique($original) and $this->isShortEnough($original)) {
            $this->addName($original, $original);
            return $original;
        }
        // create a new unique name
        return $this->createUniqueShortName($original);
    }
    /**
     * @param $original
     *
     * @return null|string
     */
    private function getMappedName($original)
    {
        foreach ($this->mappingList as $mapping) {
            if ($mapping->originalName === $original) {
                return $mapping->shortenedName;
            }
        }
        return null;
    }
    /**
     * @param string $original
     *
     * @return bool
     */
    private function isUnique($original)
    {
        foreach ($this->mappingList as $mapping) {
            if ($mapping->shortenedName === $original) {
                return false;
            }
        }
        return true;
    }
    /**
     * @param string $original
     *
     * @return string
     */
    private function createUniqueShortName($original)
    {
        $newName = substr($original, 0, 48);
        if ($this->isUnique($newName)) {
            $this->addName($original, $newName);
            return $newName;
        }
        for ($i = 0; $i < 100; $i++) {
            if ($this->isUnique($newName . $i)) {
                $this->addName($original, $newName . $i);
                return $newName . $i;
            }
        }
        $newName = "SP" . md5($original);
        $this->addName($original, $newName);
        return $newName;
    }
    /**
     * @param string $original
     *
     * @return bool
     */
    private function isShortEnough($original)
    {
        return strlen($original) < 50;
    }
    /**
     * @param $original
     * @param $shortenedName
     */
    private function addName($original, $shortenedName)
    {
        $this->mappingList[] = new NameMapping($original, $shortenedName);
    }
}
class NameMapping
{
    /**
     * @var string
     */
    public $originalName;
    /**
     * @var string
     */
    public $shortenedName;
    /**
     * @param string $original
     * @param string $shortened
     */
    public function __construct(string $original, string $shortened)
    {
        $this->originalName = $original;
        $this->shortenedName = $shortened;
    }
}