├── .ci ├── Jenkinsfile └── config │ └── parameters_test.yml ├── .gitignore ├── .php_cs.php ├── CHANGELOG-2.0.md ├── CHANGELOG-2.1.md ├── CHANGELOG.md ├── LICENCE.txt ├── README.md ├── composer.json ├── composer.lock ├── doc ├── Akeneo │ └── Bundle │ │ └── InstallerBundle │ │ ├── DependencyInjection │ │ └── PimInitInstallerExtension.php │ │ ├── PimInitInstallerBundle.php │ │ └── Resources │ │ ├── config │ │ └── parameters.yml │ │ └── fixtures │ │ └── my_dataset │ │ └── readme.md ├── Association-type-tab.rst ├── Attribute-groups.rst ├── Attribute-types.rst ├── Attributes.rst ├── Categories-tab.rst ├── Channels-tab.rst ├── Choices-tab.rst ├── Families.rst ├── Getting-started.rst ├── Group-types.rst ├── Home.rst ├── Metric-types.rst ├── Metric-units.rst ├── Options-tab.rst ├── inclusions │ └── label_table_assocition_type.html └── pictures │ ├── akeneo_excel.png │ └── bundle_icon.jpg ├── docker-compose.yml ├── spec └── Pim │ └── Bundle │ └── ExcelInitBundle │ ├── Iterator │ ├── ArrayHelperSpec.php │ ├── InitAttributesFileIteratorSpec.php │ └── InitFileIteratorSpec.php │ ├── Mapper │ └── AttributeTypeMapperSpec.php │ └── fixtures │ ├── dummy1.xlsx │ └── dummy2.xlsx └── src ├── ArrayConverter └── Flat │ └── Attribute.php ├── DependencyInjection └── PimExcelInitExtension.php ├── Iterator ├── ArrayHelper.php ├── InitAttributesFileIterator.php ├── InitFamilyFileIterator.php └── InitFileIterator.php ├── Mapper ├── AttributeTypeMapper.php └── AttributeTypeMapperInterface.php ├── PimExcelInitBundle.php ├── Reader └── AttributeXlsxReader.php └── Resources ├── config ├── array_converters.yml ├── fixtures_jobs.yml ├── fixtures_jobs_ee.yml ├── iterators.yml ├── jobs.yml ├── mappers.yml ├── readers.yml └── steps.yml ├── fixtures ├── minimal │ ├── init.xlsx │ ├── jobs.yml │ └── locales.csv └── minimal_EE │ ├── asset_categories.csv │ ├── asset_category_accesses.csv │ ├── asset_channel_configurations.yml │ ├── assets.csv │ ├── attribute_group_accesses.csv │ ├── init.xlsx │ ├── job_profile_accesses.csv │ ├── jobs.yml │ ├── locale_accesses.csv │ ├── locales.csv │ ├── product_category_accesses.csv │ └── rules.yml └── translations ├── jsmessages.en.yml ├── jsmessages.fr.yml ├── messages.en.yml └── messages.fr.yml /.ci/Jenkinsfile: -------------------------------------------------------------------------------- 1 | #!groovy 2 | 3 | milestone 1 4 | if (env.BRANCH_NAME =~ /^PR-/) { 5 | input 'Launch tests?' 6 | } 7 | milestone 2 8 | 9 | stage("Tests") { 10 | withCredentials([string(credentialsId: 'composer-token', variable: 'token')]) { 11 | podTemplate(label: 'excel-init-ee', containers: [ 12 | containerTemplate( 13 | name: "elasticsearch", 14 | image: "elasticsearch-oss:6.5.4", 15 | resourceRequestCpu: '100m', 16 | resourceRequestMemory: '200Mi', 17 | envVars: [ 18 | envVar(key: "ES_JAVA_OPTS", value: "-Xms512m -Xmx512m"), 19 | envVar(key: "FORCE", value: "true"), 20 | ] 21 | ), 22 | containerTemplate( 23 | name: "mysql", 24 | image: "mysql:5.7", 25 | resourceRequestCpu: '100m', 26 | resourceRequestMemory: '200Mi', 27 | envVars: [ 28 | envVar(key: "MYSQL_ROOT_PASSWORD", value: "root"), 29 | envVar(key: "MYSQL_USER", value: "akeneo_pim"), 30 | envVar(key: "MYSQL_PASSWORD", value: "akeneo_pim"), 31 | envVar(key: "MYSQL_DATABASE", value: "akeneo_pim"), 32 | ], volumes: [ 33 | emptyDirVolume(memory: true, mountPath: "/var/lib/mysql"), 34 | emptyDirVolume(memory: true, mountPath: "/tmp") 35 | ] 36 | ), 37 | containerTemplate( 38 | name: "php", 39 | ttyEnabled: true, 40 | command: 'cat', 41 | image: "akeneo/php:7.2", 42 | resourceRequestCpu: '100m', 43 | resourceRequestMemory: '1000Mi', 44 | envVars: [ 45 | envVar(key: "COMPOSER_AUTH", value: "{\"github-oauth\":{\"github.com\": \"$token\"}}") 46 | ] 47 | ), 48 | ]) { 49 | node('excel-init-ee') { 50 | container("php") { 51 | checkout([$class: 'GitSCM', 52 | branches: [[name: "3.0"]], 53 | userRemoteConfigs: [[credentialsId: 'github-credentials', url: 'https://github.com/akeneo/pim-enterprise-standard.git']] 54 | ]) 55 | 56 | sh """ 57 | php -d memory_limit=3G /usr/local/bin/composer require akeneo/excel-init-bundle:dev-master --no-interaction --no-progress --prefer-dist 58 | chmod -R 777 vendor 59 | """ 60 | 61 | dir("vendor/akeneo/excel-init-bundle") { 62 | deleteDir() 63 | checkout scm 64 | } 65 | 66 | sh """ 67 | composer dump-autoload -o 68 | rm var/cache/* -rf 69 | cp vendor/akeneo/excel-init-bundle/.ci/config/parameters_test.yml app/config/parameters_test.yml 70 | sed -i 's#// your app bundles should be registered here#\\0\\nnew Pim\\\\Bundle\\\\ExcelInitBundle\\\\PimExcelInitBundle(),#' app/AppKernel.php 71 | sleep 10 72 | """ 73 | 74 | sh "bin/console pim:install --force --env=test" 75 | } 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /.ci/config/parameters_test.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | database_driver: pdo_mysql 3 | database_host: 127.0.0.1 4 | database_port: null 5 | database_name: akeneo_pim 6 | database_user: akeneo_pim 7 | database_password: akeneo_pim 8 | locale: en 9 | secret: ThisTokenIsNotSoSecretChangeIt 10 | product_index_name: akeneo_pim_product 11 | product_model_index_name: akeneo_pim_product_model 12 | product_and_product_model_index_name: akeneo_pim_product_and_product_model 13 | index_hosts: '127.0.0.1:9200' 14 | 15 | pim_installer.fixture_loader.job_loader.config_file: PimExcelInitBundle/Resources/config/fixtures_jobs_ee.yml 16 | installer_data: PimExcelInitBundle:minimal_EE 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.phar 3 | /bin 4 | -------------------------------------------------------------------------------- /.php_cs.php: -------------------------------------------------------------------------------- 1 | setRules([ 4 | '@PSR2' => true, 5 | 'linebreak_after_opening_tag' => true, 6 | 'ordered_imports' => true, 7 | ]) 8 | ->setFinder( 9 | PhpCsFixer\Finder::create() 10 | ->name('*.php') 11 | ->in(__DIR__ . '/src') 12 | ); 13 | -------------------------------------------------------------------------------- /CHANGELOG-2.0.md: -------------------------------------------------------------------------------- 1 | # 2.0.2 2 | ## Improvements 3 | - Add categories step to import job 4 | 5 | # 2.0.1 6 | ## Bugs fixes 7 | - EX-23: update measures in init.xlsx 8 | 9 | # 2.0.0 10 | ## Improvements 11 | - Migration to Akeneo PIM 2.x 12 | -------------------------------------------------------------------------------- /CHANGELOG-2.1.md: -------------------------------------------------------------------------------- 1 | # 2.1.0 2 | ## Improvements 3 | - Migration to Akeneo PIM 2.2. Changes in `user` tab headers. 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.2.5 2 | ## Bugs fixes 3 | - GITHUB-19: update measures in init.xlsx 4 | 5 | # 1.2.4 6 | ## Bugs fixes 7 | - EX-26: Boolean attributes must be explicitly set to 0 8 | 9 | ## Improvements 10 | - EX-27: Add read only column for EE attributes 11 | - Add categories in fixtures 12 | 13 | # 1.2.3 14 | 15 | ## Bugs fixes 16 | 17 | - PR #43: Fix missing currencies 18 | 19 | # 1.2.1 20 | 21 | ## Improvements 22 | 23 | - PR #35: Missing jobs definitions 24 | - PR #33: More examples in EE fixtures 25 | 26 | # 1.2.0 27 | 28 | ## Bug fix 29 | - Update EE file `init.xlsx` to match the CE one and be able to work with 1.7 30 | -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | Akeneo PIM 2 | 3 | The Open Software License version 3.0 4 | 5 | Copyright (c) 2014, Akeneo SAS. 6 | 7 | Full license is at: http://opensource.org/licenses/OSL-3.0 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Excel Init Bundle 2 | 3 | [![Build Status](https://travis-ci.org/akeneo/ExcelInitBundle.svg?branch=master)](https://travis-ci.org/akeneo/ExcelInitBundle) 4 | 5 | ![alt text](./doc/pictures/bundle_icon.jpg "") 6 | 7 | This bundle adds support of Excel XSLX files as a source for initializing catalog structure for [Akeneo PIM](https://github.com/akeneo/pim-community-standard). 8 | 9 | This extension replaces the [ExcelConnectorBundle](https://github.com/akeneo-labs/ExcelConnectorBundle) for Akeneo PIM >= 1.6. 10 | Be carefull to use the new `init.xlsx` file of this bundle as there are some structure modifications. 11 | 12 | **Note**: this bundle is not compatible with Excel 2003 xls files. Editing the XLSX file with LibreOffice/OpenOffice is also not supported as it can lead to unwanted behavior. 13 | 14 | ## Requirements 15 | 16 | | ExcelInitBundle | Akeneo PIM Community Edition | 17 | |:---------------:|:----------------------------:| 18 | | v3.0.* | >= v3.0 | 19 | | v2.1.* | >= v2.2 - < 3.0 | 20 | | v2.0.* | v2.0 - v2.1 | 21 | | v1.2.* | v1.7.* | 22 | | v1.1.* | v1.6.* | 23 | | v1.0.* | v1.6.* | 24 | 25 | ## Installation 26 | 27 | From your application root: 28 | 29 | ```bash 30 | php composer.phar require --prefer-dist akeneo/excel-init-bundle:3.0 31 | ``` 32 | 33 | Enable the bundle in the `app/AppKernel.php` file in the `registerProjectBundles()` method: 34 | 35 | ```php 36 | $bundles = [ 37 | // ... 38 | new Pim\Bundle\ExcelInitBundle\PimExcelInitBundle(), 39 | ] 40 | ``` 41 | 42 | Now let's clean your cache and dump your assets: 43 | 44 | ```bash 45 | php bin/console cache:warmup --env=prod 46 | php bin/console pim:installer:assets --env=prod 47 | ``` 48 | 49 | ## Documentation 50 | 51 | ### Getting started 52 | 53 | See [doc/Getting started](./doc/Getting-started.rst) for more details on how to set your catalog structure 54 | using the [init.xslx](./src/Resources/fixtures/minimal/init.xlsx) file. 55 | 56 | See [doc folder](./doc/Home.rst) for more details on how to set your catalog structure. 57 | 58 | ### Supported file 59 | 60 | Input file must follow [init.xslx](./src/Resources/fixtures/minimal/init.xlsx) structure. 61 | 62 | Note that the file should be opened with Excel. 63 | LibreOffice/OpenOffice are not fully in compliance with validations data that are available in the spreadsheet. 64 | 65 | ## Troubleshooting 66 | 67 | ### The import fails when importing families 68 | 69 | Check that your channels names are correct in both family and channel tabs. 70 | You might have a typo in the channels tab and not in the family tab. 71 | You will have to remove the mispelled channel once you corrected this. 72 | 73 | ## Dev notes 74 | 75 | ### Unit tests 76 | 77 | You can launch the PHPSpec tests with the provided `docker-compose.yml` file: 78 | 79 | ```bash 80 | docker-compose pull 81 | docker-compose up -d 82 | docker-compose exec fpm composer install --prefer-dist 83 | docker-compose exec fpm ./bin/phpspec run 84 | ``` 85 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "akeneo/excel-init-bundle", 3 | "type": "symfony-bundle", 4 | "description": "Akeneo PIM Excel initialization bundle", 5 | "keywords": ["pim", "akeneo", "ecommerce", "e-commerce", "excel"], 6 | "homepage": "http://www.akeneo.com", 7 | "license": "OSL-3.0", 8 | "authors": [ 9 | { 10 | "name": "Akeneo", 11 | "homepage": "http://www.akeneo.com" 12 | } 13 | ], 14 | "require": { 15 | "akeneo/pim-community-dev": "^3.0.0" 16 | }, 17 | "require-dev": { 18 | "phpspec/phpspec": "@stable", 19 | "friendsofphp/php-cs-fixer": "@stable" 20 | }, 21 | "config": { 22 | "bin-dir": "bin" 23 | }, 24 | "autoload": { 25 | "psr-4": { "Pim\\Bundle\\ExcelInitBundle\\": "src/" } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /doc/Akeneo/Bundle/InstallerBundle/DependencyInjection/PimInitInstallerExtension.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class PimInitInstallerExtension extends Extension 14 | { 15 | /** 16 | * {@inheritDoc} 17 | */ 18 | public function load(array $configs, ContainerBuilder $container) 19 | { 20 | $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 21 | $loader->load('parameters.yml'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /doc/Akeneo/Bundle/InstallerBundle/PimInitInstallerBundle.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class PimInitInstallerBundle extends Bundle 11 | { 12 | } 13 | -------------------------------------------------------------------------------- /doc/Akeneo/Bundle/InstallerBundle/Resources/config/parameters.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | pim_installer.fixture_loader.job_loader.config_file: 'PimExcelInitBundle/Resources/config/fixtures_jobs.yml' 3 | # you can also use EE fixtures 4 | # pim_installer.fixture_loader.job_loader.config_file: 'PimExcelInitBundle/Resources/config/fixtures_jobs_ee.yml' 5 | installer_data: 'PimInitInstallerBundle:my_dataset' 6 | -------------------------------------------------------------------------------- /doc/Akeneo/Bundle/InstallerBundle/Resources/fixtures/my_dataset/readme.md: -------------------------------------------------------------------------------- 1 | You must copy in this folder the "minimal" or "minimal_EE" fixtures. 2 | You will find this files here : [src/Resources/fixtures](../../../../../../../src/Resources/fixtures) 3 | -------------------------------------------------------------------------------- /doc/Association-type-tab.rst: -------------------------------------------------------------------------------- 1 | Association type tab 2 | ==================== 3 | 4 | See `user guide`_ to know more about association types. 5 | 6 | Association type code 7 | --------------------- 8 | 9 | Specify here a code for your association type. 10 | Association type code must be only composed of letters, numbers and underscores. 11 | No other character will be accepted. 12 | 13 | Example: ``X_SELL``, ``UPSELL``, ``SUBSTITUTION``, ``PACK``. 14 | 15 | Labels 16 | ------ 17 | 18 | These columns allows you to define localized label for your attribute. 19 | You will have to add one column per locale. Be sure they are grouped below the Labels section (line #1). 20 | Note that the 3rd line is hidden and you will have to show it in order to add new locales. 21 | The following example is showing this hidden line. 22 | 23 | **Example:** 24 | 25 | +-------------------------------+---------------------------------------------+ 26 | | Association type properties | Labels | 27 | | +--------------+--------------+---------------+ 28 | | | en_US | es_ES | fr_FR | 29 | +===============================+==============+==============+===============+ 30 | | Association type code | label-en_US | label-es_ES | label-fr_FR | 31 | +-------------------------------+--------------+--------------+---------------+ 32 | | X_SELL | Cross sell | Venta cruzada| Vente croisée | 33 | +-------------------------------+--------------+--------------+---------------+ 34 | 35 | .. _user guide: https://www.akeneo.com/wp-content/uploads/2017/03/EN-Catalog-Setting-User-Guide-PIM-CE-EE-1.7.pdf#page=36 36 | -------------------------------------------------------------------------------- /doc/Attribute-groups.rst: -------------------------------------------------------------------------------- 1 | Attribute groups tab 2 | ==================== 3 | 4 | An attribute group is composed of attributes. Attributes groups are shown on the left menu of the product edit form. 5 | 6 | Group code 7 | ---------- 8 | 9 | Specify here a code for your attribute group. 10 | Attribute group code must be only composed of letters, numbers and underscores. 11 | No other character will be accepted. 12 | 13 | **Examples:** ``measures``, ``sizes`` and ``technical``. 14 | 15 | Position 16 | -------- 17 | 18 | Position is an integer number used to define the order of the attribute group in the left panel of the product edit form. 19 | 20 | Labels 21 | ------ 22 | 23 | These columns allows you to define localized label for your attribute. 24 | You will have to add one column per locale. Be sure they are grouped below the Labels section (line #4). 25 | 26 | **Example:** 27 | 28 | +-----------------------+---------------------------------------------+ 29 | | Group properties | Labels | 30 | | +--------------+-------------+----------------+ 31 | | | label-en_US | label-es_ES | label-fr_FR | 32 | +============+==========+==============+=============+================+ 33 | | Group code | Position | en_US | es_ES | fr_FR | 34 | +------------+----------+--------------+-------------+----------------+ 35 | | measures | 1 | Measures | Medidas | Mesures | 36 | +------------+----------+--------------+-------------+----------------+ 37 | -------------------------------------------------------------------------------- /doc/Attribute-types.rst: -------------------------------------------------------------------------------- 1 | Attribute types tab 2 | =================== 3 | 4 | This tab is only defining human readable shortcuts for attribute types with a code and a label. 5 | 6 | If you are using the `CustomEntityBundle `__ 7 | you will have to add your own attribute type here. 8 | -------------------------------------------------------------------------------- /doc/Attributes.rst: -------------------------------------------------------------------------------- 1 | Attributes tab 2 | ============== 3 | 4 | In this tab you will define every attribute depending wether they belong to one or more families. 5 | You have to define all attributes in this worksheet before defining the families. 6 | 7 | For more details about the keys concept of attribute, see `attribute in the user guide 8 | `__. 9 | 10 | General properties 11 | ------------------ 12 | 13 | Attribute code 14 | ~~~~~~~~~~~~~~ 15 | 16 | Attribute code must be only composed of letters, numbers and underscores. No other character will be accepted. 17 | 18 | Label columns 19 | ~~~~~~~~~~~~~ 20 | 21 | These columns allows you to define localized label for your attribute. 22 | You will have to add one column per locale. Be sure there are grouped below the **Labels** section (line #4) like this: 23 | 24 | +----------------+-----------------------------------------+ 25 | | Attribute code | Labels | 26 | | +-------------+-------------+-------------+ 27 | | | en_US | en_GB | fr_FR | 28 | +================+=============+=============+=============+ 29 | | code | label-en_US | label-en_GB | label-fr_FR | 30 | +----------------+-------------+-------------+-------------+ 31 | | color | Color | Colour | Couleur | 32 | +----------------+-------------+-------------+-------------+ 33 | 34 | **Note** : labels must be under 255 characters. 35 | 36 | Attribute type 37 | ~~~~~~~~~~~~~~ 38 | 39 | Attribute type can be: ``Identifier``, ``Text``, ``Text area``, ``Multiple select``, ``Simple select``, 40 | ``Price collection``, ``Number``, ``Boolean``, ``Date``, ``File``, ``Image`` and ``Metric``. 41 | 42 | These type are definded in the hidden 43 | `attribute type tab `__ 44 | attribute\_type. If you are using the `CustomEntityBundle `__, 45 | this is where you will have to add your new attribute type. 46 | 47 | Attribute group 48 | ~~~~~~~~~~~~~~~ 49 | 50 | Select here the associated attribute group code. 51 | Attributes codes are defined in the 52 | `attribute groups `__ tab. 53 | 54 | Sort order 55 | ~~~~~~~~~~ 56 | 57 | The sort order is an integer defining the display order in the attribute group on the product edit form. 58 | 59 | Is unique 60 | ~~~~~~~~~ 61 | 62 | Choose if the attribute must have unique values. 63 | 64 | Is localizable 65 | ~~~~~~~~~~~~~~ 66 | 67 | Choose if the attribute is localizable or not. 68 | 69 | Specific to locales 70 | ~~~~~~~~~~~~~~~~~~~ 71 | 72 | Define here the list of comma-separated locales. 73 | 74 | Is scopable 75 | ~~~~~~~~~~~ 76 | 77 | Choose if the attribute is scopable or not. 78 | 79 | Minimum input length 80 | ~~~~~~~~~~~~~~~~~~~~ 81 | 82 | Determines how many characters should be typed for select attributes before an option is presented. 83 | This should be used for attributes which have a large number of options 84 | 85 | Useable as grid filter 86 | ~~~~~~~~~~~~~~~~~~~~~~ 87 | 88 | Choose if the attribute is useabe as grid filter or not. 89 | 90 | Properties for text attributes 91 | ------------------------------ 92 | 93 | Max characters 94 | ~~~~~~~~~~~~~~ 95 | 96 | Max characters is an integer defining how many characters maximum can be entered in a text field. 97 | 98 | Validation rule 99 | ~~~~~~~~~~~~~~~ 100 | 101 | Validation rule can be ``email``, ``url`` or ``regexp``. 102 | 103 | Validation regexp 104 | ~~~~~~~~~~~~~~~~~ 105 | 106 | If validation rule is *regexp*, use this column to define the regular expression that will be used for validation. 107 | 108 | Rich text 109 | ~~~~~~~~~ 110 | 111 | Choose if the text field will be using a `TinyMCE WYSIWYG editor `__, 112 | allowing rich text possibilities. 113 | 114 | Properties for number attributes 115 | -------------------------------- 116 | 117 | Minimum number 118 | ~~~~~~~~~~~~~~ 119 | 120 | Specify here the minimum number. 121 | 122 | Maximum number 123 | ~~~~~~~~~~~~~~ 124 | 125 | Specify here the maximum number. 126 | 127 | Decimals allowed 128 | ~~~~~~~~~~~~~~~~ 129 | 130 | Specify here if the numbers can only be integers or not. 131 | 132 | Negative allowed 133 | ~~~~~~~~~~~~~~~~ 134 | 135 | Specify here if negative numbers are allowed. 136 | 137 | Properties for date attributes 138 | ------------------------------ 139 | 140 | Minimum date 141 | ~~~~~~~~~~~~ 142 | 143 | Specify here the minimum date users can input. 144 | 145 | Maximum date 146 | ~~~~~~~~~~~~ 147 | 148 | Specify here the maximum date users can input. 149 | 150 | Properties for metric attributes 151 | -------------------------------- 152 | 153 | Metric family 154 | ~~~~~~~~~~~~~ 155 | 156 | Choose here the metric family. Available options are: ``Area``, ``Binary``, ``Frequency``, ``Length``, 157 | ``Power``, ``Speed``, ``Temperature``, ``Volume``, ``Weight``. 158 | 159 | Metric families are defined in the hidden `metric types `__ 160 | tab. 161 | 162 | Default metric unit 163 | ~~~~~~~~~~~~~~~~~~~ 164 | 165 | Choose here the default metric unit. 166 | 167 | Metric units are defined in the hidden `metric units `__ 168 | tab. 169 | 170 | Properties for file attributes 171 | ------------------------------ 172 | 173 | Max file size 174 | ~~~~~~~~~~~~~ 175 | 176 | Define here the maximum file size in MB. 177 | 178 | Allowed extensions 179 | ~~~~~~~~~~~~~~~~~~ 180 | 181 | Insert the allowed extensions, separated by a comma. 182 | 183 | For example : ``jpg``, ``jpeg``, ``png`` or ``pdf``. 184 | -------------------------------------------------------------------------------- /doc/Categories-tab.rst: -------------------------------------------------------------------------------- 1 | Categories tab 2 | ============== 3 | 4 | Category code 5 | ------------- 6 | 7 | Category code must be only composed of letters, numbers and underscores. No other character will be accepted. 8 | 9 | Parent category code 10 | -------------------- 11 | 12 | Specify here the parent category code. Leave it empty if the category is a root of a category tree. 13 | 14 | Labels colums 15 | ------------- 16 | 17 | These columns allows you to define localized label for your attribute. 18 | You will have to add one column per locale. Be sure there are grouped below the Labels section (line #1). 19 | 20 | **Note:** labels must be under 255 characters. 21 | -------------------------------------------------------------------------------- /doc/Channels-tab.rst: -------------------------------------------------------------------------------- 1 | Channels tab 2 | ============ 3 | 4 | In this tab you can define all the channels you are using. For more details about the key concept of channels, 5 | see `channels in the user guide `__. 6 | 7 | Channel code 8 | ------------ 9 | 10 | Channel code must be only composed of letters, numbers and underscores. No other character will be accepted. 11 | 12 | Channel label 13 | ------------- 14 | 15 | These columns allows you to define the default label for your channel. 16 | 17 | **Note:** labels must be under 255 characters. 18 | 19 | Channel locales 20 | --------------- 21 | 22 | List here the comma-separated locales that compose your channel like this: 23 | 24 | en_US, fr_FR, es_ES 25 | 26 | Channel currencies 27 | ------------------ 28 | 29 | List here the comma-separated locales that compose your currencies like this: 30 | 31 | EUR, USD, GBP 32 | 33 | Category tree 34 | ------------- 35 | 36 | Specify here the top-level category tree. 37 | -------------------------------------------------------------------------------- /doc/Choices-tab.rst: -------------------------------------------------------------------------------- 1 | Choices tab 2 | =========== 3 | 4 | This tab is used to defined choices for validation rules and date choice. It is not meant to be edited. 5 | -------------------------------------------------------------------------------- /doc/Families.rst: -------------------------------------------------------------------------------- 1 | Family tabs 2 | =========== 3 | 4 | Case of families is special because you will have as many family tabs as you have families. 5 | Each of them must be named like ``family family_code``. 6 | 7 | Family code 8 | ----------- 9 | 10 | Family codes must be only composed of letters, numbers and underscores. No other character will be accepted. 11 | 12 | Localized label 13 | --------------- 14 | 15 | You can specify a different label for each locale. 16 | 17 | +-------+--------+-----------+-----------+ 18 | | | en_US | es_ES | fr_FR | 19 | +=======+========+===========+===========+ 20 | | Label | Main | Principal | Principal | 21 | +-------+--------+-----------+-----------+ 22 | 23 | 24 | Attribute code 25 | -------------- 26 | 27 | See `attribute code `__ in the attribute tab. 28 | 29 | Use as label 30 | ------------ 31 | 32 | Indicate (``0``/``1``) whether or not the attribute should be used as a label for the family. 33 | Note that this only concern text attributes. 34 | 35 | Completeness channel\_code 36 | -------------------------- 37 | 38 | Define here if the attribute is part of the completeness calculation for the channel\_code channel. 39 | Channels are defined in the `channel tab `__. 40 | Learn more about completeness in the `user guide `__. 41 | 42 | You will have to add as many Completeness column as you have channels. 43 | -------------------------------------------------------------------------------- /doc/Getting-started.rst: -------------------------------------------------------------------------------- 1 | Getting started 2 | =============== 3 | 4 | Initializing the PIM with a XLSX file 5 | ------------------------------------- 6 | 7 | Create a fixtures directory 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | 10 | You have to create a directory containing all the installer fixtures. 11 | 12 | .. code:: bash 13 | 14 | mkdir /home/akeneo/installer/fixtures/my_company 15 | 16 | Copy the fixtures 17 | ~~~~~~~~~~~~~~~~~ 18 | 19 | All minimal fixtures are located in the **src/Resources/fixtures/minimal** folder inside the **ExcelInitBundle**. 20 | 21 | For an Enterprise edition, the fixtures are located in the **src/Resources/fixtures/minimal_EE** folder. 22 | 23 | All these fixtures can't be set in the init.xslx files. 24 | Be sure to use the very same name/code in both the init.xslx files and the YML files. 25 | 26 | Place them in your fixtures directory. Here is a description of what each files contains: 27 | 28 | .. code:: bash 29 | 30 | # For CE 31 | cp -R /home/akeneo/vendor/akeneo/excel-init-bundle/src/Resources/fixtures/minimal/* /home/akeneo/installer/fixtures/my_company 32 | 33 | # For EE 34 | cp -R /home/akeneo/vendor/akeneo/excel-init-bundle/src/Resources/fixtures/minimal_EE/* /home/akeneo/installer/fixtures/my_company 35 | 36 | CE edition 37 | ^^^^^^^^^^ 38 | 39 | +------------------------+-------------------------------------------------------------------------+ 40 | | File | Description | 41 | +========================+=========================================================================+ 42 | | **init.xslx** | Contains the whole Catalog description, see init.xslx structure below | 43 | +------------------------+-------------------------------------------------------------------------+ 44 | | **locales.csv** | Defines the used locales and their currency | 45 | +------------------------+-------------------------------------------------------------------------+ 46 | 47 | EE edition (incl. CE files) 48 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 49 | 50 | EE edition adds support of ACL, please refer to the minimal fixtures set 51 | located in the InstallerBundle to see the structure and the content of 52 | the files. Note that you cannot define ACL in the init.xslx file and 53 | will have to define them separately. 54 | 55 | +---------------------------------------+-------------------------------------+ 56 | | File | Description | 57 | +=======================================+=====================================+ 58 | | **attribute\_groups\_accesses.csv** | Contains ACL for attribute groups | 59 | +---------------------------------------+-------------------------------------+ 60 | | **product\_category\_accesses.yml** | Contains ACL for product categories | 61 | +---------------------------------------+-------------------------------------+ 62 | | **locale\_accesses.csv** | Contains ACL for locales | 63 | +---------------------------------------+-------------------------------------+ 64 | | **job\_profile\_accesses.csv** | Contains ACL for jobs | 65 | +---------------------------------------+-------------------------------------+ 66 | | **asset\_categories.csv** | Contains assets master category | 67 | +---------------------------------------+-------------------------------------+ 68 | | **asset\_category\_accesses.yml** | Contains ACL for assets categories | 69 | +---------------------------------------+-------------------------------------+ 70 | 71 | Customize init.xslx ! 72 | ~~~~~~~~~~~~~~~~~~~~~ 73 | 74 | Edit the init.xlsx file to match your needs following the instructions inside 75 | the file itself. The file is composed of various tabs that allow you to 76 | set your catalog structure: 77 | 78 | - channels 79 | - categories 80 | - group types 81 | - association types 82 | - attributes 83 | - attribute groups 84 | - attribute options 85 | - families (as many tabs as required) 86 | 87 | See `tab description section `__ 88 | for more details on how to customize the init.xslx file. 89 | 90 | Change PIM parameter to use your custom installation 91 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 92 | 93 | You have to override ``pim_installer.fixture_loader.job_loader.config_file``. 94 | To do so, add the following lines in the ``parameters.yml`` of your custom installer. 95 | 96 | .. code:: yml 97 | 98 | parameters: 99 | pim_installer.fixture_loader.job_loader.config_file: 'PimExcelInitBundle/Resources/config/fixtures_jobs.yml' 100 | 101 | And for Enterprise Edition: 102 | 103 | .. code:: yml 104 | 105 | parameters: 106 | pim_installer.fixture_loader.job_loader.config_file: 'PimExcelInitBundle/Resources/config/fixtures_jobs_ee.yml' 107 | 108 | Define the data used by the installer : 109 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 110 | 111 | Here you will tell the installer to use the fixtures in your own fixtures folder: 112 | 113 | .. code:: yml 114 | 115 | # app/config/parameters.yml 116 | parameters: 117 | ... 118 | installer_data: '/home/akeneo/installer/fixtures/my_company' 119 | 120 | 121 | Alternatively, if you use a custom installer bundle, you can also use the bundle notation to locate the fixtures directory: 122 | 123 | .. code:: yml 124 | 125 | # app/config/parameters.yml 126 | parameters: 127 | ... 128 | installer_data: 'YourCustomeInstallerBundle:minimal' 129 | -------------------------------------------------------------------------------- /doc/Group-types.rst: -------------------------------------------------------------------------------- 1 | Group types 2 | =========== 3 | 4 | See `userguide `__ to know more about groups 5 | and what group types are. 6 | 7 | code 8 | ---- 9 | 10 | Attribute code must be only composed of letters, numbers and underscores. No other character will be accepted. 11 | 12 | variant 13 | ------- 14 | 15 | Indicate wether or not the group type is variant. 16 | 17 | **Note**: the header of this column has been modified and is not compatible with the `init.xlsx` of the ExcelConnectorBundle. 18 | -------------------------------------------------------------------------------- /doc/Home.rst: -------------------------------------------------------------------------------- 1 | What is Akeneo Excel Connector Bundle? 2 | ====================================== 3 | 4 | .. figure:: pictures/bundle_icon.jpg 5 | :alt: Logo ExcelInitConnector 6 | 7 | This bundle adds support of Excel XSLX files as a source for initialization of catalog structure 8 | for `Akeneo PIM `__. 9 | 10 | **Note:** The file init.xslx must be opened and edited with Excel. 11 | This extension is not comatible with Excel 2003 xls files. 12 | Usage of LibreOffice/OpenOffice disables validation of input and can lead to malformed file. 13 | 14 | Getting started 15 | --------------- 16 | 17 | - `Initializing the PIM with a XLSX file `__ 18 | 19 | Define the structure of your catalog 20 | ------------------------------------ 21 | 22 | - `Channels `__ 23 | - `Categories `__ 24 | - `Group types `__ 25 | - `Association types `__ 26 | - `Attributes `__ 27 | - `Attribute groups `__ 28 | - `Attribute options `__ 29 | - `Families `__ 30 | 31 | Define system element (for integrators) 32 | --------------------------------------- 33 | 34 | - `Attribute types `__ 35 | - `Choices `__ 36 | - `Metric types `__ 37 | - `Metric units `__ 38 | -------------------------------------------------------------------------------- /doc/Metric-types.rst: -------------------------------------------------------------------------------- 1 | Metric types tab 2 | ================ 3 | 4 | This tab is defining Metric type list. 5 | 6 | Currently, options are: 7 | 8 | - ``Area`` 9 | - ``Binary`` 10 | - ``Frequency`` 11 | - ``Length`` 12 | - ``Power`` 13 | - ``Speed`` 14 | - ``Temperature`` 15 | - ``Volume`` 16 | - ``Weight`` 17 | - ``Voltage`` 18 | - ``Intensity`` 19 | - ``Resistance`` 20 | -------------------------------------------------------------------------------- /doc/Metric-units.rst: -------------------------------------------------------------------------------- 1 | Metric units tab 2 | ================ 3 | 4 | This tab is defining the link between units and their type, i.e: 5 | ``SQUARE_FOOT`` and ``Area``. 6 | -------------------------------------------------------------------------------- /doc/Options-tab.rst: -------------------------------------------------------------------------------- 1 | Attribute options tab 2 | ===================== 3 | 4 | Attributes options are the possibilities of choices for simple and multi select attributes. 5 | 6 | Attribute code 7 | -------------- 8 | 9 | Specify here the attribute code for which you want to append the option. 10 | 11 | Option code 12 | ----------- 13 | 14 | Specify here a code for your attribute option. 15 | Attribute option codes must be only composed of letters, numbers and underscores. 16 | No other character will be accepted. 17 | 18 | Examples: ``blue``, ``XL``, ``silk``. 19 | 20 | Localizable labels 21 | ------------------ 22 | 23 | These columns allows you to define localized label for your attribute. 24 | You will have to add one column per locale. Be sure they are grouped below the Labels section (line #1). 25 | 26 | The 3rd line is hidden, you will have to show it if you want to add other locales. 27 | The following example assume you are showing this line. 28 | 29 | **Example:** 30 | 31 | 32 | +------------------------------+---------------------------------------------+ 33 | | Options properties | Labels | 34 | | +--------------+--------------+---------------+ 35 | | | en_US | es_ES | fr_FR | 36 | +================+=============+==============+==============+===============+ 37 | | Attribute code | Option code | label-en_US | label-es_ES | label-fr_FR | 38 | +----------------+-------------+--------------+--------------+---------------+ 39 | | color | blue | Blue | Azul | Bleu | 40 | +----------------+-------------+--------------+--------------+---------------+ 41 | | color | red | Red | Rojo | Rouge | 42 | +----------------+-------------+--------------+--------------+---------------+ 43 | -------------------------------------------------------------------------------- /doc/inclusions/label_table_assocition_type.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
Association type propertiesLabels
label-en\_USlabel-es\_ESlabel-fr\_FR
Association type codeen\_USfr\_FRes\_ES
X\_SELLCross sellVente croiséeVenta cruzada
28 | -------------------------------------------------------------------------------- /doc/pictures/akeneo_excel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfAkeneo/ExcelInitBundle/406380fc38d2b1585d635e21eb3d49013e28e7a5/doc/pictures/akeneo_excel.png -------------------------------------------------------------------------------- /doc/pictures/bundle_icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfAkeneo/ExcelInitBundle/406380fc38d2b1585d635e21eb3d49013e28e7a5/doc/pictures/bundle_icon.jpg -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | fpm: 5 | image: akeneo/fpm:php-7.2 6 | environment: 7 | COMPOSER_HOME: /home/docker/.composer 8 | user: docker 9 | volumes: 10 | - ./:/srv/excel-init-bundle 11 | - ~/.composer:/home/docker/.composer 12 | working_dir: /srv/excel-init-bundle 13 | networks: 14 | - akeneo-network 15 | 16 | networks: 17 | akeneo-network: ~ 18 | -------------------------------------------------------------------------------- /spec/Pim/Bundle/ExcelInitBundle/Iterator/ArrayHelperSpec.php: -------------------------------------------------------------------------------- 1 | shouldHaveType('Pim\Bundle\ExcelInitBundle\Iterator\ArrayHelper'); 12 | } 13 | 14 | function it_should_combine_arrays_with_less_keys_than_values() 15 | { 16 | $keys = array('key1', 'key2'); 17 | $values = array('value1', 'value2', 'value3'); 18 | $this->combineArrays($keys, $values)->shouldReturn(array('key1' => 'value1', 'key2' => 'value2')); 19 | } 20 | 21 | function it_should_combine_arrays_with_more_keys_than_values() 22 | { 23 | $keys = array('key1', 'key2', 'key3'); 24 | $values = array('value1', 'value2'); 25 | $this->combineArrays($keys, $values)->shouldReturn(array('key1' => 'value1', 'key2' => 'value2', 'key3' => '')); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /spec/Pim/Bundle/ExcelInitBundle/Iterator/InitAttributesFileIteratorSpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith( 14 | 'xlsx', 15 | $this->getPath() . DIRECTORY_SEPARATOR . 'dummy1.xlsx', 16 | [ 17 | 'header_key' => 'header1', 18 | 'include_worksheets' => ['/^Sheet4$/'], 19 | 'attribute_types_mapper' => $attributeTypesMapper, 20 | ] 21 | ); 22 | } 23 | 24 | public function it_must_have_a_mapper_as_option() 25 | { 26 | $this->beConstructedWith( 27 | 'xlsx', 28 | $this->getPath() . DIRECTORY_SEPARATOR . 'dummy2.xlsx', 29 | [ 30 | 'header_key' => 'header1', 31 | 'include_worksheets' => ['/^Sheet4$/'], 32 | ] 33 | ); 34 | $this->shouldThrow(MissingOptionsException::class)->duringInstantiation(); 35 | } 36 | 37 | public function it_can_get_the_mapper($attributeTypesMapper) 38 | { 39 | $this->getAttributeTypesMapper()->shouldReturn($attributeTypesMapper); 40 | } 41 | 42 | private function getPath() 43 | { 44 | return __DIR__ . DIRECTORY_SEPARATOR . '..' . 45 | DIRECTORY_SEPARATOR . 'fixtures'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /spec/Pim/Bundle/ExcelInitBundle/Iterator/InitFileIteratorSpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith( 12 | 'xlsx', 13 | $this->getPath() . DIRECTORY_SEPARATOR . 'dummy1.xlsx', 14 | [ 15 | 'header_key' => 'header1', 16 | 'include_worksheets' => ['/^Sheet1$/', '/^Sheet2$/'], 17 | ] 18 | ); 19 | $this->rewind(); 20 | $values = [ 21 | ['header1', 'header2', 'header3', 'header4', 'header5',], 22 | ['Value-1-1-1', 'Value-1-1-2', 'Value-1-1-3', 'Value-1-1-4', 'Value-1-1-5',], 23 | ['Value-1-2-1', 'Value-1-2-2', 'Value-1-2-3', 'Value-1-2-4', 'Value-1-2-5',], 24 | ['Value-1-3-1', 'Value-1-3-2', 'Value-1-3-3', 'Value-1-3-4', 'Value-1-3-5',], 25 | ['Value-1-4-1', 'Value-1-4-2', 'Value-1-4-3', 'Value-1-4-4', 'Value-1-4-5',], 26 | ['Value-1-5-1', 'Value-1-5-2', 'Value-1-5-3', 'Value-1-5-4', 'Value-1-5-5',], 27 | ['Value-2-1-1', 'Value-2-1-2', 'Value-2-1-3', 'Value-2-1-4', 'Value-2-1-5',], 28 | ['Value-2-2-1', 'Value-2-2-2', 'Value-2-2-3', 'Value-2-2-4', 'Value-2-2-5',], 29 | ['Value-2-3-1', 'Value-2-3-2', 'Value-2-3-3', 'Value-2-3-4', 'Value-2-3-5',], 30 | ['Value-2-4-1', 'Value-2-4-2', 'Value-2-4-3', 'Value-2-4-4', 'Value-2-4-5',], 31 | ['Value-2-5-1', 'Value-2-5-2', 'Value-2-5-3', 'Value-2-5-4', 'Value-2-5-5',], 32 | ]; 33 | foreach ($values as $row) { 34 | $this->current()->shouldReturn($row); 35 | $this->next(); 36 | } 37 | $this->valid()->shouldReturn(false); 38 | } 39 | 40 | public function it_can_filter_excluded_tabs() 41 | { 42 | $this->beConstructedWith( 43 | 'xlsx', 44 | $this->getPath() . DIRECTORY_SEPARATOR . 'dummy1.xlsx', 45 | [ 46 | 'header_key' => 'header1', 47 | 'exclude_worksheets' => ['/^Sheet[134]$/'], 48 | ] 49 | ); 50 | $this->rewind(); 51 | $values = [ 52 | ['header1', 'header2', 'header3', 'header4', 'header5',], 53 | ['Value-2-1-1', 'Value-2-1-2', 'Value-2-1-3', 'Value-2-1-4', 'Value-2-1-5',], 54 | ['Value-2-2-1', 'Value-2-2-2', 'Value-2-2-3', 'Value-2-2-4', 'Value-2-2-5',], 55 | ['Value-2-3-1', 'Value-2-3-2', 'Value-2-3-3', 'Value-2-3-4', 'Value-2-3-5',], 56 | ['Value-2-4-1', 'Value-2-4-2', 'Value-2-4-3', 'Value-2-4-4', 'Value-2-4-5',], 57 | ['Value-2-5-1', 'Value-2-5-2', 'Value-2-5-3', 'Value-2-5-4', 'Value-2-5-5',], 58 | ]; 59 | foreach ($values as $row) { 60 | $this->current()->shouldReturn($row); 61 | $this->next(); 62 | } 63 | $this->valid()->shouldReturn(false); 64 | } 65 | 66 | public function it_can_filter_included_and_excluded_tabs() 67 | { 68 | $this->beConstructedWith( 69 | 'xlsx', 70 | $this->getPath() . DIRECTORY_SEPARATOR . 'dummy1.xlsx', 71 | [ 72 | 'header_key' => 'header1', 73 | 'include_worksheets' => ['/^Sheet1$/', '/^Sheet2$/'], 74 | 'exclude_worksheets' => ['/^Sheet1$/'], 75 | ] 76 | ); 77 | $this->rewind(); 78 | $values = [ 79 | ['header1', 'header2', 'header3', 'header4', 'header5',], 80 | ['Value-2-1-1', 'Value-2-1-2', 'Value-2-1-3', 'Value-2-1-4', 'Value-2-1-5',], 81 | ['Value-2-2-1', 'Value-2-2-2', 'Value-2-2-3', 'Value-2-2-4', 'Value-2-2-5',], 82 | ['Value-2-3-1', 'Value-2-3-2', 'Value-2-3-3', 'Value-2-3-4', 'Value-2-3-5',], 83 | ['Value-2-4-1', 'Value-2-4-2', 'Value-2-4-3', 'Value-2-4-4', 'Value-2-4-5',], 84 | ['Value-2-5-1', 'Value-2-5-2', 'Value-2-5-3', 'Value-2-5-4', 'Value-2-5-5',], 85 | ]; 86 | foreach ($values as $row) { 87 | $this->current()->shouldReturn($row); 88 | $this->next(); 89 | } 90 | $this->valid()->shouldReturn(false); 91 | } 92 | 93 | public function it_can_use_a_different_valdata_range() 94 | { 95 | $this->beConstructedWith( 96 | 'xlsx', 97 | $this->getPath() . DIRECTORY_SEPARATOR . 'dummy1.xlsx', 98 | [ 99 | 'header_key' => 'header1', 100 | 'include_worksheets' => ['/^Sheet3$/'], 101 | ] 102 | ); 103 | $this->rewind(); 104 | $values = [ 105 | ['header1', 'header2', 'header3', 'header4', 'header5',], 106 | ['Value-3-1-1', 'Value-3-1-2', 'Value-3-1-3', 'Value-3-1-4', 'Value-3-1-5',], 107 | ['Value-3-2-1', 'Value-3-2-2', 'Value-3-2-3', 'Value-3-2-4', 'Value-3-2-5',], 108 | ['Value-3-3-1', 'Value-3-3-2', 'Value-3-3-3', 'Value-3-3-4', 'Value-3-3-5',], 109 | ['Value-3-4-1', 'Value-3-4-2', 'Value-3-4-3', 'Value-3-4-4', 'Value-3-4-5',], 110 | ['Value-3-5-1', 'Value-3-5-2', 'Value-3-5-3', 'Value-3-5-4', 'Value-3-5-5',], 111 | ]; 112 | foreach ($values as $row) { 113 | $this->current()->shouldReturn($row); 114 | $this->next(); 115 | } 116 | $this->valid()->shouldReturn(false); 117 | } 118 | 119 | 120 | private function getPath() 121 | { 122 | return __DIR__ . DIRECTORY_SEPARATOR . '..' . 123 | DIRECTORY_SEPARATOR . 'fixtures'; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /spec/Pim/Bundle/ExcelInitBundle/Mapper/AttributeTypeMapperSpec.php: -------------------------------------------------------------------------------- 1 | shouldImplement('Pim\Bundle\ExcelInitBundle\Mapper\AttributeTypeMapperInterface'); 12 | } 13 | 14 | function it_should_get_mapped_attribute_types() 15 | { 16 | $this->addAttributeTypeMapping('label1', 'type1'); 17 | $this->addAttributeTypeMapping('label2', 'type2'); 18 | 19 | $this->getMappedValue('label1')->shouldReturn('type1'); 20 | $this->getMappedValue('label2')->shouldReturn('type2'); 21 | } 22 | 23 | function it_should_return_null_for_non_mapped_attribute_types() 24 | { 25 | $this->addAttributeTypeMapping('label1', 'type1'); 26 | $this->addAttributeTypeMapping('label2', 'type2'); 27 | 28 | $this->getMappedValue('label3')->shouldReturn(null); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /spec/Pim/Bundle/ExcelInitBundle/fixtures/dummy1.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfAkeneo/ExcelInitBundle/406380fc38d2b1585d635e21eb3d49013e28e7a5/spec/Pim/Bundle/ExcelInitBundle/fixtures/dummy1.xlsx -------------------------------------------------------------------------------- /spec/Pim/Bundle/ExcelInitBundle/fixtures/dummy2.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfAkeneo/ExcelInitBundle/406380fc38d2b1585d635e21eb3d49013e28e7a5/spec/Pim/Bundle/ExcelInitBundle/fixtures/dummy2.xlsx -------------------------------------------------------------------------------- /src/ArrayConverter/Flat/Attribute.php: -------------------------------------------------------------------------------- 1 | 12 | * @copyright 2016 Akeneo SAS (http://www.akeneo.com) 13 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) 14 | */ 15 | class Attribute extends PimAttributeConverter 16 | { 17 | /** @var AttributeTypeMapperInterface */ 18 | protected $attributeTypesMapper; 19 | 20 | public function convert(array $item, array $options = []) 21 | { 22 | $this->attributeTypesMapper = $options['attribute_types_mapper']; 23 | return parent::convert($item, $options); 24 | } 25 | 26 | protected function convertFields($field, $booleanFields, $data, $convertedItem) 27 | { 28 | if (empty($field) || 'use_as_label' === $field) { 29 | return $convertedItem; 30 | } 31 | if (0 !== $data && empty($data)) { 32 | return $convertedItem; 33 | } 34 | 35 | if ('type' === $field) { 36 | $pimType = $this->attributeTypesMapper->getMappedValue($data); 37 | if (null !== $pimType) { 38 | $convertedItem['type'] = $pimType; 39 | } 40 | } else { 41 | $convertedItem = parent::convertFields($field, $booleanFields, $data, $convertedItem); 42 | } 43 | 44 | return $convertedItem; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/DependencyInjection/PimExcelInitExtension.php: -------------------------------------------------------------------------------- 1 | setParameter('pim_excel_installer.root_dir', sprintf('%s/..', __DIR__)); 23 | 24 | $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 25 | $loader->load('iterators.yml'); 26 | $loader->load('jobs.yml'); 27 | $loader->load('steps.yml'); 28 | $loader->load('readers.yml'); 29 | $loader->load('mappers.yml'); 30 | $loader->load('array_converters.yml'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Iterator/ArrayHelper.php: -------------------------------------------------------------------------------- 1 | 9 | * @copyright 2013 Akeneo SAS (http://www.akeneo.com) 10 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) 11 | */ 12 | class ArrayHelper 13 | { 14 | /** 15 | * Combines array of different sizes 16 | * 17 | * @param array $keys 18 | * @param array $values 19 | * 20 | * @return array 21 | */ 22 | public function combineArrays(array $keys, array $values) 23 | { 24 | return array_combine($keys, $this->resizeArray($values, count($keys))); 25 | } 26 | 27 | /** 28 | * Resizes an array to the specified data count 29 | * 30 | * @param array $data 31 | * @param int $count 32 | * 33 | * @return array 34 | */ 35 | protected function resizeArray(array $data, $count) 36 | { 37 | if (count($data) < $count) { 38 | $data = array_merge($data, array_fill(0, $count - count($data), '')); 39 | } 40 | 41 | return array_slice($data, 0, $count); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Iterator/InitAttributesFileIterator.php: -------------------------------------------------------------------------------- 1 | 12 | * @author Antoine Guigan 13 | * @copyright 2013 Akeneo SAS (http://www.akeneo.com) 14 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) 15 | */ 16 | class InitAttributesFileIterator extends InitFileIterator 17 | { 18 | /** @var AttributeTypeMapperInterface */ 19 | protected $attributeTypesMapper; 20 | 21 | public function __construct($type, $filePath, array $options) 22 | { 23 | parent::__construct($type, $filePath, $options); 24 | $this->attributeTypesMapper = $options['attribute_types_mapper']; 25 | } 26 | 27 | /** 28 | * @return AttributeTypeMapperInterface 29 | */ 30 | public function getAttributeTypesMapper() 31 | { 32 | return $this->attributeTypesMapper; 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function rewind() 39 | { 40 | $this->initializeAttributeTypes(); 41 | parent::rewind(); 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | protected function configureOptions(OptionsResolver $resolver) 48 | { 49 | parent::configureOptions($resolver); 50 | $resolver->setDefaults( 51 | [ 52 | 'skip_empty' => true, 53 | ] 54 | ); 55 | $resolver->setRequired([ 56 | 'attribute_types_mapper', 57 | ]); 58 | } 59 | 60 | /** 61 | * Returns the Excel Helper service 62 | * 63 | * @throws \RuntimeException 64 | */ 65 | protected function initializeAttributeTypes() 66 | { 67 | $spout = $this->reader; 68 | $spout->getSheetIterator()->rewind(); 69 | 70 | $attributeTypesWorksheet = null; 71 | 72 | foreach ($spout->getSheetIterator() as $worksheet) { 73 | if ('attribute_types' === $worksheet->getName()) { 74 | $attributeTypesWorksheet = $worksheet; 75 | break; 76 | } 77 | } 78 | 79 | if (null === $attributeTypesWorksheet) { 80 | throw new \RuntimeException('No attribute_types worksheet in the excel file'); 81 | } 82 | 83 | foreach ($attributeTypesWorksheet->getRowIterator() as $key => $row) { 84 | if ($key >= 2) { 85 | $this->attributeTypesMapper->addAttributeTypeMapping($row[1], $row[0]); 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Iterator/InitFamilyFileIterator.php: -------------------------------------------------------------------------------- 1 | 11 | * @author Antoine Guigan 12 | * @copyright 2013 Akeneo SAS (http://www.akeneo.com) 13 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) 14 | */ 15 | class InitFamilyFileIterator extends InitFileIterator 16 | { 17 | /** 18 | * {@inheritdoc} 19 | */ 20 | protected function createValuesIterator() 21 | { 22 | $familyData = $this->getChannelData(); 23 | $this->headers = array_keys($familyData); 24 | if (!$this->nextWorksheet) { 25 | $this->rows = new \ArrayIterator(['dummy_header_line', $familyData]); 26 | } else { 27 | $this->rows = new \ArrayIterator([$familyData]); 28 | } 29 | $this->rows->rewind(); 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | protected function getChannelData() 36 | { 37 | $this->rows = $this->reader->getSheetIterator()->current()->getRowIterator(); 38 | $this->rows->rewind(); 39 | 40 | $data = ['attributes' => []]; 41 | $channelLabels = []; 42 | $labelLocales = []; 43 | $codeColumn = null; 44 | $useAsLabelColumn = null; 45 | $firstChannelColumn = null; 46 | 47 | $arrayHelper = new ArrayHelper(); 48 | 49 | $rowIterator = $this->rows; 50 | 51 | foreach ($rowIterator as $index => $row) { 52 | $row = $this->trimRight($row); 53 | if ($index == $this->options['family_labels_locales_row']) { 54 | $labelLocales = array_slice($row, $this->options['family_labels_first_column']); 55 | } 56 | if ($index == $this->options['family_data_row']) { 57 | $data['code'] = $row[$this->options['family_code_column']]; 58 | $data['labels'] = $arrayHelper->combineArrays( 59 | $labelLocales, 60 | array_slice($row, $this->options['family_labels_first_column']) 61 | ); 62 | } 63 | 64 | if ($index == $this->options['channel_label_row']) { 65 | $channelLabels = $row; 66 | $firstChannelColumn = 2; 67 | array_splice($channelLabels, 0, $firstChannelColumn); 68 | $data['attribute_requirements'] = array_fill_keys($channelLabels, []); 69 | } 70 | 71 | $codeColumn = 0; 72 | $useAsLabelColumn = 1; 73 | 74 | if ($index >= (int) $this->options['attribute_data_row']) { 75 | // empty row after trim 76 | if (count($row) === 0) { 77 | continue; 78 | } 79 | $code = $row[$codeColumn]; 80 | if ($code === '') { 81 | continue; 82 | } 83 | $data['attributes'][] = $code; 84 | if (isset($row[$useAsLabelColumn]) && ('1' === trim($row[$useAsLabelColumn]))) { 85 | $data['attribute_as_label'] = $code; 86 | } 87 | $channelValues = array_slice($row, $firstChannelColumn); 88 | foreach ($channelLabels as $channelIndex => $channel) { 89 | if (isset($channelValues[$channelIndex]) && '1' === trim($channelValues[$channelIndex])) { 90 | $data['attribute_requirements'][$channel][] = $code; 91 | } 92 | } 93 | } 94 | } 95 | 96 | return $data; 97 | } 98 | 99 | /** 100 | * {@inheritdoc} 101 | */ 102 | protected function configureOptions(OptionsResolver $resolver) 103 | { 104 | parent::configureOptions($resolver); 105 | 106 | $resolver->remove([ 107 | 'header_key', 108 | ]); 109 | 110 | $resolver->setRequired([ 111 | 'family_data_row', 112 | 'family_code_column', 113 | 'family_labels_locales_row', 114 | 'family_labels_first_column', 115 | 'channel_label_row', 116 | 'attribute_data_row', 117 | ]); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Iterator/InitFileIterator.php: -------------------------------------------------------------------------------- 1 | 14 | * @author Antoine Guigan 15 | * @copyright 2013 Akeneo SAS (http://www.akeneo.com) 16 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) 17 | */ 18 | class InitFileIterator extends FlatFileIterator 19 | { 20 | /** @var SheetIterator */ 21 | protected $worksheetIterator; 22 | 23 | /** @var array */ 24 | protected $options; 25 | 26 | /** @var bool */ 27 | protected $nextWorksheet = false; 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function __construct($type, $filePath, array $options = []) 33 | { 34 | parent::__construct($type, $filePath, $options); 35 | $resolver = new OptionsResolver(); 36 | $this->configureOptions($resolver); 37 | $this->options = $resolver->resolve($options); 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | */ 43 | public function current() 44 | { 45 | $data = $this->rows->current(); 46 | if (!$this->valid() || null === $data || empty($data)) { 47 | $this->rewind(); 48 | 49 | return null; 50 | } 51 | 52 | $data = $this->trimRight($data); 53 | if (count($data) ===0) { 54 | return null; 55 | } 56 | 57 | if (count($data) == 0) { 58 | $data = null; 59 | } 60 | 61 | return $data; 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function key() 68 | { 69 | $worksheetName = $this->worksheetIterator->current()->getName(); 70 | 71 | return sprintf('%s/%s', $worksheetName, $this->rows->key()); 72 | } 73 | 74 | /** 75 | * @inheritdoc 76 | */ 77 | public function valid() 78 | { 79 | return $this->worksheetIterator->valid() && $this->rows && $this->rows->valid(); 80 | } 81 | 82 | /** 83 | * {@inheritdoc} 84 | */ 85 | public function next() 86 | { 87 | $this->rows->next(); 88 | if (!$this->rows->valid()) { 89 | $this->worksheetIterator->next(); 90 | $this->nextWorksheet = true; 91 | if ($this->worksheetIterator->valid()) { 92 | $this->initializeValuesIterator(); 93 | } 94 | } 95 | } 96 | 97 | /** 98 | * {@inheritdoc} 99 | */ 100 | public function rewind() 101 | { 102 | $this->worksheetIterator = new \CallbackFilterIterator( 103 | $this->reader->getSheetIterator(), 104 | function (Sheet $currentSheet) { 105 | return $this->isReadableWorksheet($currentSheet->getName()); 106 | } 107 | ); 108 | $this->worksheetIterator->rewind(); 109 | if ($this->worksheetIterator->valid()) { 110 | $this->initializeValuesIterator(); 111 | } 112 | } 113 | 114 | protected function trimRight($data) 115 | { 116 | $lastElement = end($data); 117 | while (false !== $lastElement && empty($lastElement)) { 118 | if ($lastElement === 0 || $lastElement === '0') { 119 | break; 120 | } 121 | array_pop($data); 122 | $lastElement = end($data); 123 | } 124 | 125 | return $data; 126 | } 127 | 128 | /** 129 | * Initializes the current worksheet 130 | */ 131 | protected function initializeValuesIterator() 132 | { 133 | $this->createValuesIterator(); 134 | 135 | if (!$this->rows->valid() || !$this->isReadableWorksheet($this->reader->getSheetIterator()->current()->getName())) { 136 | $this->worksheetIterator->next(); 137 | if ($this->worksheetIterator->valid()) { 138 | $this->initializeValuesIterator(); 139 | } 140 | } 141 | } 142 | 143 | /** 144 | * Returns true if the worksheet should be read 145 | * 146 | * @param string $title 147 | * 148 | * @return boolean 149 | */ 150 | protected function isReadableWorksheet($title) 151 | { 152 | return $this->isIncludedWorksheet($title) && !$this->isExcludedWorksheet($title); 153 | } 154 | 155 | /** 156 | * Returns true if the worksheet should be indluded 157 | * 158 | * @param string $title The title of the worksheet 159 | * 160 | * @return boolean 161 | */ 162 | protected function isIncludedWorksheet($title) 163 | { 164 | if (!isset($this->options['include_worksheets'])) { 165 | return true; 166 | } 167 | 168 | foreach ($this->options['include_worksheets'] as $regexp) { 169 | if (preg_match($regexp, $title)) { 170 | return true; 171 | } 172 | } 173 | 174 | return false; 175 | } 176 | 177 | /** 178 | * Returns true if the worksheet should be excluded 179 | * 180 | * @param string $title The title of the worksheet 181 | * 182 | * @return boolean 183 | */ 184 | protected function isExcludedWorksheet($title) 185 | { 186 | if (!isset($this->options['exclude_worksheets'])) { 187 | return false; 188 | } 189 | 190 | foreach ($this->options['exclude_worksheets'] as $regexp) { 191 | if (preg_match($regexp, $title)) { 192 | return true; 193 | } 194 | } 195 | 196 | return false; 197 | } 198 | 199 | /** 200 | * Create the values iterator according to the 'header_key' option 201 | * Set the headers 202 | * Leave reader cursor on the headers, like in the PIM 203 | */ 204 | protected function createValuesIterator() 205 | { 206 | $sheet = $this->worksheetIterator->current(); 207 | $this->rows = $sheet->getRowIterator(); 208 | $this->rows->rewind(); 209 | while ($this->rows->valid() && ($this->options['header_key'] !== trim($this->rows->current()[0]))) { 210 | $this->rows->next(); 211 | } 212 | $this->headers = $this->trimRight($this->rows->current()); 213 | if ($this->nextWorksheet) { 214 | $this->rows->next(); 215 | } 216 | $this->nextWorksheet = false; 217 | } 218 | 219 | /** 220 | * {@inheritdoc} 221 | */ 222 | protected function configureOptions(OptionsResolver $resolver) 223 | { 224 | $resolver->setDefaults([ 225 | 'skip_empty' => false, 226 | ]); 227 | 228 | $resolver->setRequired([ 229 | 'header_key', 230 | ]); 231 | 232 | $resolver->setDefined([ 233 | 'include_worksheets', 234 | 'exclude_worksheets', 235 | ]); 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /src/Mapper/AttributeTypeMapper.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2016 Akeneo SAS (http://www.akeneo.com) 11 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) 12 | */ 13 | class AttributeTypeMapper implements AttributeTypeMapperInterface 14 | { 15 | /** @var string[] */ 16 | protected $attributeTypes = []; 17 | 18 | /** 19 | * {@inheritdoc} 20 | */ 21 | public function addAttributeTypeMapping($key, $value) 22 | { 23 | $this->attributeTypes[$key] = $value; 24 | } 25 | 26 | /** 27 | * {@inheritdoc} 28 | */ 29 | public function getMappedValue($key) 30 | { 31 | if (array_key_exists($key, $this->attributeTypes)) { 32 | return $this->attributeTypes[$key]; 33 | } 34 | 35 | return null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Mapper/AttributeTypeMapperInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @author Antoine Guigan 11 | * @copyright 2013 Akeneo SAS (http://www.akeneo.com) 12 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) 13 | */ 14 | interface AttributeTypeMapperInterface 15 | { 16 | /** 17 | * @param string $key 18 | * @param string $value 19 | */ 20 | public function addAttributeTypeMapping($key, $value); 21 | 22 | /** 23 | * @param $key 24 | * 25 | * @return null|string 26 | */ 27 | public function getMappedValue($key); 28 | } 29 | -------------------------------------------------------------------------------- /src/PimExcelInitBundle.php: -------------------------------------------------------------------------------- 1 | $this->fileIterator->getAttributeTypesMapper() 17 | ]; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Resources/config/array_converters.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | pim_excel_installer.array_converter.flat_to_standard.attribute.class: Pim\Bundle\ExcelInitBundle\ArrayConverter\Flat\Attribute 3 | 4 | services: 5 | pim_excel_installer.array_converter.flat_to_standard.attribute: 6 | class: '%pim_excel_installer.array_converter.flat_to_standard.attribute.class%' 7 | parent: 'pim_connector.array_converter.flat_to_standard.attribute' 8 | 9 | pim_excel_installer.array_converter.flat_to_standard.family: 10 | class: '%pim_connector.array_converter.dummy.class%' 11 | arguments: 12 | - '@pim_connector.array_convertor.checker.fields_requirement' 13 | - ['code'] 14 | - ['code'] 15 | -------------------------------------------------------------------------------- /src/Resources/config/fixtures_jobs.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | fixtures_locale_csv: 3 | order: 10 4 | connector: Data fixtures 5 | alias: fixtures_locale_csv 6 | label: Locales data fixtures 7 | type: fixtures 8 | configuration: 9 | filePath: locales.csv 10 | 11 | fixtures_job_yml: 12 | order: 20 13 | connector: Data fixtures 14 | alias: fixtures_job_yml 15 | label: Jobs data fixtures 16 | type: fixtures 17 | configuration: 18 | filePath: jobs.yml 19 | 20 | fixtures_xlsx_init_import: 21 | order: 30 22 | connector: Akeneo Excel Initialization 23 | alias: excel_init_fixtures 24 | label: Excel initialisation 25 | type: fixtures 26 | configuration: 27 | filePath: init.xlsx 28 | -------------------------------------------------------------------------------- /src/Resources/config/fixtures_jobs_ee.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | fixtures_locale_csv: 3 | order: 10 4 | connector: Data fixtures 5 | alias: fixtures_locale_csv 6 | label: Locales data fixtures 7 | type: fixtures 8 | configuration: 9 | filePath: locales.csv 10 | 11 | fixtures_job_yml: 12 | order: 20 13 | connector: Data fixtures 14 | alias: fixtures_job_yml 15 | label: Jobs data fixtures 16 | type: fixtures 17 | configuration: 18 | filePath: jobs.yml 19 | 20 | fixtures_xlsx_init_import: 21 | order: 25 22 | connector: Akeneo Excel Initialization 23 | alias: excel_init_fixtures 24 | label: Excel initialisation 25 | type: fixtures 26 | configuration: 27 | filePath: init.xlsx 28 | -------------------------------------------------------------------------------- /src/Resources/config/iterators.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | pim_excel_installer.iterator.file.xlsx.attribute.class: Pim\Bundle\ExcelInitBundle\Iterator\AttributeXlsxFileIterator 3 | pim_excel_installer.iterator.file.xlsx.family.class: Pim\Bundle\ExcelInitBundle\Iterator\InitFamilyFileIterator 4 | pim_excel_installer.iterator.array_helper.class: Pim\Bundle\ExcelInitBundle\Iterator\ArrayHelper 5 | 6 | services: 7 | pim_excel_installer.iterator.array_helper: 8 | class: %pim_excel_installer.iterator.array_helper.class% 9 | -------------------------------------------------------------------------------- /src/Resources/config/jobs.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | pim_excel_installer.job_name.init_xlsx_fixtures: 'excel_init_fixtures' 3 | pim_excel_installer.job_name.init_xlsx_import: 'xlsx_init_import' 4 | pim_excel_installer.connector_name: 'Akeneo Excel Initialization' 5 | pim_installer.fixture_loader.job_loader.config_file: 'PimExcelInitBundle/Resources/config/fixtures_jobs.yml' 6 | 7 | services: 8 | pim_excel_installer.job.excel_init_fixture: 9 | class: '%pim_connector.job.simple_job.class%' 10 | arguments: 11 | - '%pim_excel_installer.job_name.init_xlsx_fixtures%' 12 | - '@event_dispatcher' 13 | - '@akeneo_batch.job_repository' 14 | - 15 | - '@pim_excel_installer.step.init.currencies' 16 | - '@pim_excel_installer.step.init.user_groups' 17 | - '@pim_excel_installer.step.init.user_roles' 18 | - '@pim_excel_installer.step.init.categories' 19 | - '@pim_excel_installer.step.init.channels' 20 | - '@pim_excel_installer.step.init.users' 21 | - '@pim_excel_installer.step.init.attribute_groups' 22 | - '@pim_excel_installer.step.init.group_types' 23 | - '@pim_excel_installer.step.init.association_types' 24 | - '@pim_excel_installer.step.init.attributes' 25 | - '@pim_excel_installer.step.init.attribute_options' 26 | - '@pim_excel_installer.step.init.families' 27 | tags: 28 | - 29 | name: akeneo_batch.job 30 | connector: '%pim_excel_installer.connector_name%' 31 | type: '%pim_installer.job.fixture_type%' 32 | 33 | pim_excel_installer.job.xlsx_init_import: 34 | class: '%pim_connector.job.simple_job.class%' 35 | arguments: 36 | - '%pim_excel_installer.job_name.init_xlsx_import%' 37 | - '@event_dispatcher' 38 | - '@akeneo_batch.job_repository' 39 | - 40 | - '@pim_excel_installer.step.init.user_groups' 41 | - '@pim_excel_installer.step.init.user_roles' 42 | - '@pim_excel_installer.step.init.categories' 43 | - '@pim_excel_installer.step.init.users' 44 | - '@pim_excel_installer.step.init.attribute_groups' 45 | - '@pim_excel_installer.step.init.group_types' 46 | - '@pim_excel_installer.step.init.association_types' 47 | - '@pim_excel_installer.step.init.attributes' 48 | - '@pim_excel_installer.step.init.attribute_options' 49 | - '@pim_excel_installer.step.init.families' 50 | tags: 51 | - 52 | name: akeneo_batch.job 53 | connector: '%pim_excel_installer.connector_name%' 54 | type: '%pim_connector.job.import_type%' 55 | 56 | pim_excel_installer.job.job_parameters.default_values_provider.simple_xlsx_import: 57 | class: '%pim_connector.job.job_parameters.default_values_provider.simple_xlsx_import.class%' 58 | arguments: 59 | - 60 | - '%pim_excel_installer.job_name.init_xlsx_fixtures%' 61 | - '%pim_excel_installer.job_name.init_xlsx_import%' 62 | tags: 63 | - { name: akeneo_batch.job.job_parameters.default_values_provider } 64 | 65 | pim_excel_installer.job.job_parameters.constraint_collection_provider.simple_xlsx_import: 66 | class: '%pim_connector.job.job_parameters.constraint_collection_provider.simple_xlsx_import.class%' 67 | arguments: 68 | - 69 | - '%pim_excel_installer.job_name.init_xlsx_fixtures%' 70 | - '%pim_excel_installer.job_name.init_xlsx_import%' 71 | tags: 72 | - { name: akeneo_batch.job.job_parameters.constraint_collection_provider } 73 | 74 | pim_excel_installer.job.job_parameters.form.job_instance: 75 | class: 'Akeneo\Platform\Bundle\ImportExportBundle\Provider\Form\JobInstanceFormProvider' 76 | arguments: 77 | - 78 | xlsx_init_import: pim-job-instance-xlsx-base-import 79 | tags: 80 | - { name: pim_enrich.provider.form, priority: 100 } 81 | -------------------------------------------------------------------------------- /src/Resources/config/mappers.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | pim_excel_installer.mapper.attribute_types.class: Pim\Bundle\ExcelInitBundle\Mapper\AttributeTypeMapper 3 | 4 | services: 5 | pim_excel_installer.mapper.attribute_types: 6 | class: '%pim_excel_installer.mapper.attribute_types.class%' 7 | -------------------------------------------------------------------------------- /src/Resources/config/readers.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | pim_excel_installer.reader.file.attribute.class: Pim\Bundle\ExcelInitBundle\Reader\AttributeXlsxReader 3 | pim_excel_installer.reader.file.file_iterator.class: Pim\Bundle\ExcelInitBundle\Iterator\InitFileIterator 4 | pim_excel_installer.reader.file.attributes_iterator.class: Pim\Bundle\ExcelInitBundle\Iterator\InitAttributesFileIterator 5 | pim_excel_installer.reader.file.families_iterator.class: Pim\Bundle\ExcelInitBundle\Iterator\InitFamilyFileIterator 6 | 7 | services: 8 | pim_excel_installer.reader.file.xlsx_iterator_factory: 9 | class: '%pim_connector.reader.file.file_iterator_factory.class%' 10 | arguments: 11 | - '%pim_excel_installer.reader.file.file_iterator.class%' 12 | - 'xlsx' 13 | 14 | pim_excel_installer.reader.file.xlsx_attribute_iterator_factory: 15 | class: '%pim_connector.reader.file.file_iterator_factory.class%' 16 | arguments: 17 | - '%pim_excel_installer.reader.file.attributes_iterator.class%' 18 | - 'xlsx' 19 | 20 | pim_excel_installer.reader.file.xlsx_family_iterator_factory: 21 | class: '%pim_connector.reader.file.file_iterator_factory.class%' 22 | arguments: 23 | - '%pim_excel_installer.reader.file.families_iterator.class%' 24 | - 'xlsx' 25 | 26 | pim_excel_installer.reader.xls_init.attribute_group: 27 | class: '%pim_connector.reader.file.xlsx.class%' 28 | arguments: 29 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 30 | - '@pim_connector.array_converter.flat_to_standard.attribute_group' 31 | - header_key: code 32 | include_worksheets: [ '/^attribute_groups$/' ] 33 | 34 | pim_excel_installer.reader.xls_init.currencies: 35 | class: '%pim_connector.reader.file.xlsx.class%' 36 | arguments: 37 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 38 | - '@pim_connector.array_converter.flat_to_standard.currency' 39 | - header_key: code 40 | include_worksheets: [ '/^currencies$/' ] 41 | 42 | pim_excel_installer.reader.xls_init.channel: 43 | class: '%pim_connector.reader.file.xlsx.class%' 44 | arguments: 45 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 46 | - '@pim_connector.array_converter.flat_to_standard.channel' 47 | - header_key: code 48 | include_worksheets: [ '/^channels/' ] 49 | 50 | pim_excel_installer.reader.xls_init.user_groups: 51 | class: '%pim_connector.reader.file.xlsx.class%' 52 | arguments: 53 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 54 | - '@pim_connector.array_converter.flat_to_standard.user_group' 55 | - header_key: code 56 | include_worksheets: [ '/^user_groups$/' ] 57 | 58 | pim_excel_installer.reader.xls_init.user_roles: 59 | class: '%pim_connector.reader.file.xlsx.class%' 60 | arguments: 61 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 62 | - '@pim_connector.array_converter.flat_to_standard.user_role' 63 | - header_key: role 64 | include_worksheets: [ '/^user_roles$/' ] 65 | 66 | pim_excel_installer.reader.xls_init.users: 67 | class: '%pim_connector.reader.file.xlsx.class%' 68 | arguments: 69 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 70 | - '@pim_connector.array_converter.flat_to_standard.user' 71 | - header_key: username 72 | include_worksheets: [ '/^users$/' ] 73 | 74 | pim_excel_installer.reader.xls_init.category: 75 | class: '%pim_connector.reader.file.xlsx.class%' 76 | arguments: 77 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 78 | - '@pim_connector.array_converter.flat_to_standard.category' 79 | - header_key: code 80 | include_worksheets: [ '/^categories/' ] 81 | 82 | pim_excel_installer.reader.xls_init.option: 83 | class: '%pim_connector.reader.file.xlsx.class%' 84 | arguments: 85 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 86 | - '@pim_connector.array_converter.flat_to_standard.attribute_option' 87 | - header_key: code 88 | include_worksheets: [ '/^options/' ] 89 | 90 | pim_excel_installer.reader.xls_init.group_type: 91 | class: '%pim_connector.reader.file.xlsx.class%' 92 | arguments: 93 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 94 | - '@pim_connector.array_converter.flat_to_standard.group_type' 95 | - header_key: code 96 | include_worksheets: [ '/^group_types$/' ] 97 | 98 | pim_excel_installer.reader.xls_init.association_type: 99 | class: '%pim_connector.reader.file.xlsx.class%' 100 | arguments: 101 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 102 | - '@pim_connector.array_converter.flat_to_standard.association_type' 103 | - header_key: code 104 | include_worksheets: [ '/^association_types$/' ] 105 | 106 | pim_excel_installer.reader.xls_init.attribute: 107 | class: '%pim_excel_installer.reader.file.attribute.class%' 108 | arguments: 109 | - '@pim_excel_installer.reader.file.xlsx_attribute_iterator_factory' 110 | - '@pim_excel_installer.array_converter.flat_to_standard.attribute' 111 | - header_key: code 112 | include_worksheets: [ '/^attributes/' ] 113 | attribute_types_mapper: '@pim_excel_installer.mapper.attribute_types' 114 | 115 | pim_excel_installer.reader.xls_init.attribute_option: 116 | class: '%pim_connector.reader.file.xlsx.class%' 117 | arguments: 118 | - '@pim_excel_installer.reader.file.xlsx_iterator_factory' 119 | - '@pim_connector.array_converter.flat_to_standard.attribute_option' 120 | - header_key: 'attribute' 121 | include_worksheets: [ '/^options/' ] 122 | 123 | pim_excel_installer.reader.xls_init.family: 124 | class: '%pim_connector.reader.file.xlsx.class%' 125 | arguments: 126 | - '@pim_excel_installer.reader.file.xlsx_family_iterator_factory' 127 | - '@pim_excel_installer.array_converter.flat_to_standard.family' 128 | - family_data_row: 2 129 | family_code_column: 1 130 | family_labels_locales_row: 1 131 | family_labels_first_column: 3 132 | channel_label_row: 4 133 | attribute_data_row: 6 134 | include_worksheets: [ '/^family/' ] 135 | 136 | -------------------------------------------------------------------------------- /src/Resources/config/steps.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | 3 | services: 4 | pim_excel_installer.step.init.currencies: 5 | class: '%pim_connector.step.item_step.class%' 6 | arguments: 7 | - 'import_channels' 8 | - '@event_dispatcher' 9 | - '@akeneo_batch.job_repository' 10 | - '@pim_excel_installer.reader.xls_init.currencies' 11 | - '@pim_connector.processor.denormalization.currency' 12 | - '@pim_connector.writer.database.currency' 13 | 14 | pim_excel_installer.step.init.categories: 15 | class: '%pim_connector.step.item_step.class%' 16 | arguments: 17 | - 'import_categories' 18 | - '@event_dispatcher' 19 | - '@akeneo_batch.job_repository' 20 | - '@pim_excel_installer.reader.xls_init.category' 21 | - '@pim_connector.processor.denormalization.category' 22 | - '@pim_connector.writer.database.category' 23 | - 1 24 | 25 | pim_excel_installer.step.init.channels: 26 | class: '%pim_connector.step.item_step.class%' 27 | arguments: 28 | - 'import_channels' 29 | - '@event_dispatcher' 30 | - '@akeneo_batch.job_repository' 31 | - '@pim_excel_installer.reader.xls_init.channel' 32 | - '@pim_connector.processor.denormalization.channel' 33 | - '@pim_connector.writer.database.channel' 34 | 35 | pim_excel_installer.step.init.user_groups: 36 | class: '%pim_connector.step.item_step.class%' 37 | arguments: 38 | - 'import_user_groups' 39 | - '@event_dispatcher' 40 | - '@akeneo_batch.job_repository' 41 | - '@pim_excel_installer.reader.xls_init.user_groups' 42 | - '@pim_connector.processor.denormalization.user_group' 43 | - '@pim_connector.writer.database.user_group' 44 | 45 | pim_excel_installer.step.init.user_roles: 46 | class: '%pim_connector.step.item_step.class%' 47 | arguments: 48 | - 'import_user_roles' 49 | - '@event_dispatcher' 50 | - '@akeneo_batch.job_repository' 51 | - '@pim_excel_installer.reader.xls_init.user_roles' 52 | - '@pim_connector.processor.denormalization.user_role' 53 | - '@pim_connector.writer.database.user_role' 54 | 55 | pim_excel_installer.step.init.users: 56 | class: '%pim_connector.step.item_step.class%' 57 | arguments: 58 | - 'import_users' 59 | - '@event_dispatcher' 60 | - '@akeneo_batch.job_repository' 61 | - '@pim_excel_installer.reader.xls_init.users' 62 | - '@pim_connector.processor.denormalization.user' 63 | - '@pim_connector.writer.database.user' 64 | 65 | pim_excel_installer.step.init.attribute_groups: 66 | class: '%pim_connector.step.item_step.class%' 67 | arguments: 68 | - 'import_attribute_groups' 69 | - '@event_dispatcher' 70 | - '@akeneo_batch.job_repository' 71 | - '@pim_excel_installer.reader.xls_init.attribute_group' 72 | - '@pim_connector.processor.denormalization.attribute_group' 73 | - '@pim_connector.writer.database.attribute_group' 74 | 75 | pim_excel_installer.step.init.group_types: 76 | class: '%pim_connector.step.item_step.class%' 77 | arguments: 78 | - 'import_group_types' 79 | - '@event_dispatcher' 80 | - '@akeneo_batch.job_repository' 81 | - '@pim_excel_installer.reader.xls_init.group_type' 82 | - '@pim_connector.processor.denormalization.group_type' 83 | - '@pim_connector.writer.database.group_type' 84 | 85 | pim_excel_installer.step.init.association_types: 86 | class: '%pim_connector.step.item_step.class%' 87 | arguments: 88 | - 'import_association_type' 89 | - '@event_dispatcher' 90 | - '@akeneo_batch.job_repository' 91 | - '@pim_excel_installer.reader.xls_init.association_type' 92 | - '@pim_connector.processor.denormalization.association_type' 93 | - '@pim_connector.writer.database.association_type' 94 | 95 | pim_excel_installer.step.init.attributes: 96 | class: '%pim_connector.step.item_step.class%' 97 | arguments: 98 | - 'import_attributes' 99 | - '@event_dispatcher' 100 | - '@akeneo_batch.job_repository' 101 | - '@pim_excel_installer.reader.xls_init.attribute' 102 | - '@pim_connector.processor.denormalization.attribute' 103 | - '@pim_connector.writer.database.attribute' 104 | - 1 105 | 106 | pim_excel_installer.step.init.attribute_options: 107 | class: '%pim_connector.step.item_step.class%' 108 | arguments: 109 | - 'import_attribute_options' 110 | - '@event_dispatcher' 111 | - '@akeneo_batch.job_repository' 112 | - '@pim_excel_installer.reader.xls_init.attribute_option' 113 | - '@pim_connector.processor.denormalization.attribute_option' 114 | - '@pim_connector.writer.database.attribute_option' 115 | 116 | pim_excel_installer.step.init.families: 117 | class: '%pim_connector.step.item_step.class%' 118 | arguments: 119 | - 'import_families' 120 | - '@event_dispatcher' 121 | - '@akeneo_batch.job_repository' 122 | - '@pim_excel_installer.reader.xls_init.family' 123 | - '@pim_connector.processor.denormalization.family' 124 | - '@pim_connector.writer.database.family' 125 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal/init.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfAkeneo/ExcelInitBundle/406380fc38d2b1585d635e21eb3d49013e28e7a5/src/Resources/fixtures/minimal/init.xlsx -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal/jobs.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | update_product_value: 3 | connector: Akeneo Mass Edit Connector 4 | alias: update_product_value 5 | label: Mass update products 6 | type: mass_edit 7 | add_product_value: 8 | connector: Akeneo Mass Edit Connector 9 | alias: add_product_value 10 | label: Mass add products values 11 | type: mass_edit 12 | remove_product_value: 13 | connector: Akeneo Mass Edit Connector 14 | alias: remove_product_value 15 | label: Mass remove products values 16 | type: mass_edit 17 | edit_common_attributes: 18 | connector: Akeneo Mass Edit Connector 19 | alias: edit_common_attributes 20 | label: Mass edit common product attributes 21 | type: mass_edit 22 | set_attribute_requirements: 23 | connector: Akeneo Mass Edit Connector 24 | alias: set_attribute_requirements 25 | label: Set family attribute requirements 26 | type: mass_edit 27 | csv_product_quick_export: 28 | connector: Akeneo CSV Connector 29 | alias: csv_product_quick_export 30 | label: CSV product quick export 31 | type: quick_export 32 | configuration: 33 | delimiter: ; 34 | enclosure: '"' 35 | withHeader: true 36 | filePathProduct: /tmp/1_products_export_%locale%_%scope%_%datetime%.csv 37 | filePathProductModel: /tmp/2_product_models_export_%locale%_%scope%_%datetime%.csv 38 | with_media: true 39 | csv_product_grid_context_quick_export: 40 | connector: Akeneo CSV Connector 41 | alias: csv_product_grid_context_quick_export 42 | label: CSV product quick export grid context 43 | type: quick_export 44 | configuration: 45 | delimiter: ; 46 | enclosure: '"' 47 | withHeader: true 48 | filePathProduct: /tmp/1_products_export_grid_context_%locale%_%scope%_%datetime%.csv 49 | filePathProductModel: /tmp/2_product_models_export_grid_context_%locale%_%scope%_%datetime%.csv 50 | with_media: true 51 | xlsx_product_quick_export: 52 | connector: Akeneo XLSX Connector 53 | alias: xlsx_product_quick_export 54 | label: XLSX product quick export 55 | type: quick_export 56 | configuration: 57 | withHeader: true 58 | linesPerFile: 10000 59 | filePathProduct: /tmp/1_products_export_%locale%_%scope%_%datetime%.xlsx 60 | filePathProductModel: /tmp/2_product_models_export_%locale%_%scope%_%datetime%.xlsx 61 | with_media: true 62 | xlsx_product_grid_context_quick_export: 63 | connector: Akeneo XLSX Connector 64 | alias: xlsx_product_grid_context_quick_export 65 | label: XLSX product quick export grid context 66 | type: quick_export 67 | configuration: 68 | withHeader: true 69 | filePathProduct: /tmp/1_products_export_grid_context_%locale%_%scope%_%datetime%.xlsx 70 | filePathProductModel: /tmp/2_product_models_export_grid_context_%locale%_%scope%_%datetime%.xlsx 71 | linesPerFile: 10000 72 | with_media: true 73 | compute_product_models_descendants: 74 | connector: internal 75 | alias: compute_product_models_descendants 76 | label: Compute product models descendants 77 | type: compute_product_models_descendants 78 | compute_completeness_of_products_family: 79 | connector: internal 80 | alias: compute_completeness_of_products_family 81 | label: compute completeness of products family 82 | type: compute_completeness_of_products_family 83 | compute_family_variant_structure_changes: 84 | connector: internal 85 | alias: compute_family_variant_structure_changes 86 | label: Compute variant structure changes 87 | type: compute_family_variant_structure_changes 88 | 89 | xlsx_init_import: 90 | connector: Akeneo Excel Initialization 91 | alias: xlsx_init_import 92 | label: Excel initialization 93 | type: import 94 | configuration: 95 | filePath: /tmp/init.xlsx 96 | uploadAllowed: true 97 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal/locales.csv: -------------------------------------------------------------------------------- 1 | code 2 | af_ZA 3 | am_ET 4 | ar_AE 5 | ar_BH 6 | ar_DZ 7 | ar_EG 8 | ar_IQ 9 | ar_JO 10 | ar_KW 11 | ar_LB 12 | ar_LY 13 | ar_MA 14 | arn_CL 15 | ar_OM 16 | ar_QA 17 | ar_SA 18 | ar_SY 19 | ar_TN 20 | ar_YE 21 | as_IN 22 | az_Cyrl_AZ 23 | az_Latn_AZ 24 | ba_RU 25 | be_BY 26 | bg_BG 27 | bn_BD 28 | bn_IN 29 | bo_CN 30 | br_FR 31 | bs_Cyrl_BA 32 | bs_Latn_BA 33 | ca_ES 34 | co_FR 35 | cs_CZ 36 | cy_GB 37 | da_DK 38 | de_AT 39 | de_CH 40 | de_DE 41 | de_LI 42 | de_LU 43 | dsb_DE 44 | dv_MV 45 | el_GR 46 | en_029 47 | en_AU 48 | en_BZ 49 | en_CA 50 | en_GB 51 | en_IE 52 | en_IN 53 | en_JM 54 | en_MY 55 | en_NZ 56 | en_PH 57 | en_SG 58 | en_TT 59 | en_US 60 | en_ZA 61 | en_ZW 62 | es_AR 63 | es_BO 64 | es_CL 65 | es_CO 66 | es_CR 67 | es_DO 68 | es_EC 69 | es_ES 70 | es_GT 71 | es_HN 72 | es_MX 73 | es_NI 74 | es_PA 75 | es_PE 76 | es_PR 77 | es_PY 78 | es_SV 79 | es_US 80 | es_UY 81 | es_VE 82 | et_EE 83 | eu_ES 84 | fa_IR 85 | fi_FI 86 | fil_PH 87 | fo_FO 88 | fr_BE 89 | fr_CA 90 | fr_CH 91 | fr_FR 92 | fr_LU 93 | fr_MC 94 | fy_NL 95 | ga_IE 96 | gd_GB 97 | gl_ES 98 | gsw_FR 99 | gu_IN 100 | ha_Latn_NG 101 | he_IL 102 | hi_IN 103 | hr_BA 104 | hr_HR 105 | hsb_DE 106 | hu_HU 107 | hy_AM 108 | id_ID 109 | ig_NG 110 | ii_CN 111 | is_IS 112 | it_CH 113 | it_IT 114 | iu_Cans_CA 115 | iu_Latn_CA 116 | ja_JP 117 | ka_GE 118 | kk_KZ 119 | kl_GL 120 | km_KH 121 | kn_IN 122 | kok_IN 123 | ko_KR 124 | ky_KG 125 | lb_LU 126 | lo_LA 127 | lt_LT 128 | lv_LV 129 | mi_NZ 130 | mk_MK 131 | ml_IN 132 | mn_MN 133 | mn_Mong_CN 134 | moh_CA 135 | mr_IN 136 | ms_BN 137 | ms_MY 138 | mt_MT 139 | nb_NO 140 | ne_NP 141 | nl_BE 142 | nl_NL 143 | nn_NO 144 | nso_ZA 145 | oc_FR 146 | or_IN 147 | pa_IN 148 | pl_PL 149 | prs_AF 150 | ps_AF 151 | pt_BR 152 | pt_PT 153 | qut_GT 154 | quz_BO 155 | quz_EC 156 | quz_PE 157 | rm_CH 158 | ro_RO 159 | ru_RU 160 | rw_RW 161 | sah_RU 162 | sa_IN 163 | se_FI 164 | se_NO 165 | se_SE 166 | si_LK 167 | sk_SK 168 | sl_SI 169 | sma_NO 170 | sma_SE 171 | smj_NO 172 | smj_SE 173 | smn_FI 174 | sms_FI 175 | sq_AL 176 | sr_Cyrl_BA 177 | sr_Cyrl_CS 178 | sr_Cyrl_ME 179 | sr_Cyrl_RS 180 | sr_Latn_BA 181 | sr_Latn_CS 182 | sr_Latn_ME 183 | sr_Latn_RS 184 | sv_FI 185 | sv_SE 186 | sw_KE 187 | syr_SY 188 | ta_IN 189 | te_IN 190 | tg_Cyrl_TJ 191 | th_TH 192 | tk_TM 193 | tn_ZA 194 | tr_TR 195 | tt_RU 196 | tzm_Latn_DZ 197 | ug_CN 198 | uk_UA 199 | ur_PK 200 | uz_Cyrl_UZ 201 | uz_Latn_UZ 202 | vi_VN 203 | wo_SN 204 | xh_ZA 205 | yo_NG 206 | zh_CN 207 | zh_HK 208 | zh_MO 209 | zh_SG 210 | zh_TW 211 | zu_ZA 212 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/asset_categories.csv: -------------------------------------------------------------------------------- 1 | code;parent;label-en_US 2 | asset_main_catalog;;Asset main catalog 3 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/asset_category_accesses.csv: -------------------------------------------------------------------------------- 1 | category;view_items;edit_items 2 | asset_main_catalog;IT support,Manager,Redactor;IT support,Manager,Redactor 3 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/asset_channel_configurations.yml: -------------------------------------------------------------------------------- 1 | asset_channel_configurations: ~ -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/assets.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfAkeneo/ExcelInitBundle/406380fc38d2b1585d635e21eb3d49013e28e7a5/src/Resources/fixtures/minimal_EE/assets.csv -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/attribute_group_accesses.csv: -------------------------------------------------------------------------------- 1 | attribute_group;view_attributes;edit_attributes 2 | other;IT support,Manager,Redactor;IT support,Manager,Redactor 3 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/init.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfAkeneo/ExcelInitBundle/406380fc38d2b1585d635e21eb3d49013e28e7a5/src/Resources/fixtures/minimal_EE/init.xlsx -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/job_profile_accesses.csv: -------------------------------------------------------------------------------- 1 | job_profile;execute_job_profile 2 | update_product_value;All 3 | add_product_value;All 4 | remove_product_value;All 5 | publish_product;All 6 | unpublish_product;All 7 | edit_common_attributes;All 8 | set_attribute_requirements;All 9 | approve_product_draft;All 10 | refuse_product_draft;All 11 | apply_assets_mass_upload;All 12 | csv_product_quick_export;All 13 | csv_product_grid_context_quick_export;All 14 | csv_published_product_quick_export;All 15 | csv_published_product_grid_context_quick_export;All 16 | xlsx_product_quick_export;All 17 | xlsx_product_grid_context_quick_export;All 18 | xlsx_published_product_quick_export;All 19 | xlsx_published_product_grid_context_quick_export;All 20 | rule_impacted_product_count;All 21 | classify_assets;All 22 | add_tags_to_assets;All 23 | project_calculation;All 24 | refresh_project_completeness_calculation;All 25 | compute_product_models_descendants;All 26 | compute_completeness_of_products_family;All 27 | compute_family_variant_structure_changes;All 28 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/jobs.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | add_product_value: 3 | connector: Akeneo Mass Edit Connector 4 | alias: add_product_value 5 | label: Mass add products values 6 | type: mass_edit 7 | update_product_value: 8 | connector: Akeneo Mass Edit Connector 9 | alias: update_product_value 10 | label: Mass update products 11 | type: mass_edit 12 | remove_product_value: 13 | connector: Akeneo Mass Edit Connector 14 | alias: remove_product_value 15 | label: Mass remove products values 16 | type: mass_edit 17 | publish_product: 18 | connector: Akeneo Mass Edit Connector 19 | alias: publish_product 20 | label: Mass publish products 21 | type: mass_edit 22 | unpublish_product: 23 | connector: Akeneo Mass Edit Connector 24 | alias: unpublish_product 25 | label: Mass unpublish products 26 | type: mass_edit 27 | edit_common_attributes: 28 | connector: Akeneo Mass Edit Connector 29 | alias: edit_common_attributes 30 | label: Mass edit common product attributes 31 | type: mass_edit 32 | set_attribute_requirements: 33 | connector: Akeneo Mass Edit Connector 34 | alias: set_attribute_requirements 35 | label: Set family attribute requirements 36 | type: mass_edit 37 | csv_product_quick_export: 38 | connector: Akeneo CSV Connector 39 | alias: csv_product_quick_export 40 | label: CSV product quick export 41 | type: quick_export 42 | configuration: 43 | delimiter: ; 44 | enclosure: '"' 45 | withHeader: true 46 | with_media: true 47 | filePathProduct: /tmp/1_products_export_%locale%_%scope%_%datetime%.csv 48 | filePathProductModel: /tmp/2_product_models_export_%locale%_%scope%_%datetime%.csv 49 | csv_product_grid_context_quick_export: 50 | connector: Akeneo CSV Connector 51 | alias: csv_product_grid_context_quick_export 52 | label: CSV product quick export grid context 53 | type: quick_export 54 | configuration: 55 | delimiter: ; 56 | enclosure: '"' 57 | withHeader: true 58 | with_media: true 59 | filePathProduct: /tmp/1_products_export_grid_context_%locale%_%scope%_%datetime%.csv 60 | filePathProductModel: /tmp/2_product_models_export_grid_context_%locale%_%scope%_%datetime%.csv 61 | csv_published_product_quick_export: 62 | connector: Akeneo CSV Connector 63 | alias: csv_published_product_quick_export 64 | label: CSV published product quick export 65 | type: quick_export 66 | configuration: 67 | delimiter: ; 68 | enclosure: '"' 69 | withHeader: true 70 | with_media: true 71 | filePath: /tmp/published_products_export_%locale%_%scope%_%datetime%.csv 72 | csv_published_product_grid_context_quick_export: 73 | connector: Akeneo Mass Edit Connector 74 | alias: csv_published_product_grid_context_quick_export 75 | label: CSV published product quick export grid context 76 | type: quick_export 77 | configuration: 78 | delimiter: ; 79 | enclosure: '"' 80 | withHeader: true 81 | with_media: true 82 | filePath: /tmp/published_products_export_grid_context_%locale%_%scope%_%datetime%.csv 83 | approve_product_draft: 84 | connector: Akeneo Mass Edit Connector 85 | alias: approve_product_draft 86 | label: Mass approve product drafts 87 | type: mass_edit 88 | refuse_product_draft: 89 | connector: Akeneo Mass Edit Connector 90 | alias: refuse_product_draft 91 | label: Mass reject product drafts 92 | type: mass_edit 93 | apply_assets_mass_upload: 94 | connector: Akeneo Product Asset Connector 95 | alias: apply_assets_mass_upload 96 | label: Process mass uploaded assets 97 | type: mass_upload 98 | xlsx_product_quick_export: 99 | connector: Akeneo XLSX Connector 100 | alias: xlsx_product_quick_export 101 | label: XLSX product quick export 102 | type: quick_export 103 | configuration: 104 | withHeader: true 105 | linesPerFile: 10000 106 | with_media: true 107 | filePathProduct: /tmp/1_products_export_%locale%_%scope%_%datetime%.xlsx 108 | filePathProductModel: /tmp/2_product_models_export_%locale%_%scope%_%datetime%.xlsx 109 | xlsx_product_grid_context_quick_export: 110 | connector: Akeneo XLSX Connector 111 | alias: xlsx_product_grid_context_quick_export 112 | label: XLSX product quick export grid context 113 | type: quick_export 114 | configuration: 115 | withHeader: true 116 | linesPerFile: 10000 117 | with_media: true 118 | filePathProduct: /tmp/1_products_export_grid_context_%locale%_%scope%_%datetime%.xlsx 119 | filePathProductModel: /tmp/2_product_models_export_grid_context_%locale%_%scope%_%datetime%.xlsx 120 | xlsx_published_product_grid_context_quick_export: 121 | connector: Akeneo Mass Edit Connector 122 | alias: xlsx_published_product_grid_context_quick_export 123 | label: XLSX published product quick export grid context 124 | type: quick_export 125 | configuration: 126 | withHeader: true 127 | linesPerFile: 10000 128 | with_media: true 129 | filePath: /tmp/published_products_export_grid_context_%locale%_%scope%_%datetime%.xlsx 130 | xlsx_published_product_quick_export: 131 | connector: Akeneo XLSX Connector 132 | alias: xlsx_published_product_quick_export 133 | label: XLSX published product quick export 134 | type: quick_export 135 | configuration: 136 | withHeader: true 137 | linesPerFile: 10000 138 | with_media: true 139 | filePath: /tmp/published_products_export_%locale%_%scope%_%datetime%.xlsx 140 | rule_impacted_product_count: 141 | connector: Akeneo Rule Engine Connector 142 | alias: rule_impacted_product_count 143 | label: Calculation the affected products for the rules 144 | type: mass_edit_rule 145 | classify_assets: 146 | connector: Akeneo Product Asset Connector 147 | alias: classify_assets 148 | label: Mass classify product assets 149 | type: mass_edit 150 | add_tags_to_assets: 151 | connector: Akeneo Product Asset Connector 152 | alias: add_tags_to_assets 153 | label: Add tags to assets 154 | type: mass_edit 155 | project_calculation: 156 | connector: teamwork assistant 157 | alias: project_calculation 158 | label: Project calculation 159 | type: project_calculation 160 | refresh_project_completeness_calculation: 161 | connector: teamwork assistant 162 | alias: refresh_project_completeness_calculation 163 | label: Refresh project completeness 164 | type: refresh_project_completeness_calculation 165 | compute_product_models_descendants: 166 | connector: internal 167 | alias: compute_product_models_descendants 168 | label: Compute product models descendants 169 | type: compute_product_models_descendants 170 | compute_completeness_of_products_family: 171 | connector: internal 172 | alias: compute_completeness_of_products_family 173 | label: compute completeness of products family 174 | type: compute_completeness_of_products_family 175 | compute_family_variant_structure_changes: 176 | connector: internal 177 | alias: compute_family_variant_structure_changes 178 | label: Compute family variant structure changes 179 | type: compute_family_variant_structure_changes 180 | xlsx_init_import: 181 | connector: Akeneo Excel Initialization 182 | alias: xlsx_init_import 183 | label: Excel initialization 184 | type: import 185 | configuration: 186 | filePath: /tmp/init.xlsx 187 | uploadAllowed: true 188 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/locale_accesses.csv: -------------------------------------------------------------------------------- 1 | locale;view_products;edit_products 2 | af_ZA;All;All 3 | am_ET;All;All 4 | ar_AE;All;All 5 | ar_BH;All;All 6 | ar_DZ;All;All 7 | ar_EG;All;All 8 | ar_IQ;All;All 9 | ar_JO;All;All 10 | ar_KW;All;All 11 | ar_LB;All;All 12 | ar_LY;All;All 13 | ar_MA;All;All 14 | arn_CL;All;All 15 | ar_OM;All;All 16 | ar_QA;All;All 17 | ar_SA;All;All 18 | ar_SY;All;All 19 | ar_TN;All;All 20 | ar_YE;All;All 21 | as_IN;All;All 22 | az_Cyrl_AZ;All;All 23 | az_Latn_AZ;All;All 24 | ba_RU;All;All 25 | be_BY;All;All 26 | bg_BG;All;All 27 | bn_BD;All;All 28 | bn_IN;All;All 29 | bo_CN;All;All 30 | br_FR;All;All 31 | bs_Cyrl_BA;All;All 32 | bs_Latn_BA;All;All 33 | ca_ES;All;All 34 | co_FR;All;All 35 | cs_CZ;All;All 36 | cy_GB;All;All 37 | da_DK;All;All 38 | de_AT;All;All 39 | de_CH;All;All 40 | de_DE;All;All 41 | de_LI;All;All 42 | de_LU;All;All 43 | dsb_DE;All;All 44 | dv_MV;All;All 45 | el_GR;All;All 46 | en_029;All;All 47 | en_AU;All;All 48 | en_BZ;All;All 49 | en_CA;All;All 50 | en_GB;All;All 51 | en_IE;All;All 52 | en_IN;All;All 53 | en_JM;All;All 54 | en_MY;All;All 55 | en_NZ;All;All 56 | en_PH;All;All 57 | en_SG;All;All 58 | en_TT;All;All 59 | en_US;All;All 60 | en_ZA;All;All 61 | en_ZW;All;All 62 | es_AR;All;All 63 | es_BO;All;All 64 | es_CL;All;All 65 | es_CO;All;All 66 | es_CR;All;All 67 | es_DO;All;All 68 | es_EC;All;All 69 | es_ES;All;All 70 | es_GT;All;All 71 | es_HN;All;All 72 | es_MX;All;All 73 | es_NI;All;All 74 | es_PA;All;All 75 | es_PE;All;All 76 | es_PR;All;All 77 | es_PY;All;All 78 | es_SV;All;All 79 | es_US;All;All 80 | es_UY;All;All 81 | es_VE;All;All 82 | et_EE;All;All 83 | eu_ES;All;All 84 | fa_IR;All;All 85 | fi_FI;All;All 86 | fil_PH;All;All 87 | fo_FO;All;All 88 | fr_BE;All;All 89 | fr_CA;All;All 90 | fr_CH;All;All 91 | fr_FR;All;All 92 | fr_LU;All;All 93 | fr_MC;All;All 94 | fy_NL;All;All 95 | ga_IE;All;All 96 | gd_GB;All;All 97 | gl_ES;All;All 98 | gsw_FR;All;All 99 | gu_IN;All;All 100 | ha_Latn_NG;All;All 101 | he_IL;All;All 102 | hi_IN;All;All 103 | hr_BA;All;All 104 | hr_HR;All;All 105 | hsb_DE;All;All 106 | hu_HU;All;All 107 | hy_AM;All;All 108 | id_ID;All;All 109 | ig_NG;All;All 110 | ii_CN;All;All 111 | is_IS;All;All 112 | it_CH;All;All 113 | it_IT;All;All 114 | iu_Cans_CA;All;All 115 | iu_Latn_CA;All;All 116 | ja_JP;All;All 117 | ka_GE;All;All 118 | kk_KZ;All;All 119 | kl_GL;All;All 120 | km_KH;All;All 121 | kn_IN;All;All 122 | kok_IN;All;All 123 | ko_KR;All;All 124 | ky_KG;All;All 125 | lb_LU;All;All 126 | lo_LA;All;All 127 | lt_LT;All;All 128 | lv_LV;All;All 129 | mi_NZ;All;All 130 | mk_MK;All;All 131 | ml_IN;All;All 132 | mn_MN;All;All 133 | mn_Mong_CN;All;All 134 | moh_CA;All;All 135 | mr_IN;All;All 136 | ms_BN;All;All 137 | ms_MY;All;All 138 | mt_MT;All;All 139 | nb_NO;All;All 140 | ne_NP;All;All 141 | nl_BE;All;All 142 | nl_NL;All;All 143 | nn_NO;All;All 144 | nso_ZA;All;All 145 | oc_FR;All;All 146 | or_IN;All;All 147 | pa_IN;All;All 148 | pl_PL;All;All 149 | prs_AF;All;All 150 | ps_AF;All;All 151 | pt_BR;All;All 152 | pt_PT;All;All 153 | qut_GT;All;All 154 | quz_BO;All;All 155 | quz_EC;All;All 156 | quz_PE;All;All 157 | rm_CH;All;All 158 | ro_RO;All;All 159 | ru_RU;All;All 160 | rw_RW;All;All 161 | sah_RU;All;All 162 | sa_IN;All;All 163 | se_FI;All;All 164 | se_NO;All;All 165 | se_SE;All;All 166 | si_LK;All;All 167 | sk_SK;All;All 168 | sl_SI;All;All 169 | sma_NO;All;All 170 | sma_SE;All;All 171 | smj_NO;All;All 172 | smj_SE;All;All 173 | smn_FI;All;All 174 | sms_FI;All;All 175 | sq_AL;All;All 176 | sr_Cyrl_BA;All;All 177 | sr_Cyrl_CS;All;All 178 | sr_Cyrl_ME;All;All 179 | sr_Cyrl_RS;All;All 180 | sr_Latn_BA;All;All 181 | sr_Latn_CS;All;All 182 | sr_Latn_ME;All;All 183 | sr_Latn_RS;All;All 184 | sv_FI;All;All 185 | sv_SE;All;All 186 | sw_KE;All;All 187 | syr_SY;All;All 188 | ta_IN;All;All 189 | te_IN;All;All 190 | tg_Cyrl_TJ;All;All 191 | th_TH;All;All 192 | tk_TM;All;All 193 | tn_ZA;All;All 194 | tr_TR;All;All 195 | tt_RU;All;All 196 | tzm_Latn_DZ;All;All 197 | ug_CN;All;All 198 | uk_UA;All;All 199 | ur_PK;All;All 200 | uz_Cyrl_UZ;All;All 201 | uz_Latn_UZ;All;All 202 | vi_VN;All;All 203 | wo_SN;All;All 204 | xh_ZA;All;All 205 | yo_NG;All;All 206 | zh_CN;All;All 207 | zh_HK;All;All 208 | zh_MO;All;All 209 | zh_SG;All;All 210 | zh_TW;All;All 211 | zu_ZA;All;All 212 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/locales.csv: -------------------------------------------------------------------------------- 1 | code 2 | af_ZA 3 | am_ET 4 | ar_AE 5 | ar_BH 6 | ar_DZ 7 | ar_EG 8 | ar_IQ 9 | ar_JO 10 | ar_KW 11 | ar_LB 12 | ar_LY 13 | ar_MA 14 | arn_CL 15 | ar_OM 16 | ar_QA 17 | ar_SA 18 | ar_SY 19 | ar_TN 20 | ar_YE 21 | as_IN 22 | az_Cyrl_AZ 23 | az_Latn_AZ 24 | ba_RU 25 | be_BY 26 | bg_BG 27 | bn_BD 28 | bn_IN 29 | bo_CN 30 | br_FR 31 | bs_Cyrl_BA 32 | bs_Latn_BA 33 | ca_ES 34 | co_FR 35 | cs_CZ 36 | cy_GB 37 | da_DK 38 | de_AT 39 | de_CH 40 | de_DE 41 | de_LI 42 | de_LU 43 | dsb_DE 44 | dv_MV 45 | el_GR 46 | en_029 47 | en_AU 48 | en_BZ 49 | en_CA 50 | en_GB 51 | en_IE 52 | en_IN 53 | en_JM 54 | en_MY 55 | en_NZ 56 | en_PH 57 | en_SG 58 | en_TT 59 | en_US 60 | en_ZA 61 | en_ZW 62 | es_AR 63 | es_BO 64 | es_CL 65 | es_CO 66 | es_CR 67 | es_DO 68 | es_EC 69 | es_ES 70 | es_GT 71 | es_HN 72 | es_MX 73 | es_NI 74 | es_PA 75 | es_PE 76 | es_PR 77 | es_PY 78 | es_SV 79 | es_US 80 | es_UY 81 | es_VE 82 | et_EE 83 | eu_ES 84 | fa_IR 85 | fi_FI 86 | fil_PH 87 | fo_FO 88 | fr_BE 89 | fr_CA 90 | fr_CH 91 | fr_FR 92 | fr_LU 93 | fr_MC 94 | fy_NL 95 | ga_IE 96 | gd_GB 97 | gl_ES 98 | gsw_FR 99 | gu_IN 100 | ha_Latn_NG 101 | he_IL 102 | hi_IN 103 | hr_BA 104 | hr_HR 105 | hsb_DE 106 | hu_HU 107 | hy_AM 108 | id_ID 109 | ig_NG 110 | ii_CN 111 | is_IS 112 | it_CH 113 | it_IT 114 | iu_Cans_CA 115 | iu_Latn_CA 116 | ja_JP 117 | ka_GE 118 | kk_KZ 119 | kl_GL 120 | km_KH 121 | kn_IN 122 | kok_IN 123 | ko_KR 124 | ky_KG 125 | lb_LU 126 | lo_LA 127 | lt_LT 128 | lv_LV 129 | mi_NZ 130 | mk_MK 131 | ml_IN 132 | mn_MN 133 | mn_Mong_CN 134 | moh_CA 135 | mr_IN 136 | ms_BN 137 | ms_MY 138 | mt_MT 139 | nb_NO 140 | ne_NP 141 | nl_BE 142 | nl_NL 143 | nn_NO 144 | nso_ZA 145 | oc_FR 146 | or_IN 147 | pa_IN 148 | pl_PL 149 | prs_AF 150 | ps_AF 151 | pt_BR 152 | pt_PT 153 | qut_GT 154 | quz_BO 155 | quz_EC 156 | quz_PE 157 | rm_CH 158 | ro_RO 159 | ru_RU 160 | rw_RW 161 | sah_RU 162 | sa_IN 163 | se_FI 164 | se_NO 165 | se_SE 166 | si_LK 167 | sk_SK 168 | sl_SI 169 | sma_NO 170 | sma_SE 171 | smj_NO 172 | smj_SE 173 | smn_FI 174 | sms_FI 175 | sq_AL 176 | sr_Cyrl_BA 177 | sr_Cyrl_CS 178 | sr_Cyrl_ME 179 | sr_Cyrl_RS 180 | sr_Latn_BA 181 | sr_Latn_CS 182 | sr_Latn_ME 183 | sr_Latn_RS 184 | sv_FI 185 | sv_SE 186 | sw_KE 187 | syr_SY 188 | ta_IN 189 | te_IN 190 | tg_Cyrl_TJ 191 | th_TH 192 | tk_TM 193 | tn_ZA 194 | tr_TR 195 | tt_RU 196 | tzm_Latn_DZ 197 | ug_CN 198 | uk_UA 199 | ur_PK 200 | uz_Cyrl_UZ 201 | uz_Latn_UZ 202 | vi_VN 203 | wo_SN 204 | xh_ZA 205 | yo_NG 206 | zh_CN 207 | zh_HK 208 | zh_MO 209 | zh_SG 210 | zh_TW 211 | zu_ZA 212 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/product_category_accesses.csv: -------------------------------------------------------------------------------- 1 | category;view_items;edit_items;own_items 2 | main;IT support,Manager,Redactor;IT support,Manager,Redactor;IT support,Manager,Redactor 3 | main_child_1;IT support,Manager,Redactor;IT support,Manager,Redactor;IT support,Manager,Redactor 4 | main_child_2;IT support,Manager,Redactor;IT support,Manager,Redactor;IT support,Manager,Redactor 5 | -------------------------------------------------------------------------------- /src/Resources/fixtures/minimal_EE/rules.yml: -------------------------------------------------------------------------------- 1 | rules: ~ -------------------------------------------------------------------------------- /src/Resources/translations/jsmessages.en.yml: -------------------------------------------------------------------------------- 1 | batch_jobs: 2 | xlsx_init_import: 3 | label: Excel initialization 4 | import_users: 5 | label: Import users 6 | import_user_groups: 7 | label: Import user groups 8 | import_user_roles: 9 | label: Import user roles 10 | import_attribute_groups: 11 | label: Import attribute groups 12 | import_attributes: 13 | label: Import attributes 14 | import_attribute_options: 15 | label: Import attribute options 16 | import_association_type: 17 | label: Import association type 18 | import_group_types: 19 | label: Import group types 20 | import_families: 21 | label: Import families 22 | -------------------------------------------------------------------------------- /src/Resources/translations/jsmessages.fr.yml: -------------------------------------------------------------------------------- 1 | batch_jobs: 2 | xlsx_init_import: 3 | label: Initialisation Excel 4 | import_users: 5 | label: Import utilisateurs 6 | import_user_groups: 7 | label: Import groupes utilisateurs 8 | import_user_roles: 9 | label: Import rôles utilisateurs 10 | import_attribute_groups: 11 | label: Import groupes d'attributs 12 | import_attributes: 13 | label: Import attributs 14 | import_attribute_options: 15 | label: Import options d'attributs 16 | import_association_type: 17 | label: Import type d'associations 18 | import_group_types: 19 | label: Import types de groupes 20 | import_families: 21 | label: Import familles 22 | -------------------------------------------------------------------------------- /src/Resources/translations/messages.en.yml: -------------------------------------------------------------------------------- 1 | batch_jobs.xlsx_init_import: 2 | label: Excel initialization 3 | import_users: 4 | label: Import users 5 | import_user_groups: 6 | label: Import user groups 7 | import_user_roles: 8 | label: Import user roles 9 | import_attribute_groups: 10 | label: Import attribute groups 11 | import_attributes: 12 | label: Import attributes 13 | import_attribute_options: 14 | label: Import attribute options 15 | import_association_type: 16 | label: Import association type 17 | import_group_types: 18 | label: Import group types 19 | import_families: 20 | label: Import families 21 | -------------------------------------------------------------------------------- /src/Resources/translations/messages.fr.yml: -------------------------------------------------------------------------------- 1 | batch_jobs.xlsx_init_import: 2 | label: Initialisation Excel 3 | import_users: 4 | label: Import utilisateurs 5 | import_user_groups: 6 | label: Import groupes utilisateurs 7 | import_user_roles: 8 | label: Import rôles utilisateurs 9 | import_attribute_groups: 10 | label: Import groupes d'attributs 11 | import_attributes: 12 | label: Import attributs 13 | import_attribute_options: 14 | label: Import options d'attributs 15 | import_association_type: 16 | label: Import type d'associations 17 | import_group_types: 18 | label: Import types de groupes 19 | import_families: 20 | label: Import familles 21 | --------------------------------------------------------------------------------