Skip to content

Instantly share code, notes, and snippets.

@litzinger
Last active September 27, 2016 22:21
Show Gist options
  • Save litzinger/1201e382c2db123ece45 to your computer and use it in GitHub Desktop.
Save litzinger/1201e382c2db123ece45 to your computer and use it in GitHub Desktop.
This is an example of a old EE 2 method in my Publisher add-on and how I converted it to EE 3. I've also included the Behat unit(ish) tests so far for the model. For more information on that see https://github.com/litzinger/ee-behat
<?php
/*
Old EE 2 version of a method on a "model" to get all translations for a phrase.
Its one method that does it all. There are no model properties, collections, or
phrase entities. Its just a query and dumb array as a result.
*/
public function get_translations($phrase_id = null, $status = PUBLISHER_STATUS_OPEN, $lang_id = null, $site_id = null)
{
if ( !$phrase_id)
{
show_error('$phrase_id is required. publisher_phrase.php->get_translations()');
}
$site_id = $site_id ?: ee()->publisher_lib->site_id;
$qry = ee()->db->select('upd.*, up.*, up.id as phrase_id, upd.id as row_id')
->from('publisher_phrases AS up')
->join('publisher_phrase_data AS upd', 'upd.phrase_id = up.id', 'left')
->where('up.id', $phrase_id)
->where('upd.publisher_status', $status)
->where('up.site_id', $site_id)
->get();
$phrases = array();
$translations = array();
foreach ($qry->result() as $row)
{
$phrases[$row->publisher_lang_id] = $row;
}
if ($lang_id)
{
$translations[$lang_id] = isset($phrases[$lang_id]) ? $phrases[$lang_id] : $phrases[ee()->publisher_lib->default_lang_id];
}
else
{
$languages = ee()->publisher_language->get_enabled_languages();
foreach ($languages as $lang_id => $language)
{
// If we have existing phrase data
if (isset($phrases[$lang_id]))
{
$translations[$lang_id] = $phrases[$lang_id];
}
// For some reason we don't have a corresponding phrase_data row
// create the vars with an empty translation value so the view doesn't bomb.
else
{
$phrases[$lang_id] = new stdClass();
$phrases[$lang_id]->phrase_id = $phrase_id;
$phrases[$lang_id]->publisher_lang_id = $lang_id;
$phrases[$lang_id]->phrase_value = '';
$translations[$lang_id] = $phrases[$lang_id];
}
$translations[$lang_id]->text_direction = ee()->publisher_language->get_language($lang_id, 'direction');
}
}
return $translations;
}
<?php
/*
This may look like more code because it is. Its the entire model with relationships defined
with properties and getters/setters. The getTranslations() method works with models
and collections instead of a dumb array.
*/
namespace Publisher\Model;
use EllisLab\ExpressionEngine\Service\Model\Collection;
use EllisLab\ExpressionEngine\Service\Model\Query\Builder;
use Publisher\Service\Request;
/**
* @package ExpressionEngine
* @subpackage Models
* @category Publisher
* @author Brian Litzinger
* @copyright Copyright (c) 2012, 2013 - Brian Litzinger
* @link http://boldminded.com/add-ons/publisher
* @license
*
* Copyright (c) 2015. BoldMinded, LLC
* All rights reserved.
*
* This source is commercial software. Use of this software requires a
* site license for each domain it is used on. Use of this software or any
* of its source code without express written permission in the form of
* a purchased commercial or other license is prohibited.
*
* THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
* As part of the license agreement for this software, all modifications
* to this source must be submitted to the original author for review and
* possible inclusion in future releases. No compensation will be provided
* for patches, although where possible we will attribute each contribution
* in file revision notes. Submitting such modifications constitutes
* assignment of copyright to the original author (Brian Litzinger and
* BoldMinded, LLC) for such modifications. If you do not wish to assign
* copyright to the original author, your license to use and modify this
* source is null and void. Use of this software constitutes your agreement
* to this clause.
*/
class Phrase extends AbstractModel
{
const NAME = 'publisher:Phrase';
protected static $_primary_key = 'id';
protected static $_table_name = 'publisher_phrases';
protected $id;
protected $site_id;
protected $group_id;
protected $phrase_name;
protected static $_relationships = array(
'ee:Site' => array(
'type' => 'BelongsTo',
),
'PhraseGroup' => array(
'type' => 'BelongsTo',
),
'Translations' => array(
'type' => 'HasMany',
'model' => 'PhraseTranslation',
'weak' => true,
'to_key' => 'phrase_id',
),
);
/**
* @param $phraseName
* @return Phrase
*/
public function findPhraseByName($phraseName)
{
/** @var Builder $query */
$query = $this->getQueryBuilder(self::NAME);
$query
->filter('phrase_name', $phraseName);
// I could/should emit an event here and use a subscriber
// to attach the translations to the phrase intead of loading
// the Language model and Request service in the getTranslations() method.
return $query->first();
}
/**
* @param $phraseId
* @return Phrase
*/
public function findPhraseById($phraseId)
{
/** @var Builder $query */
$query = $this->getQueryBuilder(self::NAME);
$query
->filter('id', $phraseId);
return $query->first();
}
/**
* @return string
*/
public function getTableName()
{
return self::$_table_name;
}
public function createTable()
{
if (ee()->db->table_exists($this->getTableName())) {
return;
}
ee()->dbforge->add_field(array(
'id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => true, 'auto_increment' => true),
'site_id' => array('type' => 'int', 'constraint' => 4, 'unsigned' => true, 'default' => 1),
'group_id' => array('type' => 'int', 'constraint' => 4, 'unsigned' => true),
'phrase_name' => array('type' => 'text'),
'phrase_desc' => array('type' => 'text'),
));
ee()->dbforge->add_key('id', true);
ee()->dbforge->add_key('site_id');
ee()->dbforge->create_table($this->getTableName());
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @param mixed $id
*/
public function setId($id)
{
$this->setRawProperty('id', $id);
return $this;
}
/**
* @return mixed
*/
public function getSiteId()
{
return $this->site_id;
}
/**
* @param mixed $site_id
*/
public function setSiteId($site_id)
{
$this->setRawProperty('site_id', $site_id);
return $this;
}
/**
* @return mixed
*/
public function getGroupId()
{
return $this->group_id;
}
/**
* @param mixed $group_id
*/
public function setGroupId($group_id)
{
$this->setRawProperty('group_id', $group_id);
return $this;
}
/**
* @return mixed
*/
public function getPhraseName()
{
return $this->phrase_name;
}
/**
* @param mixed $phrase_name
*/
public function setPhraseName($phrase_name)
{
$this->setRawProperty('phrase_name', $phrase_name);
return $this;
}
/**
* @return PhraseGroup
*/
public function getGroup()
{
return $this->PhraseGroup;
}
/**
* @return PhraseTranslation[]
*/
public function getTranslations($status = null)
{
/** @var Language $languageModel */
$languageModel = ee('Model')->make(Language::NAME);
$languages = $languageModel->findAllEnabledLanguages();
$defaultLanguage = $languageModel->findDefaultLanguage();
if (!$status) {
/** @var Request $request */
$request = ee(Request::NAME);
$status = $request->getCurrentStatus();
}
/** @var Collection $translations */
$translationsCollection = $this->Translations
->filter('status', $status);
/** @var Collection $defaultTranslationCollection */
$defaultTranslationCollection = $this->Translations
->filter('lang_id', $defaultLanguage->getId())
->filter('status', $status);
/** @var PhraseTranslation $defaultTranslation */
$defaultTranslation = $defaultTranslationCollection->first();
// Iterate all enabled languages. If there is no translation for the language,
// then set the translation to the default language so the translated phrase
// collection is the same in all languages.
foreach ($languages as $language) {
/** @var Collection $matchingTranslation */
$matchingTranslationCollection = $this->Translations
->filter('lang_id', $language->getId())
->filter('status', $status);
if ($matchingTranslationCollection->count() == 0) {
/** @var PhraseTranslation $appendedTranslation */
$appendedTranslation = $defaultTranslation;
$appendedTranslation->setPhraseValue($defaultTranslation->getPhraseValue());
$translationsCollection->add($appendedTranslation);
}
}
return $translationsCollection;
}
}
<?php
/*
The best part about defining the relationships on the model is you get
access to all the relationships. $phrase->getGroup() or $phrase->PhraseGroup
returns the related group model. Same for $phrase->Translations. If I
didn't have extra filtering to perform on the translations the model
would be much smaller, yet I still get all the data needed.
*/
/** @var Phrase $phraseModel */
$phraseModel = ee('Model')->make(Phrase::NAME);
$phrase = $phraseModel->findPhraseById(1);
/** @var PhraseTranslation[] $translations */
$translations = $phrase->getTranslations();
<?php
use Behat\Behat\Context\Context;
use Behat\Gherkin\Node\TableNode;
use Publisher\Model\Phrase;
use Publisher\Model\PhraseGroup;
use Publisher\Model\PhraseTranslation;
use Publisher\Service\Request;
class PhraseContext implements Context
{
/**
* @Given /^I have phrases:$/
*/
public function iHavePhrases(TableNode $table)
{
/** @var Phrase $phraseModel */
$phraseModel = ee('Model')->make(Phrase::NAME);
$phraseModel->createTable();
$rows = $table->getColumnsHash();
foreach ($rows as $row) {
ee()->db->insert($phraseModel->getTableName(), $row);
}
}
/**
* @Given /^I have phrase translations:$/
*/
public function iHavePhraseTranslations(TableNode $table)
{
/** @var PhraseTranslation $phraseTranslationModel */
$phraseTranslationModel = ee('Model')->make(PhraseTranslation::NAME);
$phraseTranslationModel->createTable();
$rows = $table->getColumnsHash();
foreach ($rows as $row) {
ee()->db->insert($phraseTranslationModel->getTableName(), $row);
}
}
/**
* @Given /^I have phrase groups:$/
*/
public function iHavePhraseGroups()
{
/** @var PhraseGroup $phraseGroupModel */
$phraseGroupModel = ee('Model')->make(PhraseGroup::NAME);
$phraseGroupModel->createTable();
}
/**
* @Then /^I have the phrase "([^"]*)" with the id (\d+)$/
*/
public function iHaveThePhrase($phraseName, $expectedId)
{
$phrase = $this->findPhraseByName($phraseName);
PHPUnit_Framework_Assert::assertEquals($expectedId, $phrase->getId());
}
/**
* @Given /^"([^"]*)" has (\d+) translations$/
*/
public function hasTranslations($phraseName, $expectedCount)
{
$this->setStatus('open');
$phrase = $this->findPhraseByName($phraseName);
/** @var PhraseTranslation[] $translations */
$translations = $phrase->getTranslations();
PHPUnit_Framework_Assert::assertEquals($expectedCount, count($translations));
}
/**
* @Given /^"([^"]*)" translations equal "([^"]*)"$/
*/
public function translationsEqual($phraseName, $expectedTranslations)
{
$this->setStatus('open');
$phrase = $this->findPhraseByName($phraseName);
/** @var PhraseTranslation[] $translations */
$translations = $phrase->getTranslations();
$translationArray = [];
foreach ($translations as $index => $translation) {
$translationArray[] = $translation->getPhraseValue();
}
PHPUnit_Framework_Assert::assertEquals($expectedTranslations, $translationArray);
}
private function setStatus($status)
{
/** @var Request $request */
$request = ee(Request::NAME);
$request->setCurrentStatus($status);
}
private function findPhraseByName($phraseName)
{
/** @var Phrase $phraseModel */
$phraseModel = ee('Model')->make(Phrase::NAME);
return $phraseModel->findPhraseByName($phraseName);
}
/**
* @Transform /^\[(.*)\]$/
*/
public function castStringToArray($string)
{
return explode(',', $string);
}
}
Background:
Given I have phrases:
| id | site_id | group_id | phrase_name | phrase_desc |
| 1 | 1 | 2 | language_en | |
| 2 | 1 | 2 | language_de | |
| 3 | 1 | 2 | language_fr | |
| 4 | 1 | 2 | language_it | |
| 5 | 1 | 1 | some-phrase | |
| 6 | 1 | 1 | another_phrase | |
| 7 | 1 | 1 | third_phrase | |
And I have phrase translations:
| id | phrase_id | site_id | lang_id | status | edit_date | edit_by | phrase_value |
| 1 | 1 | 1 | 1 | open | 1438629647 | 1 | English |
| 2 | 2 | 1 | 1 | open | 1426683210 | 1 | German |
| 27 | 2 | 1 | 2 | open | 1426683210 | 1 | Deutsche |
| 28 | 2 | 1 | 2 | draft | 1426683210 | 1 | Deutsche DRAFT |
| 3 | 3 | 1 | 1 | open | 1426871335 | 1 | French |
| 4 | 3 | 1 | 2 | open | 1426871335 | 1 | |
| 5 | 4 | 1 | 1 | open | 1430436699 | 1 | Italian |
| 6 | 4 | 1 | 3 | open | 1430436699 | 1 | |
| 7 | 4 | 1 | 2 | open | 1430436699 | 1 | |
| 9 | 1 | 1 | 3 | open | 1438629647 | 1 | Anglais |
| 11 | 1 | 1 | 2 | open | 1438629647 | 1 | Englisch |
| 13 | 1 | 1 | 4 | open | 1438629647 | 1 | Inglese |
| 15 | 5 | 1 | 1 | open | 1439559354 | 1 | value |
| 16 | 5 | 1 | 3 | open | 1439559354 | 1 | vfr |
| 17 | 5 | 1 | 2 | open | 1439559354 | 1 | vde |
| 18 | 5 | 1 | 4 | open | 1439559354 | 1 | vit |
| 19 | 6 | 1 | 1 | open | 1446816966 | 1 | a |
| 20 | 6 | 1 | 3 | open | 1446816966 | 1 | b |
| 21 | 6 | 1 | 2 | open | 1446816966 | 1 | c |
| 22 | 6 | 1 | 4 | open | 1446816966 | 1 | |
| 23 | 7 | 1 | 1 | open | 1439555242 | 1 | |
| 24 | 7 | 1 | 3 | open | 1439555242 | 1 | |
| 25 | 7 | 1 | 2 | open | 1439555242 | 1 | |
| 26 | 7 | 1 | 4 | open | 1439555242 | 1 | |
And I have phrase groups:
Scenario: Test phrases
Then I have the phrase "language_en" with the id 1
And "language_en" has 4 translations
And "language_en" translations equal "[English,Anglais,Englisch,Inglese]"
Then I have the phrase "language_de" with the id 2
And "language_de" has 4 translations
And "language_de" translations equal "[German,Deutsche,German,German]"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment