Skip to content

Instantly share code, notes, and snippets.

@JanSuchanek
Forked from Tharos/Mapper.php
Created July 15, 2014 14:07
Show Gist options
  • Save JanSuchanek/acae250a592731b8a442 to your computer and use it in GitHub Desktop.
Save JanSuchanek/acae250a592731b8a442 to your computer and use it in GitHub Desktop.
<?php
$connection->registerFilter('translate', array($translator, 'translate'), Connection::WIRE_ENTITY | Connection::WIRE_PROPERTY);
$connection->registerFilter('translateByTable', array($translator, 'translateByTable'));
<?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';
}
}
<?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;
}
}
<?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);
}
}
<?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