Skip to content

Commit

Permalink
[FEATURE] Handle priority for file definition sources (#173)
Browse files Browse the repository at this point in the history
The file definition sources are now sorted by the priority they are
given.

Default definition files have a high priority, to easily allow other
files to override definition values.
  • Loading branch information
romm committed Dec 21, 2018
1 parent 9ca335d commit 911c135
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 16 deletions.
6 changes: 3 additions & 3 deletions Classes/Core/Exception/FileNotFoundException.php
Expand Up @@ -18,16 +18,16 @@

class FileNotFoundException extends NotizException
{
const DEFINITION_SOURCE_TYPOSCRIPT_FILE_NOT_FOUND = 'The TypoScript definition file at path `%s` was not found.';
const DEFINITION_SOURCE_FILE_NOT_FOUND = 'The definition file at path `%s` was not found.';

/**
* @param string $filePath
* @return self
*/
public static function definitionSourceTypoScriptFileNotFound($filePath)
public static function definitionSourceFileNotFound($filePath)
{
return self::makeNewInstance(
self::DEFINITION_SOURCE_TYPOSCRIPT_FILE_NOT_FOUND,
self::DEFINITION_SOURCE_FILE_NOT_FOUND,
1503853091,
[$filePath]
);
Expand Down
Expand Up @@ -31,6 +31,8 @@
*/
class DefaultDefinitionComponents implements SingletonInterface
{
const DEFAULT_DEFINITION_FILE_PRIORITY = 1337;

/**
* @var bool
*/
Expand Down Expand Up @@ -66,26 +68,37 @@ public function register(DefinitionComponents $components)
/** @var TypoScriptDefinitionSource $typoScriptDefinitionSource */
$typoScriptDefinitionSource = $components->addSource(DefinitionSource::SOURCE_TYPOSCRIPT);

// Default channels.
$typoScriptDefinitionSource->addFilePath(NotizConstants::TYPOSCRIPT_PATH . 'Channel/Channels.Default.typoscript');
foreach ($this->getDefaultFiles() as $file) {
$typoScriptDefinitionSource->addFilePath($file, self::DEFAULT_DEFINITION_FILE_PRIORITY);
}
}

// Default notifications.
$typoScriptDefinitionSource->addFilePath(NotizConstants::TYPOSCRIPT_PATH . 'Notification/Notifications.typoscript');
/**
* @return array
*/
private function getDefaultFiles()
{
$defaultFiles = [
NotizConstants::TYPOSCRIPT_PATH . 'Channel/Channels.Default.typoscript',
NotizConstants::TYPOSCRIPT_PATH . 'Notification/Notifications.typoscript',
];

// TYPO3 events can be enabled/disabled in the extension configuration.
if ($this->extensionConfigurationService->getConfigurationValue('events.typo3')) {
$typoScriptDefinitionSource->addFilePath(NotizConstants::TYPOSCRIPT_PATH . 'Event/Events.TYPO3.typoscript');
$defaultFiles[] = NotizConstants::TYPOSCRIPT_PATH . 'Event/Events.TYPO3.typoscript';

if (ExtensionManagementUtility::isLoaded('scheduler')) {
$typoScriptDefinitionSource->addFilePath(NotizConstants::TYPOSCRIPT_PATH . 'Event/Events.Scheduler.typoscript');
$defaultFiles[] = NotizConstants::TYPOSCRIPT_PATH . 'Event/Events.Scheduler.typoscript';
}
}

// The core extension "form" can dispatch events.
if (ExtensionManagementUtility::isLoaded('form')
&& version_compare(VersionNumberUtility::getCurrentTypo3Version(), '8.0.0', '>=')
) {
$typoScriptDefinitionSource->addFilePath(NotizConstants::TYPOSCRIPT_PATH . 'Event/Events.Form.typoscript');
$defaultFiles[] = NotizConstants::TYPOSCRIPT_PATH . 'Event/Events.Form.typoscript';
}

return $defaultFiles;
}
}
Expand Up @@ -18,6 +18,7 @@

use CuyZ\Notiz\Core\Definition\Builder\Component\Source\DefinitionSource;
use CuyZ\Notiz\Core\Exception\FileNotFoundException;
use Generator;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;

Expand All @@ -33,7 +34,7 @@ abstract class FileDefinitionSource implements DefinitionSource, SingletonInterf
/**
* @var array
*/
protected $filePaths = [];
private $filePaths = [];

/**
* When the class is initialized, configured files are automatically
Expand All @@ -47,28 +48,50 @@ public function initializeObject()
/**
* Registers a path to a file that should contain definition for the API.
*
* The highest the given priority is, the sooner the file will be handled.
* Files with the lowest priority have more chance to override definition
* values.
*
* @param string $path
* @param int $priority
* @return $this
*
* @throws FileNotFoundException
*/
public function addFilePath($path)
public function addFilePath($path, $priority = 0)
{
if (isset($this->filePaths[$path])) {
if (!isset($this->filePaths[$priority])) {
$this->filePaths[$priority] = [];
krsort($this->filePaths);
}

if (isset($this->filePaths[$priority][$path])) {
return $this;
}

$absolutePath = GeneralUtility::getFileAbsFileName($path);

if (false === file_exists($absolutePath)) {
throw FileNotFoundException::definitionSourceTypoScriptFileNotFound($path);
throw FileNotFoundException::definitionSourceFileNotFound($path);
}

$this->filePaths[$path] = $absolutePath;
$this->filePaths[$priority][$path] = $absolutePath;

return $this;
}

/**
* @return Generator
*/
final protected function filePaths()
{
foreach ($this->filePaths as $priority => $paths) {
foreach ($paths as $path) {
yield $priority => $path;
}
}
}

/**
* This will automatically register paths to TypoScript files that were
* registered inside `ext_localconf.php` files:
Expand Down
Expand Up @@ -92,7 +92,7 @@ public function getDefinitionArray()
{
$content = '';

foreach ($this->filePaths as $path) {
foreach ($this->filePaths() as $path) {
$content .= GeneralUtility::getUrl($path) . LF;
}

Expand Down
Expand Up @@ -57,6 +57,20 @@ Now the actual definition component service can be written:
}
}
.. hint::

A priority can be given to the file for sorting purposes. The files with the
highest priority will be handled first; this means that the files with the
lowest priority have more chance to override definition values.

By default, a file has a priority of ``0``.

.. code-block:: php
// The definition values from `$file2` will override the ones from `$file1`.
$typoScriptSource->addFilePath($file1, 50);
$typoScriptSource->addFilePath($file2, 10);
3. Write definition in the file
-------------------------------

Expand Down

0 comments on commit 911c135

Please sign in to comment.