diff --git a/.check-author.yml b/.check-author.yml index c051b7c..4c5202a 100644 --- a/.check-author.yml +++ b/.check-author.yml @@ -1,6 +1,5 @@ -exclude: - - contao/languages - - /^contao\/languages/ - ignore: - 'Mini Model ' + +exclude: + - /^src\/Resources\/contao\/languages/ diff --git a/.travis.yml b/.travis.yml index f09e23b..4bc4168 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,26 +11,42 @@ php: - "7.3" - "7.2" - "7.1" - - "7.0" - - "5.6" env: - - CONTAO_VERSION=~3.5.5 + - CONTAO_VERSION=~4.7.0 + - CONTAO_VERSION=~4.6.0 + - CONTAO_VERSION=~4.5.0 + - CONTAO_VERSION=~4.4.0 + +# Exclude impossible Contao Version combinations. +matrix: + exclude: + fast_finish: true + allow_failures: + - env: CONTAO_VERSION=~4.7.0 + - env: CONTAO_VERSION=~4.6.0 + - env: CONTAO_VERSION=~4.5.0 before_script: - echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - travis_retry composer self-update && composer --version - - travis_retry composer require contao/core $CONTAO_VERSION --no-update + - travis_retry composer require contao/core-bundle $CONTAO_VERSION --no-update - > if [ "x${TRAVIS_TAG}" != "x" ]; then export COMPOSER_ROOT_VERSION=${TRAVIS_TAG} else - export COMPOSER_ROOT_VERSION=$([[ ${TRAVIS_BRANCH} =~ hotfix/([0-9.]*(-(alpha|beta|rc)[0-9]+)?) ]] \ - && echo ${BASH_REMATCH[1]} \ + export COMPOSER_ROOT_VERSION=$([[ ${TRAVIS_BRANCH} =~ (hotfix|release)/([0-9.]*(-(alpha|beta|rc)[0-9]+)?) ]] \ + && echo ${BASH_REMATCH[2]} \ || echo dev-${TRAVIS_BRANCH}) fi - echo "Using root version ${COMPOSER_ROOT_VERSION}" - - travis_retry composer update --prefer-dist --no-interaction + - > + echo "PHP version: ${TRAVIS_PHP_VERSION}"; + if [ "x${TRAVIS_PHP_VERSION}" == "xnightly" ]; then + travis_retry composer update --ignore-platform-reqs --prefer-dist --no-interaction --no-suggest + else + travis_retry composer update --prefer-dist --no-interaction --no-suggest + fi script: ant -keep-going diff --git a/build.default.properties b/build.default.properties index e3fa8ea..783213f 100644 --- a/build.default.properties +++ b/build.default.properties @@ -7,3 +7,4 @@ phpcs.standard=${basedir}/vendor/phpcq/coding-standard/phpcs/PhpCodeQuality/ruleset.xml phpmd.ruleset=${basedir}/vendor/phpcq/coding-standard/phpmd/ruleset.xml +phpcs.excluded=src/Resources/contao/languages diff --git a/composer.json b/composer.json index c8d5355..d943244 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "file", "translatable" ], - "type": "contao-module", + "type": "contao-bundle", "homepage": "http://now.metamodel.me/", "license": "LGPL-3.0-or-later", "authors": [ @@ -32,33 +32,38 @@ "source": "https://github.com/MetaModels/attribute_translatedfile" }, "require": { - "php": "^5.6 || ^7.0", - "contao-community-alliance/composer-plugin": "^2.4", - "contao-community-alliance/dc-general": "^2.0.0", - "contao/core": "^3.5.5", - "metamodels/core": "^2.0" + "php": "^7.1", + "contao-community-alliance/dc-general": "^2.1.3", + "contao/core-bundle": "^4.4.8", + "metamodels/core": "^2.1.1", + "metamodels/attribute_file": "^2.1.1", + "symfony/dependency-injection": "^3.3 || ^4.0", + "symfony/http-kernel": "^3.3 || ^4.0" }, "require-dev": { - "metamodels/base-unit-tests": "^1.0.4", + "contao/manager-plugin": "^2.1", + "menatwork/contao-multicolumnwizard-bundle": "^3.4", "phpcq/all-tasks": "^1.2" }, "autoload": { - "psr-0": { - "MetaModels": "src/" + "psr-4": { + "MetaModels\\AttributeTranslatedFileBundle\\": "src" + }, + "files": [ + "src/deprecated-autoload.php" + ] + }, + "autoload-dev": { + "psr-4": { + "MetaModels\\AttributeTranslatedFileBundle\\Test\\": "tests" } }, "extra": { - "contao": { - "symlinks": { - "contao": "system/modules/metamodelsattribute_translatedfile" - } - }, + "contao-manager-plugin": "MetaModels\\AttributeTranslatedFileBundle\\ContaoManager\\Plugin", "branch-alias": { - "dev-master": "2.0.x-dev", - "dev-develop": "2.1.x-dev" + "dev-master": "2.1.x-dev" } }, - "prefer-stable": true, "config": { "sort-packages": true } diff --git a/contao/config/autoload.ini b/contao/config/autoload.ini deleted file mode 100644 index 56a51b1..0000000 --- a/contao/config/autoload.ini +++ /dev/null @@ -1,7 +0,0 @@ - -;; -; Configure what you want the autoload creator to register -;; -register_namespaces = true -register_classes = true -register_templates = true diff --git a/contao/config/event_listeners.php b/contao/config/event_listeners.php deleted file mode 100644 index 2435085..0000000 --- a/contao/config/event_listeners.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - * @filesource - */ - -use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; -use MetaModels\Attribute\TranslatedFile\AttributeTypeFactory; -use MetaModels\Attribute\Events\CreateAttributeFactoryEvent; -use MetaModels\Events\Attribute\TranslatedFile\ImageSizeOptions; -use MetaModels\MetaModelsEvents; - -return array -( - MetaModelsEvents::ATTRIBUTE_FACTORY_CREATE => array( - function (CreateAttributeFactoryEvent $event) { - $factory = $event->getFactory(); - $factory->addTypeFactory(new AttributeTypeFactory()); - } - ), - - GetPropertyOptionsEvent::NAME => array( - array(new ImageSizeOptions(), 'getPropertyOptions') - ) -); diff --git a/contao/dca/tl_metamodel_attribute.php b/contao/dca/tl_metamodel_attribute.php deleted file mode 100644 index 0ad9555..0000000 --- a/contao/dca/tl_metamodel_attribute.php +++ /dev/null @@ -1,115 +0,0 @@ - - * @author Stefan heimes - * @author Andreas Isaak - * @author David Greminger - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - * @filesource - */ - -/** - * Table tl_metamodel_attribute - */ - -/** - * Add palette configuration. - */ -$GLOBALS['TL_DCA']['tl_metamodel_attribute']['metapalettes']['translatedfile extends _complexattribute_'] = array( - '+advanced' => array('file_customFiletree', 'file_multiple'), - '+display' => array('-width50'), -); - -$GLOBALS['TL_DCA']['tl_metamodel_attribute']['metasubpalettes']['file_customFiletree'] = array( - 'file_uploadFolder', - 'file_validFileTypes', - 'file_filesOnly', -); - -/** - * Add data provider. - */ -$GLOBALS['TL_DCA']['tl_metamodel_attribute']['dca_config']['data_provider']['tl_metamodel_translatedlongblob'] = - array - ( - 'source' => 'tl_metamodel_translatedlongblob' - ); - -/** - * Add child condition. - */ -$GLOBALS['TL_DCA']['tl_metamodel_attribute']['dca_config']['childCondition'][] = array -( - 'from' => 'tl_metamodel_attribute', - 'to' => 'tl_metamodel_translatedlongblob', - 'setOn' => array - ( - array - ( - 'to_field' => 'att_id', - 'from_field' => 'id', - ), - ), - 'filter' => array - ( - array - ( - 'local' => 'att_id', - 'remote' => 'id', - 'operation' => '=', - ), - ) -); - -/** - * Add field configuration. - */ -$GLOBALS['TL_DCA']['tl_metamodel_attribute']['fields']['file_customFiletree'] = array( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['file_customFiletree'], - 'inputType' => 'checkbox', - 'eval' => array('submitOnChange' => true, 'tl_class' => 'w50'), - 'sql' => 'char(1) NOT NULL default \'\'' -); - -$GLOBALS['TL_DCA']['tl_metamodel_attribute']['fields']['file_multiple'] = array( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['file_multiple'], - 'inputType' => 'checkbox', - 'eval' => array('submitOnChange' => true, 'tl_class' => 'w50'), - 'sql' => 'char(1) NOT NULL default \'\'' -); - -$GLOBALS['TL_DCA']['tl_metamodel_attribute']['fields']['file_uploadFolder'] = array( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['file_uploadFolder'], - 'exclude' => true, - 'inputType' => 'fileTree', - 'eval' => array('fieldType' => 'radio', 'tl_class' => 'clr'), - 'sql' => 'blob NULL' -); - -$GLOBALS['TL_DCA']['tl_metamodel_attribute']['fields']['file_validFileTypes'] = array( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['file_validFileTypes'], - 'inputType' => 'text', - 'eval' => array('maxlength' => 255, 'tl_class' => 'w50'), - 'sql' => 'varchar(255) NOT NULL default \'\'' -); - -$GLOBALS['TL_DCA']['tl_metamodel_attribute']['fields']['file_filesOnly'] = array( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_attribute']['file_filesOnly'], - 'inputType' => 'checkbox', - 'eval' => array('tl_class' => 'w50 m12'), - 'sql' => 'char(1) NOT NULL default \'\'' -); diff --git a/contao/dca/tl_metamodel_rendersetting.php b/contao/dca/tl_metamodel_rendersetting.php deleted file mode 100644 index 1510d97..0000000 --- a/contao/dca/tl_metamodel_rendersetting.php +++ /dev/null @@ -1,76 +0,0 @@ - - * @author Stefan heimes - * @author Andreas Isaak - * @author David Greminger - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -$GLOBALS['TL_DCA']['tl_metamodel_rendersetting']['metapalettes']['translatedfile extends default'] = array( - '+advanced' => array('file_sortBy', 'file_showLink', 'file_showImage'), -); - -$GLOBALS['TL_DCA']['tl_metamodel_rendersetting']['metasubpalettes']['file_showImage'] = array( - 'file_imageSize', -); - -$GLOBALS['TL_DCA']['tl_metamodel_rendersetting']['fields']['file_sortBy'] = array( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['file_sortBy'], - 'exclude' => true, - 'inputType' => 'select', - 'options' => array('name_asc', 'name_desc', 'date_asc', 'date_desc', 'meta', 'random'), - 'reference' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting'], - 'eval' => array( - 'tl_class' => 'w50', - 'chosen' => true, - ), - 'sql' => 'varchar(32) NOT NULL default \'\'' -); - -$GLOBALS['TL_DCA']['tl_metamodel_rendersetting']['fields']['file_showLink'] = array( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['file_showLink'], - 'inputType' => 'checkbox', - 'eval' => array('tl_class' => 'w50 m12'), - 'sql' => 'char(1) NOT NULL default \'\'' -); - -$GLOBALS['TL_DCA']['tl_metamodel_rendersetting']['fields']['file_showImage'] = array( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['file_showImage'], - 'inputType' => 'checkbox', - 'eval' => array( - 'submitOnChange' => true, - 'tl_class' => 'clr', - ), - 'sql' => 'char(1) NOT NULL default \'\'' -); - -$GLOBALS['TL_DCA']['tl_metamodel_rendersetting']['fields']['file_imageSize'] = array( - 'label' => &$GLOBALS['TL_LANG']['tl_metamodel_rendersetting']['file_imageSize'], - 'exclude' => true, - 'inputType' => 'imageSize', - 'options' => $GLOBALS['TL_CROP'], - 'reference' => &$GLOBALS['TL_LANG']['MSC'], - 'eval' => array( - 'rgxp' => 'digit', - 'includeBlankOption' => true, - 'nospace' => true, - 'helpwizard' => true, - 'tl_class' => 'w50', - ), - 'sql' => 'varchar(255) NOT NULL default \'\'' -); diff --git a/contao/html/.htaccess b/contao/html/.htaccess deleted file mode 100644 index 1c68f30..0000000 --- a/contao/html/.htaccess +++ /dev/null @@ -1,7 +0,0 @@ - - Require all granted - - - Order Deny,Allow - Allow from all - diff --git a/ctb.json b/ctb.json index fe912ea..5d32de8 100644 --- a/ctb.json +++ b/ctb.json @@ -2,7 +2,7 @@ "transifex": { "project": "metamodels", "prefix": "attribute_translatedfile-", - "languages_cto": "contao/languages", + "languages_cto": "src/Resources/contao/languages", "languages_tx": ".tx", "php-file-header": [ "This file is part of MetaModels/attribute_translatedfile.", diff --git a/src/Attribute/AttributeOrderTypeFactory.php b/src/Attribute/AttributeOrderTypeFactory.php new file mode 100644 index 0000000..5f49da7 --- /dev/null +++ b/src/Attribute/AttributeOrderTypeFactory.php @@ -0,0 +1,94 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Attribute; + +use Doctrine\DBAL\Connection; +use MetaModels\Attribute\IAttributeTypeFactory; + +/** + * Attribute type factory for file order attributes. + */ +class AttributeOrderTypeFactory implements IAttributeTypeFactory +{ + /** + * Database connection. + * + * @var Connection + */ + private $connection; + + /** + * Create a new instance. + * + * @param Connection $connection Database connection. + */ + public function __construct(Connection $connection) + { + $this->connection = $connection; + } + + /** + * {@inheritDoc} + */ + public function getTypeName() + { + return 'translatedfilesort'; + } + + /** + * {@inheritDoc} + */ + public function getTypeIcon() + { + return ''; + } + + /** + * {@inheritDoc} + */ + public function createInstance($information, $metaModel) + { + return new TranslatedFileOrder($metaModel, $information, $this->connection); + } + + /** + * {@inheritDoc} + */ + public function isTranslatedType() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function isSimpleType() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function isComplexType() + { + return true; + } +} diff --git a/src/Attribute/AttributeTypeFactory.php b/src/Attribute/AttributeTypeFactory.php new file mode 100644 index 0000000..0054a8a --- /dev/null +++ b/src/Attribute/AttributeTypeFactory.php @@ -0,0 +1,161 @@ + + * @author Sven Baumann + * @author David Molineus + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Attribute; + +use Contao\Config; +use Contao\CoreBundle\Framework\Adapter; +use Contao\FilesModel; +use Contao\StringUtil; +use Contao\Validator; +use Doctrine\DBAL\Connection; +use MetaModels\Attribute\IAttributeTypeFactory; +use MetaModels\Helper\ToolboxFile; + +/** + * Attribute type factory for translated combined values attributes. + */ +class AttributeTypeFactory implements IAttributeTypeFactory +{ + /** + * Database connection. + * + * @var Connection + */ + private $connection; + /** + * The toolbox for file. + * + * @var ToolboxFile + */ + private $toolboxFile; + + /** + * The string util. + * + * @var Adapter|StringUtil + */ + private $stringUtil; + + /** + * The validator. + * + * @var Adapter|Validator + */ + private $validator; + + /** + * The repository for files. + * + * @var Adapter|FilesModel + */ + private $fileRepository; + + /** + * The contao configurations. + * + * @var Adapter|Config + */ + private $config; + + /** + * Create a new instance. + * + * @param Connection $connection Database connection. + * @param ToolboxFile $toolboxFile The toolbox for file. + * @param Adapter|StringUtil $stringUtil The string util. + * @param Adapter|Validator $validator The validator. + * @param Adapter|FilesModel $fileRepository The repository for files. + * @param Adapter|Config $config The contao configurations. + */ + public function __construct( + Connection $connection, + ToolboxFile $toolboxFile, + Adapter $stringUtil, + Adapter $validator, + Adapter $fileRepository, + Adapter $config + ) { + $this->connection = $connection; + $this->toolboxFile = $toolboxFile; + $this->stringUtil = $stringUtil; + $this->validator = $validator; + $this->fileRepository = $fileRepository; + $this->config = $config; + } + + /** + * {@inheritDoc} + */ + public function getTypeName() + { + return 'translatedfile'; + } + + /** + * {@inheritDoc} + */ + public function getTypeIcon() + { + return 'bundles/metamodelsattributetranslatedfile/file.png'; + } + + /** + * {@inheritDoc} + */ + public function createInstance($information, $metaModel) + { + return new TranslatedFile( + $metaModel, + $information, + $this->connection, + $this->toolboxFile, + $this->stringUtil, + $this->validator, + $this->fileRepository, + $this->config + ); + } + + /** + * {@inheritDoc} + */ + public function isTranslatedType() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function isSimpleType() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function isComplexType() + { + return true; + } +} diff --git a/src/Attribute/TranslatedFile.php b/src/Attribute/TranslatedFile.php new file mode 100644 index 0000000..89ad963 --- /dev/null +++ b/src/Attribute/TranslatedFile.php @@ -0,0 +1,566 @@ + + * @author Stefan heimes + * @author Andreas Isaak + * @author cogizz + * @author David Maack + * @author David Greminger + * @author Andreas Nölke + * @author Sven Baumann + * @author Ingolf Steinhardt + * @author David Molineus + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Attribute; + +use Contao\Config; +use Contao\CoreBundle\Framework\Adapter; +use Contao\FilesModel; +use Contao\StringUtil; +use Contao\System; +use Contao\Validator; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Platforms\Keywords\KeywordList; +use Doctrine\DBAL\Query\QueryBuilder; +use MetaModels\Attribute\TranslatedReference; +use MetaModels\AttributeFileBundle\Doctrine\DBAL\Platforms\Keywords\NotSupportedKeywordList; +use MetaModels\Helper\ToolboxFile; +use MetaModels\IMetaModel; +use MetaModels\Render\Template; + +/** + * This is the MetaModelAttribute class for handling translated file fields. + */ +class TranslatedFile extends TranslatedReference +{ + /** + * The toolbox for file. + * + * @var ToolboxFile|null + */ + private $toolboxFile; + + /** + * The string util. + * + * @var Adapter|StringUtil|null + */ + private $stringUtil; + + /** + * The validator. + * + * @var Adapter|Validator|null + */ + private $validator; + + /** + * The repository for files. + * + * @var Adapter|FilesModel|null + */ + private $fileRepository; + + /** + * The contao configurations. + * + * @var Adapter|Config|null + */ + private $config; + + /** + * The platform reserved keyword list. + * + * @var KeywordList + */ + private $platformReservedWord; + + /** + * {@inheritDoc} + * + * @param ToolboxFile|null $toolboxFile The toolbox for file. + * @param Adapter|StringUtil|null $stringUtil The string util. + * @param Adapter|Validator|null $validator The validator. + * @param Adapter|FilesModel|null $fileRepository The repository for files. + * @param Adapter|Config|null $config The contao configurations. + */ + public function __construct( + IMetaModel $objMetaModel, + $arrData = [], + Connection $connection = null, + ToolboxFile $toolboxFile = null, + Adapter $stringUtil = null, + Adapter $validator = null, + Adapter $fileRepository = null, + Adapter $config = null + ) { + parent::__construct($objMetaModel, $arrData, $connection); + + if (null === $toolboxFile) { + // @codingStandardsIgnoreStart + @\trigger_error( + 'Toolbox file is missing. It has to be passed in the constructor. Fallback will be dropped.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + $toolboxFile = System::getContainer()->get('metamodels.attribute_file.toolbox.file'); + } + + if (null === $stringUtil) { + // @codingStandardsIgnoreStart + @\trigger_error( + 'String util file is missing. It has to be passed in the constructor. Fallback will be dropped.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + $stringUtil = System::getContainer()->get('contao.framework')->getAdapter(StringUtil::class); + } + + if (null === $validator) { + // @codingStandardsIgnoreStart + @\trigger_error( + 'Validator is missing. It has to be passed in the constructor. Fallback will be dropped.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + $validator = System::getContainer()->get('contao.framework')->getAdapter(Validator::class); + } + + if (null === $fileRepository) { + // @codingStandardsIgnoreStart + @\trigger_error( + 'File repository is missing. It has to be passed in the constructor. Fallback will be dropped.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + $fileRepository = System::getContainer()->get('contao.framework')->getAdapter(FilesModel::class); + } + + if (null === $config) { + // @codingStandardsIgnoreStart + @\trigger_error( + 'Config is missing. It has to be passed in the constructor. Fallback will be dropped.', + E_USER_DEPRECATED + ); + // @codingStandardsIgnoreEnd + + $config = System::getContainer()->get('contao.framework')->getAdapter(Config::class); + } + + $this->toolboxFile = $toolboxFile; + $this->stringUtil = $stringUtil; + $this->validator = $validator; + $this->fileRepository = $fileRepository; + $this->config = $config; + } + + /** + * {@inheritdoc} + */ + protected function getValueTable() + { + return 'tl_metamodel_translatedlongblob'; + } + + /** + * Build a where clause for the given id(s) and language code. + * + * @param string[]|string|null $mixIds One, none or many ids to use. + * + * @param string|string[] $mixLangCode The language code/s to use, optional. + * + * @return array + * + * @deprecated This is deprecated since 2.1 and where removed in 3.0. + * Implement your own replacement for this. + */ + protected function getWhere($mixIds, $mixLangCode = '') + { + $procedure = 'att_id=?'; + $parameters = [$this->get('id')]; + + if (!empty($mixIds)) { + if (\is_array($mixIds)) { + $procedure .= ' AND item_id IN (' . $this->parameterMask($mixIds) . ')'; + $parameters = \array_merge($parameters, $mixIds); + } else { + $procedure .= ' AND item_id=?'; + $parameters[] = $mixIds; + } + } + + if (!empty($mixLangCode)) { + if (\is_array($mixLangCode)) { + $procedure .= ' AND langcode IN (' . $this->parameterMask($mixLangCode) . ')'; + $parameters = \array_merge($parameters, $mixLangCode); + } else { + $procedure .= ' AND langcode=?'; + $parameters[] = $mixLangCode; + } + } + + return [ + 'procedure' => $procedure, + 'params' => $parameters + ]; + } + + /** + * Add a where clause for the given id(s) and language code to the query builder. + * + * @param QueryBuilder $builder The query builder. + * @param string[]|string|null $mixIds One, none or many ids to use. + * @param string|string[] $mixLangCode The language code/s to use, optional. + * + * @return void + */ + private function addWhere(QueryBuilder $builder, $mixIds, $mixLangCode = ''): void + { + $builder + ->andWhere($builder->expr()->eq($this->quoteReservedWord('att_id'), ':attributeID')) + ->setParameter(':attributeID', $this->get('id')); + + if (!empty($mixIds)) { + if (\is_array($mixIds)) { + $builder + ->andWhere($builder->expr()->in($this->quoteReservedWord('item_id'), ':itemIDs')) + ->setParameter('itemIDs', \array_map('intval', $mixIds), Connection::PARAM_INT_ARRAY); + } else { + $builder + ->andWhere($builder->expr()->eq($this->quoteReservedWord('item_id'), ':itemID')) + ->setParameter('itemID', $mixIds); + } + } + + if (!empty($mixLangCode)) { + if (\is_array($mixLangCode)) { + $builder + ->andWhere($builder->expr()->in($this->quoteReservedWord('langcode'), ':langcodes')) + ->setParameter('langcodes', \array_map('strval', $mixLangCode), Connection::PARAM_STR_ARRAY); + } else { + $builder + ->andWhere($builder->expr()->eq($this->quoteReservedWord('langcode'), ':langcode')) + ->setParameter('langcode', $mixLangCode); + } + } + } + + /** + * {@inheritdoc} + * + * @throws \InvalidArgumentException If no binary in value throw invalid exception. + */ + protected function prepareTemplate(Template $objTemplate, $arrRowData, $objSettings) + { + parent::prepareTemplate($objTemplate, $arrRowData, $objSettings); + + $toolbox = clone $this->toolboxFile; + $toolbox + ->setBaseLanguage($this->getMetaModel()->getActiveLanguage()) + ->setFallbackLanguage($this->getMetaModel()->getFallbackLanguage()) + ->setLightboxId( + \sprintf( + '%s.%s.%s', + $this->getMetaModel()->getTableName(), + $objSettings->get('id'), + $arrRowData['id'] + ) + ) + ->setShowImages($objSettings->get('file_showImage')); + + if (($types = \trim($this->get('file_validFileTypes')))) { + $toolbox->setAcceptedExtensions($types); + } + + if ($objSettings->get('file_imageSize')) { + $toolbox->setResizeImages($objSettings->get('file_imageSize')); + } + + if ($arrRowData[$this->getColName()]) { + if (!isset($arrRowData[$this->getColName()]['value']['bin'])) { + throw new \InvalidArgumentException('No binary in value.'); + } + + foreach ($arrRowData[$this->getColName()]['value']['bin'] as $strFile) { + $toolbox->addPathById($strFile); + } + } + + $arrData = []; + $toolbox->resolveFiles(); + if ('manual' !== $objSettings->get('file_sortBy')) { + $arrData = $toolbox->sortFiles($objSettings->get('file_sortBy')); + } + if ('manual' === $objSettings->get('file_sortBy')) { + $arrData = $toolbox->sortFiles( + $objSettings->get('file_sortBy'), + ($arrRowData[$this->getColName()]['value_sorting']['bin'] ?? []) + ); + } + + $objTemplate->files = $arrData['files']; + $objTemplate->src = $arrData['source']; + } + + /** + * {@inheritdoc} + */ + public function getAttributeSettingNames() + { + return \array_merge( + parent::getAttributeSettingNames(), + [ + 'file_multiple', + 'file_customFiletree', + 'file_uploadFolder', + 'file_validFileTypes', + 'file_filesOnly', + 'file_widgetMode' + ] + ); + } + + /** + * Manipulate the field definition for custom file trees. + * + * @param array $fieldDefinition The field definition to manipulate. + * + * @return void + */ + private function handleCustomFileTree(&$fieldDefinition) + { + if ($this->get('file_uploadFolder')) { + // Set root path of file chooser depending on contao version. + $file = null; + + if ($this->validator->isStringUuid($this->get('file_uploadFolder')) + || $this->validator->isBinaryUuid($this->get('file_uploadFolder')) + ) { + $file = $this->fileRepository->findByUuid($this->get('file_uploadFolder')); + } + + // Check if we have a file. + if (null !== $file) { + $fieldDefinition['eval']['path'] = $file->path; + } else { + // Fallback. + $fieldDefinition['eval']['path'] = $this->get('file_uploadFolder'); + } + } + + if ($this->get('file_validFileTypes')) { + $fieldDefinition['eval']['extensions'] = $this->get('file_validFileTypes'); + } + + if ($this->get('file_filesOnly')) { + $fieldDefinition['eval']['filesOnly'] = true; + } + } + + /** + * {@inheritdoc} + */ + public function getFieldDefinition($arrOverrides = array()) + { + $fieldDefinition = parent::getFieldDefinition($arrOverrides); + + $fieldDefinition['inputType'] = 'fileTree'; + $fieldDefinition['eval']['files'] = true; + $fieldDefinition['eval']['extensions'] = $this->config->get('allowedDownload'); + $fieldDefinition['eval']['multiple'] = (bool) $this->get('file_multiple'); + + $widgetMode = $this->getOverrideValue('file_widgetMode', $arrOverrides); + + if (('normal' !== $widgetMode) + && ((bool) $this->get('file_multiple')) + ) { + $fieldDefinition['eval']['orderField'] = $this->getColName() . '__sort'; + } + + $fieldDefinition['eval']['isDownloads'] = ('downloads' === $widgetMode); + $fieldDefinition['eval']['isGallery'] = ('gallery' === $widgetMode); + + if ($this->get('file_multiple')) { + $fieldDefinition['eval']['fieldType'] = 'checkbox'; + } else { + $fieldDefinition['eval']['fieldType'] = 'radio'; + } + + if ($this->get('file_customFiletree')) { + $this->handleCustomFileTree($fieldDefinition); + } + + return $fieldDefinition; + } + + /** + * {@inheritdoc} + */ + public function valueToWidget($varValue) + { + if (empty($varValue) || empty($varValue['value'])) { + return null; + } + + return $this->get('file_multiple') + ? $varValue['value']['bin'] + : ($varValue['value']['bin'][0] ?? null); + } + + /** + * {@inheritdoc} + */ + public function widgetToValue($varValue, $itemId) + { + return [ + $this->quoteReservedWord('tstamp') => \time(), + $this->quoteReservedWord('value') => ToolboxFile::convertUuidsOrPathsToMetaModels((array) $varValue), + $this->quoteReservedWord('att_id') => $this->get('id') + ]; + } + + /** + * Take the native data and serialize it for the database. + * + * @param mixed $mixValues The data to serialize. + * + * @return string An serialized array with binary data or a binary data. + */ + private function convert($mixValues) + { + $data = ToolboxFile::convertValuesToDatabase($mixValues); + + // Check single file or multiple file. + return $this->get('file_multiple') + ? \serialize($data) + : ($data[0] ?? null); + } + + /** + * {@inheritdoc} + */ + protected function getSetValues($arrValue, $intId, $strLangCode) + { + return [ + 'tstamp' => \time(), + 'value' => (!empty($arrValue)) ? $this->convert($arrValue['value']) : null, + 'att_id' => $this->get('id'), + 'langcode' => $strLangCode, + 'item_id' => $intId + ]; + } + + /** + * {@inheritDoc} + */ + public function setTranslatedDataFor($arrValues, $strLangCode) + { + // First off determine those to be updated and those to be inserted. + $valueIds = \array_keys($arrValues); + $existingIds = \array_keys($this->getTranslatedDataFor($valueIds, $strLangCode)); + $newIds = \array_diff($valueIds, $existingIds); + + // Update existing values - delete if empty. + foreach ($existingIds as $existingId) { + $builder = $this->connection->createQueryBuilder(); + + if ($arrValues[$existingId]['value']['bin'][0]) { + $setValues = $this->getSetValues($arrValues[$existingId], $existingId, $strLangCode); + $builder->update($this->quoteReservedWord($this->getValueTable())); + foreach ($setValues as $setValueKey => $setValue) { + $builder->set($this->quoteReservedWord($setValueKey), ':' . $setValueKey); + $builder->setParameter(':' . $setValueKey, $setValue); + } + } else { + $builder->delete($this->quoteReservedWord($this->getValueTable())); + } + + $this->addWhere($builder, $existingId, $strLangCode); + $builder->execute(); + } + + // Insert the new values - if not empty. + foreach ($newIds as $newId) { + if (!$arrValues[$newId]['value']['bin'][0]) { + continue; + } + + $setValues = []; + foreach ($this->getSetValues($arrValues[$newId], $newId, $strLangCode) as $setValueKey => $setValue) { + $setValues[$this->quoteReservedWord($setValueKey)] = $setValue; + } + + $this->connection->insert($this->quoteReservedWord($this->getValueTable()), $setValues); + } + } + + /** + * {@inheritDoc} + */ + public function getTranslatedDataFor($arrIds, $strLangCode) + { + $metaModel = $this->getMetaModel(); + + $values = parent::getTranslatedDataFor($arrIds, $strLangCode); + foreach ($values as $valueId => $value) { + $values[$valueId]['value'] = ToolboxFile::convertUuidsOrPathsToMetaModels( + $this->stringUtil->deserialize($value['value'], true) + ); + } + + if ($metaModel->hasAttribute($this->getColName() . '__sort')) { + $orderAttribute = $metaModel->getAttribute($this->getColName() . '__sort'); + + $sortedValues = $orderAttribute->getTranslatedDataFor($arrIds, $strLangCode); + foreach ($values as $valueId => $value) { + $values[$valueId]['value_sorting'] = $sortedValues[$valueId]['value_sorting']; + } + } + + return $values; + } + + /** + * Quote the reserved platform key word. + * + * @param string $word The key word. + * + * @return string + */ + private function quoteReservedWord(string $word): string + { + if (null === $this->platformReservedWord) { + try { + $this->platformReservedWord = $this->connection->getDatabasePlatform()->getReservedKeywordsList(); + } catch (DBALException $exception) { + // Add the not support key word list, if the platform has not a list of keywords. + $this->platformReservedWord = new NotSupportedKeywordList(); + } + } + + if (false === $this->platformReservedWord->isKeyword($word)) { + return $word; + } + + return $this->connection->quoteIdentifier($word); + } +} diff --git a/src/Attribute/TranslatedFileOrder.php b/src/Attribute/TranslatedFileOrder.php new file mode 100644 index 0000000..dcb00e5 --- /dev/null +++ b/src/Attribute/TranslatedFileOrder.php @@ -0,0 +1,258 @@ + + * @copyright 2012-2017 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0 + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Attribute; + +use Contao\StringUtil; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Platforms\Keywords\KeywordList; +use Doctrine\DBAL\Query\QueryBuilder; +use MetaModels\Attribute\IInternal; +use MetaModels\Attribute\TranslatedReference; +use MetaModels\AttributeFileBundle\Doctrine\DBAL\Platforms\Keywords\NotSupportedKeywordList; +use MetaModels\Helper\ToolboxFile; + +/** + * This is the MetaModelAttribute class for handling translated file fields. + */ +class TranslatedFileOrder extends TranslatedReference implements IInternal +{ + /** + * The platform reserved keyword list. + * + * @var KeywordList + */ + private $platformReservedWord; + + /** + * {@inheritdoc} + */ + protected function getValueTable() + { + return 'tl_metamodel_translatedlongblob'; + } + + /** + * {@inheritdoc} + */ + public function getAttributeSettingNames() + { + return array_merge( + parent::getAttributeSettingNames(), + [ + 'file_multiple', + 'file_customFiletree', + 'file_uploadFolder', + 'file_validFileTypes', + 'file_filesOnly', + 'file_widgetMode' + ] + ); + } + + /** + * {@inheritdoc} + */ + public function valueToWidget($varValue) + { + if (empty($varValue) || empty($varValue['value_sorting'])) { + return null; + } + + return $this->get('file_multiple') + ? $varValue['value_sorting']['bin'] + : ($varValue['value_sorting']['bin'][0] ?? null); + } + + /** + * {@inheritdoc} + */ + public function widgetToValue($varValue, $itemId) + { + $sortingValue = ToolboxFile::convertUuidsOrPathsToMetaModels((array) $varValue); + return [ + $this->quoteReservedWord('tstamp') => \time(), + $this->quoteReservedWord('value_sorting') => $sortingValue, + $this->quoteReservedWord('att_id') => \substr($this->get('id'), 0, -\strlen('__sort')) + ]; + } + + /** + * {@inheritDoc} + */ + public function get($key) + { + $metaModel = $this->getMetaModel(); + + $mainColumnName = \substr($this->getColName(), 0, -\strlen('__sort')); + if (\in_array($key, ['id', 'file_multiple']) && $metaModel->hasAttribute($mainColumnName)) { + $mainAttribute = $metaModel->getAttribute($mainColumnName); + + return $mainAttribute->get($key); + } + + return null; + } + + /** + * Take the native data and serialize it for the database. + * + * @param mixed $values The data to serialize. + * + * @return string An serialized array with binary data or a binary data. + */ + private function convert($values) + { + $data = ToolboxFile::convertValuesToDatabase($values); + + // Check single file or multiple file. + if ($this->get('file_multiple')) { + return \serialize($data); + } + + return ($data[0] ?? null); + } + + /** + * {@inheritdoc} + */ + protected function getSetValues($arrValue, $intId, $strLangCode) + { + if (empty($arrValue)) { + return []; + } + + return [ + 'tstamp' => \time(), + 'value_sorting' => $this->convert($arrValue['value_sorting']) + ]; + } + + /** + * {@inheritDoc} + */ + public function setTranslatedDataFor($values, $langCode) + { + // First off determine those to be updated and those to be inserted. + $existingIds = \array_keys($this->getTranslatedDataFor(\array_keys($values), $langCode)); + + foreach ($existingIds as $existingId) { + if (!isset($values[$existingId]['value_sorting']['bin'][0]) + || !\count(($setValues = $this->getSetValues($values[$existingId], $existingId, $langCode))) + ) { + continue; + } + + $builder = $this->connection->createQueryBuilder(); + $builder->update($this->quoteReservedWord($this->getValueTable())); + foreach ($setValues as $setValueKey => $setValue) { + $builder->set($this->quoteReservedWord($setValueKey), ':' . $setValueKey); + $builder->setParameter(':' . $setValueKey, $setValue); + } + + $this->addWhere($builder, $existingId, $langCode); + $builder->execute(); + } + } + + /** + * {@inheritDoc} + */ + public function getTranslatedDataFor($arrIds, $strLangCode) + { + $values = parent::getTranslatedDataFor($arrIds, $strLangCode); + foreach ($values as $valueId => $value) { + $values[$valueId]['value_sorting'] = ToolboxFile::convertUuidsOrPathsToMetaModels( + StringUtil::deserialize($value['value_sorting'], true) + ); + } + + return $values; + } + + /** + * Add a where clause for the given id(s) and language code to the query builder. + * + * @param QueryBuilder $builder The query builder. + * @param string[]|string|null $mixIds One, none or many ids to use. + * @param string|string[] $mixLangCode The language code/s to use, optional. + * + * @return void + */ + private function addWhere(QueryBuilder $builder, $mixIds, $mixLangCode = ''): void + { + $builder + ->andWhere($builder->expr()->eq('att_id', ':attributeID')) + ->setParameter(':attributeID', $this->get('id')); + + if (!empty($mixLangCode)) { + if (\is_array($mixLangCode)) { + $builder + ->andWhere($builder->expr()->in('langcode', ':langcodes')) + ->setParameter('langcodes', \array_map('strval', $mixLangCode), Connection::PARAM_STR_ARRAY); + } else { + $builder + ->andWhere($builder->expr()->eq('langcode', ':langcode')) + ->setParameter('langcode', $mixLangCode); + } + } + + if (!empty($mixIds)) { + if (\is_array($mixIds)) { + $builder + ->andWhere($builder->expr()->in('item_id', ':itemIDs')) + ->setParameter('itemIDs', \array_map('intval', $mixIds), Connection::PARAM_INT_ARRAY); + } else { + $builder + ->andWhere($builder->expr()->eq('item_id', ':itemID')) + ->setParameter('itemID', $mixIds); + } + } + } + + /** + * Quote the reserved platform key word. + * + * @param string $word The key word. + * + * @return string + */ + private function quoteReservedWord(string $word): string + { + if (null === $this->platformReservedWord) { + try { + $this->platformReservedWord = $this->connection->getDatabasePlatform()->getReservedKeywordsList(); + } catch (DBALException $exception) { + // Add the not support key word list, if the platform has not a list of keywords. + $this->platformReservedWord = new NotSupportedKeywordList(); + } + } + + if (false === $this->platformReservedWord->isKeyword($word)) { + return $word; + } + + return $this->connection->quoteIdentifier($word); + } +} diff --git a/src/ContaoManager/Plugin.php b/src/ContaoManager/Plugin.php new file mode 100644 index 0000000..1864cd8 --- /dev/null +++ b/src/ContaoManager/Plugin.php @@ -0,0 +1,53 @@ + + * @author Sven Baumann + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\ContaoManager; + +use Contao\CoreBundle\ContaoCoreBundle; +use Contao\ManagerPlugin\Bundle\BundlePluginInterface; +use Contao\ManagerPlugin\Bundle\Config\BundleConfig; +use Contao\ManagerPlugin\Bundle\Parser\ParserInterface; +use MetaModels\AttributeFileBundle\MetaModelsAttributeFileBundle; +use MetaModels\AttributeTranslatedFileBundle\MetaModelsAttributeTranslatedFileBundle; +use MetaModels\CoreBundle\MetaModelsCoreBundle; + +/** + * Plugin for the Contao Manager. + */ +class Plugin implements BundlePluginInterface +{ + /** + * {@inheritdoc} + */ + public function getBundles(ParserInterface $parser) + { + return [ + BundleConfig::create(MetaModelsAttributeTranslatedFileBundle::class) + ->setLoadAfter( + [ + ContaoCoreBundle::class, + MetaModelsCoreBundle::class, + MetaModelsAttributeFileBundle::class + ] + ) + ->setReplace(['metamodelsattribute_translatedfile']) + ]; + } +} diff --git a/src/DcGeneral/AttributeTranslatedFileDefinition.php b/src/DcGeneral/AttributeTranslatedFileDefinition.php new file mode 100644 index 0000000..4cc76f4 --- /dev/null +++ b/src/DcGeneral/AttributeTranslatedFileDefinition.php @@ -0,0 +1,61 @@ + + * @copyright 2012-2017 The MetaModels team. + * @license https://github.com/MetaModels/attribute_file/blob/master/LICENSE LGPL-3.0 + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\DcGeneral; + +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\DefinitionInterface; + +/** + * This definition holds the mapping between translated file attributes and a property. + */ +class AttributeTranslatedFileDefinition implements DefinitionInterface +{ + /** + * The buffered properties. + * + * @var string[] + */ + private $fileProperties = []; + + /** + * Add a file property. + * + * @param string $filePropertyName The name of the file property. + * + * @return void + */ + public function add($filePropertyName) + { + if (\in_array($filePropertyName, $this->fileProperties)) { + return; + } + $this->fileProperties[] = $filePropertyName; + } + + /** + * Retrieve the names of the file properties. + * + * @return string[] + */ + public function get() + { + return $this->fileProperties; + } +} diff --git a/src/DependencyInjection/MetaModelsAttributeTranslatedFileExtension.php b/src/DependencyInjection/MetaModelsAttributeTranslatedFileExtension.php new file mode 100644 index 0000000..8ce736f --- /dev/null +++ b/src/DependencyInjection/MetaModelsAttributeTranslatedFileExtension.php @@ -0,0 +1,43 @@ + + * @author Sven Baumann + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\DependencyInjection; + +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\DependencyInjection\Loader; + +/** + * This is the class that loads and manages the bundle configuration + */ +class MetaModelsAttributeTranslatedFileExtension extends Extension +{ + /** + * {@inheritDoc} + */ + public function load(array $configs, ContainerBuilder $container) + { + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader->load('factory.yml'); + $loader->load('event_listeners.yml'); + $loader->load('services.yml'); + } +} diff --git a/src/EventListener/BuildAttributeListener.php b/src/EventListener/BuildAttributeListener.php new file mode 100644 index 0000000..468820b --- /dev/null +++ b/src/EventListener/BuildAttributeListener.php @@ -0,0 +1,85 @@ + + * @copyright 2012-2017 The MetaModels team. + * @license https://github.com/MetaModels/attribute_file/blob/master/LICENSE LGPL-3.0 + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\EventListener; + +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Definition\Properties\DefaultProperty; +use MetaModels\AttributeTranslatedFileBundle\Attribute\TranslatedFile; +use MetaModels\AttributeTranslatedFileBundle\DcGeneral\AttributeTranslatedFileDefinition; +use MetaModels\DcGeneral\Events\MetaModel\BuildAttributeEvent; + +/** + * The build attribute listener. + */ +class BuildAttributeListener +{ + /** + * This builds the dc-general property information for the virtual translated file order attribute. + * + * @param BuildAttributeEvent $event The event being processed. + * + * @return void + */ + public function buildAttribute(BuildAttributeEvent $event) + { + $attribute = $event->getAttribute(); + + if (!($attribute instanceof TranslatedFile) + || !$attribute->get('file_multiple') + ) { + return; + } + + $container = $event->getContainer(); + $properties = $container->getPropertiesDefinition(); + $name = $attribute->getColName(); + + if ($properties->hasProperty($name . '__sort')) { + $this->addAttributeToDefinition($container, $name); + + $properties->getProperty($name . '__sort')->setWidgetType('fileTreeOrder'); + + return; + } + + $properties->addProperty($property = new DefaultProperty($name . '__sort')); + $property->setWidgetType('fileTreeOrder'); + + $this->addAttributeToDefinition($container, $name); + } + + /** + * Add attribute to metamodels translated file attributes definition. + * + * @param ContainerInterface $container The metamodel data definition. + * @param string $name The attribute name. + * + * @return void + */ + protected function addAttributeToDefinition(ContainerInterface $container, $name) + { + if (!$container->hasDefinition('metamodels.translatedfile-attributes')) { + $container->setDefinition('metamodels.translatedfile-attributes', new AttributeTranslatedFileDefinition()); + } + + $container->getDefinition('metamodels.translatedfile-attributes')->add($name); + } +} diff --git a/src/EventListener/BuildDataDefinitionListener.php b/src/EventListener/BuildDataDefinitionListener.php new file mode 100644 index 0000000..cf1e3f0 --- /dev/null +++ b/src/EventListener/BuildDataDefinitionListener.php @@ -0,0 +1,67 @@ + + * @copyright 2012-2017 The MetaModels team. + * @license https://github.com/MetaModels/attribute_file/blob/master/LICENSE LGPL-3.0 + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\EventListener; + +use ContaoCommunityAlliance\DcGeneral\DataDefinition\Palette\Property; +use ContaoCommunityAlliance\DcGeneral\Factory\Event\BuildDataDefinitionEvent; + +/** + * The build data definition listener. + */ +class BuildDataDefinitionListener +{ + /** + * This handles all translated file attributes and + * clones the visible conditions to reflect those of the translated file attribute. + * + * @param BuildDataDefinitionEvent $event The event being processed. + * + * @return void + */ + public static function buildDataDefinition(BuildDataDefinitionEvent $event) + { + $container = $event->getContainer(); + if (!$container->hasDefinition('metamodels.translatedfile-attributes')) { + return; + } + // All properties... + foreach ($container->getDefinition('metamodels.translatedfile-attributes')->get() as $propertyName) { + // ... in all palettes ... + foreach ($container->getPalettesDefinition()->getPalettes() as $palette) { + // ... in any legend ... + foreach ($palette->getLegends() as $legend) { + // ... of the searched name ... + if (($legend->hasProperty($propertyName)) + && ($container->getPropertiesDefinition()->hasProperty($propertyName . '__sort')) + ) { + // ... must have the order field as companion, visible only when the real property is. + $file = $legend->getProperty($propertyName); + + $legend->addProperty($order = new Property($propertyName . '__sort'), $file); + + $order->setEditableCondition($file->getEditableCondition()); + $order->setVisibleCondition($file->getVisibleCondition()); + } + } + } + } + } +} diff --git a/src/EventListener/DcGeneral/Table/Attribute/RemoveTypeOptions.php b/src/EventListener/DcGeneral/Table/Attribute/RemoveTypeOptions.php new file mode 100644 index 0000000..c7b36ef --- /dev/null +++ b/src/EventListener/DcGeneral/Table/Attribute/RemoveTypeOptions.php @@ -0,0 +1,53 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\Attribute; + +use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; + +/** + * This class provide functions for remove type options, from the attribute table. + */ +class RemoveTypeOptions +{ + /** + * Remove the internal sort attribute from the option list. + * + * @param GetPropertyOptionsEvent $event The event. + * + * @return void + */ + public function removeOption(GetPropertyOptionsEvent $event) + { + $environment = $event->getEnvironment(); + if (('type' !== $event->getPropertyName()) + || ('tl_metamodel_attribute' !== $environment->getDataDefinition()->getName()) + ) { + return; + } + + $options = $event->getOptions(); + if (!\array_key_exists('translatedfilesort', $options)) { + return; + } + + unset($options['translatedfilesort']); + $event->setOptions($options); + } +} diff --git a/src/EventListener/DcGeneral/Table/FilterSetting/RemoveAttIdOptions.php b/src/EventListener/DcGeneral/Table/FilterSetting/RemoveAttIdOptions.php new file mode 100644 index 0000000..8aad9a2 --- /dev/null +++ b/src/EventListener/DcGeneral/Table/FilterSetting/RemoveAttIdOptions.php @@ -0,0 +1,57 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\FilterSetting; + +use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; + +/** + * This class provide functions for remove type options, from the filter setting table. + */ +class RemoveAttIdOptions +{ + /** + * Remove the internal sort attribute from the option list. + * + * @param GetPropertyOptionsEvent $event The event. + * + * @return void + */ + public function removeOption(GetPropertyOptionsEvent $event) + { + $environment = $event->getEnvironment(); + if (('attr_id' !== $event->getPropertyName()) + || ('tl_metamodel_filtersetting' !== $environment->getDataDefinition()->getName()) + ) { + return; + } + + $options = $event->getOptions(); + foreach ($options as $key => $name) { + $sortKey = $key . '__sort'; + if (\array_key_exists($sortKey, $options) + && ('[translatedfile]' === \substr($name, -\strlen('[translatedfile]'))) + ) { + unset($options[$sortKey]); + } + } + + $event->setOptions($options); + } +} diff --git a/src/EventListener/Factory/AddAttributeInformation.php b/src/EventListener/Factory/AddAttributeInformation.php new file mode 100644 index 0000000..cb8ea77 --- /dev/null +++ b/src/EventListener/Factory/AddAttributeInformation.php @@ -0,0 +1,96 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\EventListener\Factory; + +use MetaModels\Attribute\Events\CollectMetaModelAttributeInformationEvent; + +/** + * This class add attribute information. + */ +class AddAttributeInformation +{ + /** + * Add the information. + * + * @param CollectMetaModelAttributeInformationEvent $event The event. + * + * @return void + */ + public function addInformation(CollectMetaModelAttributeInformationEvent $event) + { + if (!\count($information = $event->getAttributeInformation())) { + return; + } + + if (!\count($fileInformation = $this->collectFileInformation($information))) { + return; + } + + $event->setAttributeInformation($this->updateInformation($fileInformation, $information)); + } + + /** + * Collect the file information. + * + * @param array $information The information search for file informtation. + * + * @return array + */ + private function collectFileInformation(array $information) + { + return \array_filter( + $information, + function ($attributeInformation) { + return (('translatedfile' === $attributeInformation['type']) + && \array_key_exists('file_multiple', $attributeInformation) + && $attributeInformation['file_multiple']); + } + ); + } + + /** + * Update the information. + * + * @param array $inputInformation The input information, who add to the update information. + * @param array $updateInformation The update information, who becomes update from the input information. + * + * @return array + */ + private function updateInformation(array $inputInformation, array $updateInformation) + { + foreach ($inputInformation as $name => $information) { + $columnName = $information['colname'] . '__sort'; + $position = \array_flip(\array_keys($updateInformation))[$name]; + + $updateInformation = \array_merge( + \array_slice($updateInformation, 0, ($position + 1)), + [ + $columnName => [ + 'colname' => $columnName, + 'type' => 'translatedfilesort' + ] + ], + \array_slice($updateInformation, ($position ? $position - 1 : $position + 1)) + ); + } + + return $updateInformation; + } +} diff --git a/src/MetaModels/Events/Attribute/TranslatedFile/ImageSizeOptions.php b/src/EventListener/ImageSizeOptions.php similarity index 81% rename from src/MetaModels/Events/Attribute/TranslatedFile/ImageSizeOptions.php rename to src/EventListener/ImageSizeOptions.php index eb6c352..8b7c47d 100644 --- a/src/MetaModels/Events/Attribute/TranslatedFile/ImageSizeOptions.php +++ b/src/EventListener/ImageSizeOptions.php @@ -13,12 +13,13 @@ * @package MetaModels/attribute_translatedfile * @author Sven Baumann * @author Stefan Heimes + * @author Christian Schiffler * @copyright 2012-2019 The MetaModels team. * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -namespace MetaModels\Events\Attribute\TranslatedFile; +namespace MetaModels\AttributeTranslatedFileBundle\EventListener; use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; use ContaoCommunityAlliance\DcGeneral\Data\DefaultDataProvider; @@ -43,13 +44,12 @@ public function getPropertyOptions(GetPropertyOptionsEvent $event) return; } - $sizes = $this->getThemeImageSizes(); - if (!$sizes) { + if (!$sizes = $this->getThemeImageSizes()) { return; } $options = $event->getOptions(); - $options['image_sizes'] = array_replace($sizes, (array) $options['image_sizes']); + $options['image_sizes'] = \array_replace($sizes, (array) $options['image_sizes']); $event->setOptions($options); } @@ -62,18 +62,18 @@ public function getPropertyOptions(GetPropertyOptionsEvent $event) private function getThemeImageSizes() { $dataProvider = new DefaultDataProvider(); - $dataProvider->setBaseConfig(array('source' => 'tl_image_size')); + $dataProvider->setBaseConfig(['source' => 'tl_image_size']); $config = $dataProvider->getEmptyConfig(); - $config->setFields(array('id', 'name', 'width', 'height')); - $config->setSorting(array('pid', 'name')); + $config->setFields(['id', 'name', 'width', 'height']); + $config->setSorting(['pid', 'name']); $collection = $dataProvider->fetchAll($config); if (!$collection->count()) { - return array(); + return []; } - $sizes = array(); + $sizes = []; foreach ($collection as $model) { $sizes[$model->getProperty('id')] = sprintf( '%s (%sx%s)', diff --git a/src/MetaModels/Attribute/TranslatedFile/AttributeTypeFactory.php b/src/MetaModels/Attribute/TranslatedFile/AttributeTypeFactory.php deleted file mode 100644 index b2168e4..0000000 --- a/src/MetaModels/Attribute/TranslatedFile/AttributeTypeFactory.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -namespace MetaModels\Attribute\TranslatedFile; - -use MetaModels\Attribute\AbstractAttributeTypeFactory; - -/** - * Attribute type factory for translated combined values attributes. - */ -class AttributeTypeFactory extends AbstractAttributeTypeFactory -{ - /** - * {@inheritDoc} - */ - public function __construct() - { - parent::__construct(); - $this->typeName = 'translatedfile'; - $this->typeIcon = 'system/modules/metamodelsattribute_translatedfile/html/file.png'; - $this->typeClass = 'MetaModels\Attribute\TranslatedFile\TranslatedFile'; - } -} diff --git a/src/MetaModels/Attribute/TranslatedFile/TranslatedFile.php b/src/MetaModels/Attribute/TranslatedFile/TranslatedFile.php deleted file mode 100644 index a96709e..0000000 --- a/src/MetaModels/Attribute/TranslatedFile/TranslatedFile.php +++ /dev/null @@ -1,341 +0,0 @@ - - * @author Stefan heimes - * @author Andreas Isaak - * @author cogizz - * @author David Maack - * @author David Greminger - * @author Andreas Nölke - * @author Sven Baumann - * @author Ingolf Steinhardt - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -namespace MetaModels\Attribute\TranslatedFile; - -use MetaModels\Attribute\TranslatedReference; -use MetaModels\Helper\ToolboxFile; -use MetaModels\Render\Template; - -/** - * This is the MetaModelAttribute class for handling translated file fields. - */ -class TranslatedFile extends TranslatedReference -{ - /** - * {@inheritdoc} - */ - protected function getValueTable() - { - return 'tl_metamodel_translatedlongblob'; - } - - /** - * Build a where clause for the given id(s) and language code. - * - * @param string[]|string|null $mixIds One, none or many ids to use. - * - * @param string|string[] $mixLangCode The language code/s to use, optional. - * - * @return array - */ - protected function getWhere($mixIds, $mixLangCode = '') - { - $procedure = 'att_id=?'; - $parameters = array($this->get('id')); - - if (!empty($mixIds)) { - if (is_array($mixIds)) { - $procedure .= ' AND item_id IN (' . $this->parameterMask($mixIds) . ')'; - $parameters = array_merge($parameters, $mixIds); - } else { - $procedure .= ' AND item_id=?'; - $parameters[] = $mixIds; - } - } - - if (!empty($mixLangCode)) { - if (is_array($mixLangCode)) { - $procedure .= ' AND langcode IN (' . $this->parameterMask($mixLangCode) . ')'; - $parameters = array_merge($parameters, $mixLangCode); - } else { - $procedure .= ' AND langcode=?'; - $parameters[] = $mixLangCode; - } - } - - return array( - 'procedure' => $procedure, - 'params' => $parameters - ); - } - - /** - * {@inheritdoc} - * - * @throws \InvalidArgumentException If no binary in value throw invalid exception. - */ - protected function prepareTemplate(Template $objTemplate, $arrRowData, $objSettings) - { - parent::prepareTemplate($objTemplate, $arrRowData, $objSettings); - - $objToolbox = new ToolboxFile(); - - $objToolbox->setBaseLanguage($this->getMetaModel()->getActiveLanguage()); - - $objToolbox->setFallbackLanguage($this->getMetaModel()->getFallbackLanguage()); - - $objToolbox->setLightboxId( - sprintf( - '%s.%s.%s', - $this->getMetaModel()->getTableName(), - $objSettings->get('id'), - $arrRowData['id'] - ) - ); - - if (strlen($types = trim($this->get('file_validFileTypes')))) { - $objToolbox->setAcceptedExtensions($types); - } - - $objToolbox->setShowImages($objSettings->get('file_showImage')); - - if ($objSettings->get('file_imageSize')) { - $objToolbox->setResizeImages($objSettings->get('file_imageSize')); - } - - if ($arrRowData[$this->getColName()]) { - if (!isset($arrRowData[$this->getColName()]['value']['bin'])) { - throw new \InvalidArgumentException('No binary in value.'); - } - - foreach ($arrRowData[$this->getColName()]['value']['bin'] as $strFile) { - $objToolbox->addPathById($strFile); - } - } - - $objToolbox->resolveFiles(); - $arrData = $objToolbox->sortFiles($objSettings->get('file_sortBy')); - - $objTemplate->files = $arrData['files']; - $objTemplate->src = $arrData['source']; - } - - /** - * {@inheritdoc} - */ - public function getAttributeSettingNames() - { - return array_merge(parent::getAttributeSettingNames(), array( - 'file_multiple', - 'file_customFiletree', - 'file_uploadFolder', - 'file_validFileTypes', - 'file_filesOnly', - )); - } - - /** - * Manipulate the field definition for custom file trees. - * - * @param array $arrFieldDef The field definition to manipulate. - * - * @return void - */ - private function handleCustomFileTree(&$arrFieldDef) - { - if (strlen($this->get('file_uploadFolder'))) { - // Set root path of file chooser depending on contao version. - $objFile = null; - - if (\Validator::isStringUuid($this->get('file_uploadFolder')) - || \Validator::isBinaryUuid($this->get('file_uploadFolder')) - ) { - $objFile = \FilesModel::findByUuid($this->get('file_uploadFolder')); - } - - // Check if we have a file. - if ($objFile != null) { - $arrFieldDef['eval']['path'] = $objFile->path; - } else { - // Fallback. - $arrFieldDef['eval']['path'] = $this->get('file_uploadFolder'); - } - } - - if (strlen($this->get('file_validFileTypes'))) { - $arrFieldDef['eval']['extensions'] = $this->get('file_validFileTypes'); - } - - if (strlen($this->get('file_filesOnly'))) { - $arrFieldDef['eval']['filesOnly'] = true; - } - } - - /** - * {@inheritdoc} - */ - public function getFieldDefinition($arrOverrides = array()) - { - $arrFieldDef = parent::getFieldDefinition($arrOverrides); - - $arrFieldDef['inputType'] = 'fileTree'; - $arrFieldDef['eval']['files'] = true; - $arrFieldDef['eval']['extensions'] = \Config::get('allowedDownload'); - $arrFieldDef['eval']['multiple'] = (bool) $this->get('file_multiple'); - - if ($this->get('file_multiple')) { - $arrFieldDef['eval']['fieldType'] = 'checkbox'; - } else { - $arrFieldDef['eval']['fieldType'] = 'radio'; - } - - if ($this->get('file_customFiletree')) { - $this->handleCustomFileTree($arrFieldDef); - } - - return $arrFieldDef; - } - - /** - * {@inheritdoc} - */ - public function valueToWidget($varValue) - { - if (empty($varValue) || empty($varValue['value'])) { - return null; - } - - if (!$this->get('file_multiple')) { - return isset($varValue['value']['bin'][0]) ? $varValue['value']['bin'][0] : null; - } - - return $varValue['value']['bin']; - } - - /** - * {@inheritdoc} - */ - public function widgetToValue($varValue, $itemId) - { - return array( - 'tstamp' => time(), - 'value' => ToolboxFile::convertUuidsOrPathsToMetaModels((array) $varValue), - 'att_id' => $this->get('id'), - ); - } - - /** - * Take the native data and serialize it for the database. - * - * @param mixed $mixValues The data to serialize. - * - * @return string An serialized array with binary data or a binary data. - */ - private function convert($mixValues) - { - $data = ToolboxFile::convertValuesToDatabase($mixValues); - - // Check single file or multiple file. - if ($this->get('file_multiple')) { - return serialize($data); - } - - return isset($data[0]) ? $data[0] : null; - } - - /** - * {@inheritdoc} - */ - protected function getSetValues($arrValue, $intId, $strLangCode) - { - if (empty($arrValue)) { - return array( - 'tstamp' => time(), - 'value' => null, - 'att_id' => $this->get('id'), - 'langcode' => $strLangCode, - 'item_id' => $intId, - ); - } - - return array( - 'tstamp' => time(), - 'value' => $this->convert($arrValue['value']), - 'att_id' => $this->get('id'), - 'langcode' => $strLangCode, - 'item_id' => $intId, - ); - } - - /** - * {@inheritDoc} - */ - public function setTranslatedDataFor($arrValues, $strLangCode) - { - $objDB = $this->getMetaModel()->getServiceContainer()->getDatabase(); - // First off determine those to be updated and those to be inserted. - $arrIds = array_keys($arrValues); - $arrExisting = array_keys($this->getTranslatedDataFor($arrIds, $strLangCode)); - $arrNewIds = array_diff($arrIds, $arrExisting); - - // Update existing values - delete if empty. - $strQueryUpdate = 'UPDATE ' . $this->getValueTable() . ' %s'; - $strQueryDelete = 'DELETE FROM ' . $this->getValueTable(); - - foreach ($arrExisting as $intId) { - $arrWhere = $this->getWhere($intId, $strLangCode); - - if ($arrValues[$intId]['value']['bin'][0]) { - $objDB->prepare($strQueryUpdate . ($arrWhere ? ' WHERE ' . $arrWhere['procedure'] : '')) - ->set($this->getSetValues($arrValues[$intId], $intId, $strLangCode)) - ->execute(($arrWhere ? $arrWhere['params'] : null)); - } else { - $objDB->prepare($strQueryDelete . ($arrWhere ? ' WHERE ' . $arrWhere['procedure'] : '')) - ->execute(($arrWhere ? $arrWhere['params'] : null)); - } - } - - // Insert the new values - if not empty. - $strQueryInsert = 'INSERT INTO ' . $this->getValueTable() . ' %s'; - foreach ($arrNewIds as $intId) { - if (!$arrValues[$intId]['value']['bin'][0]) { - continue; - } - - $objDB->prepare($strQueryInsert) - ->set($this->getSetValues($arrValues[$intId], $intId, $strLangCode)) - ->execute(); - } - } - - /** - * {@inheritDoc} - */ - public function getTranslatedDataFor($arrIds, $strLangCode) - { - $arrValues = parent::getTranslatedDataFor($arrIds, $strLangCode); - - foreach ($arrValues as $intId => $arrValue) { - $arrValues[$intId]['value'] = ToolboxFile::convertUuidsOrPathsToMetaModels( - deserialize($arrValue['value'], true) - ); - } - - return $arrValues; - } -} diff --git a/src/MetaModelsAttributeTranslatedFileBundle.php b/src/MetaModelsAttributeTranslatedFileBundle.php new file mode 100644 index 0000000..dd447d7 --- /dev/null +++ b/src/MetaModelsAttributeTranslatedFileBundle.php @@ -0,0 +1,30 @@ + + * @author Sven Baumann + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +/** + * This is the bundle class. + */ +class MetaModelsAttributeTranslatedFileBundle extends Bundle +{ +} diff --git a/src/Resources/config/event_listeners.yml b/src/Resources/config/event_listeners.yml new file mode 100644 index 0000000..83a7b3f --- /dev/null +++ b/src/Resources/config/event_listeners.yml @@ -0,0 +1,38 @@ +services: + metamodels.attribute_translatedfile.event_listener.build_data_definition: + class: MetaModels\AttributeTranslatedFileBundle\EventListener\BuildDataDefinitionListener + tags: + - name: kernel.event_listener + event: dc-general.factory.build-data-definition + method: buildDataDefinition + priority: 0 + + metamodels.attribute_translatedfile.event_listener.build_attribute: + class: MetaModels\AttributeTranslatedFileBundle\EventListener\BuildAttributeListener + tags: + - name: kernel.event_listener + event: metamodels.dc-general.events.metamodel.build.attribute + method: buildAttribute + + metamodels.attribute_translatedfile.event_listener.image_size_options: + class: MetaModels\AttributeTranslatedFileBundle\EventListener\ImageSizeOptions + tags: + - name: kernel.event_listener + event: dc-general.view.contao2backend.get-property-options + method: getPropertyOptions + + metamodels.attribute_translatedfile.event_listener.remove_type_options: + class: MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\Attribute\RemoveTypeOptions + tags: + - name: kernel.event_listener + event: dc-general.view.contao2backend.get-property-options + method: removeOption + priority: -1 + + metamodels.attribute_translatedfile.event_listener.remove_att_id_options: + class: MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\FilterSetting\RemoveAttIdOptions + tags: + - name: kernel.event_listener + event: dc-general.view.contao2backend.get-property-options + method: removeOption + priority: -1 diff --git a/src/Resources/config/factory.yml b/src/Resources/config/factory.yml new file mode 100644 index 0000000..325ea67 --- /dev/null +++ b/src/Resources/config/factory.yml @@ -0,0 +1,27 @@ +services: + metamodels.attribute_translatedfile.factory: + class: MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeTypeFactory + arguments: + - "@database_connection" + - "@metamodels.attribute_file.toolbox.file" + - "@=service('contao.framework').getAdapter('Contao\\\\StringUtil')" + - "@=service('contao.framework').getAdapter('Contao\\\\Validator')" + - "@=service('contao.framework').getAdapter('Contao\\\\FilesModel')" + - "@=service('contao.framework').getAdapter('Contao\\\\Config')" + tags: + - { name: metamodels.attribute_factory } + + metamodels.attribute_translatedfile_order.factory: + class: MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeOrderTypeFactory + arguments: + - "@database_connection" + tags: + - { name: metamodels.attribute_factory } + + metamodels.attribute_translatedfile.event_listener_factory.add_attribute_information: + class: MetaModels\AttributeTranslatedFileBundle\EventListener\Factory\AddAttributeInformation + tags: + - name: kernel.event_listener + event: metamodels.metamodel.collect-metamodel-attribute-information + method: addInformation + priority: -1 diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml new file mode 100644 index 0000000..0baad47 --- /dev/null +++ b/src/Resources/config/services.yml @@ -0,0 +1 @@ +services: diff --git a/src/Resources/contao/dca/tl_metamodel_attribute.php b/src/Resources/contao/dca/tl_metamodel_attribute.php new file mode 100644 index 0000000..8726a95 --- /dev/null +++ b/src/Resources/contao/dca/tl_metamodel_attribute.php @@ -0,0 +1,66 @@ + + * @author Stefan heimes + * @author Andreas Isaak + * @author David Greminger + * @author Sven Baumann + * @author David Molineus + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +/* + * Table tl_metamodel_attribute + */ + +/* + * Add palette configuration. + */ + +$GLOBALS['TL_DCA']['tl_metamodel_attribute']['metapalettes']['translatedfile extends _complexattribute_'] = [ + '+advanced' => ['file_customFiletree', 'file_multiple'], + '+display' => ['-width50'] +]; + +/* + * Add data provider. + */ + +$GLOBALS['TL_DCA']['tl_metamodel_attribute']['dca_config']['data_provider']['tl_metamodel_translatedlongblob'] = [ + 'source' => 'tl_metamodel_translatedlongblob' +]; + +/* + * Add child condition. + */ + +$GLOBALS['TL_DCA']['tl_metamodel_attribute']['dca_config']['childCondition'][] = [ + 'from' => 'tl_metamodel_attribute', + 'to' => 'tl_metamodel_translatedlongblob', + 'setOn' => [ + [ + 'to_field' => 'att_id', + 'from_field' => 'id' + ] + ], + 'filter' => [ + [ + 'local' => 'att_id', + 'remote' => 'id', + 'operation' => '=' + ] + ] +]; diff --git a/contao/dca/tl_metamodel_dcasetting.php b/src/Resources/contao/dca/tl_metamodel_dcasetting.php similarity index 82% rename from contao/dca/tl_metamodel_dcasetting.php rename to src/Resources/contao/dca/tl_metamodel_dcasetting.php index 7832684..34043d8 100644 --- a/contao/dca/tl_metamodel_dcasetting.php +++ b/src/Resources/contao/dca/tl_metamodel_dcasetting.php @@ -16,17 +16,18 @@ * @author Andreas Isaak * @author David Greminger * @author Sven Baumann + * @author David Molineus * @copyright 2012-2019 The MetaModels team. * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later * @filesource * @filesource */ -$GLOBALS['TL_DCA']['tl_metamodel_dcasetting']['metasubselectpalettes']['attr_id']['translatedfile'] = array( - 'presentation' => array( - 'tl_class', - ), - 'functions' => array( - 'mandatory', - ), -); +$GLOBALS['TL_DCA']['tl_metamodel_dcasetting']['metasubselectpalettes']['attr_id']['translatedfile'] = [ + 'presentation' => [ + 'tl_class' + ], + 'functions' => [ + 'mandatory' + ] +]; diff --git a/contao/config/autoload.php b/src/Resources/contao/dca/tl_metamodel_rendersetting.php similarity index 69% rename from contao/config/autoload.php rename to src/Resources/contao/dca/tl_metamodel_rendersetting.php index eab0d65..41fe756 100644 --- a/contao/config/autoload.php +++ b/src/Resources/contao/dca/tl_metamodel_rendersetting.php @@ -12,17 +12,17 @@ * * @package MetaModels/attribute_translatedfile * @author Christian Schiffler + * @author Stefan heimes * @author Andreas Isaak * @author David Greminger * @author Sven Baumann + * @author David Molineus + * @author Ingolf Steinhardt * @copyright 2012-2019 The MetaModels team. * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -/** - * Register the templates - */ -TemplateLoader::addFiles(array( - 'mm_attr_translatedfile' => 'system/modules/metamodelsattribute_translatedfile/templates', -)); +$GLOBALS['TL_DCA']['tl_metamodel_rendersetting']['metapalettes']['translatedfile extends default'] = [ + '+advanced' => ['file_sortBy', 'file_showLink', 'file_showImage'] +]; diff --git a/contao/dca/tl_metamodel_translatedlongblob.php b/src/Resources/contao/dca/tl_metamodel_translatedlongblob.php similarity index 70% rename from contao/dca/tl_metamodel_translatedlongblob.php rename to src/Resources/contao/dca/tl_metamodel_translatedlongblob.php index 919c99b..73004ed 100644 --- a/contao/dca/tl_metamodel_translatedlongblob.php +++ b/src/Resources/contao/dca/tl_metamodel_translatedlongblob.php @@ -12,6 +12,7 @@ * * @package MetaModels/attribute_translatedfile * @author Sven Baumann + * @author Christian Schiffler * @copyright 2012-2019 The MetaModels team. * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later * @filesource @@ -21,46 +22,38 @@ /** * Table tl_metamodel_translatedlongblob */ -$GLOBALS['TL_DCA']['tl_metamodel_translatedlongblob'] = array -( +$GLOBALS['TL_DCA']['tl_metamodel_translatedlongblob'] = [ // Config - 'config' => array - ( - 'sql' => array - ( - 'keys' => array - ( + 'config' => [ + 'sql' => [ + 'keys' => [ 'id' => 'primary', 'att_id,item_id,langcode' => 'index' - ) - ) - ), + ] + ] + ], // Fields - 'fields' => array - ( - 'id' => array - ( + 'fields' => [ + 'id' => [ 'sql' => 'int(10) unsigned NOT NULL auto_increment' - ), - 'tstamp' => array - ( + ], + 'tstamp' => [ 'sql' => 'int(10) unsigned NOT NULL default \'0\'' - ), - 'att_id' => array - ( + ], + 'att_id' => [ 'sql' => 'int(10) unsigned NOT NULL default \'0\'' - ), - 'item_id' => array - ( + ], + 'item_id' => [ 'sql' => 'int(10) unsigned NOT NULL default \'0\'' - ), - 'langcode' => array - ( + ], + 'langcode' => [ 'sql' => 'varchar(5) NOT NULL default \'\'' - ), - 'value' => array - ( + ], + 'value' => [ 'sql' => 'longblob NULL' - ) - ) -); + ], + 'value_sorting' => [ + 'sql' => 'longblob NULL' + ] + ] +]; diff --git a/contao/languages/de/tl_metamodel_attribute.php b/src/Resources/contao/languages/de/tl_metamodel_attribute.php similarity index 100% rename from contao/languages/de/tl_metamodel_attribute.php rename to src/Resources/contao/languages/de/tl_metamodel_attribute.php diff --git a/contao/languages/el/tl_metamodel_attribute.php b/src/Resources/contao/languages/el/tl_metamodel_attribute.php similarity index 100% rename from contao/languages/el/tl_metamodel_attribute.php rename to src/Resources/contao/languages/el/tl_metamodel_attribute.php diff --git a/contao/languages/en/tl_metamodel_attribute.php b/src/Resources/contao/languages/en/tl_metamodel_attribute.php similarity index 100% rename from contao/languages/en/tl_metamodel_attribute.php rename to src/Resources/contao/languages/en/tl_metamodel_attribute.php diff --git a/contao/languages/et/tl_metamodel_attribute.php b/src/Resources/contao/languages/et/tl_metamodel_attribute.php similarity index 100% rename from contao/languages/et/tl_metamodel_attribute.php rename to src/Resources/contao/languages/et/tl_metamodel_attribute.php diff --git a/contao/languages/fr/tl_metamodel_attribute.php b/src/Resources/contao/languages/fr/tl_metamodel_attribute.php similarity index 100% rename from contao/languages/fr/tl_metamodel_attribute.php rename to src/Resources/contao/languages/fr/tl_metamodel_attribute.php diff --git a/contao/languages/it/tl_metamodel_attribute.php b/src/Resources/contao/languages/it/tl_metamodel_attribute.php similarity index 100% rename from contao/languages/it/tl_metamodel_attribute.php rename to src/Resources/contao/languages/it/tl_metamodel_attribute.php diff --git a/contao/languages/rm/tl_metamodel_attribute.php b/src/Resources/contao/languages/rm/tl_metamodel_attribute.php similarity index 100% rename from contao/languages/rm/tl_metamodel_attribute.php rename to src/Resources/contao/languages/rm/tl_metamodel_attribute.php diff --git a/contao/languages/ru/tl_metamodel_attribute.php b/src/Resources/contao/languages/ru/tl_metamodel_attribute.php similarity index 100% rename from contao/languages/ru/tl_metamodel_attribute.php rename to src/Resources/contao/languages/ru/tl_metamodel_attribute.php diff --git a/contao/templates/mm_attr_translatedfile.html5 b/src/Resources/contao/templates/mm_attr_translatedfile.html5 similarity index 100% rename from contao/templates/mm_attr_translatedfile.html5 rename to src/Resources/contao/templates/mm_attr_translatedfile.html5 diff --git a/contao/templates/mm_attr_translatedfile.text b/src/Resources/contao/templates/mm_attr_translatedfile.text similarity index 100% rename from contao/templates/mm_attr_translatedfile.text rename to src/Resources/contao/templates/mm_attr_translatedfile.text diff --git a/contao/templates/mm_attr_translatedfile.xhtml b/src/Resources/contao/templates/mm_attr_translatedfile.xhtml similarity index 100% rename from contao/templates/mm_attr_translatedfile.xhtml rename to src/Resources/contao/templates/mm_attr_translatedfile.xhtml diff --git a/contao/templates/mm_attr_translatedfile_alternative.html5 b/src/Resources/contao/templates/mm_attr_translatedfile_alternative.html5 similarity index 100% rename from contao/templates/mm_attr_translatedfile_alternative.html5 rename to src/Resources/contao/templates/mm_attr_translatedfile_alternative.html5 diff --git a/contao/templates/mm_attr_translatedfile_alternative.text b/src/Resources/contao/templates/mm_attr_translatedfile_alternative.text similarity index 100% rename from contao/templates/mm_attr_translatedfile_alternative.text rename to src/Resources/contao/templates/mm_attr_translatedfile_alternative.text diff --git a/contao/templates/mm_attr_translatedfile_alternative.xhtml b/src/Resources/contao/templates/mm_attr_translatedfile_alternative.xhtml similarity index 100% rename from contao/templates/mm_attr_translatedfile_alternative.xhtml rename to src/Resources/contao/templates/mm_attr_translatedfile_alternative.xhtml diff --git a/contao/html/file.png b/src/Resources/public/file.png similarity index 100% rename from contao/html/file.png rename to src/Resources/public/file.png diff --git a/src/deprecated-autoload.php b/src/deprecated-autoload.php new file mode 100644 index 0000000..b60e9e7 --- /dev/null +++ b/src/deprecated-autoload.php @@ -0,0 +1,44 @@ + + * @author Sven Baumann + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +use MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeTypeFactory; +use MetaModels\AttributeTranslatedFileBundle\Attribute\TranslatedFile; + +// This hack is to load the "old locations" of the classes. +spl_autoload_register( + function ($class) { + static $classes = [ + 'MetaModels\Attribute\TranslatedFile\TranslatedFile' => TranslatedFile::class, + 'MetaModels\Attribute\TranslatedFile\AttributeTypeFactory' => AttributeTypeFactory::class + ]; + + if (isset($classes[$class])) { + // @codingStandardsIgnoreStart Silencing errors is discouraged + @trigger_error('Class "' . $class . '" has been renamed to "' . $classes[$class] . '"', E_USER_DEPRECATED); + // @codingStandardsIgnoreEnd + + if (!class_exists($classes[$class])) { + spl_autoload_call($class); + } + + class_alias($classes[$class], $class); + } + } +); diff --git a/tests/Attribute/TranslatedFileAttributeTypeFactoryTest.php b/tests/Attribute/TranslatedFileAttributeTypeFactoryTest.php new file mode 100644 index 0000000..8f24b2e --- /dev/null +++ b/tests/Attribute/TranslatedFileAttributeTypeFactoryTest.php @@ -0,0 +1,281 @@ + + * @author Sven Baumann + * @author David Molineus + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Test\Attribute; + +use Contao\CoreBundle\Framework\Adapter; +use Doctrine\DBAL\Connection; +use MetaModels\Attribute\Events\CollectMetaModelAttributeInformationEvent; +use MetaModels\Attribute\IAttribute; +use MetaModels\Attribute\IAttributeTypeFactory; +use MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeOrderTypeFactory; +use MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeTypeFactory; +use MetaModels\AttributeTranslatedFileBundle\Attribute\TranslatedFile; +use MetaModels\AttributeTranslatedFileBundle\Attribute\TranslatedFileOrder; +use MetaModels\AttributeTranslatedFileBundle\EventListener\Factory\AddAttributeInformation; +use MetaModels\Helper\ToolboxFile; +use MetaModels\IMetaModel; +use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; + +/** + * Test the attribute factory. + * + * @covers \MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeTypeFactory + * @covers \MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeOrderTypeFactory + * @covers \MetaModels\AttributeTranslatedFileBundle\EventListener\Factory\AddAttributeInformation + */ +class TranslatedFileAttributeTypeFactoryTest extends TestCase +{ + /** + * Mock a MetaModel. + * + * @param string $tableName The table name. + * + * @param string $language The language. + * + * @param string $fallbackLanguage The fallback language. + * + * @return IMetaModel + */ + protected function mockMetaModel($tableName, $language, $fallbackLanguage) + { + $metaModel = $this->getMockForAbstractClass(IMetaModel::class); + $mockAttributes = []; + + $metaModel + ->expects($this->any()) + ->method('getTableName') + ->will($this->returnValue($tableName)); + + $metaModel + ->expects($this->any()) + ->method('getActiveLanguage') + ->will($this->returnValue($language)); + + $metaModel + ->expects($this->any()) + ->method('getFallbackLanguage') + ->will($this->returnValue($fallbackLanguage)); + + $metaModel + ->expects($this->any()) + ->method('addAttribute') + ->will( + $this->returnCallback( + function (IAttribute $objAttribute) use ($metaModel, &$mockAttributes) { + $mockAttributes[$objAttribute->getColName()] = $objAttribute; + + return $metaModel; + } + ) + ); + + $metaModel + ->expects($this->any()) + ->method('hasAttribute') + ->will( + $this->returnCallback( + function ($strAttributeName) use (&$mockAttributes) { + return array_key_exists($strAttributeName, $mockAttributes); + } + ) + ); + + $metaModel + ->expects($this->any()) + ->method('getAttribute') + ->will( + $this->returnCallback( + function ($strAttributeName) use (&$mockAttributes) { + return array_key_exists($strAttributeName, $mockAttributes) + ? $mockAttributes[$strAttributeName] + : null; + } + ) + ); + + return $metaModel; + } + + /** + * Mock the database connection. + * + * @return \PHPUnit_Framework_MockObject_MockObject|Connection + */ + private function mockConnection() + { + return $this->getMockBuilder(Connection::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockToolboxFile() + { + return $this + ->getMockBuilder(ToolboxFile::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockStringUtil() + { + return $this + ->getMockBuilder(Adapter::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockValidator() + { + return $this + ->getMockBuilder(Adapter::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockFileRepository() + { + return $this + ->getMockBuilder(Adapter::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockConfig() + { + return $this + ->getMockBuilder(Adapter::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockAttributeFactory($connection) + { + $factory = $this->getMockForAbstractClass('\MetaModels\Attribute\IAttributeFactory'); + + $factories = [ + 'translatedfile' => new AttributeTypeFactory( + $connection, + $this->mockToolboxFile(), + $this->mockStringUtil(), + $this->mockValidator(), + $this->mockFileRepository(), + $this->mockConfig() + ), + 'translatedfilesort' => new AttributeOrderTypeFactory($connection) + ]; + + $factory + ->expects($this->any()) + ->method('getTypeFactory') + ->will( + $this->returnCallback( + function ($typeFactory) use ($factories) { + return isset($factories[(string) $typeFactory]) ? $factories[(string) $typeFactory] : null; + } + ) + ); + + return $factory; + } + + private function createEventDispatcher() + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener( + CollectMetaModelAttributeInformationEvent::NAME, + [new AddAttributeInformation(), 'addInformation'] + ); + + return $dispatcher; + } + + /** + * Override the method to run the tests on the attribute factories to be tested. + * + * @return IAttributeTypeFactory[] + */ + protected function getAttributeFactories() + { + return [new AttributeTypeFactory($this->mockConnection())]; + } + + /** + * Test creation of an translated select. + * + * @return void + */ + public function testCreateSelectOfNotSortableFile() + { + $metaModel = $this->mockMetaModel('mm_test', 'de', 'en'); + $factory = $this->mockAttributeFactory($this->mockConnection()); + $dispatcher = $this->createEventDispatcher(); + $event = new CollectMetaModelAttributeInformationEvent($metaModel); + $event->setAttributeInformation( + ['foo' => ['type' => 'translatedfile', 'colname' => 'foo', 'file_multiple' => null]] + ); + $dispatcher->dispatch($event::NAME, $event); + + foreach ($event->getAttributeInformation() as $name => $information) { + if (null === ($typeFactory = $factory->getTypeFactory($information['type']))) { + continue; + } + + $metaModel->addAttribute($typeFactory->createInstance($information, $metaModel)); + } + + $this->assertTrue($metaModel->hasAttribute('foo')); + $this->assertInstanceOf(TranslatedFile::class, $metaModel->getAttribute('foo')); + $this->assertFalse($metaModel->hasAttribute('foo__sort')); + $this->assertNull($metaModel->getAttribute('foo_sort')); + } + + /** + * Test creation of an translated select. + * + * @return void + */ + public function testCreateSelectOfSortableFile() + { + $metaModel = $this->mockMetaModel('mm_test', 'de', 'en'); + $factory = $this->mockAttributeFactory($this->mockConnection()); + $dispatcher = $this->createEventDispatcher(); + $event = new CollectMetaModelAttributeInformationEvent($metaModel); + $event->setAttributeInformation( + ['foo' => ['type' => 'translatedfile', 'colname' => 'foo', 'file_multiple' => '1']] + ); + $dispatcher->dispatch($event::NAME, $event); + + foreach ($event->getAttributeInformation() as $name => $information) { + if (null === ($typeFactory = $factory->getTypeFactory($information['type']))) { + continue; + } + + $metaModel->addAttribute($typeFactory->createInstance($information, $metaModel)); + } + + $this->assertTrue($metaModel->hasAttribute('foo')); + $this->assertInstanceOf(TranslatedFile::class, $metaModel->getAttribute('foo')); + $this->assertTrue($metaModel->hasAttribute('foo__sort')); + $this->assertInstanceOf(TranslatedFileOrder::class, $metaModel->getAttribute('foo__sort')); + } +} diff --git a/tests/MetaModels/Test/Attribute/TranslatedFile/TranslatedFileTest.php b/tests/Attribute/TranslatedFileOrderTest.php similarity index 72% rename from tests/MetaModels/Test/Attribute/TranslatedFile/TranslatedFileTest.php rename to tests/Attribute/TranslatedFileOrderTest.php index 9c02831..90ddeff 100644 --- a/tests/MetaModels/Test/Attribute/TranslatedFile/TranslatedFileTest.php +++ b/tests/Attribute/TranslatedFileOrderTest.php @@ -11,23 +11,24 @@ * This project is provided in good faith and hope to be usable by anyone. * * @package MetaModels/attribute_translatedfile - * @author Christian Schiffler - * @author David Greminger * @author Sven Baumann * @copyright 2012-2019 The MetaModels team. * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later * @filesource */ -namespace MetaModels\Test\Attribute\TranslatedFile; +namespace MetaModels\AttributeTranslatedFileBundle\Test\Attribute; -use MetaModels\Attribute\TranslatedFile\TranslatedFile; +use Doctrine\DBAL\Connection; +use MetaModels\AttributeTranslatedFileBundle\Attribute\TranslatedFileOrder; use PHPUnit\Framework\TestCase; /** * Unit tests to test class GeoProtection. + * + * @covers \MetaModels\AttributeTranslatedFileBundle\Attribute\TranslatedFileOrder */ -class TranslatedFileTest extends TestCase +class TranslatedFileOrderTest extends TestCase { /** * Mock a MetaModel. @@ -59,6 +60,13 @@ protected function mockMetaModel($language, $fallbackLanguage) return $metaModel; } + private function mockConnection() + { + return $this->getMockBuilder(Connection::class) + ->disableOriginalConstructor() + ->getMock(); + } + /** * Test that the attribute can be instantiated. * @@ -66,7 +74,7 @@ protected function mockMetaModel($language, $fallbackLanguage) */ public function testInstantiation() { - $text = new TranslatedFile($this->mockMetaModel('en', 'en')); - $this->assertInstanceOf('MetaModels\Attribute\TranslatedFile\TranslatedFile', $text); + $text = new TranslatedFileOrder($this->mockMetaModel('en', 'en'), [], $this->mockConnection()); + $this->assertInstanceOf(TranslatedFileOrder::class, $text); } } diff --git a/tests/Attribute/TranslatedFileTest.php b/tests/Attribute/TranslatedFileTest.php new file mode 100644 index 0000000..8ca8ff4 --- /dev/null +++ b/tests/Attribute/TranslatedFileTest.php @@ -0,0 +1,140 @@ + + * @author David Greminger + * @author Sven Baumann + * @author David Molineus + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Test\Attribute; + +use Contao\CoreBundle\Framework\Adapter; +use Doctrine\DBAL\Connection; +use MetaModels\AttributeTranslatedFileBundle\Attribute\TranslatedFile; +use MetaModels\Helper\ToolboxFile; +use MetaModels\IMetaModel; +use PHPUnit\Framework\TestCase; + +/** + * Unit tests to test class GeoProtection. + * + * @covers \MetaModels\AttributeTranslatedFileBundle\Attribute\TranslatedFile + */ +class TranslatedFileTest extends TestCase +{ + /** + * Mock a MetaModel. + * + * @param string $language The language. + * @param string $fallbackLanguage The fallback language. + * + * @return \MetaModels\IMetaModel + */ + protected function mockMetaModel($language, $fallbackLanguage) + { + $metaModel = $this->getMockForAbstractClass(IMetaModel::class); + + $metaModel + ->expects($this->any()) + ->method('getTableName') + ->will($this->returnValue('mm_unittest')); + + $metaModel + ->expects($this->any()) + ->method('getActiveLanguage') + ->will($this->returnValue($language)); + + $metaModel + ->expects($this->any()) + ->method('getFallbackLanguage') + ->will($this->returnValue($fallbackLanguage)); + + return $metaModel; + } + + /** + * Mock the database connection. + * + * @return \PHPUnit_Framework_MockObject_MockObject|Connection + */ + private function mockConnection() + { + return $this->getMockBuilder(Connection::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockToolboxFile() + { + return $this + ->getMockBuilder(ToolboxFile::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockStringUtil() + { + return $this + ->getMockBuilder(Adapter::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockValidator() + { + return $this + ->getMockBuilder(Adapter::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockFileRepository() + { + return $this + ->getMockBuilder(Adapter::class) + ->disableOriginalConstructor() + ->getMock(); + } + + private function mockConfig() + { + return $this + ->getMockBuilder(Adapter::class) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * Test that the attribute can be instantiated. + * + * @return void + */ + public function testInstantiation() + { + $text = new TranslatedFile( + $this->mockMetaModel('en', 'en'), + [], + $this->mockConnection(), + $this->mockToolboxFile(), + $this->mockStringUtil(), + $this->mockValidator(), + $this->mockFileRepository(), + $this->mockConfig() + ); + $this->assertInstanceOf(TranslatedFile::class, $text); + } +} diff --git a/tests/ContaoManager/PluginTest.php b/tests/ContaoManager/PluginTest.php new file mode 100644 index 0000000..b9ca24d --- /dev/null +++ b/tests/ContaoManager/PluginTest.php @@ -0,0 +1,77 @@ + + * @author Sven Baumann + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Test\ContaoManager; + +use Contao\CoreBundle\ContaoCoreBundle; +use Contao\ManagerPlugin\Bundle\BundlePluginInterface; +use Contao\ManagerPlugin\Bundle\Config\BundleConfig; +use Contao\ManagerPlugin\Bundle\Parser\ParserInterface; +use MetaModels\AttributeFileBundle\MetaModelsAttributeFileBundle; +use MetaModels\AttributeTranslatedFileBundle\ContaoManager\Plugin; +use MetaModels\CoreBundle\MetaModelsCoreBundle; +use PHPUnit\Framework\TestCase; + +/** + * Unit tests the contao manager plugin. + */ +class PluginTest extends TestCase +{ + /** + * Test that plugin can be instantiated. + * + * @return void + */ + public function testInstantiation() + { + $plugin = new Plugin(); + + $this->assertInstanceOf(Plugin::class, $plugin); + $this->assertInstanceOf(BundlePluginInterface::class, $plugin); + } + + /** + * Tests that the a valid bundle config is created. + * + * @return void + */ + public function testBundleConfig() + { + $parser = $this->getMockBuilder(ParserInterface::class)->getMock(); + $plugin = new Plugin(); + $bundles = $plugin->getBundles($parser); + + $this->assertContainsOnlyInstancesOf(BundleConfig::class, $bundles); + $this->assertCount(1, $bundles); + + /** @var BundleConfig $bundleConfig */ + $bundleConfig = $bundles[0]; + + $this->assertEquals( + $bundleConfig->getLoadAfter(), + [ + ContaoCoreBundle::class, + MetaModelsCoreBundle::class, + MetaModelsAttributeFileBundle::class + ] + ); + $this->assertEquals($bundleConfig->getReplace(), ['metamodelsattribute_translatedfile']); + } +} diff --git a/tests/DependencyInjection/MetaModelsAttributeTranslatedFileExtensionTest.php b/tests/DependencyInjection/MetaModelsAttributeTranslatedFileExtensionTest.php new file mode 100644 index 0000000..97c19b7 --- /dev/null +++ b/tests/DependencyInjection/MetaModelsAttributeTranslatedFileExtensionTest.php @@ -0,0 +1,178 @@ + + * @author Sven Baumann + * @author Christian Schiffler + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Test\DependencyInjection; + +use MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeOrderTypeFactory; +use MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeTypeFactory; +use MetaModels\AttributeTranslatedFileBundle\DependencyInjection\MetaModelsAttributeTranslatedFileExtension; +use MetaModels\AttributeTranslatedFileBundle\EventListener\BuildAttributeListener; +use MetaModels\AttributeTranslatedFileBundle\EventListener\BuildDataDefinitionListener; +use MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\Attribute\RemoveTypeOptions; +use MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\FilterSetting\RemoveAttIdOptions; +use MetaModels\AttributeTranslatedFileBundle\EventListener\Factory\AddAttributeInformation; +use MetaModels\AttributeTranslatedFileBundle\EventListener\ImageSizeOptions; +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; + +/** + * This test case test the extension. + */ +class MetaModelsAttributeTranslatedFileExtensionTest extends TestCase +{ + /** + * Test that extension can be instantiated. + * + * @return void + */ + public function testInstantiation() + { + $extension = new MetaModelsAttributeTranslatedFileExtension(); + + $this->assertInstanceOf(MetaModelsAttributeTranslatedFileExtension::class, $extension); + $this->assertInstanceOf(ExtensionInterface::class, $extension); + } + + /** + * Test that the services are loaded. + * + * @return void + */ + public function testFactoryIsRegistered() + { + $container = $this->getMockBuilder(ContainerBuilder::class)->getMock(); + + $container + ->expects($this->exactly(8)) + ->method('setDefinition') + ->withConsecutive( + [ + 'metamodels.attribute_translatedfile.factory', + $this->callback( + function ($value) { + /** @var Definition $value */ + $this->assertInstanceOf(Definition::class, $value); + $this->assertEquals(AttributeTypeFactory::class, $value->getClass()); + $this->assertCount(1, $value->getTag('metamodels.attribute_factory')); + + return true; + } + ) + ], + [ + 'metamodels.attribute_translatedfile_order.factory', + $this->callback( + function ($value) { + /** @var Definition $value */ + $this->assertInstanceOf(Definition::class, $value); + $this->assertEquals(AttributeOrderTypeFactory::class, $value->getClass()); + $this->assertCount(1, $value->getTag('metamodels.attribute_factory')); + + return true; + } + ) + ], + [ + 'metamodels.attribute_translatedfile.event_listener_factory.add_attribute_information', + $this->callback( + function ($value) { + /** @var Definition $value */ + $this->assertInstanceOf(Definition::class, $value); + $this->assertEquals(AddAttributeInformation::class, $value->getClass()); + $this->assertCount(1, $value->getTag('kernel.event_listener')); + + return true; + } + ) + ], + [ + 'metamodels.attribute_translatedfile.event_listener.build_data_definition', + $this->callback( + function ($value) { + /** @var Definition $value */ + $this->assertInstanceOf(Definition::class, $value); + $this->assertEquals(BuildDataDefinitionListener::class, $value->getClass()); + $this->assertCount(1, $value->getTag('kernel.event_listener')); + + return true; + } + ) + ], + [ + 'metamodels.attribute_translatedfile.event_listener.build_attribute', + $this->callback( + function ($value) { + /** @var Definition $value */ + $this->assertInstanceOf(Definition::class, $value); + $this->assertEquals(BuildAttributeListener::class, $value->getClass()); + $this->assertCount(1, $value->getTag('kernel.event_listener')); + + return true; + } + ) + ], + [ + 'metamodels.attribute_translatedfile.event_listener.image_size_options', + $this->callback( + function ($value) { + /** @var Definition $value */ + $this->assertInstanceOf(Definition::class, $value); + $this->assertEquals(ImageSizeOptions::class, $value->getClass()); + $this->assertCount(1, $value->getTag('kernel.event_listener')); + + return true; + } + ) + ], + [ + 'metamodels.attribute_translatedfile.event_listener.remove_type_options', + $this->callback( + function ($value) { + /** @var Definition $value */ + $this->assertInstanceOf(Definition::class, $value); + $this->assertEquals(RemoveTypeOptions::class, $value->getClass()); + $this->assertCount(1, $value->getTag('kernel.event_listener')); + + return true; + } + ) + ], + [ + 'metamodels.attribute_translatedfile.event_listener.remove_att_id_options', + $this->callback( + function ($value) { + /** @var Definition $value */ + $this->assertInstanceOf(Definition::class, $value); + $this->assertEquals(RemoveAttIdOptions::class, $value->getClass()); + $this->assertCount(1, $value->getTag('kernel.event_listener')); + + return true; + } + ) + ] + ); + + $extension = new MetaModelsAttributeTranslatedFileExtension(); + $extension->load([], $container); + } +} diff --git a/tests/DeprecatedAutoloaderTest.php b/tests/DeprecatedAutoloaderTest.php new file mode 100644 index 0000000..b7aa789 --- /dev/null +++ b/tests/DeprecatedAutoloaderTest.php @@ -0,0 +1,75 @@ + + * @author Sven Baumann + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Test; + +use MetaModels\AttributeTranslatedFileBundle\Attribute\AttributeTypeFactory; +use MetaModels\AttributeTranslatedFileBundle\Attribute\TranslatedFile; +use PHPUnit\Framework\TestCase; + +/** + * This class tests if the deprecated autoloader works. + */ +class DeprecatedAutoloaderTest extends TestCase +{ + /** + * TranslatedFilees of old classes to the new one. + * + * @var array + */ + private static $classes = [ + 'MetaModels\Attribute\TranslatedFile\TranslatedFile' => TranslatedFile::class, + 'MetaModels\Attribute\TranslatedFile\AttributeTypeFactory' => AttributeTypeFactory::class + ]; + + /** + * Provide the file class map. + * + * @return array + */ + public function provideFileClassMap() + { + $values = []; + + foreach (static::$classes as $translatedFile => $class) { + $values[] = [$translatedFile, $class]; + } + + return $values; + } + + /** + * Test if the deprecated classes are fileed to the new one. + * + * @param string $oldClass Old class name. + * @param string $newClass New class name. + * + * @dataProvider provideFileClassMap + */ + public function testDeprecatedClassesAreFileed($oldClass, $newClass) + { + $this->assertTrue(class_exists($oldClass), sprintf('Class TranslatedFile "%s" is not found.', $oldClass)); + + $oldClassReflection = new \ReflectionClass($oldClass); + $newClassReflection = new \ReflectionClass($newClass); + + $this->assertSame($newClassReflection->getFileName(), $oldClassReflection->getFileName()); + } +} diff --git a/tests/EventListener/AddAttributeInformationTest.php b/tests/EventListener/AddAttributeInformationTest.php new file mode 100644 index 0000000..8683089 --- /dev/null +++ b/tests/EventListener/AddAttributeInformationTest.php @@ -0,0 +1,192 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Test\EventListener; + +use MetaModels\Attribute\Events\CollectMetaModelAttributeInformationEvent; +use MetaModels\AttributeTranslatedFileBundle\EventListener\Factory\AddAttributeInformation; +use MetaModels\IMetaModel; +use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; + +/** + * This test the event listener add attribute information. + * + * @covers \MetaModels\AttributeTranslatedFileBundle\EventListener\Factory\AddAttributeInformation + */ +class AddAttributeInformationTest extends TestCase +{ + public function dataProviderAddInformation() + { + return [ + [ + [], + [] + ], + + [ + [ + 'file' => ['type' => 'nofile'] + ], + [ + 'file' => ['type' => 'nofile'] + ] + ], + + [ + [ + 'file' => ['type' => 'nofile', 'file_multiple' => ''] + ], + [ + 'file' => ['type' => 'nofile', 'file_multiple' => ''] + ] + ], + + [ + [ + 'file' => ['type' => 'nofile', 'file_multiple' => '1'] + ], + [ + 'file' => ['type' => 'nofile', 'file_multiple' => '1'] + ] + ], + + [ + [ + 'file' => ['type' => 'translatedfile'] + ], + [ + 'file' => ['type' => 'translatedfile'] + ] + ], + + [ + [ + 'file' => ['type' => 'translatedfile', 'file_multiple' => ''] + ], + [ + 'file' => ['type' => 'translatedfile', 'file_multiple' => ''] + ] + ], + + [ + [ + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'file__sort' => ['colname' => 'file__sort', 'type' => 'translatedfilesort'] + ], + [ + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'] + ] + ], + + [ + [ + 'beforeNoFile' => ['type' => 'nofile'], + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'file__sort' => ['colname' => 'file__sort', 'type' => 'translatedfilesort'] + ], + [ + 'beforeNoFile' => ['type' => 'nofile'], + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'] + ] + ], + + [ + [ + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'file__sort' => ['colname' => 'file__sort', 'type' => 'translatedfilesort'], + 'afterNoFile' => ['type' => 'nofile'] + ], + [ + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'afterNoFile' => ['type' => 'nofile'] + ] + ], + + [ + [ + 'beforeNoFile' => ['type' => 'nofile'], + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'file__sort' => ['colname' => 'file__sort', 'type' => 'translatedfilesort'], + 'afterNoFile' => ['type' => 'nofile'] + ], + [ + 'beforeNoFile' => ['type' => 'nofile'], + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'afterNoFile' => ['type' => 'nofile'] + ] + ], + + [ + [ + 'beforeNoFile' => ['type' => 'nofile'], + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'file__sort' => ['colname' => 'file__sort', 'type' => 'translatedfilesort'], + 'file2' => ['colname' => 'file2', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'file2__sort' => ['colname' => 'file2__sort', 'type' => 'translatedfilesort'], + 'afterNoFile' => ['type' => 'nofile'] + ], + [ + 'beforeNoFile' => ['type' => 'nofile'], + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'file2' => ['colname' => 'file2', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'afterNoFile' => ['type' => 'nofile'] + ] + ], + + [ + [ + 'beforeNoFile' => ['type' => 'nofile'], + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'file__sort' => ['colname' => 'file__sort', 'type' => 'translatedfilesort'], + 'middleNoFile' => ['type' => 'nofile'], + 'file2' => ['colname' => 'file2', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'file2__sort' => ['colname' => 'file2__sort', 'type' => 'translatedfilesort'], + 'afterNoFile' => ['type' => 'nofile'] + ], + [ + 'beforeNoFile' => ['type' => 'nofile'], + 'file' => ['colname' => 'file', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'middleNoFile' => ['type' => 'nofile'], + 'file2' => ['colname' => 'file2', 'type' => 'translatedfile', 'file_multiple' => '1'], + 'afterNoFile' => ['type' => 'nofile'] + ] + ] + ]; + } + + /** + * @dataProvider dataProviderAddInformation + */ + public function testAddInformation($expected, $information) + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener( + CollectMetaModelAttributeInformationEvent::NAME, + [new AddAttributeInformation(), 'addInformation'] + ); + + $metaModel = $this->getMockForAbstractClass(IMetaModel::class); + $event = new CollectMetaModelAttributeInformationEvent($metaModel); + $event->setAttributeInformation($information); + $dispatcher->dispatch($event::NAME, $event); + + $this->assertSame($expected, $event->getAttributeInformation()); + } +} diff --git a/tests/EventListener/DcGeneral/Table/Attribute/RemoveTypeOptionsTest.php b/tests/EventListener/DcGeneral/Table/Attribute/RemoveTypeOptionsTest.php new file mode 100644 index 0000000..51dcb50 --- /dev/null +++ b/tests/EventListener/DcGeneral/Table/Attribute/RemoveTypeOptionsTest.php @@ -0,0 +1,120 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Test\EventListener\DcGeneral\Table\Attribute; + +use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; +use MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\Attribute\RemoveTypeOptions; +use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; + +/** + * This test the event listener. + * + * @covers \MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\Attribute\RemoveTypeOptions + */ +class RemoveTypeOptionsTest extends TestCase +{ + private function mockEnvironment() + { + $dataDefinition = null; + + $environment = $this->getMockForAbstractClass(EnvironmentInterface::class); + + $environment + ->expects($this->any()) + ->method('getDataDefinition') + ->will( + $this->returnCallback( + function () use (&$dataDefinition) { + return $dataDefinition; + } + ) + ); + + $environment + ->expects($this->any()) + ->method('setDataDefinition') + ->will( + $this->returnCallback( + function (ContainerInterface $container) use (&$dataDefinition, $environment) { + $dataDefinition = $container; + + return $environment; + } + ) + ); + + return $environment; + } + + private function mockDataDefinition($name = null) + { + $dataDefinition = $this->getMockForAbstractClass(ContainerInterface::class); + + $dataDefinition + ->expects($this->any()) + ->method('getName') + ->willReturn($name); + + return $dataDefinition; + } + + private function mockModel() + { + return $this->getMockForAbstractClass(ModelInterface::class); + } + + public function dataProviderTestRemoveOption() + { + $sortType = 'translatedfilesort'; + return [ + [['foo' => 'bar', $sortType => 'foo'], 'foo', 'foo', ['foo' => 'bar', $sortType => 'foo']], + [['foo' => 'bar', $sortType => 'foo'], 'foo', 'type', ['foo' => 'bar', $sortType => 'foo']], + [['foo' => 'bar'], 'tl_metamodel_attribute', 'type', ['foo' => 'bar']], + [['foo' => 'bar'], 'tl_metamodel_attribute', 'type', ['foo' => 'bar', $sortType => 'foo']] + ]; + } + + /** + * @dataProvider dataProviderTestRemoveOption + */ + public function testRemoveOption(array $expected, $providerName, $propertyName, $options) + { + $environment = $this->mockEnvironment(); + $environment->setDataDefinition($this->mockDataDefinition($providerName)); + + $dispatcher = new EventDispatcher(); + $dispatcher->addListener( + GetPropertyOptionsEvent::NAME, + [new RemoveTypeOptions(), 'removeOption'] + ); + + + $event = new GetPropertyOptionsEvent($environment, $this->mockModel()); + $event->setPropertyName($propertyName); + $event->setOptions($options); + $dispatcher->dispatch($event::NAME, $event); + + $this->assertSame($expected, $event->getOptions()); + } +} diff --git a/tests/EventListener/DcGeneral/Table/FilterSetting/RemoveAttIdOptionsTest.php b/tests/EventListener/DcGeneral/Table/FilterSetting/RemoveAttIdOptionsTest.php new file mode 100644 index 0000000..38cad47 --- /dev/null +++ b/tests/EventListener/DcGeneral/Table/FilterSetting/RemoveAttIdOptionsTest.php @@ -0,0 +1,120 @@ + + * @copyright 2012-2019 The MetaModels team. + * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later + * @filesource + */ + +namespace MetaModels\AttributeTranslatedFileBundle\Test\EventListener\DcGeneral\Table\FilterSetting; + +use ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent; +use ContaoCommunityAlliance\DcGeneral\Data\ModelInterface; +use ContaoCommunityAlliance\DcGeneral\DataDefinition\ContainerInterface; +use ContaoCommunityAlliance\DcGeneral\EnvironmentInterface; +use MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\FilterSetting\RemoveAttIdOptions; +use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; + +/** + * This test the event listener. + * + * @covers \MetaModels\AttributeTranslatedFileBundle\EventListener\DcGeneral\Table\FilterSetting\RemoveAttIdOptions + */ +class RemoveAttIdOptionsTest extends TestCase +{ + private function mockEnvironment() + { + $dataDefinition = null; + + $environment = $this->getMockForAbstractClass(EnvironmentInterface::class); + + $environment + ->expects($this->any()) + ->method('getDataDefinition') + ->will( + $this->returnCallback( + function () use (&$dataDefinition) { + return $dataDefinition; + } + ) + ); + + $environment + ->expects($this->any()) + ->method('setDataDefinition') + ->will( + $this->returnCallback( + function (ContainerInterface $container) use (&$dataDefinition, $environment) { + $dataDefinition = $container; + + return $environment; + } + ) + ); + + return $environment; + } + + private function mockDataDefinition($name = null) + { + $dataDefinition = $this->getMockForAbstractClass(ContainerInterface::class); + + $dataDefinition + ->expects($this->any()) + ->method('getName') + ->willReturn($name); + + return $dataDefinition; + } + + private function mockModel() + { + return $this->getMockForAbstractClass(ModelInterface::class); + } + + public function dataProviderTestRemoveOption() + { + + return [ + [['foo' => 'bar [translatedfile]', 'filesort' => 'foo'], 'foo', 'foo', ['foo' => 'bar [translatedfile]', 'filesort' => 'foo']], + [['foo' => 'bar [translatedfile]', 'filesort' => 'foo'], 'foo', 'attr_id', ['foo' => 'bar [translatedfile]', 'filesort' => 'foo']], + [['foo' => 'bar [translatedfile]'], 'tl_metamodel_filtersetting', 'attr_id', ['foo' => 'bar [translatedfile]']], + [['foo' => 'bar [translatedfile]'], 'tl_metamodel_filtersetting', 'attr_id', ['foo' => 'bar [translatedfile]', 'foo__sort' => 'foo']] + ]; + } + + /** + * @dataProvider dataProviderTestRemoveOption + */ + public function testRemoveOption(array $expected, $providerName, $propertyName, $options) + { + $environment = $this->mockEnvironment(); + $environment->setDataDefinition($this->mockDataDefinition($providerName)); + + $dispatcher = new EventDispatcher(); + $dispatcher->addListener( + GetPropertyOptionsEvent::NAME, + [new RemoveAttIdOptions(), 'removeOption'] + ); + + + $event = new GetPropertyOptionsEvent($environment, $this->mockModel()); + $event->setPropertyName($propertyName); + $event->setOptions($options); + $dispatcher->dispatch($event::NAME, $event); + + $this->assertSame($expected, $event->getOptions()); + } +} diff --git a/tests/MetaModels/Test/Attribute/TranslatedFile/TranslatedFileAttributeTypeFactoryTest.php b/tests/MetaModels/Test/Attribute/TranslatedFile/TranslatedFileAttributeTypeFactoryTest.php deleted file mode 100644 index 5a70128..0000000 --- a/tests/MetaModels/Test/Attribute/TranslatedFile/TranslatedFileAttributeTypeFactoryTest.php +++ /dev/null @@ -1,91 +0,0 @@ - - * @author Sven Baumann - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -namespace MetaModels\Test\Attribute\TranslatedFile; - -use MetaModels\Attribute\IAttributeTypeFactory; -use MetaModels\Attribute\TranslatedFile\AttributeTypeFactory; -use MetaModels\IMetaModel; -use MetaModels\Test\Attribute\AttributeTypeFactoryTest; - -/** - * Test the attribute factory. - */ -class TranslatedFileAttributeTypeFactoryTest extends AttributeTypeFactoryTest -{ - /** - * Mock a MetaModel. - * - * @param string $tableName The table name. - * - * @param string $language The language. - * - * @param string $fallbackLanguage The fallback language. - * - * @return IMetaModel - */ - protected function mockMetaModel($tableName, $language, $fallbackLanguage) - { - $metaModel = $this->getMockForAbstractClass('MetaModels\IMetaModel'); - - $metaModel - ->expects($this->any()) - ->method('getTableName') - ->will($this->returnValue($tableName)); - - $metaModel - ->expects($this->any()) - ->method('getActiveLanguage') - ->will($this->returnValue($language)); - - $metaModel - ->expects($this->any()) - ->method('getFallbackLanguage') - ->will($this->returnValue($fallbackLanguage)); - - return $metaModel; - } - - /** - * Override the method to run the tests on the attribute factories to be tested. - * - * @return IAttributeTypeFactory[] - */ - protected function getAttributeFactories() - { - return array(new AttributeTypeFactory()); - } - - /** - * Test creation of an translated select. - * - * @return void - */ - public function testCreateSelect() - { - $factory = new AttributeTypeFactory(); - $attribute = $factory->createInstance( - array(), - $this->mockMetaModel('mm_test', 'de', 'en') - ); - - $this->assertInstanceOf('MetaModels\Attribute\TranslatedFile\TranslatedFile', $attribute); - } -} diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index 756b85a..0000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @author David Greminger - * @copyright 2012-2019 The MetaModels team. - * @license https://github.com/MetaModels/attribute_translatedfile/blob/master/LICENSE LGPL-3.0-or-later - * @filesource - */ - -error_reporting(E_ALL); - -function includeIfExists($file) -{ - return file_exists($file) ? include $file : false; -} - -if ( - // Locally installed dependencies - (!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) - // We are within an composer install. - && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) { - echo 'You must set up the project dependencies, run the following commands:'.PHP_EOL. - 'curl -sS https://getcomposer.org/installer | php'.PHP_EOL. - 'php composer.phar install'.PHP_EOL; - exit(1); -}