<?php
namespace JLaso\TranslationsApiBundle\Translation\Loader;
use JLaso\TranslationsApiBundle\Entity\Translation;
use JLaso\TranslationsApiBundle\Tools\ArrayTools;
use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Translator;
use Doctrine\ORM\EntityManager;
use Doctrine\DBAL\Statement;
class PdoLoader implements LoaderInterface, ResourceInterface
{
protected $con;
protected $options = array(
'table' => 'jlaso_translations',
'columns' => array(
'key' => 'key',
'message' => 'message',
'locale' => 'locale',
'domain' => 'domain',
'updated_at' => 'updated_at',
'bundle' => 'bundle',
),
'blank' => 'key',
);
protected $freshnessStatement;
protected $resourcesStatement;
protected $translationsStatement;
public function __construct(EntityManager $entityManager, array $options = array())
{
$this->con = $entityManager->getConnection();
$this->options = array_replace_recursive($this->options, $options);
if(isset($this->options['fill_blank_messages_with_keyname'])
&& (filter_var($this->options['fill_blank_messages_with_keyname'], FILTER_VALIDATE_BOOLEAN))){
$this->con->exec("update `jlaso_translations` set `message` = `key` where message = \"\"");
}
}
/**
* @return array
*/
public function getOptions()
{
return $this->options;
}
/**
* Loads a locale.
*
* @param mixed $resource A resource
* @param string $locale A locale
* @param string $domain The domain
*
* @throws \RuntimeException
* @return MessageCatalogue
*/
public function load($resource, $locale, $domain = Translation::DEFAULT_DOMAIN)
{
//echo "domain=", $domain, ", locale=$locale<br>"; die;
// The loader only accepts itself as a resource.
if ($resource !== $this) {
return new MessageCatalogue($locale);
}
$stmt = $this->getTranslationsStatement();
$stmt->bindValue(':locale', $locale, \PDO::PARAM_STR);
$stmt->bindValue(':domain', $domain, \PDO::PARAM_STR);
if (false === $stmt->execute()) {
throw new \RuntimeException('Could not fetch translation data from database.');
}
//$stmt->bindColumn('key', $key);
//$stmt->bindColumn('message', $trans);
$catalogue = new MessageCatalogue($locale);
while ($row = $stmt->fetch()) {
$catalogue->set($row['key'], $row['message'], $domain);
}
return $catalogue;
}
protected function getTranslationsStatement()
{
if ($this->translationsStatement instanceOf \PDOStatement) {
return $this->translationsStatement;
}
$sql = vsprintf('SELECT `%s` AS `key`, `%s` AS `message` FROM `%s` WHERE `%s` = :locale AND `%s` = :domain', array(
// SELECT ..
$this->getColumnname('key'),
$this->getColumnname('message'),
// FROM ..
$this->getTablename(),
// WHERE ..
$this->getColumnname('locale'),
$this->getColumnname('domain'),
));
$stmt = $this->getConnection()->prepare($sql);
$stmt->setFetchMode(\PDO::FETCH_ASSOC);
$this->translationsStatement = $stmt;
return $stmt;
}
public function getTranslations($locale, $criteria, $hierarchicalArray = true)
{
$sql = vsprintf('SELECT `%s` AS `key`, `%s` AS `message` FROM `%s` WHERE `%s` = :locale AND `%s` = :domain', array(
// SELECT ..
$this->getColumnname('key'),
$this->getColumnname('message'),
// FROM ..
$this->getTablename(),
// WHERE ..
$this->getColumnname('locale'),
strpos('Bundle', $criteria) !== false ? $this->getColumnname('domain') : $this->getColumnname('bundle'),
));
$stmt = $this->getConnection()->prepare($sql);
$stmt->bindParam('locale', $locale);
if(strpos('Bundle', $criteria) !== false){
$stmt->bindParam('bundle', $criteria);
}else{
$stmt->bindParam('domain', $criteria);
}
if (false === $stmt->execute()) {
throw new \RuntimeException('Could not fetch translation data from database.');
}
$result = array();
while ($row = $stmt->fetch()) {
$result[$row['key']] = $row['message'];
}
if($hierarchicalArray){
return ArrayTools::keyedAssocToHierarchical($result);
}
return $result;
}
/**
* Retrieves all locale-domain combinations and add them as a resource to
* the translator.
*
* @param Translator $translator
*
* @throws \RuntimeException
*/
public function registerResources(Translator $translator)
{
$stmt = $this->getResourcesStatement();
if (false === $stmt->execute()) {
throw new \RuntimeException('Could not fetch translation data from database.');
}
//$stmt->bindColumn('locale', $locale);
//$stmt->bindColumn('domain', $domain);
while ($row = $stmt->fetch()) {
$translator->addResource('pdo', $this, $row['locale'], $row['domain']);
}
}
protected function getResourcesStatement()
{
if ($this->resourcesStatement instanceOf \PDOStatement) {
return $this->resourcesStatement;
}
$sql = vsprintf('SELECT DISTINCT `%s` AS `locale`, `%s` AS `domain` FROM `%s`', array(
// SELECT ..
$this->getColumnname('locale'),
$this->getColumnname('domain'),
// FROM ..
$this->getTablename(),
));
$stmt = $this->getConnection()->prepare($sql);
$stmt->setFetchMode(\PDO::FETCH_ASSOC);
$this->resourcesStatement = $stmt;
return $stmt;
}
public function __toString()
{
return 'PDOLoader::'.base64_encode($this->options);
}
public function isFresh($timestamp)
{
$stmt = $this->getFreshnessStatement($timestamp);
// If we cannot fetch from database, keep the cache, even if it's not fresh.
if (false === $stmt->execute()) {
return true;
}
$stmt->bindColumn(1, $count);
$stmt->fetch();
return (Boolean) $count;
}
protected function getFreshnessStatement($timestamp)
{
if ($this->freshnessStatement instanceOf \PDOStatement) {
return $this->freshnessStatement;
}
$sql = vsprintf('SELECT COUNT(*) FROM `%s` WHERE UNIX_TIMESTAMP(`%s`) > :timestamp', array(
$this->getTablename(),
$this->getColumnname('updated_at'),
));
$stmt = $this->con->prepare($sql);
$stmt->bindParam(':timestamp', $timestamp, \PDO::PARAM_INT);
$this->freshnessStatement = $stmt;
return $stmt;
}
public function getResource()
{
return $this;
}
public function getConnection()
{
return $this->con;
}
public function getTablename()
{
return $this->options['table'];
}
public function getColumnname($column)
{
return $this->options['columns'][$column];
}
}
|