From 086190fa1287ed42abab2656a705ef7c9026bbd7 Mon Sep 17 00:00:00 2001 From: Sander Borgman Date: Wed, 25 Nov 2015 16:06:18 +0100 Subject: [PATCH 01/23] add query setting to scaffolding --- src/DI/Scaffolding.php | 16 ++++++++++++++++ src/DI/Scaffolding/Adapter/Mongo.php | 18 ++++++++++++++++++ src/DI/Scaffolding/AdapterInterface.php | 8 ++++++++ src/DI/ScaffoldingInterface.php | 8 ++++++++ 4 files changed, 50 insertions(+) diff --git a/src/DI/Scaffolding.php b/src/DI/Scaffolding.php index dc27d7f..3eaa43b 100644 --- a/src/DI/Scaffolding.php +++ b/src/DI/Scaffolding.php @@ -76,6 +76,13 @@ class Scaffolding implements ScaffoldingInterface */ protected $formName; + /** + * Query + * + * @var array + */ + protected $query = []; + /** * {@inheritdoc} */ @@ -135,6 +142,15 @@ public function setModelName($name) return $this; } + /** + * {@inheritdoc} + */ + public function setQuery($query) + { + $this->adapter->setQuery($query); + return $this; + } + /** * {@inheritdoc} */ diff --git a/src/DI/Scaffolding/Adapter/Mongo.php b/src/DI/Scaffolding/Adapter/Mongo.php index 877e597..30c0af4 100644 --- a/src/DI/Scaffolding/Adapter/Mongo.php +++ b/src/DI/Scaffolding/Adapter/Mongo.php @@ -38,6 +38,13 @@ class Mongo implements AdapterInterface, ScaffoldingAdapterInterface */ protected $scaffolding; + /** + * Query for paginator + * + * @var array + */ + protected $query = []; + /** * Constructor * Verifies services required by Mongo @@ -49,6 +56,16 @@ public function __construct() $this->setupExtraServices($di); } + /** + * {@inheritdoc} + */ + public function setQuery($query) + { + $this->query = $query; + + return $this; + } + /** * {@inheritdoc} */ @@ -69,6 +86,7 @@ public function retrieveOne($id) public function getPaginator($page = 1, $limit = 10) { return new PaginatorAdapterMongo(array( + 'query' => $this->query, 'model' => $this->scaffolding->getRecord(), 'limit' => $limit, 'page' => $page diff --git a/src/DI/Scaffolding/AdapterInterface.php b/src/DI/Scaffolding/AdapterInterface.php index 3f27e5f..f016c91 100644 --- a/src/DI/Scaffolding/AdapterInterface.php +++ b/src/DI/Scaffolding/AdapterInterface.php @@ -27,6 +27,14 @@ interface AdapterInterface */ public function retrieveOne($id); + /** + * Sets query for the paginator + * + * @param $id + * @return mixed + */ + public function setQuery($query); + /** * Retrieve list of records as paginator object. * diff --git a/src/DI/ScaffoldingInterface.php b/src/DI/ScaffoldingInterface.php index ca362be..595e682 100644 --- a/src/DI/ScaffoldingInterface.php +++ b/src/DI/ScaffoldingInterface.php @@ -57,6 +57,14 @@ public function getForm($entity = null); */ public function setFormName($name); + /** + * Sets query for paginator + * + * @param $query + * @return mixed + */ + public function setQuery($query); + /** * Sets model name * From c1f808d7b025f06f73882c754439b507da811694 Mon Sep 17 00:00:00 2001 From: Sander Borgman Date: Wed, 25 Nov 2015 16:23:04 +0100 Subject: [PATCH 02/23] Add option to set query from crud controller --- src/Mvc/Controller/CrudAbstract.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Mvc/Controller/CrudAbstract.php b/src/Mvc/Controller/CrudAbstract.php index b6dbc30..6a86e76 100644 --- a/src/Mvc/Controller/CrudAbstract.php +++ b/src/Mvc/Controller/CrudAbstract.php @@ -77,6 +77,13 @@ public function initialize() */ protected $modelName; + /** + * Query that will be used in index action + * + * @var array + */ + protected $query = []; + /** * Array of fields names that will be used in index action * @@ -104,6 +111,7 @@ protected function initializeScaffolding() $this->scaffolding->setModelName($this->modelName); $this->scaffolding->setFormName($this->formName); + $this->scaffolding->setQuery($this->query); } /** From 8c7db8bcda47751dcc82b63b32487e1f9f0f1796 Mon Sep 17 00:00:00 2001 From: Sander Borgman Date: Wed, 25 Nov 2015 17:10:30 +0100 Subject: [PATCH 03/23] Add query option to Scaffolding MySQL adapter --- src/DI/Scaffolding/Adapter/Mysql.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/DI/Scaffolding/Adapter/Mysql.php b/src/DI/Scaffolding/Adapter/Mysql.php index b8d649d..d7aaa8c 100644 --- a/src/DI/Scaffolding/Adapter/Mysql.php +++ b/src/DI/Scaffolding/Adapter/Mysql.php @@ -38,6 +38,13 @@ class Mysql implements AdapterInterface, ScaffoldingAdapterInterface */ protected $scaffolding; + /** + * Query for paginator + * + * @var array + */ + protected $query = []; + /** * Constructor */ @@ -47,6 +54,16 @@ public function __construct() $this->verifyRequiredServices($di); } + /** + * {@inheritdoc} + */ + public function setQuery($query) + { + $this->query = $query; + + return $this; + } + /** * {@inheritdoc} */ @@ -71,7 +88,7 @@ public function getPaginator($page = 1, $limit = 10) $this->ensureScaffolding(); return new PaginatorAdapterModel(array( - 'data' => (object) call_user_func(array($this->scaffolding->getRecord(), 'find')), + 'data' => (object) call_user_func(array($this->scaffolding->getRecord(), 'find'), $this->query), 'limit' => $limit, 'page' => $page )); From e850773ec10e099d7afb29057c75397350dcc62c Mon Sep 17 00:00:00 2001 From: Sander Borgman Date: Thu, 26 Nov 2015 11:45:11 +0100 Subject: [PATCH 04/23] Add tests for paginator and query options --- tests/DI/ScaffoldingTest.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/DI/ScaffoldingTest.php b/tests/DI/ScaffoldingTest.php index 696de04..c3a78a0 100644 --- a/tests/DI/ScaffoldingTest.php +++ b/tests/DI/ScaffoldingTest.php @@ -30,6 +30,10 @@ protected function setUp() $record = new \Vegas\Tests\Stub\Models\FakeModel(); $record->fake_field = 'test'; $record->save(); + + $record = new \Vegas\Tests\Stub\Models\FakeModel(); + $record->fake_field = 'test_query'; + $record->save(); $this->record = $record; } @@ -133,4 +137,29 @@ public function testDoDelete() $this->assertInstanceOf('\Vegas\DI\Scaffolding\Exception\RecordNotFoundException', $ex); } } + + public function testShouldReturnValidPagination() + { + $pagination = $this->scaffolding->doPaginate(); + + $this->assertInstanceOf('\Vegas\Paginator\Adapter\Mongo', $pagination); + + $results = $pagination->getResults(); + + $this->assertNotCount(0, $results); + $this->assertInstanceOf('\Vegas\Tests\Stub\Models\FakeModel', $results[0]); + } + + public function testShouldReturnFilteredPagination() + { + $this->scaffolding->setQuery([ + 'fake_field' => 'test_query' + ]); + + $pagination = $this->scaffolding->doPaginate(); + $results = $pagination->getResults(); + + $this->assertNotCount(0, $results); + $this->assertEquals('test_query', $results[0]->fake_field); + } } From 4bb2963b3a07a7a68b69fb192b2af27f481c861b Mon Sep 17 00:00:00 2001 From: Sander Borgman Date: Thu, 26 Nov 2015 16:53:21 +0100 Subject: [PATCH 05/23] - Update tests for Scaffolding MySQL pagination - Add vendor module assets for better coverage in AssetsTask test --- src/DI/Scaffolding/Adapter/Mysql.php | 2 +- tests/DI/Scaffolding/Adapter/MysqlTest.php | 34 +++++++++++++++++-- .../app/modules/Test/models/FakeSql.php | 27 +++++++++++++++ .../public/assets/css/vendor.another.css | 3 ++ .../public/assets/css/vendor.test.css | 3 ++ .../public/assets/js/vendor.example.js | 3 ++ .../assets/css/vendor.another.css | 3 ++ .../assets/css/vendor.test.css | 3 ++ .../assets/js/vendor.example.js | 3 ++ 9 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 tests/fixtures/app/modules/Test/models/FakeSql.php create mode 100644 tests/fixtures/public/assets/css/vendor.another.css create mode 100644 tests/fixtures/public/assets/css/vendor.test.css create mode 100644 tests/fixtures/public/assets/js/vendor.example.js create mode 100644 tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/css/vendor.another.css create mode 100644 tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/css/vendor.test.css create mode 100644 tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/js/vendor.example.js diff --git a/src/DI/Scaffolding/Adapter/Mysql.php b/src/DI/Scaffolding/Adapter/Mysql.php index d7aaa8c..61494f3 100644 --- a/src/DI/Scaffolding/Adapter/Mysql.php +++ b/src/DI/Scaffolding/Adapter/Mysql.php @@ -88,7 +88,7 @@ public function getPaginator($page = 1, $limit = 10) $this->ensureScaffolding(); return new PaginatorAdapterModel(array( - 'data' => (object) call_user_func(array($this->scaffolding->getRecord(), 'find'), $this->query), + 'data' => call_user_func(array($this->scaffolding->getRecord(), 'find'), $this->query), 'limit' => $limit, 'page' => $page )); diff --git a/tests/DI/Scaffolding/Adapter/MysqlTest.php b/tests/DI/Scaffolding/Adapter/MysqlTest.php index 44c6b93..15e3ee7 100644 --- a/tests/DI/Scaffolding/Adapter/MysqlTest.php +++ b/tests/DI/Scaffolding/Adapter/MysqlTest.php @@ -92,7 +92,29 @@ public function testShouldReturnValidPagination() $mysql = new \Vegas\DI\Scaffolding\Adapter\Mysql(); $scaffolding = new Scaffolding($mysql); - $scaffolding->setModelName('\Test\Models\Fake'); + $scaffolding->setModelName('\Test\Models\FakeSql'); + $scaffolding->setFormName('\Test\Forms\Fake'); + $scaffolding->doCreate([ + 'fake_field' => 'fake' + ]); + $scaffolding->doCreate([ + 'fake_field' => 'fake2' + ]); + + $pagination = $mysql->getPaginator(); + $paginate = $pagination->getPaginate(); + + $this->assertInstanceOf('\Phalcon\Paginator\Adapter\Model', $pagination); + $this->assertInstanceOf('\stdClass', $paginate); + $this->assertNotEquals(0, $paginate->total_items); + } + + public function testShouldReturnFilteredPagination() + { + $mysql = new \Vegas\DI\Scaffolding\Adapter\Mysql(); + $scaffolding = new Scaffolding($mysql); + + $scaffolding->setModelName('\Test\Models\FakeSql'); $scaffolding->setFormName('\Test\Forms\Fake'); $scaffolding->doCreate([ 'fake_field' => 'fake' @@ -100,9 +122,17 @@ public function testShouldReturnValidPagination() $scaffolding->doCreate([ 'fake_field' => 'fake2' ]); + $scaffolding->doCreate([ + 'fake_field' => 'fake' + ]); + $scaffolding->setQuery('fake_field = "fake2"'); $pagination = $mysql->getPaginator(); + $paginate = $pagination->getPaginate(); + $this->assertInstanceOf('\Phalcon\Paginator\Adapter\Model', $pagination); - $this->assertInstanceOf('\stdClass', $pagination->getPaginate()); + $this->assertInstanceOf('\stdClass', $paginate); + $this->assertNotEquals(0, $paginate->total_items); + $this->assertEquals('fake2', $paginate->items[0]->fake_field); } } \ No newline at end of file diff --git a/tests/fixtures/app/modules/Test/models/FakeSql.php b/tests/fixtures/app/modules/Test/models/FakeSql.php new file mode 100644 index 0000000..e40f5b9 --- /dev/null +++ b/tests/fixtures/app/modules/Test/models/FakeSql.php @@ -0,0 +1,27 @@ + + * @copyright Amsterdam Standard Sp. Z o.o. + * @homepage http://vegas-cmf.github.io + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Test\Models; + +use Vegas\Db\Decorator\ModelAbstract; + +class FakeSql extends ModelAbstract +{ + public function getSource() + { + return 'fake'; + } + + protected $mappings = array( + 'arraydata' => 'json' + ); +} \ No newline at end of file diff --git a/tests/fixtures/public/assets/css/vendor.another.css b/tests/fixtures/public/assets/css/vendor.another.css new file mode 100644 index 0000000..9b00552 --- /dev/null +++ b/tests/fixtures/public/assets/css/vendor.another.css @@ -0,0 +1,3 @@ +p { + color: #111; +} \ No newline at end of file diff --git a/tests/fixtures/public/assets/css/vendor.test.css b/tests/fixtures/public/assets/css/vendor.test.css new file mode 100644 index 0000000..0fdd20e --- /dev/null +++ b/tests/fixtures/public/assets/css/vendor.test.css @@ -0,0 +1,3 @@ +body { + background-color: #FDFDFD; +} \ No newline at end of file diff --git a/tests/fixtures/public/assets/js/vendor.example.js b/tests/fixtures/public/assets/js/vendor.example.js new file mode 100644 index 0000000..04a470a --- /dev/null +++ b/tests/fixtures/public/assets/js/vendor.example.js @@ -0,0 +1,3 @@ +/** + * Created by arius on 30.05.14. + */ diff --git a/tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/css/vendor.another.css b/tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/css/vendor.another.css new file mode 100644 index 0000000..9b00552 --- /dev/null +++ b/tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/css/vendor.another.css @@ -0,0 +1,3 @@ +p { + color: #111; +} \ No newline at end of file diff --git a/tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/css/vendor.test.css b/tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/css/vendor.test.css new file mode 100644 index 0000000..0fdd20e --- /dev/null +++ b/tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/css/vendor.test.css @@ -0,0 +1,3 @@ +body { + background-color: #FDFDFD; +} \ No newline at end of file diff --git a/tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/js/vendor.example.js b/tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/js/vendor.example.js new file mode 100644 index 0000000..04a470a --- /dev/null +++ b/tests/fixtures/vendor/vegas-cmf/fake-vendor-module/assets/js/vendor.example.js @@ -0,0 +1,3 @@ +/** + * Created by arius on 30.05.14. + */ From 8c3b5261c93043f07b1856b1333ee018d2756fd7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Wed, 23 Mar 2016 12:17:34 +0100 Subject: [PATCH 06/23] php to 5.5 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9839451..20cc738 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: php php: - - 5.4 + - 5.5 services: - mongodb From dd5b6cfa38c195fbd959e401bdd2b6ce0d04c96b Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Tue, 29 Mar 2016 07:15:37 +0200 Subject: [PATCH 07/23] php 5.6 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 20cc738..9d845f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: php php: - - 5.5 + - 5.6 services: - mongodb From 557c276068b4d00776cd49c1df2f9be523d4ee2b Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 09:11:30 +0200 Subject: [PATCH 08/23] i18n task --- src/Task/I18nTask.php | 334 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 src/Task/I18nTask.php diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php new file mode 100644 index 0000000..14bad17 --- /dev/null +++ b/src/Task/I18nTask.php @@ -0,0 +1,334 @@ +getTmpFile(); + +file_put_contents($tmpPo, $this->generatePoContent([ +'message1', 'other message', 'dynamic %s message' +])); + +$this->addPo($tmpPo, $tmpPo); +} +``` + * + * If You are using non-utf8 standard charset, consider adding own header into PO files. + */ +class I18nTask extends TaskAbstract +{ + protected $xgettext = 'xgettext'; + protected $xgettextTemplate = 'xgettext-template'; + protected $msgcat = 'msgcat'; + + protected $encoding = 'UTF-8'; + protected $directories = [ + APP_ROOT . '/app/modules', + APP_ROOT . '/app/layouts', + ]; + protected $langDir = APP_ROOT . '/lang'; + protected $langs = [ + 'nl_NL.utf8' + ]; + protected $textKeywords = [ + '_' + ]; + protected $templateKeywords = [ + 'i18n._', '_' + ]; + + private $parser = '{xgettext} --omit-header --no-wrap --language="{lang}" --from-code="{encoding}" -k"{keys}" -j -o"{out}" {in}'; + private $templateParser = '{xgettextTemplate} --force-po=false --language="{lang}" --from-code="{encoding}" --keyword="{keys}" --output="{out}" {in}'; + private $mergePoCmd = '{msgcat} --force-po --no-wrap --use-first {extra} {base} -o {base} 2>/dev/null'; + + public function setupOptions() + { + $action = new Action('generate', 'Generate *.PO files for each lang'); + $this->addTaskAction($action); + } + + public function generateAction() + { + if ( ! $this->isInstalled($this->xgettext) ) { + $this->throwError("xgettext not installed : https://www.gnu.org/software/gettext/"); + } + if ( ! $this->isInstalled($this->msgcat) ) { + $this->throwError("msgcat not installed"); + } + if ( ! $this->isInstalled($this->xgettextTemplate) ) { + $this->throwError("xgettext-template not installed : https://www.npmjs.com/package/xgettext-template"); + } + + $textTmpPo = $this->getTmpFile(); + $templateTmpPo = $this->getTmpFile(); + + foreach ($this->directories as $directory) { + $directoryIterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator( + $directory, + \RecursiveDirectoryIterator::SKIP_DOTS + ), + \RecursiveIteratorIterator::SELF_FIRST, + \RecursiveIteratorIterator::CATCH_GET_CHILD + ); + + $phpTmpPo = $this->getTmpFile(); + $voltTmpPo = $this->getTmpFile(); + + echo "Scanning $directory\n"; + + foreach ($directoryIterator as $file=>$info) { + if ( $this->isFile($file, 'php') ) { + $this->exec($this->getTextParser('PHP', $file, $phpTmpPo)); + } elseif ( $this->isFile($file, 'volt') ) { + $tmpPo = $this->getTmpFile(); + $this->exec($this->getTemplateParser('Volt', $file, $tmpPo)); + + $lines = count( file( $tmpPo )); + if ($lines > 2) { + $this->removeTopLines($tmpPo, 2); + + $this->addPo($voltTmpPo, $tmpPo); + } else { + unlink($tmpPo); + } + } + } + + $this->addPo($textTmpPo, $phpTmpPo); + $this->addPo($templateTmpPo, $voltTmpPo); + } + + echo "Preparing final files...\n"; + + $this->addPo($textTmpPo, $templateTmpPo); + + $this->addToFinalPo($textTmpPo); + + $langPos = $this->savePo($textTmpPo); + + echo "\nGenerated files:"; + foreach ($langPos as $langPo) { + echo "\n$langPo"; + } + + } + + /** + * @param string $tmpPo generated PO file + */ + protected function addToFinalPo($tmpPo) + { + + } + + /** + * @param string[]|array $items string|[msgid,?msgstr,?comment] + * @return string + */ + protected function generatePoContent(array $items) + { + $poText = ''; + + foreach ($items as $item) { + if (is_array($item) && isset($item['msgid'])) { + if (isset($item['comment'])) { + $poText .= sprintf( + "\n#: %s", + $item['comment'] + ); + } + $poText .= sprintf( + "\nmsgid \"%s\"\nmsgstr \"%s\"\n", + $item['msgid'], + ( isset($item['msgstr']) ) ? $item['msgstr'] : '' + ); + } elseif (is_string($item)) { + $poText .= sprintf( + "\nmsgid \"%s\"\nmsgstr \"\"\n", + $item + ); + } + } + + return $poText; + } + + /** + * merge new PO file and remove it + * @param string $basePo + * @param string $newPo + */ + protected function addPo($basePo, $newPo) + { + $this->exec($this->getMsgCat($newPo, $basePo)); + unlink($newPo); + } + + /** + * @param string $poFile + * @return string[] + */ + protected function savePo($poFile) + { + $files = []; + + foreach ($this->langs as $lang) { + $poBaseFile = $this->langDir . "/$lang/LC_MESSAGES/messages.po"; + + if (!is_file($poBaseFile)) { + mkdir( dirname($poBaseFile), 0777, true ); + touch($poBaseFile); + } + + $this->addPo($poBaseFile, $poFile); + + $files[] = $poBaseFile; + } + + return $files; + } + + protected function getMsgCat($extra, $base) + { + return str_replace( + [ + '{msgcat}', + '{extra}', + '{base}' + ], + [ + $this->msgcat, + $extra, + $base + ], + $this->mergePoCmd + ); + } + + /** + * @param string $lang PHP + * @param string $in filename + * @param string $out filename + * @return string command + */ + protected function getTemplateParser($lang, $in, $out) + { + return str_replace( + [ + '{xgettextTemplate}', + '{lang}', + '{encoding}', + '{keys}', + '{out}', + '{in}' + ], + [ + $this->xgettextTemplate, + $lang, + $this->encoding, + implode(',', $this->templateKeywords), + $out, + $in + ], + $this->templateParser + ); + } + + /** + * @param string $lang PHP + * @param string $in filename + * @param string $out filename + * @return string command + */ + protected function getTextParser($lang, $in, $out) + { + return str_replace( + [ + '{xgettext}', + '{lang}', + '{encoding}', + '{keys}', + '{out}', + '{in}' + ], + [ + $this->xgettext, + $lang, + $this->encoding, + implode(',', $this->textKeywords), + $out, + $in + ], + $this->parser + ); + } + + protected function getTmpFile($file=null) + { + $tmpFile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . ($file ?: uniqid()); + touch($tmpFile); + if (!is_file($tmpFile)) + $this->throwError("Cant create $tmpFile from $file"); + + return $tmpFile; + } + + protected function isInstalled($cmd) + { + return strlen($this->exec("command -v $cmd")) > 0; + } + + protected function exec($cmd) + { + return shell_exec($cmd); + } + + protected function isFile($filename, $ext) + { + return is_file($filename) && preg_match('/^.+\.'.$ext.'$/i', $filename); + } + + private function removeTopLines($filename, $lines=0) + { + if ($lines<1) + return false; + + $content = file_get_contents($filename); + for ($i=0;$i<$lines;$i++) { + $content = preg_replace('/^.+\n/', '', $content); + } + file_put_contents($filename, $content); + } + +} \ No newline at end of file From 90b0c728da20b03ea749914b0d709cf44a3316ab Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 09:15:18 +0200 Subject: [PATCH 09/23] i18n task --- src/Task/I18nTask.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php index 14bad17..b84dafb 100644 --- a/src/Task/I18nTask.php +++ b/src/Task/I18nTask.php @@ -30,18 +30,18 @@ * * * Sample of `addToFinalPo` using: -``` -protected function addToFinalPo($tmpPo) -{ -$tmpPo = $this->getTmpFile(); - -file_put_contents($tmpPo, $this->generatePoContent([ -'message1', 'other message', 'dynamic %s message' -])); - -$this->addPo($tmpPo, $tmpPo); -} -``` + * ``` + * protected function addToFinalPo($tmpPo) + * { + * $tmpPo = $this->getTmpFile(); + * + * file_put_contents($tmpPo, $this->generatePoContent([ + * 'message1', 'other message', 'dynamic %s message' + * ])); + * + * $this->addPo($tmpPo, $tmpPo); + * } + * ``` * * If You are using non-utf8 standard charset, consider adding own header into PO files. */ From 9900c601fe424fda175651c27e2adf7f58a03e6f Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 10:38:31 +0200 Subject: [PATCH 10/23] build & testing --- .travis.yml | 3 +++ tests/Task/I18nTest.php | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/Task/I18nTest.php diff --git a/.travis.yml b/.travis.yml index 9d845f1..36b800f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: php php: - 5.6 +node_js: + - 5 services: - mongodb @@ -13,6 +15,7 @@ before_install: - echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list - sudo apt-get update - sudo apt-get install mongodb-org-server + - npm install -g xgettext-template before_script: - phpenv config-add travis/php.ini diff --git a/tests/Task/I18nTest.php b/tests/Task/I18nTest.php new file mode 100644 index 0000000..fd7de26 --- /dev/null +++ b/tests/Task/I18nTest.php @@ -0,0 +1,16 @@ +runCliAction('cli/cli.php vegas:i18n generate'); + + $this->assertContains("Scanning", $result); + $this->assertContains("Preparing final files...", $result); + $this->assertContains("Generated files", $result); + } +} \ No newline at end of file From 931000e527874a54f6e1b018ba8de1bb26206595 Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 11:05:52 +0200 Subject: [PATCH 11/23] build & testing --- src/Task/I18nTask.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php index b84dafb..4598e10 100644 --- a/src/Task/I18nTask.php +++ b/src/Task/I18nTask.php @@ -33,13 +33,13 @@ * ``` * protected function addToFinalPo($tmpPo) * { - * $tmpPo = $this->getTmpFile(); + * $newPo = $this->getTmpFile(); * - * file_put_contents($tmpPo, $this->generatePoContent([ + * file_put_contents($newPo, $this->generatePoContent([ * 'message1', 'other message', 'dynamic %s message' * ])); * - * $this->addPo($tmpPo, $tmpPo); + * $this->addPo($tmpPo, $newPo); * } * ``` * From a711edf07de1725b06287e40733b266aa078efa3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 11:29:28 +0200 Subject: [PATCH 12/23] Create I18nTask.php --- src/Task/I18nTask.php | 334 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 src/Task/I18nTask.php diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php new file mode 100644 index 0000000..2ad005f --- /dev/null +++ b/src/Task/I18nTask.php @@ -0,0 +1,334 @@ +getTmpFile(); + * + * file_put_contents($newPo, $this->generatePoContent([ + * 'message1', 'other message', 'dynamic %s message' + * ])); + * + * $this->addPo($tmpPo, $newPo); + * } + * ``` + * + * If You are using non-utf8 standard charset, consider adding own header into PO files. + */ +class I18nTask extends TaskAbstract +{ + protected $xgettext = 'xgettext'; + protected $xgettextTemplate = 'xgettext-template'; + protected $msgcat = 'msgcat'; + + protected $encoding = 'UTF-8'; + protected $directories = [ + APP_ROOT . '/app/modules', + APP_ROOT . '/app/layouts', + ]; + protected $langDir = APP_ROOT . '/lang'; + protected $langs = [ + 'nl_NL.utf8' + ]; + protected $textKeywords = [ + '_' + ]; + protected $templateKeywords = [ + 'i18n._', '_' + ]; + + private $parser = '{xgettext} --omit-header --no-wrap --language="{lang}" --from-code="{encoding}" -k"{keys}" -j -o"{out}" {in}'; + private $templateParser = '{xgettextTemplate} --force-po=false --language="{lang}" --from-code="{encoding}" --keyword="{keys}" --output="{out}" {in}'; + private $mergePoCmd = '{msgcat} --force-po --no-wrap --use-first {extra} {base} -o {base} 2>/dev/null'; + + public function setupOptions() + { + $action = new Action('generate', 'Generate *.PO files for each lang'); + $this->addTaskAction($action); + } + + public function generateAction() + { + if ( ! $this->isInstalled($this->xgettext) ) { + $this->throwError("xgettext not installed : https://www.gnu.org/software/gettext/"); + } + if ( ! $this->isInstalled($this->msgcat) ) { + $this->throwError("msgcat not installed"); + } + if ( ! $this->isInstalled($this->xgettextTemplate) ) { + $this->throwError("xgettext-template not installed : https://www.npmjs.com/package/xgettext-template"); + } + + $textTmpPo = $this->getTmpFile(); + $templateTmpPo = $this->getTmpFile(); + + foreach ($this->directories as $directory) { + $directoryIterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator( + $directory, + \RecursiveDirectoryIterator::SKIP_DOTS + ), + \RecursiveIteratorIterator::SELF_FIRST, + \RecursiveIteratorIterator::CATCH_GET_CHILD + ); + + $phpTmpPo = $this->getTmpFile(); + $voltTmpPo = $this->getTmpFile(); + + echo "Scanning $directory\n"; + + foreach ($directoryIterator as $file=>$info) { + if ( $this->isFile($file, 'php') ) { + $this->exec($this->getTextParser('PHP', $file, $phpTmpPo)); + } elseif ( $this->isFile($file, 'volt') ) { + $tmpPo = $this->getTmpFile(); + $this->exec($this->getTemplateParser('Volt', $file, $tmpPo)); + + $lines = count( file( $tmpPo )); + if ($lines > 2) { + $this->removeTopLines($tmpPo, 2); + + $this->addPo($voltTmpPo, $tmpPo); + } else { + unlink($tmpPo); + } + } + } + + $this->addPo($textTmpPo, $phpTmpPo); + $this->addPo($templateTmpPo, $voltTmpPo); + } + + echo "Preparing final files...\n"; + + $this->addPo($textTmpPo, $templateTmpPo); + + $this->addToFinalPo($textTmpPo); + + $langPos = $this->savePo($textTmpPo); + + echo "\nGenerated files:"; + foreach ($langPos as $langPo) { + echo "\n$langPo"; + } + + } + + /** + * @param string $tmpPo generated PO file + */ + protected function addToFinalPo($tmpPo) + { + + } + + /** + * @param string[]|array $items string|[msgid,?msgstr,?comment] + * @return string + */ + protected function generatePoContent(array $items) + { + $poText = ''; + + foreach ($items as $item) { + if (is_array($item) && isset($item['msgid'])) { + if (isset($item['comment'])) { + $poText .= sprintf( + "\n#: %s", + $item['comment'] + ); + } + $poText .= sprintf( + "\nmsgid \"%s\"\nmsgstr \"%s\"\n", + $item['msgid'], + ( isset($item['msgstr']) ) ? $item['msgstr'] : '' + ); + } elseif (is_string($item)) { + $poText .= sprintf( + "\nmsgid \"%s\"\nmsgstr \"\"\n", + $item + ); + } + } + + return $poText; + } + + /** + * merge new PO file and remove it + * @param string $basePo + * @param string $newPo + */ + protected function addPo($basePo, $newPo) + { + $this->exec($this->getMsgCat($newPo, $basePo)); + unlink($newPo); + } + + /** + * @param string $poFile + * @return string[] + */ + protected function savePo($poFile) + { + $files = []; + + foreach ($this->langs as $lang) { + $poBaseFile = $this->langDir . "/$lang/LC_MESSAGES/messages.po"; + + if (!is_file($poBaseFile)) { + mkdir( dirname($poBaseFile), 0777, true ); + touch($poBaseFile); + } + + $this->addPo($poBaseFile, $poFile); + + $files[] = $poBaseFile; + } + + return $files; + } + + protected function getMsgCat($extra, $base) + { + return str_replace( + [ + '{msgcat}', + '{extra}', + '{base}' + ], + [ + $this->msgcat, + $extra, + $base + ], + $this->mergePoCmd + ); + } + + /** + * @param string $lang PHP + * @param string $in filename + * @param string $out filename + * @return string command + */ + protected function getTemplateParser($lang, $in, $out) + { + return str_replace( + [ + '{xgettextTemplate}', + '{lang}', + '{encoding}', + '{keys}', + '{out}', + '{in}' + ], + [ + $this->xgettextTemplate, + $lang, + $this->encoding, + implode(',', $this->templateKeywords), + $out, + $in + ], + $this->templateParser + ); + } + + /** + * @param string $lang PHP + * @param string $in filename + * @param string $out filename + * @return string command + */ + protected function getTextParser($lang, $in, $out) + { + return str_replace( + [ + '{xgettext}', + '{lang}', + '{encoding}', + '{keys}', + '{out}', + '{in}' + ], + [ + $this->xgettext, + $lang, + $this->encoding, + implode(',', $this->textKeywords), + $out, + $in + ], + $this->parser + ); + } + + protected function getTmpFile($file=null) + { + $tmpFile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . ($file ?: uniqid()); + touch($tmpFile); + if (!is_file($tmpFile)) + $this->throwError("Cant create $tmpFile from $file"); + + return $tmpFile; + } + + protected function isInstalled($cmd) + { + return strlen($this->exec("command -v $cmd")) > 0; + } + + protected function exec($cmd) + { + return shell_exec($cmd); + } + + protected function isFile($filename, $ext) + { + return is_file($filename) && preg_match('/^.+\.'.$ext.'$/i', $filename); + } + + private function removeTopLines($filename, $lines=0) + { + if ($lines<1) + return false; + + $content = file_get_contents($filename); + for ($i=0;$i<$lines;$i++) { + $content = preg_replace('/^.+\n/', '', $content); + } + file_put_contents($filename, $content); + } + +} From a1979ec93d5b0cbfaf7cd64f250701656b3a282d Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 12:43:40 +0200 Subject: [PATCH 13/23] quickfix --- src/Task/I18nTask.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php index 4598e10..817499b 100644 --- a/src/Task/I18nTask.php +++ b/src/Task/I18nTask.php @@ -188,11 +188,16 @@ protected function generatePoContent(array $items) * merge new PO file and remove it * @param string $basePo * @param string $newPo + * @return bool */ protected function addPo($basePo, $newPo) { + if (!is_file($basePo) || !is_file($newPo)) + return false; + $this->exec($this->getMsgCat($newPo, $basePo)); unlink($newPo); + return true; } /** From 8a3086be4d49054bca4bc91590cf0636daf3094c Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 12:50:38 +0200 Subject: [PATCH 14/23] quickfix --- src/Task/I18nTask.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php index 817499b..758211d 100644 --- a/src/Task/I18nTask.php +++ b/src/Task/I18nTask.php @@ -188,15 +188,19 @@ protected function generatePoContent(array $items) * merge new PO file and remove it * @param string $basePo * @param string $newPo + * @param bool $withoutRemoving * @return bool */ - protected function addPo($basePo, $newPo) + protected function addPo($basePo, $newPo, $withoutRemoving=false) { if (!is_file($basePo) || !is_file($newPo)) return false; $this->exec($this->getMsgCat($newPo, $basePo)); - unlink($newPo); + + if (!$withoutRemoving) + unlink($newPo); + return true; } @@ -216,7 +220,7 @@ protected function savePo($poFile) touch($poBaseFile); } - $this->addPo($poBaseFile, $poFile); + $this->addPo($poBaseFile, $poFile, true); $files[] = $poBaseFile; } From 3a9da70e3abe705481ed2df07bff4b5b69443e97 Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 12:59:14 +0200 Subject: [PATCH 15/23] quickfix --- src/Task/I18nTask.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php index 758211d..1056488 100644 --- a/src/Task/I18nTask.php +++ b/src/Task/I18nTask.php @@ -129,7 +129,7 @@ public function generateAction() $this->addPo($templateTmpPo, $voltTmpPo); } - echo "Preparing final files...\n"; + echo "\nPreparing final files...\n"; $this->addPo($textTmpPo, $templateTmpPo); @@ -220,9 +220,10 @@ protected function savePo($poFile) touch($poBaseFile); } - $this->addPo($poBaseFile, $poFile, true); + $updated = $this->addPo($poBaseFile, $poFile, true); - $files[] = $poBaseFile; + if ($updated) + $files[] = $poBaseFile; } return $files; From da69448f21004485be0ad0cf68d4da13b0bd94eb Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 13:01:16 +0200 Subject: [PATCH 16/23] Update I18nTask.php --- src/Task/I18nTask.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php index 2ad005f..498b845 100644 --- a/src/Task/I18nTask.php +++ b/src/Task/I18nTask.php @@ -188,11 +188,20 @@ protected function generatePoContent(array $items) * merge new PO file and remove it * @param string $basePo * @param string $newPo + * @param bool $withoutRemoving + * @return bool */ - protected function addPo($basePo, $newPo) + protected function addPo($basePo, $newPo, $withoutRemoving=false) { + if (!is_file($basePo) || !is_file($newPo)) + return false; + $this->exec($this->getMsgCat($newPo, $basePo)); - unlink($newPo); + + if (!$withoutRemoving) + unlink($newPo); + + return true; } /** @@ -211,9 +220,10 @@ protected function savePo($poFile) touch($poBaseFile); } - $this->addPo($poBaseFile, $poFile); - - $files[] = $poBaseFile; + $updated = $this->addPo($poBaseFile, $poFile, true); + + if ($updated) + $files[] = $poBaseFile; } return $files; From 0f9fa600ccc235524c3cc59ca82596db5eefe8d3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 7 Apr 2016 13:36:58 +0200 Subject: [PATCH 17/23] quickfix --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 36b800f..b80ae49 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: php php: - 5.6 node_js: - - 5 + - 3 services: - mongodb From abd59b279bb62990a136a3f6a39a038fab0581b4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 19 May 2016 14:40:06 +0200 Subject: [PATCH 18/23] Update I18nTask.php make compatible with php version older than 5.6 --- src/Task/I18nTask.php | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php index 498b845..8f2a7f2 100644 --- a/src/Task/I18nTask.php +++ b/src/Task/I18nTask.php @@ -52,25 +52,35 @@ class I18nTask extends TaskAbstract protected $msgcat = 'msgcat'; protected $encoding = 'UTF-8'; - protected $directories = [ - APP_ROOT . '/app/modules', - APP_ROOT . '/app/layouts', - ]; + protected $directories; protected $langDir = APP_ROOT . '/lang'; - protected $langs = [ - 'nl_NL.utf8' - ]; - protected $textKeywords = [ - '_' - ]; - protected $templateKeywords = [ - 'i18n._', '_' - ]; + protected $langs; + protected $textKeywords; + protected $templateKeywords; private $parser = '{xgettext} --omit-header --no-wrap --language="{lang}" --from-code="{encoding}" -k"{keys}" -j -o"{out}" {in}'; private $templateParser = '{xgettextTemplate} --force-po=false --language="{lang}" --from-code="{encoding}" --keyword="{keys}" --output="{out}" {in}'; private $mergePoCmd = '{msgcat} --force-po --no-wrap --use-first {extra} {base} -o {base} 2>/dev/null'; + public function __construct() + { + parent::__construct(); + + $this->langs = [ + 'nl_NL.utf8' + ]; + $this->textKeywords = [ + '_' + ]; + $this->templateKeywords = [ + 'i18n._', '_' + ]; + $this->directories = [ + APP_ROOT . '/app/modules', + APP_ROOT . '/app/layouts', + ]; + } + public function setupOptions() { $action = new Action('generate', 'Generate *.PO files for each lang'); From 05d207ab141fdd503b00d94ffafb663c8dd24593 Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Thu, 19 May 2016 14:48:52 +0200 Subject: [PATCH 19/23] Update I18nTask.php make compatible with PHP older than 5.6 --- src/Task/I18nTask.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php index 8f2a7f2..6a7db9c 100644 --- a/src/Task/I18nTask.php +++ b/src/Task/I18nTask.php @@ -53,7 +53,7 @@ class I18nTask extends TaskAbstract protected $encoding = 'UTF-8'; protected $directories; - protected $langDir = APP_ROOT . '/lang'; + protected $langDir; protected $langs; protected $textKeywords; protected $templateKeywords; @@ -66,6 +66,7 @@ public function __construct() { parent::__construct(); + $langDir = APP_ROOT . '/lang'; $this->langs = [ 'nl_NL.utf8' ]; From c92018aed58829fc07a6419f9094969e90a48d55 Mon Sep 17 00:00:00 2001 From: Krzysztof Kabala Date: Tue, 2 Aug 2016 09:25:56 +0200 Subject: [PATCH 20/23] Update I18nTask.php bug fix: missing translations (header needed when non-standard chars used) --- src/Task/I18nTask.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php index 6a7db9c..150097a 100644 --- a/src/Task/I18nTask.php +++ b/src/Task/I18nTask.php @@ -57,10 +57,11 @@ class I18nTask extends TaskAbstract protected $langs; protected $textKeywords; protected $templateKeywords; + protected $poHeader = 'msgid ""'."\n".'msgstr "Content-Type: text/plain; charset=utf-8\n"'."\n"; private $parser = '{xgettext} --omit-header --no-wrap --language="{lang}" --from-code="{encoding}" -k"{keys}" -j -o"{out}" {in}'; private $templateParser = '{xgettextTemplate} --force-po=false --language="{lang}" --from-code="{encoding}" --keyword="{keys}" --output="{out}" {in}'; - private $mergePoCmd = '{msgcat} --force-po --no-wrap --use-first {extra} {base} -o {base} 2>/dev/null'; + private $mergePoCmd = '{msgcat} --force-po --no-wrap --use-first {extra} {base} -o {base}'; public function __construct() { @@ -127,8 +128,6 @@ public function generateAction() $lines = count( file( $tmpPo )); if ($lines > 2) { - $this->removeTopLines($tmpPo, 2); - $this->addPo($voltTmpPo, $tmpPo); } else { unlink($tmpPo); @@ -169,7 +168,7 @@ protected function addToFinalPo($tmpPo) */ protected function generatePoContent(array $items) { - $poText = ''; + $poText = $this->poHeader; foreach ($items as $item) { if (is_array($item) && isset($item['msgid'])) { From 58da14e34625db630c2e9aab9532bbe11047d093 Mon Sep 17 00:00:00 2001 From: krzysztof_kabala Date: Thu, 9 Feb 2017 12:47:32 +0100 Subject: [PATCH 21/23] cleanup --- .travis.yml | 2 +- src/Task/I18nTask.php | 344 ---------------------------------------- tests/Task/I18nTest.php | 16 -- 3 files changed, 1 insertion(+), 361 deletions(-) delete mode 100644 src/Task/I18nTask.php delete mode 100644 tests/Task/I18nTest.php diff --git a/.travis.yml b/.travis.yml index b80ae49..1a107b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: php php: - - 5.6 + - 5.4 node_js: - 3 diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php deleted file mode 100644 index 1056488..0000000 --- a/src/Task/I18nTask.php +++ /dev/null @@ -1,344 +0,0 @@ -getTmpFile(); - * - * file_put_contents($newPo, $this->generatePoContent([ - * 'message1', 'other message', 'dynamic %s message' - * ])); - * - * $this->addPo($tmpPo, $newPo); - * } - * ``` - * - * If You are using non-utf8 standard charset, consider adding own header into PO files. - */ -class I18nTask extends TaskAbstract -{ - protected $xgettext = 'xgettext'; - protected $xgettextTemplate = 'xgettext-template'; - protected $msgcat = 'msgcat'; - - protected $encoding = 'UTF-8'; - protected $directories = [ - APP_ROOT . '/app/modules', - APP_ROOT . '/app/layouts', - ]; - protected $langDir = APP_ROOT . '/lang'; - protected $langs = [ - 'nl_NL.utf8' - ]; - protected $textKeywords = [ - '_' - ]; - protected $templateKeywords = [ - 'i18n._', '_' - ]; - - private $parser = '{xgettext} --omit-header --no-wrap --language="{lang}" --from-code="{encoding}" -k"{keys}" -j -o"{out}" {in}'; - private $templateParser = '{xgettextTemplate} --force-po=false --language="{lang}" --from-code="{encoding}" --keyword="{keys}" --output="{out}" {in}'; - private $mergePoCmd = '{msgcat} --force-po --no-wrap --use-first {extra} {base} -o {base} 2>/dev/null'; - - public function setupOptions() - { - $action = new Action('generate', 'Generate *.PO files for each lang'); - $this->addTaskAction($action); - } - - public function generateAction() - { - if ( ! $this->isInstalled($this->xgettext) ) { - $this->throwError("xgettext not installed : https://www.gnu.org/software/gettext/"); - } - if ( ! $this->isInstalled($this->msgcat) ) { - $this->throwError("msgcat not installed"); - } - if ( ! $this->isInstalled($this->xgettextTemplate) ) { - $this->throwError("xgettext-template not installed : https://www.npmjs.com/package/xgettext-template"); - } - - $textTmpPo = $this->getTmpFile(); - $templateTmpPo = $this->getTmpFile(); - - foreach ($this->directories as $directory) { - $directoryIterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator( - $directory, - \RecursiveDirectoryIterator::SKIP_DOTS - ), - \RecursiveIteratorIterator::SELF_FIRST, - \RecursiveIteratorIterator::CATCH_GET_CHILD - ); - - $phpTmpPo = $this->getTmpFile(); - $voltTmpPo = $this->getTmpFile(); - - echo "Scanning $directory\n"; - - foreach ($directoryIterator as $file=>$info) { - if ( $this->isFile($file, 'php') ) { - $this->exec($this->getTextParser('PHP', $file, $phpTmpPo)); - } elseif ( $this->isFile($file, 'volt') ) { - $tmpPo = $this->getTmpFile(); - $this->exec($this->getTemplateParser('Volt', $file, $tmpPo)); - - $lines = count( file( $tmpPo )); - if ($lines > 2) { - $this->removeTopLines($tmpPo, 2); - - $this->addPo($voltTmpPo, $tmpPo); - } else { - unlink($tmpPo); - } - } - } - - $this->addPo($textTmpPo, $phpTmpPo); - $this->addPo($templateTmpPo, $voltTmpPo); - } - - echo "\nPreparing final files...\n"; - - $this->addPo($textTmpPo, $templateTmpPo); - - $this->addToFinalPo($textTmpPo); - - $langPos = $this->savePo($textTmpPo); - - echo "\nGenerated files:"; - foreach ($langPos as $langPo) { - echo "\n$langPo"; - } - - } - - /** - * @param string $tmpPo generated PO file - */ - protected function addToFinalPo($tmpPo) - { - - } - - /** - * @param string[]|array $items string|[msgid,?msgstr,?comment] - * @return string - */ - protected function generatePoContent(array $items) - { - $poText = ''; - - foreach ($items as $item) { - if (is_array($item) && isset($item['msgid'])) { - if (isset($item['comment'])) { - $poText .= sprintf( - "\n#: %s", - $item['comment'] - ); - } - $poText .= sprintf( - "\nmsgid \"%s\"\nmsgstr \"%s\"\n", - $item['msgid'], - ( isset($item['msgstr']) ) ? $item['msgstr'] : '' - ); - } elseif (is_string($item)) { - $poText .= sprintf( - "\nmsgid \"%s\"\nmsgstr \"\"\n", - $item - ); - } - } - - return $poText; - } - - /** - * merge new PO file and remove it - * @param string $basePo - * @param string $newPo - * @param bool $withoutRemoving - * @return bool - */ - protected function addPo($basePo, $newPo, $withoutRemoving=false) - { - if (!is_file($basePo) || !is_file($newPo)) - return false; - - $this->exec($this->getMsgCat($newPo, $basePo)); - - if (!$withoutRemoving) - unlink($newPo); - - return true; - } - - /** - * @param string $poFile - * @return string[] - */ - protected function savePo($poFile) - { - $files = []; - - foreach ($this->langs as $lang) { - $poBaseFile = $this->langDir . "/$lang/LC_MESSAGES/messages.po"; - - if (!is_file($poBaseFile)) { - mkdir( dirname($poBaseFile), 0777, true ); - touch($poBaseFile); - } - - $updated = $this->addPo($poBaseFile, $poFile, true); - - if ($updated) - $files[] = $poBaseFile; - } - - return $files; - } - - protected function getMsgCat($extra, $base) - { - return str_replace( - [ - '{msgcat}', - '{extra}', - '{base}' - ], - [ - $this->msgcat, - $extra, - $base - ], - $this->mergePoCmd - ); - } - - /** - * @param string $lang PHP - * @param string $in filename - * @param string $out filename - * @return string command - */ - protected function getTemplateParser($lang, $in, $out) - { - return str_replace( - [ - '{xgettextTemplate}', - '{lang}', - '{encoding}', - '{keys}', - '{out}', - '{in}' - ], - [ - $this->xgettextTemplate, - $lang, - $this->encoding, - implode(',', $this->templateKeywords), - $out, - $in - ], - $this->templateParser - ); - } - - /** - * @param string $lang PHP - * @param string $in filename - * @param string $out filename - * @return string command - */ - protected function getTextParser($lang, $in, $out) - { - return str_replace( - [ - '{xgettext}', - '{lang}', - '{encoding}', - '{keys}', - '{out}', - '{in}' - ], - [ - $this->xgettext, - $lang, - $this->encoding, - implode(',', $this->textKeywords), - $out, - $in - ], - $this->parser - ); - } - - protected function getTmpFile($file=null) - { - $tmpFile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . ($file ?: uniqid()); - touch($tmpFile); - if (!is_file($tmpFile)) - $this->throwError("Cant create $tmpFile from $file"); - - return $tmpFile; - } - - protected function isInstalled($cmd) - { - return strlen($this->exec("command -v $cmd")) > 0; - } - - protected function exec($cmd) - { - return shell_exec($cmd); - } - - protected function isFile($filename, $ext) - { - return is_file($filename) && preg_match('/^.+\.'.$ext.'$/i', $filename); - } - - private function removeTopLines($filename, $lines=0) - { - if ($lines<1) - return false; - - $content = file_get_contents($filename); - for ($i=0;$i<$lines;$i++) { - $content = preg_replace('/^.+\n/', '', $content); - } - file_put_contents($filename, $content); - } - -} \ No newline at end of file diff --git a/tests/Task/I18nTest.php b/tests/Task/I18nTest.php deleted file mode 100644 index fd7de26..0000000 --- a/tests/Task/I18nTest.php +++ /dev/null @@ -1,16 +0,0 @@ -runCliAction('cli/cli.php vegas:i18n generate'); - - $this->assertContains("Scanning", $result); - $this->assertContains("Preparing final files...", $result); - $this->assertContains("Generated files", $result); - } -} \ No newline at end of file From 8ad04b8acf96a800c033537cafa6dac71c67a5f4 Mon Sep 17 00:00:00 2001 From: krzysztof_kabala Date: Thu, 9 Feb 2017 12:48:53 +0100 Subject: [PATCH 22/23] cleanup --- .travis.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1a107b6..a7cf694 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,6 @@ language: php php: - 5.4 -node_js: - - 3 services: - mongodb @@ -15,7 +13,6 @@ before_install: - echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list - sudo apt-get update - sudo apt-get install mongodb-org-server - - npm install -g xgettext-template before_script: - phpenv config-add travis/php.ini @@ -23,7 +20,7 @@ before_script: - (cd cphalcon/ext; export CFLAGS="-g3 -O1 -fno-delete-null-pointer-checks -Wall"; phpize && ./configure --enable-phalcon && make -j4 && sudo make install && phpenv config-add ../unit-tests/ci/phalcon.ini) - curl -s http://getcomposer.org/installer | php - php composer.phar install --dev - + script: - cp tests/config.sample.php tests/config.php - mkdir -p tests/fixtures/cache @@ -32,4 +29,4 @@ script: - php vendor/bin/phpunit -c travis/phpunit.xml.dist after_script: - - php vendor/bin/coveralls -v + - php vendor/bin/coveralls -v \ No newline at end of file From 1310ef71dc17f3a0c949c9aefe6ec3f7e02f364a Mon Sep 17 00:00:00 2001 From: krzysztof_kabala Date: Fri, 10 Feb 2017 12:06:04 +0100 Subject: [PATCH 23/23] remove i18n --- src/Task/I18nTask.php | 354 ------------------------------------------ 1 file changed, 354 deletions(-) delete mode 100644 src/Task/I18nTask.php diff --git a/src/Task/I18nTask.php b/src/Task/I18nTask.php deleted file mode 100644 index 150097a..0000000 --- a/src/Task/I18nTask.php +++ /dev/null @@ -1,354 +0,0 @@ -getTmpFile(); - * - * file_put_contents($newPo, $this->generatePoContent([ - * 'message1', 'other message', 'dynamic %s message' - * ])); - * - * $this->addPo($tmpPo, $newPo); - * } - * ``` - * - * If You are using non-utf8 standard charset, consider adding own header into PO files. - */ -class I18nTask extends TaskAbstract -{ - protected $xgettext = 'xgettext'; - protected $xgettextTemplate = 'xgettext-template'; - protected $msgcat = 'msgcat'; - - protected $encoding = 'UTF-8'; - protected $directories; - protected $langDir; - protected $langs; - protected $textKeywords; - protected $templateKeywords; - protected $poHeader = 'msgid ""'."\n".'msgstr "Content-Type: text/plain; charset=utf-8\n"'."\n"; - - private $parser = '{xgettext} --omit-header --no-wrap --language="{lang}" --from-code="{encoding}" -k"{keys}" -j -o"{out}" {in}'; - private $templateParser = '{xgettextTemplate} --force-po=false --language="{lang}" --from-code="{encoding}" --keyword="{keys}" --output="{out}" {in}'; - private $mergePoCmd = '{msgcat} --force-po --no-wrap --use-first {extra} {base} -o {base}'; - - public function __construct() - { - parent::__construct(); - - $langDir = APP_ROOT . '/lang'; - $this->langs = [ - 'nl_NL.utf8' - ]; - $this->textKeywords = [ - '_' - ]; - $this->templateKeywords = [ - 'i18n._', '_' - ]; - $this->directories = [ - APP_ROOT . '/app/modules', - APP_ROOT . '/app/layouts', - ]; - } - - public function setupOptions() - { - $action = new Action('generate', 'Generate *.PO files for each lang'); - $this->addTaskAction($action); - } - - public function generateAction() - { - if ( ! $this->isInstalled($this->xgettext) ) { - $this->throwError("xgettext not installed : https://www.gnu.org/software/gettext/"); - } - if ( ! $this->isInstalled($this->msgcat) ) { - $this->throwError("msgcat not installed"); - } - if ( ! $this->isInstalled($this->xgettextTemplate) ) { - $this->throwError("xgettext-template not installed : https://www.npmjs.com/package/xgettext-template"); - } - - $textTmpPo = $this->getTmpFile(); - $templateTmpPo = $this->getTmpFile(); - - foreach ($this->directories as $directory) { - $directoryIterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator( - $directory, - \RecursiveDirectoryIterator::SKIP_DOTS - ), - \RecursiveIteratorIterator::SELF_FIRST, - \RecursiveIteratorIterator::CATCH_GET_CHILD - ); - - $phpTmpPo = $this->getTmpFile(); - $voltTmpPo = $this->getTmpFile(); - - echo "Scanning $directory\n"; - - foreach ($directoryIterator as $file=>$info) { - if ( $this->isFile($file, 'php') ) { - $this->exec($this->getTextParser('PHP', $file, $phpTmpPo)); - } elseif ( $this->isFile($file, 'volt') ) { - $tmpPo = $this->getTmpFile(); - $this->exec($this->getTemplateParser('Volt', $file, $tmpPo)); - - $lines = count( file( $tmpPo )); - if ($lines > 2) { - $this->addPo($voltTmpPo, $tmpPo); - } else { - unlink($tmpPo); - } - } - } - - $this->addPo($textTmpPo, $phpTmpPo); - $this->addPo($templateTmpPo, $voltTmpPo); - } - - echo "Preparing final files...\n"; - - $this->addPo($textTmpPo, $templateTmpPo); - - $this->addToFinalPo($textTmpPo); - - $langPos = $this->savePo($textTmpPo); - - echo "\nGenerated files:"; - foreach ($langPos as $langPo) { - echo "\n$langPo"; - } - - } - - /** - * @param string $tmpPo generated PO file - */ - protected function addToFinalPo($tmpPo) - { - - } - - /** - * @param string[]|array $items string|[msgid,?msgstr,?comment] - * @return string - */ - protected function generatePoContent(array $items) - { - $poText = $this->poHeader; - - foreach ($items as $item) { - if (is_array($item) && isset($item['msgid'])) { - if (isset($item['comment'])) { - $poText .= sprintf( - "\n#: %s", - $item['comment'] - ); - } - $poText .= sprintf( - "\nmsgid \"%s\"\nmsgstr \"%s\"\n", - $item['msgid'], - ( isset($item['msgstr']) ) ? $item['msgstr'] : '' - ); - } elseif (is_string($item)) { - $poText .= sprintf( - "\nmsgid \"%s\"\nmsgstr \"\"\n", - $item - ); - } - } - - return $poText; - } - - /** - * merge new PO file and remove it - * @param string $basePo - * @param string $newPo - * @param bool $withoutRemoving - * @return bool - */ - protected function addPo($basePo, $newPo, $withoutRemoving=false) - { - if (!is_file($basePo) || !is_file($newPo)) - return false; - - $this->exec($this->getMsgCat($newPo, $basePo)); - - if (!$withoutRemoving) - unlink($newPo); - - return true; - } - - /** - * @param string $poFile - * @return string[] - */ - protected function savePo($poFile) - { - $files = []; - - foreach ($this->langs as $lang) { - $poBaseFile = $this->langDir . "/$lang/LC_MESSAGES/messages.po"; - - if (!is_file($poBaseFile)) { - mkdir( dirname($poBaseFile), 0777, true ); - touch($poBaseFile); - } - - $updated = $this->addPo($poBaseFile, $poFile, true); - - if ($updated) - $files[] = $poBaseFile; - } - - return $files; - } - - protected function getMsgCat($extra, $base) - { - return str_replace( - [ - '{msgcat}', - '{extra}', - '{base}' - ], - [ - $this->msgcat, - $extra, - $base - ], - $this->mergePoCmd - ); - } - - /** - * @param string $lang PHP - * @param string $in filename - * @param string $out filename - * @return string command - */ - protected function getTemplateParser($lang, $in, $out) - { - return str_replace( - [ - '{xgettextTemplate}', - '{lang}', - '{encoding}', - '{keys}', - '{out}', - '{in}' - ], - [ - $this->xgettextTemplate, - $lang, - $this->encoding, - implode(',', $this->templateKeywords), - $out, - $in - ], - $this->templateParser - ); - } - - /** - * @param string $lang PHP - * @param string $in filename - * @param string $out filename - * @return string command - */ - protected function getTextParser($lang, $in, $out) - { - return str_replace( - [ - '{xgettext}', - '{lang}', - '{encoding}', - '{keys}', - '{out}', - '{in}' - ], - [ - $this->xgettext, - $lang, - $this->encoding, - implode(',', $this->textKeywords), - $out, - $in - ], - $this->parser - ); - } - - protected function getTmpFile($file=null) - { - $tmpFile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . ($file ?: uniqid()); - touch($tmpFile); - if (!is_file($tmpFile)) - $this->throwError("Cant create $tmpFile from $file"); - - return $tmpFile; - } - - protected function isInstalled($cmd) - { - return strlen($this->exec("command -v $cmd")) > 0; - } - - protected function exec($cmd) - { - return shell_exec($cmd); - } - - protected function isFile($filename, $ext) - { - return is_file($filename) && preg_match('/^.+\.'.$ext.'$/i', $filename); - } - - private function removeTopLines($filename, $lines=0) - { - if ($lines<1) - return false; - - $content = file_get_contents($filename); - for ($i=0;$i<$lines;$i++) { - $content = preg_replace('/^.+\n/', '', $content); - } - file_put_contents($filename, $content); - } - -}