Skip to content
This repository has been archived by the owner on Nov 30, 2021. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
elvenpath committed Jul 24, 2012
1 parent bf28785 commit 7b6117d
Show file tree
Hide file tree
Showing 26 changed files with 1,145 additions and 0 deletions.
351 changes: 351 additions & 0 deletions I18nWithSlugBehavior.php
@@ -0,0 +1,351 @@
<?php
require_once dirname(__FILE__) . '/I18nWithSlugBehaviorObjectBuilderModifier.php';
require_once dirname(__FILE__) . '/I18nWithSlugBehaviorQueryBuilderModifier.php';
require_once dirname(__FILE__) . '/I18nWithSlugBehaviorPeerBuilderModifier.php';

/**
* Allows translation of text columns through transparent one-to-many relationship
* with slug on the translated object
*
* @author Vlad Jula-Nedelcu <vlad.nedelcu@mfq.ro>
*/
class I18nWithSlugBehavior extends Behavior
{
const DEFAULT_CULTURE = 'en_EN';

// default parameters value
protected $parameters = array(
'i18n_table' => '%TABLE%_i18n',
'i18n_phpname' => '%PHPNAME%I18n',
'i18n_columns' => '',
'culture_column' => 'culture',
'default_culture' => null,
'culture_alias' => '',
'slug_column' => 'slug',
'slug_pattern' => '',
'replace_pattern' => '/\W+/', // Tip: use '/[^\\pL\\d]+/u' instead if you're in PHP5.3
'replacement' => '-',
'separator' => '-',
'permanent' => 'false'
);

protected $tableModificationOrder = 70;

protected
$objectBuilderModifier,
$queryBuilderModifier,
$peerBuilderModifier,
$i18nTable;

public function modifyDatabase()
{

foreach ($this->getDatabase()->getTables() as $table)
{
if ($table->hasBehavior('i18n_with_slug') && !$table->getBehavior('i18n_with_slug')->getParameter('default_culture'))
{
$table->getBehavior('i18n_with_slug')->addParameter(array(
'name' => 'default_culture',
'value' => $this->getParameter('default_culture')
));
}
}
}

public function modifyTable()
{
$this->addI18nTable();
$this->relateI18nTableToMainTable();
$this->addCultureColumnToI18n();
$this->addSlugColumnToI18n();
$this->moveI18nColumns();
}

protected function addI18nTable()
{
$table = $this->getTable();
$database = $table->getDatabase();
$i18nTableName = $this->getI18nTableName();
if ($database->hasTable($i18nTableName))
{
$this->i18nTable = $database->getTable($i18nTableName);
}
else
{
$this->i18nTable = $database->addTable(array(
'name' => $i18nTableName,
'phpName' => $this->getI18nTablePhpName(),
'package' => $table->getPackage(),
'schema' => $table->getSchema(),
'namespace' => $table->getNamespace() ? '\\' . $table->getNamespace() : null,
));
// every behavior adding a table should re-execute database behaviors
foreach ($database->getBehaviors() as $behavior)
{
/** @var $behavior Behavior */
$behavior->modifyDatabase();
}
}
}

protected function relateI18nTableToMainTable()
{
$table = $this->getTable();
$i18nTable = $this->i18nTable;
$pks = $this->getTable()->getPrimaryKey();
if (count($pks) > 1)
{
throw new EngineException('The i18n behavior does not support tables with composite primary keys');
}
foreach ($pks as $column)
{
if (!$i18nTable->hasColumn($column->getName()))
{
$column = clone $column;
$column->setAutoIncrement(false);
$i18nTable->addColumn($column);
}
}
if (in_array($table->getName(), $i18nTable->getForeignTableNames()))
{
return;
}
$fk = new ForeignKey();
$fk->setForeignTableCommonName($table->getCommonName());
$fk->setForeignSchemaName($table->getSchema());
$fk->setDefaultJoin('LEFT JOIN');
$fk->setOnDelete(ForeignKey::CASCADE);
$fk->setOnUpdate(ForeignKey::CASCADE);
foreach ($pks as $column)
{
$fk->addReference($column->getName(), $column->getName());
}
$i18nTable->addForeignKey($fk);
}

protected function addCultureColumnToI18n()
{
$cultureColumnName = $this->getCultureColumnName();
if (!$this->i18nTable->hasColumn($cultureColumnName))
{
$this->i18nTable->addColumn(array(
'name' => $cultureColumnName,
'type' => PropelTypes::VARCHAR,
'size' => 5,
'default' => $this->getDefaultCulture(),
'primaryKey' => 'true',
));
}
}

/**
* Moves i18n columns from the main table to the i18n table
*/
protected function moveI18nColumns()
{
$table = $this->getTable();
$i18nTable = $this->i18nTable;
foreach ($this->getI18nColumnNamesFromConfig() as $columnName)
{
if (!$i18nTable->hasColumn($columnName))
{
if (!$table->hasColumn($columnName))
{
throw new EngineException(sprintf('No column named %s found in table %s', $columnName, $table->getName()));
}
$column = $table->getColumn($columnName);
// add the column
$i18nColumn = $i18nTable->addColumn(clone $column);
// add related validators
if ($validator = $column->getValidator())
{
$i18nValidator = $i18nTable->addValidator(clone $validator);
}
// FIXME: also move FKs, and indices on this column
}
if ($table->hasColumn($columnName))
{
$table->removeColumn($columnName);
$table->removeValidatorForColumn($columnName);
}
}
}

protected function addSlugColumnToI18n()
{
$slugColumnName = $this->getSlugColumnName();
if (!$this->i18nTable->hasColumn($slugColumnName))
{
$this->i18nTable->addColumn(array(
'name' => $slugColumnName,
'type' => 'VARCHAR',
'size' => 255
));

// add a unique to column
$unique = new Unique();
$unique->addColumn($this->i18nTable->getColumn($this->getParameter('slug_column')));
$unique->addColumn($this->i18nTable->getColumn($this->getParameter('culture_column')));
$this->i18nTable->addUnique($unique);
}


}

protected function getI18nTableName()
{
return $this->replaceTokens($this->getParameter('i18n_table'));
}

protected function getI18nTablePhpName()
{
return $this->replaceTokens($this->getParameter('i18n_phpname'));
}

protected function getCultureColumnName()
{
return $this->replaceTokens($this->getParameter('culture_column'));
}
protected function getSlugColumnName()
{
return $this->replaceTokens($this->getParameter('slug_column'));
}

protected function getI18nColumnNamesFromConfig()
{
$columnNames = explode(',', $this->getParameter('i18n_columns'));
$columnNames[] = $this->getParameter('slug_column');
foreach ($columnNames as $key => $columnName)
{
if ($columnName = trim($columnName))
{
$columnNames[$key] = $columnName;
}
else
{
unset($columnNames[$key]);
}
}

return $columnNames;
}

public function getDefaultCulture()
{
if (!$defaultCulture = $this->getParameter('default_culture'))
{
$defaultCulture = self::DEFAULT_CULTURE;
}
return $defaultCulture;
}

public function getI18nTable()
{
return $this->i18nTable;
}

public function getI18nForeignKey()
{
foreach ($this->i18nTable->getForeignKeys() as $fk)
{
if ($fk->getForeignTableName() == $this->table->getName())
{
return $fk;
}
}
}

public function getCultureColumn()
{
return $this->getI18nTable()->getColumn($this->getCultureColumnName());
}
public function getSlugColumn()
{
return $this->getI18nTable()->getColumn($this->getSlugColumnName());
}

public function getI18nColumns()
{
$columns = array();
$i18nTable = $this->getI18nTable();
if ($columnNames = $this->getI18nColumnNamesFromConfig())
{
// Strategy 1: use the i18n_columns parameter
foreach ($columnNames as $columnName)
{
$columns [] = $i18nTable->getColumn($columnName);
}
}
else
{
// strategy 2: use the columns of the i18n table
// warning: does not work when database behaviors add columns to all tables
// (such as timestampable behavior)
foreach ($i18nTable->getColumns() as $column)
{
if (!$column->isPrimaryKey())
{
$columns [] = $column;
}
}
}

return $columns;
}

public function replaceTokens($string)
{
$table = $this->getTable();
return strtr($string, array(
'%TABLE%' => $table->getName(),
'%PHPNAME%' => $table->getPhpName(),
));
}

public function getObjectBuilderModifier()
{
if (is_null($this->objectBuilderModifier))
{
$this->objectBuilderModifier = new I18nWithSlugBehaviorObjectBuilderModifier($this);
}
return $this->objectBuilderModifier;
}

public function getQueryBuilderModifier()
{
if (is_null($this->queryBuilderModifier))
{
$this->queryBuilderModifier = new I18nWithSlugBehaviorQueryBuilderModifier($this);
}
return $this->queryBuilderModifier;
}

public function getPeerBuilderModifier()
{
if (is_null($this->peerBuilderModifier))
{
$this->peerBuilderModifier = new I18nWithSlugBehaviorPeerBuilderModifier($this);
}
return $this->peerBuilderModifier;
}

/**
* Get the getter of the column of the behavior
*
* @return string The related getter, e.g. 'getSlug'
*/
public function getColumnGetter()
{
return 'get' . $this->i18nTable->getColumn($this->getParameter('slug_column'))->getPhpName();
}

/**
* Get the setter of the column of the behavior
*
* @return string The related setter, e.g. 'setSlug'
*/
public function getColumnSetter()
{
return 'set' . $this->i18nTable->getColumn($this->getParameter('slug_column'))->getPhpName();
}
}

0 comments on commit 7b6117d

Please sign in to comment.