Last active
December 21, 2015 06:39
-
-
Save Tharos/6266039 to your computer and use it in GitHub Desktop.
Translations in Lean Mapper. See http://www.leanmapper.com/samples/translations.zip for working example.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$connection->registerFilter('translate', array($translator, 'translate'), Connection::WIRE_ENTITY | Connection::WIRE_PROPERTY); | |
$connection->registerFilter('translateByTable', array($translator, 'translateByTable')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Model; | |
class Mapper extends \LeanMapper\DefaultMapper implements ITranslatingMapper | |
{ | |
/** | |
* @return string | |
*/ | |
public function getLangTable() | |
{ | |
return 'lang'; | |
} | |
/** | |
* @param string $table | |
* @return string | |
*/ | |
public function getTranslationTable($table) | |
{ | |
return $table . '_translation'; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Model\Entity; | |
/** | |
* @property Lang $lang m:hasOne m:translatable | |
*/ | |
abstract class TranslatableEntity extends \LeanMapper\Entity | |
{ | |
/** | |
* @return array | |
*/ | |
public function getTranslatableColumns() | |
{ | |
$columns = array(); | |
foreach ($this->getCurrentReflection()->getEntityProperties() as $property) { | |
if ($property->hasCustomFlag('translatable')) { | |
$columns[] = $property->getColumn(); | |
} | |
} | |
return $columns; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Model\Repository; | |
use Exception; | |
use LeanMapper\Connection; | |
use LeanMapper\Entity; | |
use LeanMapper\Events; | |
use Model\Entity\Lang; | |
use Model\Entity\TranslatableEntity; | |
use Model\ITranslatingMapper; | |
abstract class TranslatingRepository extends \LeanMapper\Repository | |
{ | |
/** @var LangRepository */ | |
private $langRepository; | |
/** | |
* @param Connection $connection | |
* @param ITranslatingMapper $mapper | |
* @param LangRepository $langRepository | |
*/ | |
public function __construct(Connection $connection, ITranslatingMapper $mapper, LangRepository $langRepository) | |
{ | |
parent::__construct($connection, $mapper); | |
$this->langRepository = $langRepository; | |
} | |
/** | |
* @param mixed $id | |
* @param Lang $lang | |
* @return Entity | |
* @throws Exception | |
*/ | |
public function find($id, Lang $lang) | |
{ | |
$table = $this->getTable(); | |
$row = $this->connection->select('%n.*', $table) | |
->from($table) | |
->where('%n.%n = %i', $table, $this->mapper->getPrimaryKey($table), $id) | |
->applyFilter('translateByTable', $table, $lang) | |
->fetch(); | |
if ($row === false) { | |
throw new Exception('Entity was not found.'); | |
} | |
return $this->createEntity($row); | |
} | |
/** | |
* @param Lang $lang | |
* @return Entity[] | |
*/ | |
public function findAll(Lang $lang) | |
{ | |
$table = $this->getTable(); | |
return $this->createEntities( | |
$this->connection->select('%n.*', $table) | |
->from($table) | |
->applyFilter('translateByTable', $table, $lang) | |
->fetchAll() | |
); | |
} | |
/** | |
* @param Entity $entity | |
* @return mixed | |
*/ | |
protected function insertIntoDatabase(Entity $entity) | |
{ | |
$table = $this->getTable(); | |
$mapper = $this->mapper; | |
$primaryKey = $mapper->getPrimaryKey($table); | |
$translationTable = $mapper->getTranslationTable($table); | |
$relationshipColumn = $mapper->getRelationshipColumn($translationTable, $table); | |
$langRelationshipColumn = $mapper->getRelationshipColumn($translationTable, $mapper->getLangTable()); | |
list($primaryValues, $translatedValues) = $this->getSeparatedModifierRowData($entity); | |
$this->connection->query( | |
'INSERT INTO %n %v', $table, $primaryValues | |
); | |
$id = isset($primaryValues[$primaryKey]) ? $primaryValues[$primaryKey] : $this->connection->getInsertId(); | |
$translatedValues[$relationshipColumn] = $id; | |
foreach ($this->langRepository->findAll() as $lang) { | |
$values = $translatedValues; | |
if ($translatedValues[$langRelationshipColumn] !== $lang->id) { | |
$values = array( | |
$relationshipColumn => $id, | |
$langRelationshipColumn => $lang->id | |
); | |
} | |
$this->connection->query( | |
'INSERT INTO %n %v', $translationTable, $values | |
); | |
} | |
return $id; | |
} | |
/** | |
* @param Entity $entity | |
* @return mixed | |
*/ | |
protected function updateInDatabase(Entity $entity) | |
{ | |
$table = $this->getTable(); | |
$mapper = $this->mapper; | |
$primaryKey = $mapper->getPrimaryKey($table); | |
$idField = $mapper->getEntityField($table, $primaryKey); | |
$translationTable = $mapper->getTranslationTable($table); | |
$relationshipColumn = $mapper->getRelationshipColumn($translationTable, $table); | |
$langRelationshipColumn = $mapper->getRelationshipColumn($translationTable, $mapper->getLangTable()); | |
list($primaryValues, $translatedValues) = $this->getSeparatedModifierRowData($entity); | |
if (!empty($primaryValues)) { | |
$this->connection->query( | |
'UPDATE %n SET %a WHERE %n = ?', $table, $primaryValues, $primaryKey, $entity->$idField | |
); | |
} | |
if (!empty($translatedValues)) { | |
$this->connection->query( | |
'UPDATE %n SET %a', $translationTable, $translatedValues, | |
'WHERE %n = %i AND %n = %s', $relationshipColumn, $entity->$idField, $langRelationshipColumn, $entity->lang->id | |
); | |
} | |
} | |
//////////////////// | |
//////////////////// | |
/** | |
* @param TranslatableEntity $entity | |
* @return array | |
*/ | |
private function getSeparatedModifierRowData(TranslatableEntity $entity) | |
{ | |
$translatableColumns = array_flip($entity->getTranslatableColumns()); | |
$primaryValues = array(); | |
$translatedValues = array(); | |
foreach ($entity->getModifiedRowData() as $column => $value) { | |
if (isset($translatableColumns[$column])) { | |
$translatedValues[$column] = $value; | |
} else { | |
$primaryValues[$column] = $value; | |
} | |
} | |
return array($primaryValues, $translatedValues); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Model\Filter; | |
use LeanMapper\Fluent; | |
use LeanMapper\Reflection\Property; | |
use Model\Entity\Lang; | |
use Model\Entity\TranslatableEntity; | |
use Model\ITranslatingMapper; | |
class Translator | |
{ | |
/** @var ITranslatingMapper */ | |
private $mapper; | |
/** | |
* @param ITranslatingMapper $mapper | |
*/ | |
public function __construct(ITranslatingMapper $mapper) | |
{ | |
$this->mapper = $mapper; | |
} | |
/** | |
* @param Fluent $statement | |
* @param TranslatableEntity $entity | |
* @param Property $property | |
* @param Lang $lang | |
*/ | |
public function translate(Fluent $statement, TranslatableEntity $entity, Property $property, Lang $lang = null) | |
{ | |
if ($lang === null) { | |
$lang = $entity->lang; | |
} | |
$targetTable = $property->getRelationship()->getTargetTable(); | |
$this->translateByTable($statement, $targetTable, $lang); | |
} | |
/** | |
* @param Fluent $statement | |
* @param string $targetTable | |
* @param Lang $lang | |
*/ | |
public function translateByTable(Fluent $statement, $targetTable, Lang $lang) | |
{ | |
$translationTable = $this->mapper->getTranslationTable($targetTable); | |
$statement->removeclause('select') | |
->select('%n.*, %n.*', $translationTable, $targetTable) | |
->leftJoin('%n', $translationTable)->on( | |
'%n.%n = %n.%n', | |
$translationTable, | |
$this->mapper->getRelationshipColumn($translationTable, $targetTable), | |
$targetTable, | |
$this->mapper->getPrimaryKey($targetTable) | |
) | |
->where('%n = %s', $this->mapper->getRelationshipColumn($translationTable, $this->mapper->getLangTable()), $lang->id); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It would be great to use DefaultMapper::$defaultEntityNamespace as a prefix for Model\Entity\TranslatableEntity in Mapper::getImplicitFilters()
Somehow like this...
Found this function in the ZIP but in this Gist it's not mentioned.