Skip to content

Commit

Permalink
Allow extending parsers and dynamic parsers (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
mlocati authored Aug 1, 2024
1 parent e4bf308 commit 8a73507
Show file tree
Hide file tree
Showing 17 changed files with 413 additions and 31 deletions.
6 changes: 4 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.* export-ignore
README.md export-ignore
/test/ export-ignore
/phpunit.xml export-ignore
/README.md export-ignore
/.* export-ignore
53 changes: 53 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
with:
exclude: |
.php-cs-fixer.php
test
php-cs:
name: PHP Coding Style
Expand All @@ -50,3 +51,55 @@ jobs:
-
name: Run PHP-CS-Fixer
run: php-cs-fixer check --ansi --no-interaction --using-cache=no --diff --show-progress=none


phpunit:
name: PHPUnit
strategy:
matrix:
os:
- ubuntu-latest
php-version:
- "5.3"
- "5.4"
- "5.5"
- "5.6"
- "7.0"
- "7.1"
- "7.2"
- "7.3"
- "7.4"
- "8.0"
- "8.1"
- "8.2"
- "8.3"
include:
-
os: windows-latest
php-version: "5.6"
-
os: windows-latest
php-version: "7.4"
-
os: windows-latest
php-version: "8.3"
runs-on: ${{ matrix.os }}
steps:
-
name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: composer
coverage: none
-
name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
-
name: Install Composer dependencies
run: composer --ansi --no-interaction --no-progress update
-
name: Run PHPUnit
run: composer --ansi --no-interaction run-script test -- -v
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/.settings/
/vendor/
/.buildpath
/.project
/.phpunit.result.cache
/composer.lock
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# concrete5 Translation Library
# concrete5 Translation Library

Useful tools to extract translatable strings from concrete5 projects.

Expand All @@ -8,4 +8,3 @@ It's used by
- since version 5.7.5.4 to translate packages
- [concrete5-translation-tools](https://github.com/mlocati/concrete5-translation-tools)
- to translate the core (core is fetched from GitHub both for [concrete5](https://github.com/concrete5/concrete5) and [concrete5-legacy](https://github.com/concrete5/concrete5-legacy), parsed with this library and translations are fetched by [Transifex](https://www.transifex.com/concrete5/concrete5))

14 changes: 14 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,22 @@
"C5TL\\": "src/"
}
},
"require-dev": {
"phpunit/phpunit": "^4.8.36 || ^6.5.14 || ^8.5.39"
},
"autoload-dev": {
"psr-4": {
"C5TL\\Test\\": [
"test/helpers/",
"test/tests/"
]
}
},
"config": {
"preferred-install": "dist",
"optimize-autoloader": true
},
"scripts": {
"test": "phpunit"
}
}
20 changes: 20 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<phpunit
bootstrap="./test/bootstrap.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
>
<testsuites>
<testsuite name="Tests">
<directory>./test/tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./src</directory>
</whitelist>
</filter>
</phpunit>
52 changes: 32 additions & 20 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ abstract class Parser
*/
private static $cache = array();

/**
* The parser factory.
*
* @var \C5TL\ParserFactory|null
*/
private static $factory;

/**
* Returns the parser name.
*
Expand Down Expand Up @@ -248,37 +255,42 @@ private static function getDirectoryStructureDo($relativePath, $rootDirectory, $
return $result;
}

final public static function getParserFactory()
{
if (self::$factory === null) {
self::$factory = new ParserFactory();
}

return self::$factory;
}

final public static function setParserFactory(ParserFactory $value)
{
self::$factory = $value;
}

/**
* Retrieves all the available parsers.
* @deprecated Use ParserFactory
*
* @return array[\C5TL\Parser]
* @return \C5TL\Parser[]
*/
final public static function getAllParsers()
{
$result = array();
$dir = __DIR__ . '/Parser';
if (is_dir($dir) && is_readable($dir)) {
$matches = null;
foreach (scandir($dir) as $item) {
if (($item[0] !== '.') && preg_match('/^(.+)\.php$/i', $item, $matches)) {
$fqClassName = '\\' . __NAMESPACE__ . '\\Parser\\' . $matches[1];
$result[] = new $fqClassName();
}
}
}
$factory = self::getParserFactory();

return $result;
return $factory->getParsers();
}

/**
* @deprecated Use ParserFactory
*
* @return \C5TL\Parser|null
*/
final public static function getByHandle($parserHandle)
{
$parser = null;
$fqClassName = '\\' . __NAMESPACE__ . '\\Parser\\' . static::camelifyString($parserHandle);
if (class_exists($fqClassName, true)) {
$parser = new $fqClassName();
}
$factory = self::getParserFactory();

return $parser;
return $factory->getParserByHandle($parserHandle);
}

/**
Expand Down
45 changes: 41 additions & 4 deletions src/Parser/Dynamic.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,22 @@

namespace C5TL\Parser;

use C5TL\Parser\DynamicItem\DynamicItem;

/**
* Extract translatable strings from block type templates.
*/
class Dynamic extends \C5TL\Parser
{
private $subParsers = array();

public function __construct()
{
foreach ($this->getDefaultSubParsers() as $subParser) {
$this->registerSubParser($subParser);
}
}

/**
* {@inheritdoc}
*
Expand All @@ -27,6 +38,16 @@ public function canParseRunningConcrete5()
return true;
}

/**
* @return $this
*/
public function registerSubParser(DynamicItem $subParser)
{
$this->subParsers[$subParser->getDynamicItemsParserHandler()] = $subParser;

return $this;
}

/**
* {@inheritdoc}
*
Expand All @@ -44,9 +65,27 @@ protected function parseRunningConcrete5Do(\Gettext\Translations $translations,
/**
* Returns the fully-qualified class names of all the sub-parsers.
*
* @return array[\C5TL\Parser\DynamicItem\DynamicItem]
* @return \C5TL\Parser\DynamicItem\DynamicItem[]
*/
public function getSubParsers()
{
return array_values($this->subParsers);
}

/**
* @param string|mixed $handle
*
* @return \C5TL\Parser\DynamicItem\DynamicItem|null
*/
public function getSubParserByHandle($handle)
{
return is_string($handle) && isset($this->subParsers[$handle]) ? $this->subParsers[$handle] : null;
}

/**
* @return \C5TL\Parser\DynamicItem\DynamicItem[]
*/
private function getDefaultSubParsers()
{
$result = array();
$dir = __DIR__ . '/DynamicItem';
Expand All @@ -55,9 +94,7 @@ public function getSubParsers()
foreach (scandir($dir) as $item) {
if (($item[0] !== '.') && preg_match('/^(.+)\.php$/i', $item, $matches) && ($matches[1] !== 'DynamicItem')) {
$fqClassName = '\\' . __NAMESPACE__ . '\\DynamicItem\\' . $matches[1];
$instance = new $fqClassName();
/* @var $instance \C5TL\Parser\DynamicItem\DynamicItem */
$result[$instance->getDynamicItemsParserHandler()] = $instance;
$result[] = new $fqClassName();
}
}
}
Expand Down
68 changes: 68 additions & 0 deletions src/ParserFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace C5TL;

/**
* A class that provides parsers.
*/
class ParserFactory
{
/**
* @var \C5TL\Parser[]
*/
private $parsers = array();

public function __construct()
{
foreach ($this->getDefaultParsers() as $parser) {
$this->registerParser($parser);
}
}
/**
* * @return \C5TL\Parser[]
*/
public function getParsers()
{
return array_values($this->parsers);
}

/**
* @param string|mixed $handle
*
* @return \C5TL\Parser|null
*/
public function getParserByHandle($handle)
{
return is_string($handle) && isset($this->parsers[$handle]) ? $this->parsers[$handle] : null;
}

/**
* @return $this
*/
public function registerParser(Parser $parser)
{
$this->parsers[$parser->getParserHandle()] = $parser;

return $this;
}

/**
* @return \C5TL\Parser[]
*/
private function getDefaultParsers()
{
$result = array();
$dir = __DIR__ . '/Parser';
if (is_dir($dir) && is_readable($dir)) {
$matches = null;
foreach (scandir($dir) as $item) {
if (($item[0] !== '.') && preg_match('/^(.+)\.php$/i', $item, $matches)) {
$fqClassName = '\\' . __NAMESPACE__ . '\\Parser\\' . $matches[1];
$result[] = new $fqClassName();
}
}
}

return $result;
}
}
1 change: 1 addition & 0 deletions src/Util/ConfigFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ private function readFile($filename)
*/
private function setCustomizersPosition()
{
$m = null;
if (!preg_match('/^\s*return[\n\s]+(?:\[|array[\s\n]*\()/ims', $this->contents, $m)) {
throw new Exception('Failed to determine the start of the return array');
}
Expand Down
11 changes: 11 additions & 0 deletions test/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

require_once __DIR__ . '/../vendor/autoload.php';

if (class_exists('PHPUnit\\Runner\\Version') && version_compare(PHPUnit\Runner\Version::id(), '8') >= 0) {
class_alias('C5TL\\Test\\TestCase8', 'C5TL\\Test\\TestCase');
} elseif (class_exists('PHPUnit\\Runner\\Version') && version_compare(PHPUnit\Runner\Version::id(), '6') >= 0) {
class_alias('C5TL\\Test\\TestCase6', 'C5TL\\Test\\TestCase');
} else {
class_alias('C5TL\\Test\\TestCase4', 'C5TL\\Test\\TestCase');
}
16 changes: 16 additions & 0 deletions test/helpers/TestCase4.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace C5TL\Test;

abstract class TestCase4 extends TestCaseBase
{
final public static function setupBeforeClass()
{
static::doSetUpBeforeClass();
}

final public function setUp()
{
static::doSetUp();
}
}
Loading

0 comments on commit 8a73507

Please sign in to comment.