├── .gitignore
├── .scrutinizer.yml
├── .travis.yml
├── CHANGELOG-2.0.md
├── LICENSE.md
├── README.md
├── UPGRADE-1.0.md
├── UPGRADE-2.0.md
├── composer.json
├── doc
└── en
│ ├── columns
│ ├── action.md
│ ├── boolean.md
│ ├── collection.md
│ ├── datetime.md
│ ├── entity.md
│ ├── money.md
│ ├── number.md
│ ├── text.md
│ └── tree.md
│ └── extensions
│ ├── core.md
│ └── doctrine.md
├── lib
├── Column
│ ├── CellView.php
│ ├── CellViewInterface.php
│ ├── ColumnAbstractType.php
│ ├── ColumnAbstractTypeExtension.php
│ ├── ColumnTypeExtensionInterface.php
│ ├── ColumnTypeInterface.php
│ ├── HeaderView.php
│ └── HeaderViewInterface.php
├── Data
│ ├── DataRowset.php
│ └── DataRowsetInterface.php
├── DataGrid.php
├── DataGridAbstractExtension.php
├── DataGridEvent.php
├── DataGridEventInterface.php
├── DataGridEvents.php
├── DataGridExtensionInterface.php
├── DataGridFactory.php
├── DataGridFactoryInterface.php
├── DataGridInterface.php
├── DataGridRowView.php
├── DataGridRowViewInterface.php
├── DataGridView.php
├── DataGridViewInterface.php
├── DataMapper
│ ├── ChainMapper.php
│ ├── DataMapperInterface.php
│ ├── PropertyAccessorMapper.php
│ └── ReflectionMapper.php
├── Exception
│ ├── DataGridColumnException.php
│ ├── DataGridException.php
│ ├── DataMappingException.php
│ ├── UnexpectedTypeException.php
│ └── UnknownOptionException.php
└── Extension
│ ├── Core
│ ├── ColumnType
│ │ ├── Action.php
│ │ ├── Batch.php
│ │ ├── Boolean.php
│ │ ├── Collection.php
│ │ ├── DateTime.php
│ │ ├── Money.php
│ │ ├── Number.php
│ │ └── Text.php
│ ├── ColumnTypeExtension
│ │ ├── DefaultColumnOptionsExtension.php
│ │ └── ValueFormatColumnOptionsExtension.php
│ ├── CoreExtension.php
│ └── EventSubscriber
│ │ └── ColumnOrder.php
│ ├── Doctrine
│ ├── ColumnType
│ │ └── Entity.php
│ ├── ColumnTypeExtension
│ │ └── ValueFormatColumnOptionsExtension.php
│ └── DoctrineExtension.php
│ └── Gedmo
│ ├── ColumnType
│ └── Tree.php
│ └── GedmoDoctrineExtension.php
├── phpunit.xml.dist
└── tests
├── Data
└── DataRowsetTest.php
├── DataGridFactoryTest.php
├── DataGridRowViewTest.php
├── DataGridTest.php
├── DataGridViewTest.php
├── DataMapper
├── ChainMapperTest.php
└── ReflectionMapperTest.php
├── Extension
├── Core
│ ├── ColumnType
│ │ ├── ActionTest.php
│ │ ├── BooleanTest.php
│ │ ├── CollectionTest.php
│ │ ├── DateTimeTest.php
│ │ ├── MoneyTest.php
│ │ ├── NumberTest.php
│ │ └── TextTest.php
│ ├── ColumnTypeExtension
│ │ ├── DefaultColumnOptionsExtensionTest.php
│ │ └── ValueFormatColumnOptionsExtensionTest.php
│ └── CoreExtensionTest.php
├── Doctrine
│ ├── ColumnType
│ │ └── EntityTypeTest.php
│ ├── ColumnTypeExtension
│ │ └── ValueFormatColumnOptionsExtensionTest.php
│ └── DoctrineExtensionTest.php
└── Gedmo
│ ├── ColumnType
│ └── Tree
│ │ └── TreeTypeTest.php
│ └── GedmoDoctrineExtensionTest.php
└── Fixtures
├── ColumnType
└── FooType.php
├── Entity.php
├── EntityCategory.php
├── EntityManagerMock.php
├── EntityMapper.php
├── EntityRepositoryMock.php
├── EntityTree.php
├── EventManagerMock.php
├── FooExtension.php
└── GedmoTreeListenerMock.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin
2 | /vendor
3 | /tests/temp
4 | composer.lock
5 | composer.phar
6 | autoload.php
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | ---
2 | filter:
3 | excluded_paths: [vendor/*, bin/*]
4 |
5 | checks:
6 | php:
7 | code_rating: true
8 | duplication: true
9 |
10 | tools:
11 | php_cpd: true
12 | php_pdepend:
13 | excluded_dirs: [vendor]
14 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | matrix:
4 | include:
5 | - php: 7.1
6 | env:
7 | - COMPOSER_FLAGS='--prefer-lowest'
8 | - php: 7.2
9 | - php: 7.3
10 |
11 | sudo: false
12 |
13 | cache:
14 | directories:
15 | - $HOME/.composer/cache
16 | - vendor
17 |
18 | before_script:
19 | - phpenv config-rm xdebug.ini
20 | - composer validate
21 | - composer update $COMPOSER_FLAGS
22 |
23 | script: vendor/bin/phpunit
24 |
--------------------------------------------------------------------------------
/CHANGELOG-2.0.md:
--------------------------------------------------------------------------------
1 | # Changelog 1.x to 2.0
2 |
3 | This is a list changes done in the 2.0 vesion.
4 |
5 | ## Deleted Symfony extension
6 |
7 | Since it was moved to [datagrid-bundle](https://github.com/fsi-open/datagrid-bundle),
8 | it has been removed from this component.
9 |
10 | ## Changed null value semantic in boolean column
11 |
12 | Boolean column now treats `null`s like non existing value instead of `false` value. It displays empty string when
13 | all input values are `null`s.
14 |
15 | ## Dropped support for PHP below 7.1
16 |
17 | To be able to fully utilize new functionality introduced in 7.1, we have decided
18 | to only support PHP versions equal or higher to it.
19 |
20 | ## Removed deprecated methods
21 |
22 | The following deprecated interfaces, classes and methods were removed because they were replaced by
23 | [data-indexer](https://github.com/fsi-open/data-indexer/) component.
24 |
25 | - `FSi\Component\DataGrid\Data\IndexingStrategyInterface`
26 | - `FSi\Component\DataGrid\Data\EntityIndexingStrategy`
27 | - `FSi\Component\DataGrid\DataGridFactoryInterface::getIndexingStrategy`
28 | - `FSi\Component\DataGrid\DataGridInterface::getIndexingStrategy`
29 |
30 | ## Added argument and return typehints
31 |
32 | All interfaces and classes are now strictly typed.
33 |
34 | ## Removed fluent interfaces
35 |
36 | All interfaces except `DataGridInterface` are no longer fluent.
37 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (C) 2012-2014 FSi Sp. z o.o.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/UPGRADE-1.0.md:
--------------------------------------------------------------------------------
1 | UPGRADE FROM 0.9.x to 1.0.0
2 | ============================
3 |
4 | ## Options
5 |
6 | ### mapping_fields
7 |
8 | Before: ``mapping_fields``
9 | After: ``field_mapping``
10 |
11 | ### order
12 |
13 | Before: ``order``
14 | After: ``display_order``
15 |
16 |
17 | ### fields_options
18 |
19 | Before: ``fields_options``
20 | Example code:
21 | ```php
22 | $datagrid->addColumn('active', 'boolean', array(
23 | 'label' => 'Active',
24 | 'editable' => true,
25 | 'true_value' => 'YES',
26 | 'false_value' => 'NO',
27 | 'form_options' => array(
28 | 'active' => array(
29 | 'type' => 'choice',
30 | 'options' => array(
31 | 'choices' => array(
32 | 0 => 'NO',
33 | 1 => 'YES'
34 | )
35 | )
36 | )
37 | )
38 | ));
39 |
40 | ```
41 |
42 | After: ``form_options`` and ``form_type``
43 | Example code:
44 | ```php
45 | $datagrid->addColumn('active', 'boolean', array(
46 | 'label' => 'Active',
47 | 'editable' => true,
48 | 'true_value' => 'YES',
49 | 'false_value' => 'NO',
50 | 'form_options' => array(
51 | 'active' => array(
52 | 'choices' => array(
53 | 0 => 'NO',
54 | 1 => 'YES'
55 | )
56 | )
57 | ),
58 | 'form_type' => array(
59 | 'active' => 'choice'
60 | )
61 | ));
62 | ```
63 |
64 | ### glue
65 |
66 | Before: ``glue``
67 | After: ``value_glue``
68 |
69 | ### format
70 |
71 | Before: ``format``
72 | After: ``value_format``
73 |
74 |
75 | ### input
76 |
77 | Before: ``input``
78 | After: ``input_format``
79 |
80 | ### mapping_fields_format
81 |
82 | Before: ``mapping_fields_format``
83 | After: ``input_field_format``
84 |
85 |
86 | ### actions (action)
87 |
88 | Before: ``anchor``
89 | After: **removed**
90 |
91 | Before: ``parameters``
92 | After: ``parameters_field_mapping``
93 |
94 | Before: ``parameters_values``
95 | After: ``additional_parameters``
96 |
97 | ```php
98 | $datagrid->addColumn('action', 'action', array(
99 | 'label' => 'Actions',
100 | 'field_mapping' => array('id'),
101 | 'actions' => array(
102 | 'edit' => array(
103 | 'anchor' => 'Edit',
104 | 'absolute' => fasle,
105 | 'redirect_uri' => true,
106 | 'route_name' => '_news_edit',
107 | 'parameters' => array('id' => 'id'),
108 | 'parameters_values' => array('constant_param' => '1'),
109 | ),
110 | 'delete' => array(
111 | 'anchor' => 'Delete',
112 | 'absolute' => fasle,
113 | 'redirect_uri' => true,
114 | 'route_name' => '_news_delete',
115 | 'parameters' => array('id' => 'id'),
116 | 'parameters_values' => array('constant_param' => '1'),
117 | )
118 | )
119 | ));
120 | ```
121 |
122 | After:
123 | ```php
124 | $datagrid->addColumn('action', 'action', array(
125 | 'label' => 'Actions',
126 | 'field_mapping' => array('id', 'title'),
127 | 'actions' => array(
128 | 'edit' => array(
129 | 'route_name' => '_news_edit',
130 | 'parameters_field_mapping' => array('id' => 'id'),
131 | 'additional_parameters' => array('constant_param' => '1'),
132 | ),
133 | 'delete' => array(
134 | 'route_name' => '_news_delete',
135 | 'parameters_field_mapping' => array('id' => 'id'),
136 | 'additional_parameters' => array('constant_param' => '1'),
137 | )
138 | )
139 | ));
140 | ```
141 |
142 | *Important! Option anchor has been removed. From now url content is build from
143 | action name translated with translation_domain.*
144 |
--------------------------------------------------------------------------------
/UPGRADE-2.0.md:
--------------------------------------------------------------------------------
1 | # This is a guide on how to update from version 1.x to 2.0
2 |
3 | ## Use datagrid-bundle to utilize Symfony extension
4 |
5 | Since it was moved to [datagrid-bundle](https://github.com/fsi-open/datagrid-bundle),
6 | you will need to install it in order to be able to use the extension.
7 |
8 | ## Use null in boolean column only when you mean it
9 |
10 | If any of your boolean columns can contain `null` then an empty string will be displayed
11 | instead of value passed as `false_value` option. You should either ensure the column does
12 | not contain `null` or that it adheres to the new behaviour.
13 |
14 | ## Upgrade to PHP 7.1 or higher
15 |
16 | In order to use this library, you will need PHP 7.1 or higher.
17 |
18 | ## Add argument and return typehints
19 |
20 | There is quite a big chance that your custom column type or column type extension
21 | need to have added typehints to most of its methods accordingly to extended
22 | class or implemented interface.
23 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fsi/datagrid",
3 | "type": "library",
4 | "description": "FSi DataGrid Component",
5 | "keywords": ["fsi", "component", "datagrid"],
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "Norbert Orzechowicz",
10 | "email": "norbert@orzechowicz.pl"
11 | }
12 | ],
13 | "require": {
14 | "php": ">=7.1",
15 | "symfony/event-dispatcher" : "^2.2|^3.0|^4.0",
16 | "symfony/property-access": "^2.3|^3.0|^4.0",
17 | "symfony/options-resolver": "^2.6|^3.0|^4.0",
18 | "fsi/reflection" : "0.9.*",
19 | "fsi/data-indexer" : "0.9.*"
20 | },
21 | "require-dev": {
22 | "doctrine/orm": "^2.5",
23 | "doctrine/common": "^2.5",
24 | "gedmo/doctrine-extensions": "^2.3.10",
25 | "phpunit/phpunit": "^7.1"
26 | },
27 | "autoload": {
28 | "psr-4": {
29 | "FSi\\Component\\DataGrid\\": "lib/"
30 | }
31 | },
32 | "autoload-dev": {
33 | "psr-4": {
34 | "FSi\\Component\\DataGrid\\Tests\\": "tests/"
35 | }
36 | },
37 | "config": {
38 | "bin-dir": "vendor/bin"
39 | },
40 | "extra": {
41 | "branch-alias": {
42 | "dev-master": "3.0-dev",
43 | "2.0": "2.0-dev",
44 | "1.3": "1.3-dev",
45 | "1.2": "1.2-dev",
46 | "1.1": "1.1-dev",
47 | "1.0": "1.0-dev"
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/doc/en/columns/action.md:
--------------------------------------------------------------------------------
1 | # Action Column Type #
2 |
3 | Provided by ``DataGrid\Extension\Core\CoreExtension``
4 |
5 | ## Available Options ##
6 |
7 | * ``label`` - string, by default ``[$field->getName()]``
8 | * ``field_mapping`` - **required**, array, by default ``[$field->getName()]``
9 | * ``display_order`` - integer
10 | * ``actions`` - **required**, array
11 |
12 | ## Options Description ##
13 |
14 | **field_mapping** Fields that should be used when data is retrieved from the source. By default there is only one field
15 | and its taken from the name under what column was registered in grid.
16 |
17 | **label** By default label value its taken from name under what column was registered in grid.
18 |
19 | **display_order** Optional integer value specifying order of column in grid. Columns in grid are sorted according
20 | to ascending value of this option. Columns without this option will stay in their natural order (between columns with
21 | positive and negative values of this option)
22 |
23 | **actions** Array of actions. Each action has following options:
24 |
25 | * ``uri_scheme`` - **required**, string, scheme of an uri
26 | * ``protocol`` - string, by default ``'http://``
27 | * ``domain`` - string, domain for an anchor
28 | * ``redirect_uri`` - string, optional parameter in uri, might be useful to create return from actions.
29 |
30 | ## Example Usage ##
31 |
32 | ``` php
33 | addColumn('actions', 'action', [
36 | 'label' => 'Actions',
37 | 'mapping_fields' => ['identity'],
38 | 'actions' => [
39 | edit' => [
40 | 'uri_scheme' => '/test/%s',
41 | 'domain' => 'fsi.pl',
42 | 'protocol' => 'https://',
43 | 'redirect_uri' => 'http://onet.pl/'
44 | ],
45 | ]
46 | ]);
47 |
48 | ```
49 |
50 | **Important** - ``parameters_field_mapping``, ``url_attr`` and ``content`` allows \Closure function as value. It can be used to format
51 | option value depending on the field_mapping values. Closure function will be called with 2 arguments:
52 |
53 | ``function($fieldMappingValues, $rowIndex)``
54 |
--------------------------------------------------------------------------------
/doc/en/columns/boolean.md:
--------------------------------------------------------------------------------
1 | # Boolean Column Type #
2 |
3 | Provided by ``DataGrid\Extension\Core\CoreExtension``
4 |
5 | ## Available Options ##
6 |
7 | * ``label`` - string, by default ``[$field->getName()]``
8 | * ``field_mapping`` - **required**, array, by default ``[$field->getName()]``
9 | * ``value_glue`` - string
10 | * ``value_format`` - string
11 | * ``display_order`` - integer
12 | * ``empty_value`` - string|array, by default ``""`` (empty string)
13 | * ``true_value`` - what should be stetted as cell view value if mapping_fields give true values.
14 | * ``false_value`` - what should be stetted as cell view value if mapping_fields give false values.
15 | * ``editable`` - **required**, boolean, by default ``false``
16 | * ``form_options`` - array, by default ``[]``
17 | * ``form_type`` - array, by default ``[]``
18 |
19 | ## Options Description ##
20 |
21 | **label** Label for column.
22 |
23 | **field_mapping** Fields that should be used when data is retrieved from the source. By default there is only one
24 | field and its taken from the name under what column was registered in grid.
25 | Option is useful when you need to implode few fields from object in one column.
26 |
27 | **label** By default label value its taken from name under what column was registered in grid.
28 |
29 | **value_glue** Useful only when you need to implode data from few source object fields into one column.
30 |
31 | **value_format** Useful when you need to format value before passing it to view. Value formatted with php ``sprintf`` function. There should be at least same count of ``mapping_fields`` option
32 | values as placeholders count in format string. This option can be used with ``value_glue`` option.
33 | ``format`` option also accept ``\Closure`` function that should return valid formatted string.
34 |
35 | **display_order** Optional integer value specifying order of column in grid. Columns in grid are sorted according
36 | to ascending value of this option. Columns without this option will stay in their natural order (between columns with
37 | positive and negative values of this option)
38 |
39 | **editable** If enabled SymfonyForm object is automatically created and passed into view as attribute and you can easily use it to display quick edit.
40 |
41 | **form_options** Array of options for forms, where key is name of field (one of field_mapping) and value is
42 | options passed to form.
43 |
44 | **form_type** Array of types for forms, where key is name of field (one of field_mapping) and value is form type.
45 |
46 | **empty_value** if value from field_mapping is empty (null, !strlen) then it will be replaced with ``empty_value`` option value which by default is empty string. There is also possibility to pass ``empty_value`` to selected ``mapping_fields``.
47 | To do it you just need set ``empty_value`` as array where keys are ``mapping_fields`` keys. If mapping field value is empty and its not included in ``empty_value`` option it will be replaced with empty string.
48 |
49 |
50 | ## Example Usage ##
51 |
52 | ``` php
53 | false)
56 | //Input Data1: Object ('available' => true)
57 | //Input Data3: Object ('available' => null)
58 | $datagrid->addColumn('available', 'boolean', [
59 | 'editable' => false,
60 | 'true_value' => '',
61 | 'false_value' => '',
62 | 'form_options' => [
63 | 'available' => [
64 | 'required' => false
65 | ]
66 | ]
67 | 'form_type' => [
68 | 'available' => 'checkbox'
69 | ]
70 | ));
71 | //Output1: ""
72 | //Output2: "'"
73 | //Output3: ""
74 |
75 | //Input Data1: Object ('accessible' => true, 'visible' => true)
76 | //Input Data2: Object ('accessible' => true, 'visible' => false)
77 | //Input Data3: Object ('accessible' => false, 'visible' => false)
78 | $datagrid->addColumn('available', 'boolean', [
79 | 'field_mapping' => ['accessible', 'visible']
80 | 'editable' => false,
81 | 'true_value' => '',
82 | 'false_value' => '',
83 | 'form_options' => [
84 | 'available' => [
85 | 'required' => false
86 | ]
87 | ],
88 | 'form_type' => [
89 | 'available' => 'checkbox'
90 | ]
91 | ));
92 | //Output1: "'"
93 | //Output2: ""
94 | //Output3: ""
95 |
--------------------------------------------------------------------------------
/doc/en/columns/collection.md:
--------------------------------------------------------------------------------
1 | # Text Column Type #
2 |
3 | Provided by ``DataGrid\Extension\Core\CoreExtension``
4 |
5 | ## Available Options ##
6 |
7 | * ``collection_glue`` - string, by default `` ``
8 | * ``label`` - string, by default ``[$field->getName()]``
9 | * ``field_mapping`` - **required**, array, by default ``[$field->getName()]``
10 | * ``value_glue`` - string
11 | * ``display_order`` - integer
12 | * ``empty_value`` - string|array, by default ``""`` (empty string)
13 |
14 | ## Options Description ##
15 |
16 | **collection_glue** option used to implode array elements, by default empty string " ".
17 |
18 | **label** Label for column.
19 |
20 | **mapping_fields** Fields that should be used when data is retrieved from the source. By default there is only one mapping
21 | field and its taken from name under what column was registered in grid.
22 | Option is useful when you need to implode few fields from object in one column.
23 |
24 | **label** By default label value its taken from name under what column was registered in grid.
25 |
26 | **field_mapping** Fields that should be used when data is retrieved from the source. By default there is only one
27 | field and its taken from the name under what column was registered in grid.
28 | Option is useful when you need to implode few fields from object in one column.
29 |
30 | **value_glue** Useful only when you need to implode data from few source object fields into one column.
31 |
32 | **value_format** Useful when you need to format value before passing it to view. Value formatted with php ``sprintf`` function. There should be at least same count of ``mapping_fields`` option
33 | values as placeholders count in format string. This option can be used with ``value_glue`` option.
34 | ``format`` option also accept ``\Closure`` function that should return valid formatted string.
35 |
36 | **display_order** Optional integer value specifying order of column in grid. Columns in grid are sorted according
37 | to ascending value of this option. Columns without this option will stay in their natural order (between columns with
38 | positive and negative values of this option)
39 |
40 | ## Example Usage ##
41 |
42 | ``` php
43 | ['ROLE_ADMIN, 'ROLE_USER'])
46 | $grid->addColumn('roles', 'collection', ['collection_glue' => ' | ']);
47 | //Output: "ROLE_ADMIN | ROLE_USER"
48 |
49 | ```
50 |
--------------------------------------------------------------------------------
/doc/en/columns/datetime.md:
--------------------------------------------------------------------------------
1 | # DateTime Column Type #
2 |
3 | Provided by ``DataGrid\Extension\Core\CoreExtension``
4 |
5 | ## Available Options ##
6 |
7 | * ``datetime_format`` - **required**, string, by default ``Y-m-d H:i:s``
8 | * ``input_type`` - string
9 | * ``input_field_format`` - array
10 | * ``label`` - string, by default ``[$field->getName()]``
11 | * ``field_mapping`` - **required**, array, by default ``[$field->getName()]``
12 | * ``value_glue`` - string
13 | * ``value_format`` - string
14 | * ``display_order`` - integer
15 | * ``editable`` - **required**, boolean, by default ``false``
16 | * ``form_options`` - array, by default ``[]``
17 | * ``form_type`` - array, by default ``[]``
18 | * ``empty_value`` - string|array, by default ``""`` (empty string)
19 |
20 | ## Options Description ##
21 |
22 | **datetime_format** Format of showed date and/or time.
23 |
24 | **input_type** Kind of data you are giving to column (``array``, ``datetime``, ``datetime_interface``, ``string``, ``timestamp``) - if no specified, column will try to guess it.
25 |
26 | **input_field_format** Array of formats used if you specify more than one field in field_mapping option (that keys match 'field_mapping` option keys), otherwise its equal to 'datetime_format' option.
27 |
28 | **label** By default label value its taken from name under what column was registered in grid.
29 |
30 | **field_mapping** Fields that should be used when data is retrieved from the source. By default there is only one
31 | field and its taken from the name under what column was registered in grid.
32 | Option is useful when you need to implode few fields from object in one column.
33 |
34 | **value_glue** Useful only when you need to implode data from few source object fields into one column.
35 |
36 | **value_format** Useful when you need to format value before passing it to view. Value formatted with php ``sprintf`` function. There should be at least same count of ``mapping_fields`` option
37 | values as placeholders count in format string. This option can be used with ``value_glue`` option.
38 | ``format`` option also accept ``\Closure`` function that should return valid formatted string.
39 |
40 | **display_order** Optional integer value specifying order of column in grid. Columns in grid are sorted according
41 | to ascending value of this option. Columns without this option will stay in their natural order (between columns with
42 | positive and negative values of this option)
43 |
44 | **editable** If enabled SymfonyForm object is automatically created and passed into view as attribute and you can easily use it to display quick edit.
45 |
46 | **form_options** Array of options for forms, where key is name of field (one of field_mapping) and value is
47 | options passed to form.
48 |
49 | **form_type** Array of types for forms, where key is name of field (one of field_mapping) and value is form type.
50 |
51 | ## Example Usage ##
52 |
53 | ``` php
54 | addColumn('purchase_date', 'datetime', [
58 | 'label' => 'Purchase date',
59 | 'datetime_format' => 'Y-m-d H:i:s',
60 | 'editable' => true,
61 | ]);
62 |
63 | //Shows column with date that is combination of create_date and create_time fields.
64 | $datagrid->addColumn('create_datetime', 'datetime', [
65 | 'label' => 'Create datetime',
66 | 'field_mapping' => ['create_date', 'create_time'],
67 | 'value_glue' => ' ',
68 | 'editable' => true,
69 | 'input_type' => 'array',
70 | 'datetime_format' => ['create_date' => 'Y-m-d', 'create_time' => "H:i:s"],
71 | 'input_field_format' => ['create_date' => ['input_type' => 'datetime'], 'create_time' => {'input_type' => 'datetime']],
72 | ]);
73 |
74 | //Shows column that value is combination formatted fields create_date and timestamp.
75 | $datagrid->addColumn('create_date_timestamp', 'datetime', [
76 | 'label' => 'Crate date from timestamp',
77 | 'field_mapping' => [create_date', 'timestamp'],
78 | 'value_glue' => '
',
79 | 'editable' => true,
80 | 'input_type' => 'array',
81 | 'datetime_format' => ['timestamp' => 'Y-m-d h:i:s', 'create_date' => 'Y-m-d'],
82 | 'input_field_format' => ['create_date' => ['input_type' => 'datetime'], 'timestamp' => ['input_type' => 'timestamp']]
83 | ]);
84 |
85 | //Shows date, that is combination of three integer fields.
86 | $datagrid->addColumn('join_date', 'datetime', [
87 | 'label' => 'Join date',
88 | 'field_mapping' => ['int_year', 'int_month', 'int_day'],
89 | 'glue' => '-',
90 | 'input_type' => 'array',
91 | 'datetime_format' => ['int_year' => 'Y', 'int_month' => 'm', 'int_day' => 'd'],
92 | 'input_field_format' => [
93 | 'int_year' => ['input_type' => 'string', 'datetime_format' => 'Y'],
94 | 'int_month' => ['input_type' => 'string', 'datetime_format' => 'm'],
95 | 'int_day' => ['input_type' => 'string', 'datetime_format' => 'd']
96 | ]
97 | ]);
98 |
99 | ```
100 |
--------------------------------------------------------------------------------
/doc/en/columns/entity.md:
--------------------------------------------------------------------------------
1 | # Entity Column Type #
2 |
3 | Provided by ``FSi\Component\DataGrid\Extension\Doctrine\DoctrineExtension``
4 |
5 | ## Available Options ##
6 |
7 | * ``label`` - string, by default ``[$field->getName()]``
8 | * ``field_mapping`` - **required**, array, by default ``[$field->getName()]``
9 | * ``value_glue`` - string
10 | * ``empty_value`` - string|array|null, by default ``null``
11 | * ``glue_multiple`` - string, by default ``" "`` (space character)
12 | * ``relation_field`` - **required**, string
13 | * ``display_order`` - integer
14 | * ``editable`` - **required**, boolean, by default ``false``
15 | * ``form_options`` - array, by default ``[]``
16 | * ``form_type`` - array, by default ``[]``
17 |
18 | ## Options Description ##
19 |
20 | **label** By default label value its taken from name under what column was registered in grid.
21 |
22 | **field_mapping** Fields that should be used when data is retrieved from the source. By default there is only one
23 | field and its taken from the name under what column was registered in grid.
24 | Option is useful when you need to implode few fields from object in one column.
25 |
26 | **value_format** Useful when you need to format value before passing it to view. Value formatted with php ``sprintf`` function. There should be at least same count of ``mapping_fields`` option
27 | values as placeholders count in format string. This option can be used with ``value_glue`` option.
28 | ``format`` option also accept ``\Closure`` function that should return valid formatted string.
29 |
30 | **empty_value** Useful when value is empty and you want override this value.
31 |
32 | **display_order** Optional integer value specifying order of column in grid. Columns in grid are sorted according
33 | to ascending value of this option. Columns without this option will stay in their natural order (between columns with
34 | positive and negative values of this option)
35 |
36 | **editable** If enabled SymfonyForm object is automatically created and passed into view as attribute and you can easily use it to display quick edit.
37 |
38 | **glue_multiple** Glue between objects from relation. Should be used if you want to display relation with many objects and add some separator between them.
39 |
40 | **relation_field** Field that relates to other entity (entities).
41 |
42 | **editable** If enabled SymfonyForm object is automatically created and passed into view as attribute and you can easily use it to display quick edit.
43 |
44 | **form_options** Array of options for forms, where key is name of field (one of field_mapping) and value is
45 | options passed to form.
46 |
47 | **form_type** Array of types for forms, where key is name of field (one of field_mapping) and value is form type.
48 |
49 | ## Example Usage ##
50 |
51 | ``` php
52 | Object('id' => 1, 'name' => 'Foo'))
55 |
56 | $dataGrid->addColumn('category', 'entity', [
57 | 'label' => 'News category',
58 | 'relation_field' => 'category',
59 | 'value_format' => '%s %s',
60 | 'field_mapping' => ['id', 'name']
61 | ]);
62 |
63 | //Output: "1 Foo"
64 |
65 | //Input Data: Object (category => Object('id' => null, 'name' => 'Foo'))
66 |
67 | $dataGrid->addColumn('category', 'entity', [
68 | 'label' => 'News category',
69 | 'relation_field' => 'category',
70 | 'value_glue' => ' ',
71 | 'empty_value' => 'no',
72 | 'field_mapping' => ['id', 'name']
73 | ]);
74 |
75 | //Output: "no Foo"
76 |
77 | //Input Data: Object (category => Object('id' => null, 'name' => null))
78 |
79 | $dataGrid->addColumn('category', 'entity', [
80 | 'label' => 'News category',
81 | 'relation_field' => 'category',
82 | 'value_glue' => ' ',
83 | 'empty_value' => ['id' => 'no', 'name' => 'no'],
84 | 'field_mapping' => ['id', 'name']
85 | ]);
86 |
87 | //Output: "no no"
88 |
89 | //Input Data: Object (newses => [0 => Object('id' => 1, 'name' => 'Foo'), 1 => Object('id' => 2, 'name' => 'Bar')])
90 |
91 | $dataGrid->addColumn('newses', 'entity', [
92 | 'label' => 'Category Newses',
93 | 'relation_field' => 'newses',
94 | 'value_format' => '(%s: %s)',
95 | 'glue_multiple' => ' - ',
96 | 'field_mapping' => ['id', 'name']
97 | ]);
98 |
99 | //Output: "(1: Foo) - (2: Bar)"
100 | ```
101 |
--------------------------------------------------------------------------------
/doc/en/columns/money.md:
--------------------------------------------------------------------------------
1 | # Money Column Type #
2 |
3 | Provided by ``DataGrid\Extension\Core\CoreExtension``
4 |
5 | ## Available Options ##
6 |
7 | * ``round_mode`` - integer
8 | * ``precision`` - integer, by default ``2``
9 | * ``decimals`` - integer, by default ``2``
10 | * ``dec_point`` - string, by default ``.``
11 | * ``thousands_sep`` - string, by default ``,``
12 | * ``value_currency_separator`` - string, by default `` `` (space character)
13 | * ``currency_field`` - string
14 | * ``currency`` - string
15 | * ``label`` - string, by default ``[$field->getName()]``
16 | * ``field_mapping`` - **required**, array, by default ``[$field->getName()]``
17 | * ``value_glue`` - string
18 | * ``display_order`` - integer
19 | * ``editable`` - **required**, boolean, by default ``false``
20 | * ``empty_value`` - string|array, by default ``""`` (empty string)
21 | * ``form_options`` - array, by default ``[]``
22 | * ``form_type`` - array, by default ``[]``
23 |
24 | ## Options Description ##
25 |
26 | **round_mode** One of ``Number::ROUND_HALF_UP``, ``Number::ROUND_HALF_DOWN``, ``Number::ROUND_HALF_EVEN`` or ``Number::ROUND_HALF_ODD``.
27 |
28 | **precision** Number of decimal digits to round to.
29 |
30 | **decimals** The number of decimal points.
31 |
32 | **dec_point** Decimal point.
33 |
34 | **thousands_sep** Thousands separator.
35 |
36 | **value_currency_separator** Separator between currency and value.
37 |
38 | **currency_field** Field to take actual currency from. Mandatory if currency_value not specified.
39 |
40 | **currency** Currency. Mandatory if currency_field not specified.
41 |
42 | **field_mapping** Fields that should be used when data is retrieved from the source. By default there is only one
43 | field and its taken from the name under what column was registered in grid.
44 | Option is useful when you need to implode few fields from object in one column.
45 |
46 | **value_glue** Useful only when you need to implode data from few source object fields into one column.
47 |
48 | **value_format** Useful when you need to format value before passing it to view. Value formatted with php ``sprintf`` function. There should be at least same count of ``mapping_fields`` option
49 | values as placeholders count in format string. This option can be used with ``value_glue`` option.
50 | ``format`` option also accept ``\Closure`` function that should return valid formatted string.
51 |
52 | **display_order** Optional integer value specifying order of column in grid. Columns in grid are sorted according
53 | to ascending value of this option. Columns without this option will stay in their natural order (between columns with
54 | positive and negative values of this option)
55 |
56 | **editable** If enabled SymfonyForm object is automatically created and passed into view as attribute and you can easily use it to display quick edit.
57 |
58 | **form_options** Array of options for forms, where key is name of field (one of field_mapping) and value is
59 | options passed to form.
60 |
61 | **form_type** Array of types for forms, where key is name of field (one of field_mapping) and value is form type.
62 |
63 | ## Example Usage ##
64 |
65 | ``` php
66 | addColumn('productprice', 'money', [
70 | 'label' => 'Product price',
71 | 'field_mapping' => ['price', 'currency'],
72 | 'currency_field' => 'currency',
73 | 'value_currency_separator' => ' - ',
74 | 'value_glue' => '
',
75 | ]);
76 |
77 | //This configuration will show price from two fields ('price' and 'promo_price') with arbitrary USD currency.
78 | $datagrid->addColumn('productprice', 'money', [
79 | 'label' => 'Product price',
80 | 'field_mapping' => ['price', 'promo_price'],
81 | 'currency' => 'USD',
82 | 'value_currency_separator' => '$ ',
83 | 'dec_point' => ',',
84 | ]);
85 |
86 | ```
87 |
--------------------------------------------------------------------------------
/doc/en/columns/number.md:
--------------------------------------------------------------------------------
1 | # Number Column Type #
2 |
3 | Provided by ``DataGrid\Extension\Core\CoreExtension``
4 |
5 | ## Available Options ##
6 |
7 | * ``round_mode`` - integer
8 | * ``precision`` - integer, by default ``2``
9 | * ``label`` - string, by default ``[$field->getName()]``
10 | * ``field_mapping`` - **required**, array, by default ``[$field->getName()]``
11 | * ``value_glue`` - string
12 | * ``display_order`` - integer
13 | * ``editable`` - **required**, boolean, by default ``false``
14 | * ``empty_value`` - string|array, by default ``""`` (empty string)
15 | * ``form_options`` - array, by default ``[]``
16 | * ``form_type`` - array, by default ``[]``
17 | * ``format`` - boolean, by default ``false``
18 | * ``format_decimals`` - integer, by default ``0``
19 | * ``format_dec_point`` - string, by default ``.``
20 | * ``format_thousands_sep`` - string, by default ``,``
21 |
22 | ## Options Description ##
23 |
24 | **round_mode** One of ``Number::ROUND_HALF_UP``, ``Number::ROUND_HALF_DOWN``, ``Number::ROUND_HALF_EVEN`` or ``Number::ROUND_HALF_ODD``.
25 |
26 | **precision** Number of decimal digits to round to.
27 |
28 | **label** By default label value its taken from name under what column was registered in grid.
29 |
30 | **field_mapping** Fields that should be used when data is retrieved from the source. By default there is only one
31 | field and its taken from the name under what column was registered in grid.
32 | Option is useful when you need to implode few fields from object in one column.
33 |
34 | **value_glue** Useful only when you need to implode data from few source object fields into one column.
35 |
36 | **value_format** Useful when you need to format value before passing it to view. Value formatted with php ``sprintf`` function. There should be at least same count of ``mapping_fields`` option
37 | values as placeholders count in format string. This option can be used with ``value_glue`` option.
38 | ``format`` option also accept ``\Closure`` function that should return valid formatted string.
39 |
40 | **display_order** Optional integer value specifying order of column in grid. Columns in grid are sorted according
41 | to ascending value of this option. Columns without this option will stay in their natural order (between columns with
42 | positive and negative values of this option)
43 |
44 | **editable** If enabled SymfonyForm object is automatically created and passed into view as attribute and you can easily use it to display quick edit.
45 |
46 | **form_options** Array of options for forms, where key is name of field (one of field_mapping) and value is
47 | options passed to form.
48 |
49 | **form_type** Array of types for forms, where key is name of field (one of field_mapping) and value is form type.
50 |
51 | **format** If set to true, number will be formatted using options ``format_decimals``, ``format_dec_point`` and ``format_thousands_sep`` according to http://php.net/manual/en/function.number-format.php By default ``format`` option is disabled, so value will not be formatted in case it is phone number or some id number.
52 |
53 | **format_decimals** By default ``2``. See **format** option for description.
54 |
55 | **format_dec_point** By default ``.``. See **format** option for description.
56 |
57 | **format_thousands_sep** By default ``,``. See **format** option for description.
58 |
59 | ## Example Usage ##
60 |
61 | ``` php
62 | 10.123)
65 | $grid->addColumn('price', 'number', [
66 | 'field_mapping' => [
67 | 'value'
68 | ],
69 | 'round_mode' => Number::ROUND_HALF_UP
70 | 'precision' => 2
71 | ]);
72 | //Output: 10.12
73 |
74 | //Input Data: Object ('value' => 10.126)
75 | $grid->addColumn('price', 'number', [
76 | 'field_mapping' => [
77 | 'value'
78 | ],
79 | 'round_mode' => Number::ROUND_HALF_UP
80 | 'precision' => 2
81 | ]);
82 |
83 | //Output: 10.13
84 | ```
85 |
--------------------------------------------------------------------------------
/doc/en/columns/text.md:
--------------------------------------------------------------------------------
1 | # Text Column Type #
2 |
3 | Provided by ``DataGrid\Extension\Core\CoreExtension``
4 |
5 | ## Available Options ##
6 |
7 | * ``trim`` - boolean, by default ``false``
8 | * ``label`` - string, by default ``[$field->getName()]``
9 | * ``field_mapping`` - **required**, array, by default ``[$field->getName()]``
10 | * ``value_glue`` - string
11 | * ``display_order`` - integer
12 | * ``editable`` - **required**, boolean, by default ``false``
13 | * ``empty_value`` - string|array, by default ``""`` (empty string)
14 | * ``form_options`` - array, by default ``[]``
15 | * ``form_type`` - array, by default ``[]``
16 |
17 | ## Options Description ##
18 |
19 | **trim** By default option is disabled. If enabled value from every single mapping_filed is trimmed before ``buildView`` method will pass it into view object.
20 |
21 | **label** Label for column.
22 |
23 | **mapping_fields** Fields that should be used when data is retrieved from the source. By default there is only one mapping
24 | field and its taken from name under what column was registered in grid.
25 | Option is useful when you need to implode few fields from object in one column.
26 |
27 | **label** By default label value its taken from name under what column was registered in grid.
28 |
29 | **field_mapping** Fields that should be used when data is retrieved from the source. By default there is only one
30 | field and its taken from the name under what column was registered in grid.
31 | Option is useful when you need to implode few fields from object in one column.
32 |
33 | **value_glue** Useful only when you need to implode data from few source object fields into one column.
34 |
35 | **value_format** Useful when you need to format value before passing it to view. Value formatted with php ``sprintf`` function. There should be at least same count of ``mapping_fields`` option
36 | values as placeholders count in format string. This option can be used with ``value_glue`` option.
37 | ``format`` option also accept ``\Closure`` function that should return valid formatted string.
38 |
39 | **display_order** Optional integer value specifying order of column in grid. Columns in grid are sorted according
40 | to ascending value of this option. Columns without this option will stay in their natural order (between columns with
41 | positive and negative values of this option)
42 |
43 | **editable** If enabled SymfonyForm object is automatically created and passed into view as attribute and you can easily use it to display quick edit.
44 |
45 | **form_options** Array of options for forms, where key is name of field (one of field_mapping) and value is
46 | options passed to form.
47 |
48 | **form_type** Array of types for forms, where key is name of field (one of field_mapping) and value is form type.
49 |
50 | ## Example Usage ##
51 |
52 | ``` php
53 | 'Norbert', 'surname' => 'Orzechowicz')
56 | $grid->addColumn('name_surname', 'text', [
57 | 'field_mapping' => [
58 | 'name',
59 | 'surname'
60 | ]
61 | ]);
62 | //Output: "Norbert Orzechowicz"
63 |
64 | //Input Data: Object ('name' => 'Norbert', 'surname' => 'Orzechowicz')
65 | $grid->addColumn('name_surname', 'text', [
66 | 'field_mapping' => [
67 | 'name',
68 | 'surname'
69 | ],
70 | 'glue' => '-'
71 | ]);
72 | //Output: "Norbert-Orzechowicz"
73 |
74 | //Input Data: Object ('name' => ' Norbert ')
75 | $grid->addColumn('name', 'text', ['trim' => true]);
76 | //Output: "Norbert"
77 |
78 | //Input Data: Object ('name' => 'Norbert')
79 | $grid->addColumn('name_column', 'text', [
80 | 'field_mapping' => [
81 | 'name'
82 | ]
83 | ]);
84 | //Output: "Norbert"
85 |
86 | //Input Data: Object ('name' => 'Norbert')
87 | $grid->addColumn('name', 'text', [
88 | 'editable' => true
89 | ]);
90 | // $form = $column->getAttribute('form') - Symfony Form Object
91 | ```
92 |
--------------------------------------------------------------------------------
/doc/en/columns/tree.md:
--------------------------------------------------------------------------------
1 | # Tree Column Type #
2 |
3 | Provided by ``DataGrid\Extension\Gedmo\GedmoDoctrineExtension``
4 |
5 | ## Available Options ##
6 |
7 | * ``em`` - string
8 | * ``label`` - string, by default ``[$field->getName()]``
9 | * ``field_mapping`` - **required**, array, by default ``[$field->getName()]``
10 | * ``value_glue`` - string
11 | * ``display_order`` - integer
12 | * ``editable`` - **required**, boolean, by default ``false``
13 | * ``empty_value`` - string|array, by default ``""`` (empty string)
14 | * ``form_options`` - array, by default ``[]``
15 | * ``form_type`` - array, by default ``[]``
16 |
17 | ## Options Description ##
18 |
19 | **em** Name of entity manager, if null column takes default one.
20 |
21 | **label** By default label value its taken from name under what column was registered in grid.
22 |
23 | **field_mapping** Fields that should be used when data is retrieved from the source. By default there is only one
24 | field and its taken from the name under what column was registered in grid.
25 | Option is useful when you need to implode few fields from object in one column.
26 |
27 | **value_glue** Useful only when you need to implode data from few source object fields into one column.
28 |
29 | **value_format** Useful when you need to format value before passing it to view. Value formatted with php ``sprintf`` function. There should be at least same count of ``mapping_fields`` option
30 | values as placeholders count in format string. This option can be used with ``value_glue`` option.
31 | ``format`` option also accept ``\Closure`` function that should return valid formatted string.
32 |
33 | **display_order** Optional integer value specifying order of column in grid. Columns in grid are sorted according
34 | to ascending value of this option. Columns without this option will stay in their natural order (between columns with
35 | positive and negative values of this option)
36 |
37 | **editable** If enabled SymfonyForm object is automatically created and passed into view as attribute and you can easily use it to display quick edit.
38 |
39 | **form_options** Array of options for forms, where key is name of field (one of field_mapping) and value is
40 | options passed to form.
41 |
42 | **form_type** Array of types for forms, where key is name of field (one of field_mapping) and value is form type.
43 |
44 | ## Example Usage ##
45 |
46 | ``` php
47 | addColumn('item', 'gedmo_tree', [
50 | 'label' => 'Item',
51 | 'editable' => true,
52 | ]);
53 |
54 | ```
55 |
56 | Difference between ``tree`` and ``text`` column is that cellView of ``tree`` column type has few additional
57 | attributes.
58 | List of attributes and example of usage below:
59 |
60 | **Attributes**
61 | * **id** - element id
62 | * **parent** - (optional) parent id
63 | * **root** - (optional) root id of element
64 | * **left** - element left position
65 | * **right** - element right position
66 | * **level** - element nesting level
67 | * **children** - element children count
68 |
69 | **Usage** (in Twig)
70 |
71 | ```
72 | {# datagrid_column_type_{column_type}_cell #}
73 | {% block datagrid_column_type_gedmo_tree_cell %}
74 |
75 |
76 | {% spaceless %}
77 |
83 | {% endspaceless %}
84 | {{ cell.value|raw }}
85 |
86 | {{ datagrid_column_cell_form_widget(cell) }}
87 |
88 | |
89 | {% endblock %}
90 | ```
91 |
--------------------------------------------------------------------------------
/doc/en/extensions/core.md:
--------------------------------------------------------------------------------
1 | # DataGrid Extension Core #
2 |
3 | ## Column Types provided by extension ##
4 |
5 | ``FSi\Component\DataGrid\Extension\Core\ColumnType\Bollean``
6 | ``FSi\Component\DataGrid\Extension\Core\ColumnType\Text``
7 | ``FSi\Component\DataGrid\Extension\Core\ColumnType\Number``
8 | ``FSi\Component\DataGrid\Extension\Core\ColumnType\Money``
9 | ``FSi\Component\DataGrid\Extension\Core\ColumnType\DateTime``
10 | ``FSi\Component\DataGrid\Extension\Core\ColumnType\Action``
11 |
12 | ## Event Subscribers provided by extension ##
13 |
14 | ``FSi\Component\DataGrid\Extension\Core\EventSubscriber\ColumnOrder``
15 |
16 | ## Column Type Extensions provided by extension ##
17 |
18 | ``FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension\ValueFormatColumnOptionsExtension``
19 | Options added by this extension:
20 | * ``value_glue``
21 | * ``value_format``
22 | * ``empty_value``
23 |
24 | ``FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension\DefaultColumnOptionsExtension``
25 | Options added by this extension:
26 | * ``label``
27 | * ``display_order``
28 | * ``field_mapping``
--------------------------------------------------------------------------------
/doc/en/extensions/doctrine.md:
--------------------------------------------------------------------------------
1 | # DataGrid Extension Doctrine #
2 |
3 | ## Column Types provided by extension ##
4 |
5 | ``FSi\Component\DataGrid\Extension\Doctrine\ColumnType\Entity``
6 |
7 | ## Event Subscribers provided by extension ##
8 |
9 | none
10 |
11 | ## Column Type Extensions provided by extension ##
12 |
13 | ``FSi\Component\DataGrid\Extension\Doctrine\ColumnTypeExtension\ValueFormatColumnOptionsExtension``
14 | Options added by this extension (only for column type ``entity``):
15 | * ``value_glue``
16 | * ``value_format``
17 | * ``glue_multiple``
18 |
--------------------------------------------------------------------------------
/lib/Column/CellView.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Column;
13 |
14 | use FSi\Component\DataGrid\DataGridViewInterface;
15 |
16 | class CellView implements CellViewInterface
17 | {
18 | /**
19 | * The original object from which the value of the cell was retrieved.
20 | *
21 | * @var mixed
22 | */
23 | protected $source;
24 |
25 | /**
26 | * Cell value. In most cases this should be a simple string.
27 | *
28 | * @var mixed
29 | */
30 | protected $value;
31 |
32 | /**
33 | * Cell attributes.
34 | *
35 | * @var array
36 | */
37 | protected $attributes = [];
38 |
39 | /**
40 | * Cell name.
41 | *
42 | * @var string
43 | */
44 | protected $name;
45 |
46 | /**
47 | * Cell type.
48 | *
49 | * @var string
50 | */
51 | protected $type;
52 |
53 | /**
54 | * @var DataGridViewInterface
55 | */
56 | protected $datagrid;
57 |
58 | public function __construct(string $name, string $type)
59 | {
60 | $this->name = $name;
61 | $this->type = $type;
62 | }
63 |
64 | public function getName(): string
65 | {
66 | return $this->name;
67 | }
68 |
69 | public function getType(): string
70 | {
71 | return $this->type;
72 | }
73 |
74 | public function setValue($value): void
75 | {
76 | $this->value = $value;
77 | }
78 |
79 | public function getValue()
80 | {
81 | return $this->value;
82 | }
83 |
84 | public function setAttribute(string $name, $value): void
85 | {
86 | $this->attributes[$name] = $value;
87 | }
88 |
89 | public function getAttribute(string $name)
90 | {
91 | if (array_key_exists($name, $this->attributes)) {
92 | return $this->attributes[$name];
93 | }
94 |
95 | return null;
96 | }
97 |
98 | public function getAttributes(): array
99 | {
100 | return $this->attributes;
101 | }
102 |
103 | public function hasAttribute(string $name): bool
104 | {
105 | return array_key_exists($name, $this->attributes);
106 | }
107 |
108 | public function setSource($source): void
109 | {
110 | $this->source = $source;
111 | }
112 |
113 | public function getSource()
114 | {
115 | return $this->source;
116 | }
117 |
118 | public function setDataGridView(DataGridViewInterface $dataGrid): void
119 | {
120 | $this->datagrid = $dataGrid;
121 | }
122 |
123 | public function getDataGridView(): DataGridViewInterface
124 | {
125 | return $this->datagrid;
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/lib/Column/CellViewInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Column;
13 |
14 | use FSi\Component\DataGrid\DataGridViewInterface;
15 |
16 | interface CellViewInterface
17 | {
18 | public function hasAttribute(string $name): bool;
19 |
20 | public function setAttribute(string $name, $value): void;
21 |
22 | public function getAttribute(string $name);
23 |
24 | public function getAttributes(): array;
25 |
26 | public function setSource($source): void;
27 |
28 | public function getSource();
29 |
30 | public function getValue();
31 |
32 | public function setValue($value): void;
33 |
34 | public function getType(): string;
35 |
36 | public function getName(): string;
37 |
38 | public function setDataGridView(DataGridViewInterface $dataGrid): void;
39 |
40 | public function getDataGridView(): DataGridViewInterface;
41 | }
42 |
--------------------------------------------------------------------------------
/lib/Column/ColumnAbstractType.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Column;
13 |
14 | use FSi\Component\DataGrid\DataGridInterface;
15 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
16 | use FSi\Component\DataGrid\Exception\DataGridColumnException;
17 | use FSi\Component\DataGrid\Exception\UnexpectedTypeException;
18 | use FSi\Component\DataGrid\Exception\UnknownOptionException;
19 | use Symfony\Component\OptionsResolver\OptionsResolver;
20 |
21 | abstract class ColumnAbstractType implements ColumnTypeInterface
22 | {
23 | /**
24 | * @var ColumnTypeExtensionInterface[]
25 | */
26 | protected $extensions = [];
27 |
28 | /**
29 | * @var array
30 | */
31 | protected $options = [];
32 |
33 | /**
34 | * @var string
35 | */
36 | protected $name;
37 |
38 | /**
39 | * This property is used when creating column view.
40 | * After ColumnView is created it is set to null.
41 | *
42 | * @var null|string
43 | */
44 | protected $index;
45 |
46 | /**
47 | * @var DataMapperInterface
48 | */
49 | protected $dataMapper;
50 |
51 | /**
52 | * @var DataGridInterface
53 | */
54 | protected $dataGrid;
55 |
56 | /**
57 | * @var OptionsResolver
58 | */
59 | private $optionsResolver;
60 |
61 | public function getName(): string
62 | {
63 | if (null === $this->name) {
64 | throw new DataGridColumnException('Use setName method to define column name in data grid');
65 | }
66 |
67 | return $this->name;
68 | }
69 |
70 | public function setName(string $name): void
71 | {
72 | $this->name = $name;
73 | }
74 |
75 | public function setDataGrid(DataGridInterface $dataGrid): void
76 | {
77 | $this->dataGrid = $dataGrid;
78 | }
79 |
80 | public function getDataGrid(): DataGridInterface
81 | {
82 | return $this->dataGrid;
83 | }
84 |
85 | public function setDataMapper(DataMapperInterface $dataMapper): void
86 | {
87 | $this->dataMapper = $dataMapper;
88 | }
89 |
90 | public function getDataMapper(): DataMapperInterface
91 | {
92 | if (null === $this->dataMapper) {
93 | $this->setDataMapper($this->dataGrid->getDataMapper());
94 | }
95 |
96 | return $this->dataMapper;
97 | }
98 |
99 | public function getValue($object)
100 | {
101 | $values = [];
102 | if (!$this->hasOption('field_mapping') || !count($this->getOption('field_mapping'))) {
103 | throw new DataGridColumnException(
104 | sprintf('"field_mapping" option is missing in column "%s"', $this->getName())
105 | );
106 | }
107 |
108 | foreach ($this->getOption('field_mapping') as $field) {
109 | $values[$field] = $this->getDataMapper()->getData($field, $object);
110 | }
111 |
112 | return $values;
113 | }
114 |
115 | public function createCellView($object, $index): CellViewInterface
116 | {
117 | $this->setIndex($index);
118 |
119 | $view = new CellView($this->getName(), $this->getId());
120 | $view->setSource($object);
121 | $view->setAttribute('row', $index);
122 | $dataMapper = $this->getDataMapper();
123 |
124 | if (!$dataMapper instanceof DataMapperInterface) {
125 | throw new UnexpectedTypeException($dataMapper, DataMapperInterface::class);
126 | }
127 |
128 | $values = $this->getValue($object);
129 |
130 | foreach ($this->getExtensions() as $extension) {
131 | $values = $extension->filterValue($this, $values);
132 | }
133 |
134 | $value = $this->filterValue($values);
135 | $view->setValue($value);
136 |
137 | foreach ($this->getExtensions() as $extension) {
138 | $extension->buildCellView($this, $view);
139 | }
140 |
141 | $this->buildCellView($view);
142 | $this->setIndex(null);
143 |
144 | return $view;
145 | }
146 |
147 | public function buildCellView(CellViewInterface $view): void
148 | {
149 | }
150 |
151 | public function createHeaderView(): HeaderViewInterface
152 | {
153 | $view = new HeaderView($this->getName(), $this->getId());
154 |
155 | foreach ($this->getExtensions() as $extension) {
156 | $extension->buildHeaderView($this, $view);
157 | }
158 |
159 | $this->buildHeaderView($view);
160 |
161 | return $view;
162 | }
163 |
164 | public function buildHeaderView(HeaderViewInterface $view): void
165 | {
166 | }
167 |
168 | public function setOption(string $name, $value): void
169 | {
170 | $this->options = $this->getOptionsResolver()->resolve(array_merge(
171 | is_array($this->options)
172 | ? $this->options
173 | : [],
174 | [$name => $value]
175 | ));
176 | }
177 |
178 | public function setOptions(array $options): void
179 | {
180 | $this->options = $this->getOptionsResolver()->resolve($options);
181 | }
182 |
183 | public function getOption(string $name)
184 | {
185 | if (!array_key_exists($name, $this->options)) {
186 | throw new UnknownOptionException(sprintf('Option "%s" is not available in column type "%s".', $name, $this->getId()));
187 | }
188 |
189 | return $this->options[$name];
190 | }
191 |
192 | public function hasOption(string $name): bool
193 | {
194 | return array_key_exists($name, $this->options);
195 | }
196 |
197 | public function bindData($data, $object, $index): void
198 | {
199 | foreach ($this->extensions as $extension) {
200 | $extension->bindData($this, $data, $object, $index);
201 | }
202 | }
203 |
204 | public function setExtensions(array $extensions): void
205 | {
206 | foreach ($extensions as $extension) {
207 | if (!$extension instanceof ColumnTypeExtensionInterface) {
208 | throw new UnexpectedTypeException($extension, ColumnTypeExtensionInterface::class);
209 | }
210 | }
211 |
212 | $this->extensions = $extensions;
213 | }
214 |
215 | public function addExtension(ColumnTypeExtensionInterface $extension): void
216 | {
217 | $this->extensions[] = $extension;
218 | }
219 |
220 | public function getExtensions(): array
221 | {
222 | return $this->extensions;
223 | }
224 |
225 | public function getOptionsResolver(): OptionsResolver
226 | {
227 | if (null === $this->optionsResolver) {
228 | $this->optionsResolver = new OptionsResolver();
229 | }
230 |
231 | return $this->optionsResolver;
232 | }
233 |
234 | public function initOptions(): void
235 | {
236 | }
237 |
238 | /**
239 | * @param int|string|null $index
240 | * @return void
241 | */
242 | protected function setIndex($index): void
243 | {
244 | $this->index = $index;
245 | }
246 |
247 | /**
248 | * @return int|string|null
249 | */
250 | protected function getIndex()
251 | {
252 | return $this->index;
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/lib/Column/ColumnAbstractTypeExtension.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Column;
13 |
14 | abstract class ColumnAbstractTypeExtension implements ColumnTypeExtensionInterface
15 | {
16 | public function bindData(ColumnTypeInterface $column, $data, $object, $index): void
17 | {
18 | }
19 |
20 | public function buildCellView(ColumnTypeInterface $column, CellViewInterface $view): void
21 | {
22 | }
23 |
24 | public function buildHeaderView(ColumnTypeInterface $column, HeaderViewInterface $view): void
25 | {
26 | }
27 |
28 | public function initOptions(ColumnTypeInterface $column): void
29 | {
30 | }
31 |
32 | public function filterValue(ColumnTypeInterface $column, $value)
33 | {
34 | return $value;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/Column/ColumnTypeExtensionInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Column;
13 |
14 | interface ColumnTypeExtensionInterface
15 | {
16 | public function bindData(ColumnTypeInterface $column, $data, $object, $index): void;
17 |
18 | public function buildCellView(ColumnTypeInterface $column, CellViewInterface $view): void;
19 |
20 | public function buildHeaderView(ColumnTypeInterface $column, HeaderViewInterface $view): void;
21 |
22 | public function filterValue(ColumnTypeInterface $column, $value);
23 |
24 | public function initOptions(ColumnTypeInterface $column);
25 |
26 | /**
27 | * @return string[]
28 | */
29 | public function getExtendedColumnTypes(): array;
30 | }
31 |
--------------------------------------------------------------------------------
/lib/Column/ColumnTypeInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Column;
13 |
14 | use FSi\Component\DataGrid\DataGridInterface;
15 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
16 | use Symfony\Component\OptionsResolver\OptionsResolver;
17 |
18 | interface ColumnTypeInterface
19 | {
20 | public function getId(): string;
21 |
22 | public function getName(): string;
23 |
24 | public function setName(string $name): void;
25 |
26 | public function setDataGrid(DataGridInterface $dataGrid): void;
27 |
28 | public function getDataGrid(): DataGridInterface;
29 |
30 | public function setDataMapper(DataMapperInterface $dataMapper): void;
31 |
32 | public function getDataMapper(): DataMapperInterface;
33 |
34 | public function filterValue($value);
35 |
36 | public function getValue($object);
37 |
38 | public function createCellView($object, $index): CellViewInterface;
39 |
40 | public function buildCellView(CellViewInterface $view): void;
41 |
42 | public function createHeaderView(): HeaderViewInterface;
43 |
44 | public function buildHeaderView(HeaderViewInterface $view): void;
45 |
46 | public function bindData($data, $object, $index): void;
47 |
48 | public function initOptions(): void;
49 |
50 | public function setOption(string $name, $value): void;
51 |
52 | public function setOptions(array $options): void;
53 |
54 | public function getOption(string $name);
55 |
56 | public function hasOption(string $name): bool;
57 |
58 | /**
59 | * @param ColumnTypeExtensionInterface[] $extensions
60 | */
61 | public function setExtensions(array $extensions): void;
62 |
63 | public function addExtension(ColumnTypeExtensionInterface $extension): void;
64 |
65 | /**
66 | * @return ColumnTypeExtensionInterface[]
67 | */
68 | public function getExtensions(): array;
69 |
70 | public function getOptionsResolver(): OptionsResolver;
71 | }
72 |
--------------------------------------------------------------------------------
/lib/Column/HeaderView.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Column;
13 |
14 | use FSi\Component\DataGrid\DataGridViewInterface;
15 |
16 | class HeaderView implements HeaderViewInterface
17 | {
18 | /**
19 | * @var string|null
20 | */
21 | protected $label;
22 |
23 | /**
24 | * @var string
25 | */
26 | protected $name;
27 |
28 | /**
29 | * @var string
30 | */
31 | protected $type;
32 |
33 | /**
34 | * @var array
35 | */
36 | protected $attributes = [];
37 |
38 | /**
39 | * @var DataGridViewInterface
40 | */
41 | protected $datagrid;
42 |
43 | public function __construct(string $name, string $type)
44 | {
45 | $this->name = $name;
46 | $this->type = $type;
47 | }
48 |
49 | public function setAttribute(string $name, $value): void
50 | {
51 | $this->attributes[$name] = $value;
52 | }
53 |
54 | public function getAttribute(string $name)
55 | {
56 | if (array_key_exists($name, $this->attributes)) {
57 | return $this->attributes[$name];
58 | }
59 |
60 | return null;
61 | }
62 |
63 | public function hasAttribute(string $name): bool
64 | {
65 | return array_key_exists($name, $this->attributes);
66 | }
67 |
68 | public function getAttributes(): array
69 | {
70 | return $this->attributes;
71 | }
72 |
73 | public function setLabel(string $label): void
74 | {
75 | $this->label = $label;
76 | }
77 |
78 | public function getLabel(): ?string
79 | {
80 | return $this->label;
81 | }
82 |
83 | public function getName(): string
84 | {
85 | return $this->name;
86 | }
87 |
88 | public function getType(): string
89 | {
90 | return $this->type;
91 | }
92 |
93 | public function setDataGridView(DataGridViewInterface $dataGrid): void
94 | {
95 | $this->datagrid = $dataGrid;
96 | }
97 |
98 | public function getDataGridView(): DataGridViewInterface
99 | {
100 | return $this->datagrid;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/lib/Column/HeaderViewInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Column;
13 |
14 | use FSi\Component\DataGrid\DataGridViewInterface;
15 |
16 | interface HeaderViewInterface
17 | {
18 | public function setAttribute(string $name, $value): void;
19 |
20 | public function getAttribute(string $name);
21 |
22 | public function hasAttribute(string $name): bool;
23 |
24 | public function getAttributes(): array;
25 |
26 | public function getLabel(): ?string;
27 |
28 | public function setLabel(string $value): void;
29 |
30 | public function getName(): string;
31 |
32 | public function getType(): string;
33 |
34 | public function setDataGridView(DataGridViewInterface $dataGrid): void;
35 |
36 | public function getDataGridView(): DataGridViewInterface;
37 | }
38 |
--------------------------------------------------------------------------------
/lib/Data/DataRowset.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Data;
13 |
14 | use InvalidArgumentException;
15 | use RuntimeException;
16 |
17 | class DataRowset implements DataRowsetInterface
18 | {
19 | /**
20 | * @var array
21 | */
22 | protected $data = [];
23 |
24 | public function __construct(iterable $data)
25 | {
26 | foreach ($data as $id => $element) {
27 | $this->data[$id] = $element;
28 | }
29 | }
30 |
31 | public function count(): int
32 | {
33 | return count($this->data);
34 | }
35 |
36 | public function current()
37 | {
38 | return current($this->data);
39 | }
40 |
41 | public function key()
42 | {
43 | return key($this->data);
44 | }
45 |
46 | public function next(): void
47 | {
48 | next($this->data);
49 | }
50 |
51 | public function rewind(): void
52 | {
53 | reset($this->data);
54 | }
55 |
56 | public function valid(): bool
57 | {
58 | return $this->key() !== null;
59 | }
60 |
61 | public function offsetExists($offset): bool
62 | {
63 | return array_key_exists($offset, $this->data);
64 | }
65 |
66 | public function offsetGet($offset)
67 | {
68 | if ($this->offsetExists($offset)) {
69 | return $this->data[$offset];
70 | }
71 |
72 | throw new InvalidArgumentException(sprintf('Row "%s" does not exist in rowset.', $offset));
73 | }
74 |
75 | public function offsetSet($offset, $value): void
76 | {
77 | throw new RuntimeException('Method not implemented');
78 | }
79 |
80 | public function offsetUnset($offset): void
81 | {
82 | throw new RuntimeException('Method not implemented');
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/Data/DataRowsetInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Data;
13 |
14 | interface DataRowsetInterface extends \Iterator, \Countable, \ArrayAccess
15 | {
16 | }
17 |
--------------------------------------------------------------------------------
/lib/DataGridAbstractExtension.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
15 | use FSi\Component\DataGrid\Column\ColumnTypeExtensionInterface;
16 | use FSi\Component\DataGrid\Exception\UnexpectedTypeException;
17 | use FSi\Component\DataGrid\Exception\DataGridException;
18 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19 |
20 | abstract class DataGridAbstractExtension implements DataGridExtensionInterface
21 | {
22 | /**
23 | * @var ColumnTypeExtensionInterface[][]
24 | */
25 | protected $columnTypesExtensions;
26 |
27 | /**
28 | * @var ColumnTypeInterface[]
29 | */
30 | protected $columnTypes;
31 |
32 | public function getColumnType(string $type): ColumnTypeInterface
33 | {
34 | if (null === $this->columnTypes) {
35 | $this->initColumnTypes();
36 | }
37 |
38 | if (!array_key_exists($type, $this->columnTypes)) {
39 | throw new DataGridException(sprintf(
40 | 'The column type "%s" can not be loaded by this extension',
41 | $type
42 | ));
43 | }
44 |
45 | return $this->columnTypes[$type];
46 | }
47 |
48 | public function hasColumnType(string $type): bool
49 | {
50 | if (null === $this->columnTypes) {
51 | $this->initColumnTypes();
52 | }
53 |
54 | return array_key_exists($type, $this->columnTypes);
55 | }
56 |
57 | public function hasColumnTypeExtensions(string $type): bool
58 | {
59 | if (null === $this->columnTypesExtensions) {
60 | $this->initColumnTypesExtensions();
61 | }
62 |
63 | return array_key_exists($type, $this->columnTypesExtensions);
64 | }
65 |
66 | public function getColumnTypeExtensions(string $type): array
67 | {
68 | if (null === $this->columnTypesExtensions) {
69 | $this->initColumnTypesExtensions();
70 | }
71 |
72 | if (!array_key_exists($type, $this->columnTypesExtensions)) {
73 | throw new DataGridException(sprintf(
74 | 'Extension for column type "%s" can not be loaded by this data grid extension',
75 | $type
76 | ));
77 | }
78 |
79 | return $this->columnTypesExtensions[$type];
80 | }
81 |
82 | public function registerSubscribers(DataGridInterface $dataGrid): void
83 | {
84 | $subscribers = $this->loadSubscribers();
85 |
86 | foreach ($subscribers as $subscriber) {
87 | if (!$subscriber instanceof EventSubscriberInterface) {
88 | throw new UnexpectedTypeException(sprintf(
89 | '"%s" is not instance of "%s"',
90 | $subscriber,
91 | EventSubscriberInterface::class
92 | ));
93 | }
94 |
95 | $dataGrid->addEventSubscriber($subscriber);
96 | }
97 | }
98 |
99 | /**
100 | * @return ColumnTypeInterface[]
101 | */
102 | protected function loadColumnTypes(): array
103 | {
104 | return [];
105 | }
106 |
107 | /**
108 | * @return EventSubscriberInterface[]
109 | */
110 | protected function loadSubscribers(): array
111 | {
112 | return [];
113 | }
114 |
115 | /**
116 | * @return ColumnTypeExtensionInterface[]
117 | */
118 | protected function loadColumnTypesExtensions(): array
119 | {
120 | return [];
121 | }
122 |
123 | private function initColumnTypes(): void
124 | {
125 | $this->columnTypes = [];
126 |
127 | $columnTypes = $this->loadColumnTypes();
128 |
129 | foreach ($columnTypes as $columnType) {
130 | if (!$columnType instanceof ColumnTypeInterface) {
131 | throw new UnexpectedTypeException(sprintf(
132 | 'Column type must implement "%s"',
133 | ColumnTypeInterface::class
134 | ));
135 | }
136 |
137 | $this->columnTypes[$columnType->getId()] = $columnType;
138 | }
139 | }
140 |
141 | private function initColumnTypesExtensions(): void
142 | {
143 | $columnTypesExtensions = $this->loadColumnTypesExtensions();
144 | $this->columnTypesExtensions = [];
145 |
146 | foreach ($columnTypesExtensions as $extension) {
147 | if (!$extension instanceof ColumnTypeExtensionInterface) {
148 | throw new UnexpectedTypeException(sprintf(
149 | 'Extension must implement %s',
150 | ColumnTypeExtensionInterface::class
151 | ));
152 | }
153 |
154 | $types = $extension->getExtendedColumnTypes();
155 | foreach ($types as $type) {
156 | if (!array_key_exists($type, $this->columnTypesExtensions)) {
157 | $this->columnTypesExtensions[$type] = [];
158 | }
159 |
160 | $this->columnTypesExtensions[$type][] = $extension;
161 | }
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/lib/DataGridEvent.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | use FSi\Component\DataGrid\DataGridInterface;
15 | use FSi\Component\DataGrid\DataGridEventInterface;
16 | use Symfony\Component\EventDispatcher\Event;
17 |
18 | class DataGridEvent extends Event implements DataGridEventInterface
19 | {
20 | /**
21 | * @var DataGridInterface
22 | */
23 | protected $dataGrid;
24 |
25 | /**
26 | * @var mixed
27 | */
28 | protected $data;
29 |
30 | public function __construct(DataGridInterface $dataGrid, $data)
31 | {
32 | $this->dataGrid = $dataGrid;
33 | $this->data = $data;
34 | }
35 |
36 | public function getDataGrid(): DataGridInterface
37 | {
38 | return $this->dataGrid;
39 | }
40 |
41 | public function getData()
42 | {
43 | return $this->data;
44 | }
45 |
46 | public function setData($data): void
47 | {
48 | $this->data = $data;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/lib/DataGridEventInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | interface DataGridEventInterface
15 | {
16 | public function getDataGrid(): DataGridInterface;
17 |
18 | public function getData();
19 |
20 | public function setData($data): void;
21 | }
22 |
--------------------------------------------------------------------------------
/lib/DataGridEvents.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | final class DataGridEvents
15 | {
16 | public const PRE_SET_DATA = 'datagrid.pre_set_data';
17 |
18 | public const POST_SET_DATA = 'datagrid.post_set_data';
19 |
20 | public const PRE_BIND_DATA = 'datagrid.pre_bind_data';
21 |
22 | public const POST_BIND_DATA = 'datagrid.post_bind_data';
23 |
24 | public const PRE_BUILD_VIEW = 'datagrid.pre_build_view';
25 |
26 | public const POST_BUILD_VIEW = 'datagrid.post_build_view';
27 | }
28 |
--------------------------------------------------------------------------------
/lib/DataGridExtensionInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnTypeExtensionInterface;
15 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
16 |
17 | interface DataGridExtensionInterface
18 | {
19 | public function registerSubscribers(DataGridInterface $dataGrid): void;
20 |
21 | public function hasColumnType(string $type): bool;
22 |
23 | public function getColumnType(string $type): ColumnTypeInterface;
24 |
25 | public function hasColumnTypeExtensions(string $type): bool;
26 |
27 | /**
28 | * @param string $type
29 | * @return ColumnTypeExtensionInterface[]
30 | */
31 | public function getColumnTypeExtensions(string $type): array;
32 | }
33 |
--------------------------------------------------------------------------------
/lib/DataGridFactory.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
15 | use FSi\Component\DataGrid\Exception\DataGridColumnException;
16 | use FSi\Component\DataGrid\Exception\UnexpectedTypeException;
17 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
18 | use InvalidArgumentException;
19 |
20 | class DataGridFactory implements DataGridFactoryInterface
21 | {
22 | /**
23 | * @var DataGridInterface[]
24 | */
25 | protected $dataGrids = [];
26 |
27 | /**
28 | * @var ColumnTypeInterface[]
29 | */
30 | protected $columnTypes = [];
31 |
32 | /**
33 | * @var DataMapperInterface
34 | */
35 | protected $dataMapper;
36 |
37 | /**
38 | * @var DataGridExtensionInterface[]
39 | */
40 | protected $extensions = [];
41 |
42 | /**
43 | * @param DataGridExtensionInterface[] $extensions
44 | * @param DataMapperInterface $dataMapper
45 | * @throws InvalidArgumentException
46 | */
47 | public function __construct(array $extensions, DataMapperInterface $dataMapper)
48 | {
49 | foreach ($extensions as $extension) {
50 | if (!$extension instanceof DataGridExtensionInterface) {
51 | throw new InvalidArgumentException(sprintf(
52 | 'Each extension must implement "%s"',
53 | DataGridExtensionInterface::class
54 | ));
55 | }
56 | }
57 |
58 | $this->dataMapper = $dataMapper;
59 | $this->extensions = $extensions;
60 | }
61 |
62 | public function createDataGrid(string $name = 'grid'): DataGridInterface
63 | {
64 | if (array_key_exists($name, $this->dataGrids)) {
65 | throw new DataGridColumnException(sprintf(
66 | 'Datagrid name "%s" is not uniqe, it was used before to create datagrid',
67 | $name
68 | ));
69 | }
70 |
71 | $this->dataGrids[$name] = new DataGrid($name, $this, $this->dataMapper);
72 |
73 | return $this->dataGrids[$name];
74 | }
75 |
76 | public function hasColumnType(string $type): bool
77 | {
78 | if (array_key_exists($type, $this->columnTypes)) {
79 | return true;
80 | }
81 |
82 | try {
83 | $this->loadColumnType($type);
84 | } catch (UnexpectedTypeException $e) {
85 | return false;
86 | }
87 |
88 | return true;
89 | }
90 |
91 | /**
92 | * @param string $type
93 | * @return ColumnTypeInterface
94 | * @throws UnexpectedTypeException
95 | */
96 | public function getColumnType(string $type): ColumnTypeInterface
97 | {
98 | if ($this->hasColumnType($type)) {
99 | return clone $this->columnTypes[$type];
100 | }
101 |
102 | $this->loadColumnType($type);
103 |
104 | return clone $this->columnTypes[$type];
105 | }
106 |
107 | public function getExtensions(): array
108 | {
109 | return $this->extensions;
110 | }
111 |
112 | public function getDataMapper(): DataMapperInterface
113 | {
114 | return $this->dataMapper;
115 | }
116 |
117 | /**
118 | * @param string $type
119 | * @throws UnexpectedTypeException
120 | */
121 | private function loadColumnType(string $type): void
122 | {
123 | if (isset($this->columnTypes[$type])) {
124 | return;
125 | }
126 |
127 | $typeInstance = null;
128 | foreach ($this->extensions as $extension) {
129 | if ($extension->hasColumnType($type)) {
130 | $typeInstance = $extension->getColumnType($type);
131 | break;
132 | }
133 | }
134 |
135 | if (null === $typeInstance) {
136 | throw new UnexpectedTypeException(sprintf(
137 | 'There is no column with type "%s" registered in factory.',
138 | $type
139 | ));
140 | }
141 |
142 | foreach ($this->extensions as $extension) {
143 | if ($extension->hasColumnTypeExtensions($type)) {
144 | $columnExtensions = $extension->getColumnTypeExtensions($type);
145 | foreach ($columnExtensions as $columnExtension) {
146 | $typeInstance->addExtension($columnExtension);
147 | }
148 | }
149 | }
150 |
151 | $this->columnTypes[$type] = $typeInstance;
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/lib/DataGridFactoryInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
15 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
16 |
17 | interface DataGridFactoryInterface
18 | {
19 | public function hasColumnType(string $type): bool;
20 |
21 | public function getColumnType(string $type): ColumnTypeInterface;
22 |
23 | /**
24 | * @return DataGridExtensionInterface[]
25 | */
26 | public function getExtensions(): array;
27 |
28 | public function createDataGrid(string $name = 'grid'): DataGridInterface;
29 |
30 | public function getDataMapper(): DataMapperInterface;
31 | }
32 |
--------------------------------------------------------------------------------
/lib/DataGridInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
15 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
16 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17 |
18 | interface DataGridInterface
19 | {
20 | public function getName(): string;
21 |
22 | public function getDataMapper(): DataMapperInterface;
23 |
24 | public function addColumn($name, string $type = 'text', array $options = []): DataGridInterface;
25 |
26 | public function removeColumn(string $name): DataGridInterface;
27 |
28 | public function clearColumns(): DataGridInterface;
29 |
30 | public function getColumn(string $name): ColumnTypeInterface;
31 |
32 | /**
33 | * @return ColumnTypeInterface[]
34 | */
35 | public function getColumns(): array;
36 |
37 | public function hasColumn(string $name): bool;
38 |
39 | public function hasColumnType(string $type): bool;
40 |
41 | public function createView(): DataGridViewInterface;
42 |
43 | public function setData(iterable $data): void;
44 |
45 | public function bindData($data): void;
46 |
47 | public function addEventListener(string $eventName, callable $listener, int $priority = 0): DataGridInterface;
48 |
49 | public function addEventSubscriber(EventSubscriberInterface $subscriber): DataGridInterface;
50 | }
51 |
--------------------------------------------------------------------------------
/lib/DataGridRowView.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | use FSi\Component\DataGrid\Column\CellViewInterface;
15 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
16 | use FSi\Component\DataGrid\Exception\UnexpectedTypeException;
17 | use InvalidArgumentException;
18 | use RuntimeException;
19 |
20 | class DataGridRowView implements DataGridRowViewInterface
21 | {
22 | /**
23 | * @var CellViewInterface[]
24 | */
25 | protected $cellViews = [];
26 |
27 | /**
28 | * @var mixed
29 | */
30 | protected $source;
31 |
32 | /**
33 | * @var int
34 | */
35 | protected $index;
36 |
37 | /**
38 | * @param DataGridViewInterface $dataGridView
39 | * @param ColumnTypeInterface[] $columns
40 | * @param mixed $source
41 | * @param int $index
42 | * @throws Exception\UnexpectedTypeException
43 | */
44 | public function __construct(DataGridViewInterface $dataGridView, array $columns, $source, $index)
45 | {
46 | $this->source = $source;
47 | $this->index = $index;
48 | foreach ($columns as $name => $column) {
49 | if (!$column instanceof ColumnTypeInterface) {
50 | throw new UnexpectedTypeException(sprintf(
51 | 'Column object must implement "%s"',
52 | ColumnTypeInterface::class
53 | ));
54 | }
55 |
56 | $cellView = $column->createCellView($this->source, $index);
57 | $cellView->setDataGridView($dataGridView);
58 |
59 | $this->cellViews[$name] = $cellView;
60 | }
61 | }
62 |
63 | public function getIndex()
64 | {
65 | return $this->index;
66 | }
67 |
68 | public function getSource()
69 | {
70 | return $this->source;
71 | }
72 |
73 | public function count(): int
74 | {
75 | return count($this->cellViews);
76 | }
77 |
78 | public function current(): CellViewInterface
79 | {
80 | return current($this->cellViews);
81 | }
82 |
83 | public function key(): ?string
84 | {
85 | return key($this->cellViews);
86 | }
87 |
88 | public function next(): void
89 | {
90 | next($this->cellViews);
91 | }
92 |
93 | public function rewind(): void
94 | {
95 | reset($this->cellViews);
96 | }
97 |
98 | public function valid(): bool
99 | {
100 | return $this->key() !== null;
101 | }
102 |
103 | public function offsetExists($offset): bool
104 | {
105 | return array_key_exists($offset, $this->cellViews);
106 | }
107 |
108 | public function offsetGet($offset): CellViewInterface
109 | {
110 | if ($this->offsetExists($offset)) {
111 | return $this->cellViews[$offset];
112 | }
113 |
114 | throw new InvalidArgumentException(sprintf('Column "%s" does not exist in row.', $offset));
115 | }
116 |
117 | public function offsetSet($offset, $value): void
118 | {
119 | throw new RuntimeException('Method not implemented');
120 | }
121 |
122 | public function offsetUnset($offset): void
123 | {
124 | throw new RuntimeException('Method not implemented');
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/lib/DataGridRowViewInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | interface DataGridRowViewInterface extends \Iterator, \Countable, \ArrayAccess
15 | {
16 | public function getIndex();
17 |
18 | public function getSource();
19 | }
20 |
--------------------------------------------------------------------------------
/lib/DataGridView.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | use FSi\Component\DataGrid\Data\DataRowsetInterface;
15 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
16 | use FSi\Component\DataGrid\Column\HeaderViewInterface;
17 | use RuntimeException;
18 |
19 | class DataGridView implements DataGridViewInterface
20 | {
21 | /**
22 | * @var ColumnTypeInterface[]
23 | */
24 | protected $columns = [];
25 |
26 | /**
27 | * @var HeaderViewInterface[]
28 | */
29 | protected $columnsHeaders = [];
30 |
31 | /**
32 | * @var string
33 | */
34 | protected $name;
35 |
36 | /**
37 | * @var DataRowsetInterface
38 | */
39 | protected $rowset;
40 |
41 | /**
42 | * @param string $name
43 | * @param ColumnTypeInterface[] $columns
44 | * @param DataRowsetInterface $rowset
45 | * @throws \InvalidArgumentException
46 | */
47 | public function __construct(string $name, array $columns = [], DataRowsetInterface $rowset)
48 | {
49 | foreach ($columns as $column) {
50 | if (!$column instanceof ColumnTypeInterface) {
51 | throw new \InvalidArgumentException('Column must implement FSi\Component\DataGrid\Column\ColumnTypeInterface');
52 | }
53 |
54 | $this->columns[$column->getName()] = $column;
55 | $headerView = $column->createHeaderView();
56 | $headerView->setDataGridView($this);
57 | $this->columnsHeaders[$column->getName()] = $headerView;
58 | }
59 |
60 | $this->name = $name;
61 | $this->rowset = $rowset;
62 | }
63 |
64 | public function getName(): string
65 | {
66 | return $this->name;
67 | }
68 |
69 | public function hasColumn(string $name): bool
70 | {
71 | return array_key_exists($name, $this->columnsHeaders);
72 | }
73 |
74 | public function hasColumnType(string $type): bool
75 | {
76 | foreach ($this->columnsHeaders as $header) {
77 | if ($header->getType() === $type) {
78 | return true;
79 | }
80 | }
81 |
82 | return false;
83 | }
84 |
85 | public function removeColumn(string $name): void
86 | {
87 | if (array_key_exists($name, $this->columnsHeaders)) {
88 | unset($this->columnsHeaders[$name]);
89 | }
90 | }
91 |
92 | public function getColumn(string $name): HeaderViewInterface
93 | {
94 | if ($this->hasColumn($name)) {
95 | return $this->columnsHeaders[$name];
96 | }
97 |
98 | throw new \InvalidArgumentException(sprintf('Column "%s" does not exist in data grid.', $name));
99 | }
100 |
101 | public function getColumns(): array
102 | {
103 | return $this->columnsHeaders;
104 | }
105 |
106 | public function clearColumns(): void
107 | {
108 | $this->columnsHeaders = [];
109 | }
110 |
111 | public function addColumn(HeaderViewInterface $column): void
112 | {
113 | if (!array_key_exists($column->getName(), $this->columns)) {
114 | throw new \InvalidArgumentException(sprintf(
115 | 'Column with name "%s" was never registred in datagrid "%s"',
116 | $column->getName(),
117 | $this->getName()
118 | ));
119 | }
120 |
121 | $this->columnsHeaders[$column->getName()] = $column;
122 | }
123 |
124 | public function setColumns(array $columns): void
125 | {
126 | $this->columnsHeaders = [];
127 |
128 | foreach ($columns as $column) {
129 | if (!$column instanceof HeaderViewInterface) {
130 | throw new \InvalidArgumentException('Column must implement FSi\Component\DataGrid\Column\HeaderViewInterface');
131 | }
132 |
133 | if (!array_key_exists($column->getName(), $this->columns)) {
134 | throw new \InvalidArgumentException(sprintf(
135 | 'Column with name "%s" was never registred in datagrid "%s"',
136 | $column->getName(),
137 | $this->getName()
138 | ));
139 | }
140 |
141 | $this->columnsHeaders[$column->getName()] = $column;
142 | }
143 | }
144 |
145 | public function count(): int
146 | {
147 | return $this->rowset->count();
148 | }
149 |
150 | /**
151 | * @return string[]
152 | */
153 | public function getIndexes(): array
154 | {
155 | $indexes = [];
156 | foreach ($this->rowset as $index => $row) {
157 | $indexes[] = $index;
158 | }
159 |
160 | return $indexes;
161 | }
162 |
163 | public function current(): DataGridRowViewInterface
164 | {
165 | $index = $this->rowset->key();
166 |
167 | return new DataGridRowView($this, $this->getOriginColumns(), $this->rowset->current(), $index);
168 | }
169 |
170 | public function key()
171 | {
172 | return $this->rowset->key();
173 | }
174 |
175 | public function next(): void
176 | {
177 | $this->rowset->next();
178 | }
179 |
180 | public function rewind(): void
181 | {
182 | $this->rowset->rewind();
183 | }
184 |
185 | public function valid(): bool
186 | {
187 | return $this->rowset->valid();
188 | }
189 |
190 | public function offsetExists($offset): bool
191 | {
192 | return isset($this->rowset[$offset]);
193 | }
194 |
195 | public function offsetGet($offset)
196 | {
197 | if ($this->offsetExists($offset)) {
198 | return new DataGridRowView($this, $this->getOriginColumns(), $this->rowset[$offset], $offset);
199 | }
200 |
201 | throw new \InvalidArgumentException(sprintf('Row "%s" does not exist in rowset.', $offset));
202 | }
203 |
204 | public function offsetSet($offset, $value): void
205 | {
206 | throw new RuntimeException('Method not implemented');
207 | }
208 |
209 | public function offsetUnset($offset): void
210 | {
211 | throw new RuntimeException('Method not implemented');
212 | }
213 |
214 | /**
215 | * @return ColumnTypeInterface[]
216 | */
217 | protected function getOriginColumns(): array
218 | {
219 | $columns = [];
220 | foreach ($this->columnsHeaders as $name => $header) {
221 | $columns[$name] = $this->columns[$name];
222 | }
223 |
224 | return $columns;
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/lib/DataGridViewInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid;
13 |
14 | use FSi\Component\DataGrid\Column\HeaderViewInterface;
15 |
16 | interface DataGridViewInterface extends \Iterator, \Countable, \ArrayAccess
17 | {
18 | public function getName(): string;
19 |
20 | public function hasColumn(string $name): bool;
21 |
22 | public function hasColumnType(string $type): bool;
23 |
24 | public function removeColumn(string $name): void;
25 |
26 | public function getColumn(string $name): HeaderViewInterface;
27 |
28 | /**
29 | * @return HeaderViewInterface[]
30 | */
31 | public function getColumns(): array;
32 |
33 | public function clearColumns(): void;
34 |
35 | public function addColumn(HeaderViewInterface $column): void;
36 |
37 | /**
38 | * @param HeaderViewInterface[] $columns
39 | */
40 | public function setColumns(array $columns): void;
41 | }
42 |
--------------------------------------------------------------------------------
/lib/DataMapper/ChainMapper.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\DataMapper;
13 |
14 | use FSi\Component\DataGrid\Exception\DataMappingException;
15 | use InvalidArgumentException;
16 |
17 | class ChainMapper implements DataMapperInterface
18 | {
19 | /**
20 | * @var DataMapperInterface[]
21 | */
22 | protected $mappers = [];
23 |
24 | /**
25 | * @param DataMapperInterface[] $mappers
26 | * @throws InvalidArgumentException
27 | */
28 | public function __construct(array $mappers)
29 | {
30 | if (!count($mappers)) {
31 | throw new InvalidArgumentException('There must be at least one mapper in chain.');
32 | }
33 |
34 | foreach ($mappers as $mapper) {
35 | if (!$mapper instanceof DataMapperInterface) {
36 | throw new InvalidArgumentException(
37 | sprintf('Mapper needs to implement "%s"', DataMapperInterface::class)
38 | );
39 | }
40 |
41 | $this->mappers[] = $mapper;
42 | }
43 | }
44 |
45 | /**
46 | * @inheritdoc
47 | */
48 | public function getData(string $field, $object)
49 | {
50 | $data = null;
51 | $dataFound = false;
52 | $lastMsg = null;
53 |
54 | foreach ($this->mappers as $mapper) {
55 | try {
56 | $data = $mapper->getData($field, $object);
57 | } catch (DataMappingException $e) {
58 | $data = null;
59 | $lastMsg = $e->getMessage();
60 |
61 | continue;
62 | }
63 |
64 | $dataFound = true;
65 | break;
66 | }
67 |
68 | if (!$dataFound) {
69 | if (null === $lastMsg) {
70 | $lastMsg = sprintf('Cant find any data that fit "%s" field.', $field);
71 | }
72 |
73 | throw new DataMappingException($lastMsg);
74 | }
75 |
76 | return $data;
77 | }
78 |
79 | /**
80 | * @inheritdoc
81 | */
82 | public function setData(string $field, $object, $value): void
83 | {
84 | $dataChanged = false;
85 | $lastMsg = null;
86 |
87 | foreach ($this->mappers as $mapper) {
88 | try {
89 | $mapper->setData($field, $object, $value);
90 | } catch (DataMappingException $e) {
91 | $lastMsg = $e->getMessage();
92 | continue;
93 | }
94 |
95 | $dataChanged = true;
96 | break;
97 | }
98 |
99 | if (!$dataChanged) {
100 | if (!isset($lastMsg)) {
101 | $lastMsg = sprintf('Cant find any data that fit "%s" field.', $field);
102 | }
103 |
104 | throw new DataMappingException($lastMsg);
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/lib/DataMapper/DataMapperInterface.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\DataMapper;
13 |
14 | use FSi\Component\DataGrid\Exception\DataMappingException;
15 |
16 | interface DataMapperInterface
17 | {
18 | /**
19 | * @param string $field
20 | * @param mixed $object
21 | * @return mixed
22 | * @throws DataMappingException
23 | */
24 | public function getData(string $field, $object);
25 |
26 | /**
27 | * @param string $field
28 | * @param mixed $object
29 | * @param mixed $value
30 | * @throws DataMappingException
31 | */
32 | public function setData(string $field, $object, $value): void;
33 | }
34 |
--------------------------------------------------------------------------------
/lib/DataMapper/PropertyAccessorMapper.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\DataMapper;
13 |
14 | use FSi\Component\DataGrid\Exception\DataMappingException;
15 | use Symfony\Component\PropertyAccess\Exception\RuntimeException;
16 | use Symfony\Component\PropertyAccess\PropertyAccess;
17 |
18 | class PropertyAccessorMapper implements DataMapperInterface
19 | {
20 | /**
21 | * @inheritdoc
22 | */
23 | public function getData(string $field, $object)
24 | {
25 | $accessor = PropertyAccess::createPropertyAccessor();
26 |
27 | try {
28 | $data = $accessor->getValue($object, $field);
29 | } catch (RuntimeException $e) {
30 | throw new DataMappingException($e->getMessage());
31 | }
32 |
33 | return $data;
34 | }
35 |
36 | /**
37 | * @inheritdoc
38 | */
39 | public function setData(string $field, $object, $value): void
40 | {
41 | $accessor = PropertyAccess::createPropertyAccessor();
42 |
43 | try {
44 | $accessor->setValue($object, $field, $value);
45 | } catch (RuntimeException $e) {
46 | throw new DataMappingException($e->getMessage());
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lib/DataMapper/ReflectionMapper.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\DataMapper;
13 |
14 | use FSi\Component\Reflection\ReflectionClass;
15 | use FSi\Component\DataGrid\Exception\DataMappingException;
16 |
17 | class ReflectionMapper implements DataMapperInterface
18 | {
19 | /**
20 | * @inheritdoc
21 | */
22 | public function getData(string $field, $object)
23 | {
24 | if (!is_object($object)) {
25 | throw new DataMappingException('Reflection mapper needs object to retrieve data.');
26 | }
27 |
28 | $objectReflection = ReflectionClass::factory($object);
29 | $camelField = $this->camelize($field);
30 | $getter = 'get' . $camelField;
31 | $isser = 'is' . $camelField;
32 | $hasser = 'has' . $camelField;
33 |
34 | if ($objectReflection->hasMethod($getter)) {
35 | if (!$objectReflection->getMethod($getter)->isPublic()) {
36 | throw new DataMappingException(sprintf('Method "%s()" is not public in class "%s"', $getter, $objectReflection->name));
37 | }
38 |
39 | return $object->$getter();
40 | }
41 |
42 | if ($objectReflection->hasMethod($isser)) {
43 | if (!$objectReflection->getMethod($isser)->isPublic()) {
44 | throw new DataMappingException(sprintf('Method "%s()" is not public in class "%s"', $isser, $objectReflection->name));
45 | }
46 |
47 | return $object->$isser();
48 | }
49 |
50 | if ($objectReflection->hasMethod($hasser)) {
51 | if (!$objectReflection->getMethod($hasser)->isPublic()) {
52 | throw new DataMappingException(sprintf('Method "%s()" is not public in class "%s"', $hasser, $objectReflection->name));
53 | }
54 |
55 | return $object->$hasser();
56 | }
57 |
58 | if ($objectReflection->hasProperty($field)) {
59 | if (!$objectReflection->getProperty($field)->isPublic()) {
60 | throw new DataMappingException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "%s()" or "%s()"?', $field, $objectReflection->name, $getter, $isser));
61 | }
62 | $property = $objectReflection->getProperty($field);
63 | return $property->getValue($object);
64 | }
65 |
66 | throw new DataMappingException(sprintf('Neither property "%s" nor method "%s()" nor method "%s()" exists in class "%s"', $field, $getter, $isser, $objectReflection->name));
67 | }
68 |
69 | /**
70 | * @inheritdoc
71 | */
72 | public function setData(string $field, $object, $value): void
73 | {
74 | if (!is_object($object)) {
75 | throw new DataMappingException('Reflection mapper needs object to retrieve data.');
76 | }
77 |
78 | $objectReflection = ReflectionClass::factory($object);
79 | $camelField = $this->camelize($field);
80 | $setter = 'set' . $camelField;
81 | $adder = 'add' . $camelField;
82 |
83 | if ($objectReflection->hasMethod($setter)) {
84 | if (!$objectReflection->getMethod($setter)->isPublic()) {
85 | throw new DataMappingException(sprintf(
86 | 'Method "%s()" is not public in class "%s"',
87 | $setter,
88 | $objectReflection->name
89 | ));
90 | }
91 |
92 | $object->$setter($value);
93 |
94 | return;
95 | }
96 |
97 | if ($objectReflection->hasMethod($adder)) {
98 | if (!$objectReflection->getMethod($adder)->isPublic()) {
99 | throw new DataMappingException(sprintf(
100 | 'Method "%s()" is not public in class "%s"',
101 | $adder,
102 | $objectReflection->name
103 | ));
104 | }
105 |
106 | $object->$adder($value);
107 |
108 | return;
109 | }
110 |
111 | if ($objectReflection->hasProperty($field)) {
112 | if (!$objectReflection->getProperty($field)->isPublic()) {
113 | throw new DataMappingException(sprintf(
114 | 'Property "%s" is not public in class "%s". Maybe you should create method "%s()" or "%s()"?',
115 | $field,
116 | $objectReflection->name,
117 | $setter,
118 | $adder
119 | ));
120 | }
121 |
122 | $property = $objectReflection->getProperty($field);
123 | $property->setValue($object, $value);
124 |
125 | return;
126 | }
127 |
128 | throw new DataMappingException(sprintf(
129 | 'Neither property "%s" nor method "%s()" exists in class "%s"',
130 | $setter,
131 | $adder,
132 | $objectReflection->name
133 | ));
134 | }
135 |
136 | private function camelize(string $string): string
137 | {
138 | return preg_replace_callback('/(^|_|\.)+(.)/', function ($match) {
139 | return ('.' === $match[1] ? '_' : '').strtoupper($match[2]);
140 | }, $string);
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/lib/Exception/DataGridColumnException.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Exception;
13 |
14 | class DataGridColumnException extends DataGridException
15 | {
16 | }
17 |
--------------------------------------------------------------------------------
/lib/Exception/DataGridException.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Exception;
13 |
14 | class DataGridException extends \Exception
15 | {
16 | }
17 |
--------------------------------------------------------------------------------
/lib/Exception/DataMappingException.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Exception;
13 |
14 | class DataMappingException extends DataGridException
15 | {
16 | }
17 |
--------------------------------------------------------------------------------
/lib/Exception/UnexpectedTypeException.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Exception;
13 |
14 | class UnexpectedTypeException extends DataGridException
15 | {
16 | }
17 |
--------------------------------------------------------------------------------
/lib/Exception/UnknownOptionException.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Exception;
13 |
14 | class UnknownOptionException extends DataGridException
15 | {
16 | }
17 |
--------------------------------------------------------------------------------
/lib/Extension/Core/ColumnType/Action.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
15 | use Symfony\Component\OptionsResolver\OptionsResolver;
16 | use Symfony\Component\OptionsResolver\Options;
17 |
18 | class Action extends ColumnAbstractType
19 | {
20 | /**
21 | * @var OptionsResolver
22 | */
23 | protected $actionOptionsResolver;
24 |
25 | public function __construct()
26 | {
27 | $this->actionOptionsResolver = new OptionsResolver();
28 | }
29 |
30 | public function getId(): string
31 | {
32 | return 'action';
33 | }
34 |
35 | public function filterValue($value)
36 | {
37 | $return = [];
38 | $actions = $this->getOption('actions');
39 |
40 | foreach ($actions as $name => $options) {
41 | $options = $this->actionOptionsResolver->resolve((array) $options);
42 | $return[$name] = [];
43 |
44 | $url = (isset($options['protocol'], $options['domain'])) ? $options['protocol'] . $options['domain'] : '';
45 | $url .= vsprintf ($options['uri_scheme'], $value);
46 |
47 | if (isset($options['redirect_uri']) && is_string($options['redirect_uri'])) {
48 | if (strpos($url, '?') !== false) {
49 | $url .= '&redirect_uri=' . urlencode($options['redirect_uri']);
50 | } else {
51 | $url .= '?redirect_uri=' . urlencode($options['redirect_uri']);
52 | }
53 | }
54 |
55 | $return[$name]['url'] = $url;
56 | $return[$name]['field_mapping_values'] = $value;
57 | }
58 |
59 | return $return;
60 | }
61 |
62 | public function initOptions(): void
63 | {
64 | $this->getOptionsResolver()->setDefaults([
65 | 'actions' => [],
66 | ]);
67 |
68 | $this->getOptionsResolver()->setAllowedTypes('actions', 'array');
69 |
70 | $this->actionOptionsResolver->setDefaults([
71 | 'redirect_uri' => null,
72 | 'domain' => null,
73 | 'protocol' => 'http://'
74 | ]);
75 |
76 | $this->actionOptionsResolver->setRequired([
77 | 'uri_scheme'
78 | ]);
79 |
80 | $this->actionOptionsResolver->setAllowedTypes('redirect_uri', ['string', 'null']);
81 | $this->actionOptionsResolver->setAllowedTypes('uri_scheme', 'string');
82 | $this->actionOptionsResolver->setAllowedValues('protocol', ['http://', 'https://']);
83 | }
84 |
85 | public function getActionOptionsResolver(): OptionsResolver
86 | {
87 | return $this->actionOptionsResolver;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/lib/Extension/Core/ColumnType/Batch.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
15 | use FSi\Component\DataGrid\Column\CellViewInterface;
16 | use FSi\Component\DataGrid\Column\HeaderViewInterface;
17 |
18 | class Batch extends ColumnAbstractType
19 | {
20 | public function getId(): string
21 | {
22 | return 'batch';
23 | }
24 |
25 | public function filterValue($value)
26 | {
27 | return $this->getIndex();
28 | }
29 |
30 | public function getValue($object)
31 | {
32 | return null;
33 | }
34 |
35 | public function buildCellView(CellViewInterface $view): void
36 | {
37 | $view->setAttribute('datagrid_name', $this->getDataGrid()->getName());
38 | }
39 |
40 | public function buildHeaderView(HeaderViewInterface $view): void
41 | {
42 | $view->setAttribute('datagrid_name', $this->getDataGrid()->getName());
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/lib/Extension/Core/ColumnType/Boolean.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
15 |
16 | class Boolean extends ColumnAbstractType
17 | {
18 | public function getId(): string
19 | {
20 | return 'boolean';
21 | }
22 |
23 | public function filterValue($value)
24 | {
25 | $value = (array) $value;
26 |
27 | $boolValue = null;
28 | foreach ($value as $val) {
29 | if ($val === null) {
30 | continue;
31 | }
32 |
33 | if ((bool) $val === false) {
34 | $boolValue = false;
35 | break;
36 | }
37 |
38 | $boolValue = true;
39 | }
40 |
41 | if (null === $boolValue) {
42 | return '';
43 | }
44 |
45 | return $this->getOption($boolValue ? 'true_value' : 'false_value');
46 | }
47 |
48 | public function initOptions(): void
49 | {
50 | $this->getOptionsResolver()->setDefaults([
51 | 'true_value' => '',
52 | 'false_value' => ''
53 | ]);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/Extension/Core/ColumnType/Collection.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
15 |
16 | class Collection extends ColumnAbstractType
17 | {
18 | public function getId(): string
19 | {
20 | return 'collection';
21 | }
22 |
23 | public function filterValue($value)
24 | {
25 | $value = (array) $value;
26 | foreach ($value as &$val) {
27 | if (!is_array($val)) {
28 | continue;
29 | }
30 |
31 | $val = implode($this->getOption('collection_glue'), $val);
32 | }
33 |
34 | return $value;
35 | }
36 |
37 | public function initOptions(): void
38 | {
39 | $this->getOptionsResolver()->setDefaults([
40 | 'collection_glue' => ' '
41 | ]);
42 |
43 | $this->getOptionsResolver()->setAllowedTypes('collection_glue', 'string');
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/Extension/Core/ColumnType/Money.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
15 | use FSi\Component\DataGrid\Exception\DataGridColumnException;
16 |
17 | class Money extends ColumnAbstractType
18 | {
19 | public const ROUND_HALF_UP = PHP_ROUND_HALF_UP;
20 | public const ROUND_HALF_DOWN = PHP_ROUND_HALF_DOWN;
21 | public const ROUND_HALF_EVEN = PHP_ROUND_HALF_EVEN;
22 | public const ROUND_HALF_ODD = PHP_ROUND_HALF_ODD;
23 |
24 | public function getId(): string
25 | {
26 | return 'money';
27 | }
28 |
29 | public function filterValue($value)
30 | {
31 | $precision = $this->getOption('precision');
32 | $roundmode = $this->getOption('round_mode');
33 | $decimals = $this->getOption('decimals');
34 | $decPoint = $this->getOption('dec_point');
35 | $thousands = $this->getOption('thousands_sep');
36 | $currencyField = $this->getOption('currency_field');
37 | $currencyValue = $this->getOption('currency');
38 | $mappingFields = $this->getOption('field_mapping');
39 | $currencySeparator = $this->getOption('value_currency_separator');
40 |
41 | if (null === $currencyField && null === $currencyValue) {
42 | throw new DataGridColumnException(sprintf(
43 | 'At least one option from "currency" and "currency_field" must be defined in "%s" field.',
44 | $this->getName()
45 | ));
46 | }
47 |
48 | $currency = $currencyValue;
49 | if (null !== $currencyField) {
50 | if (!in_array($currencyField, $mappingFields)) {
51 | throw new DataGridColumnException(
52 | sprintf('There is no field with name "%s".', $currencyField)
53 | );
54 | }
55 |
56 | $currency = $value[$currencyField];
57 | unset($value[$currencyField]);
58 | }
59 |
60 | foreach ($value as $fieldName => &$val) {
61 | if (empty($val)) {
62 | continue;
63 | }
64 |
65 | $val = round($val, $precision, $roundmode);
66 | $val = number_format($val, $decimals, $decPoint, $thousands);
67 |
68 | $val = $val . $currencySeparator . $currency;
69 | }
70 |
71 | return $value;
72 | }
73 |
74 | public function initOptions(): void
75 | {
76 | $this->getOptionsResolver()->setDefaults([
77 | 'round_mode' => self::ROUND_HALF_UP,
78 | 'precision' => 2,
79 | 'decimals' => 2,
80 | 'dec_point' => '.',
81 | 'thousands_sep' => ',',
82 | 'value_currency_separator' => ' ',
83 | 'currency' => null,
84 | 'currency_field' => null,
85 | ]);
86 |
87 | $this->getOptionsResolver()->setAllowedTypes('round_mode', 'integer');
88 | $this->getOptionsResolver()->setAllowedTypes('precision', 'integer');
89 | $this->getOptionsResolver()->setAllowedTypes('decimals', 'integer');
90 | $this->getOptionsResolver()->setAllowedTypes('decimals', 'integer');
91 | $this->getOptionsResolver()->setAllowedTypes('dec_point', 'string');
92 | $this->getOptionsResolver()->setAllowedTypes('thousands_sep', 'string');
93 | $this->getOptionsResolver()->setAllowedTypes('value_currency_separator', 'string');
94 | $this->getOptionsResolver()->setAllowedTypes('currency', ['null', 'string']);
95 | $this->getOptionsResolver()->setAllowedTypes('currency_field', ['null', 'string']);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/lib/Extension/Core/ColumnType/Number.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
15 |
16 | class Number extends ColumnAbstractType
17 | {
18 | public const ROUND_HALF_UP = PHP_ROUND_HALF_UP;
19 | public const ROUND_HALF_DOWN = PHP_ROUND_HALF_DOWN;
20 | public const ROUND_HALF_EVEN = PHP_ROUND_HALF_EVEN;
21 | public const ROUND_HALF_ODD = PHP_ROUND_HALF_ODD;
22 |
23 | public function getId(): string
24 | {
25 | return 'number';
26 | }
27 |
28 | public function filterValue($value)
29 | {
30 | $precision = (int) $this->getOption('precision');
31 | $roundmode = $this->getOption('round_mode');
32 |
33 | $format = $this->getOption('format');
34 | $format_decimals = $this->getOption('format_decimals');
35 | $format_dec_point = $this->getOption('format_dec_point');
36 | $format_thousands_sep = $this->getOption('format_thousands_sep');
37 |
38 | foreach ($value as &$val) {
39 | if (empty($val)) {
40 | continue;
41 | }
42 |
43 | if (isset($roundmode)) {
44 | $val = round($val, $precision, $roundmode);
45 | }
46 |
47 | if ($format) {
48 | $val = number_format((float) $val, $format_decimals, $format_dec_point, $format_thousands_sep);
49 | }
50 | }
51 |
52 | return $value;
53 | }
54 |
55 | public function initOptions(): void
56 | {
57 | $this->options = [
58 | 'round_mode' => null,
59 | 'precision' => 2,
60 | 'format' => false,
61 | 'format_decimals' => 2,
62 | 'format_dec_point' => '.',
63 | 'format_thousands_sep' => ',',
64 | ];
65 |
66 | $this->getOptionsResolver()->setDefaults($this->options);
67 |
68 | $this->getOptionsResolver()->setAllowedTypes('precision', 'integer');
69 | $this->getOptionsResolver()->setAllowedTypes('format', 'bool');
70 | $this->getOptionsResolver()->setAllowedTypes('format_decimals', 'integer');
71 |
72 | $this->getOptionsResolver()->setAllowedValues('round_mode', [
73 | null,
74 | self::ROUND_HALF_UP,
75 | self::ROUND_HALF_DOWN,
76 | self::ROUND_HALF_EVEN,
77 | self::ROUND_HALF_ODD,
78 | ]);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/Extension/Core/ColumnType/Text.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
15 |
16 | class Text extends ColumnAbstractType
17 | {
18 | public function getId(): string
19 | {
20 | return 'text';
21 | }
22 |
23 | public function filterValue($value)
24 | {
25 | $trim = $this->getOption('trim');
26 | if ($trim === true) {
27 | foreach ($value as &$val) {
28 | if (empty($val)) {
29 | continue;
30 | }
31 |
32 | $val = trim($val);
33 | }
34 | }
35 |
36 | return $value;
37 | }
38 |
39 | public function initOptions(): void
40 | {
41 | $this->getOptionsResolver()->setDefaults([
42 | 'trim' => false
43 | ]);
44 |
45 | $this->getOptionsResolver()->setAllowedTypes('trim', 'bool');
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/Extension/Core/ColumnTypeExtension/DefaultColumnOptionsExtension.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
15 | use FSi\Component\DataGrid\Column\HeaderViewInterface;
16 | use FSi\Component\DataGrid\Column\ColumnAbstractTypeExtension;
17 |
18 | class DefaultColumnOptionsExtension extends ColumnAbstractTypeExtension
19 | {
20 | public function buildHeaderView(ColumnTypeInterface $column, HeaderViewInterface $view): void
21 | {
22 | $view->setLabel($column->getOption('label'));
23 | $order = $column->getOption('display_order');
24 | if (null !== $order) {
25 | $view->setAttribute('display_order', $order);
26 | }
27 | }
28 |
29 | public function getExtendedColumnTypes(): array
30 | {
31 | return [
32 | 'batch',
33 | 'text',
34 | 'boolean',
35 | 'collection',
36 | 'datetime',
37 | 'number',
38 | 'money',
39 | 'gedmo_tree',
40 | 'entity',
41 | 'action',
42 | ];
43 | }
44 |
45 | public function initOptions(ColumnTypeInterface $column): void
46 | {
47 | $column->getOptionsResolver()->setDefaults([
48 | 'label' => $column->getName(),
49 | 'display_order' => null,
50 | 'field_mapping' => [$column->getName()]
51 | ]);
52 |
53 | $column->getOptionsResolver()->setAllowedTypes('label', 'string');
54 | $column->getOptionsResolver()->setAllowedTypes('field_mapping', 'array');
55 | $column->getOptionsResolver()->setAllowedTypes('display_order', ['integer', 'null']);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/Extension/Core/ColumnTypeExtension/ValueFormatColumnOptionsExtension.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
15 | use FSi\Component\DataGrid\Column\CellViewInterface;
16 | use FSi\Component\DataGrid\Column\ColumnAbstractTypeExtension;
17 |
18 | class ValueFormatColumnOptionsExtension extends ColumnAbstractTypeExtension
19 | {
20 | public function buildCellView(ColumnTypeInterface $column, CellViewInterface $view): void
21 | {
22 | $this->validateEmptyValueOption($column);
23 | $value = $this->populateValue($view->getValue(), $column->getOption('empty_value'));
24 | $glue = $column->getOption('value_glue');
25 | $format = $column->getOption('value_format');
26 |
27 | $value = $this->formatValue($value, $format, $glue);
28 |
29 | if (!isset($glue, $format) && is_array($value)) {
30 | throw new \InvalidArgumentException(sprintf(
31 | 'At least one of "value_format" or "value_glue" option is missing in column: "%s".',
32 | $column->getName()
33 | ));
34 | }
35 |
36 | $view->setValue($value);
37 | }
38 |
39 | public function getExtendedColumnTypes(): array
40 | {
41 | return [
42 | 'text',
43 | 'boolean',
44 | 'datetime',
45 | 'collection',
46 | 'number',
47 | 'money',
48 | 'gedmo_tree',
49 | ];
50 | }
51 |
52 | public function initOptions(ColumnTypeInterface $column): void
53 | {
54 | $column->getOptionsResolver()->setDefaults([
55 | 'value_glue' => null,
56 | 'value_format' => null,
57 | 'empty_value' => '',
58 | ]);
59 |
60 | $column->getOptionsResolver()->setAllowedTypes('value_glue', ['string', 'null']);
61 | $column->getOptionsResolver()->setAllowedTypes('value_format', ['string', 'Closure', 'null']);
62 | $column->getOptionsResolver()->setAllowedTypes('empty_value', 'string');
63 | }
64 |
65 | private function validateEmptyValueOption(ColumnTypeInterface $column): void
66 | {
67 | $emptyValue = $column->getOption('empty_value');
68 | $mappingFields = $column->getOption('field_mapping');
69 |
70 | if (is_string($emptyValue)) {
71 | return;
72 | }
73 |
74 | if (!is_array($emptyValue)) {
75 | throw new \InvalidArgumentException(
76 | sprintf('Option "empty_value" in column: "%s" must be a array.', $column->getName())
77 | );
78 | }
79 |
80 | foreach ($emptyValue as $field => $value) {
81 | if (!in_array($field, $mappingFields)) {
82 | throw new \InvalidArgumentException(
83 | sprintf(
84 | 'Mapping field "%s" doesn\'t exist in column: "%s".',
85 | $field,
86 | $column->getName()
87 | )
88 | );
89 | }
90 |
91 | if (!is_string($value)) {
92 | throw new \InvalidArgumentException(
93 | sprintf(
94 | 'Option "empty_value" for field "%s" in column: "%s" must be a string.',
95 | $field,
96 | $column->getName()
97 | )
98 | );
99 | }
100 | }
101 | }
102 |
103 | /**
104 | * @param mixed $value
105 | * @param mixed $emptyValue
106 | * @return array|string
107 | */
108 | private function populateValue($value, $emptyValue)
109 | {
110 | if (is_string($emptyValue)) {
111 | if (!isset($value) || (is_string($value) && !strlen($value))) {
112 | return $emptyValue;
113 | }
114 |
115 | if (is_array($value)) {
116 | foreach ($value as &$val) {
117 | if (!isset($val) || (is_string($val) && !strlen($val))) {
118 | $val = $emptyValue;
119 | }
120 | }
121 | }
122 |
123 | return $value;
124 | }
125 |
126 | /**
127 | * If value is simple string and $empty_value is array there is no way
128 | * to guess which empty_value should be used.
129 | */
130 | if (is_string($value)) {
131 | return $value;
132 | }
133 |
134 | if (is_array($value)) {
135 | foreach ($value as $field => &$fieldValue) {
136 | if (empty($fieldValue)) {
137 | $fieldValue = array_key_exists($field, $emptyValue)
138 | ? $emptyValue[$field]
139 | : '';
140 | }
141 | }
142 | }
143 |
144 | return $value;
145 | }
146 |
147 | private function formatValue($value, $format = null, ?string $glue = null)
148 | {
149 | if (is_array($value) && isset($glue) && !isset($format)) {
150 | $value = implode($glue, $value);
151 | }
152 |
153 | if (isset($format)) {
154 | if (is_array($value)) {
155 | if (isset($glue)) {
156 | $renderedValues = [];
157 | foreach ($value as $val) {
158 | $renderedValues[] = $this->formatSingleValue($val, $format);
159 | }
160 |
161 | $value = implode($glue, $renderedValues);
162 | } else {
163 | $value = $this->formatMultipleValues($value, $format);
164 | }
165 | } else {
166 | $value = $this->formatSingleValue($value, $format);
167 | }
168 | }
169 |
170 | if (is_array($value) && count($value) === 1) {
171 | reset($value);
172 | $value = current($value);
173 | }
174 |
175 | return $value;
176 | }
177 |
178 | /**
179 | * @param mixed $value
180 | * @param string|\Closure $template
181 | * @return string
182 | */
183 | private function formatSingleValue($value, $template): string
184 | {
185 | if ($template instanceof \Closure) {
186 | return $template($value);
187 | }
188 |
189 | return sprintf($template, $value);
190 | }
191 |
192 | /**
193 | * @param mixed $value
194 | * @param string|\Closure $template
195 | * @return string
196 | */
197 | private function formatMultipleValues($value, $template): string
198 | {
199 | if ($template instanceof \Closure) {
200 | return $template($value);
201 | }
202 |
203 | return vsprintf($template, $value);
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/lib/Extension/Core/CoreExtension.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core;
13 |
14 | use FSi\Component\DataGrid\DataGridAbstractExtension;
15 | use FSi\Component\DataGrid\Extension\Core\ColumnType;
16 | use FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension;
17 | use FSi\Component\DataGrid\Extension\Core\EventSubscriber;
18 |
19 | class CoreExtension extends DataGridAbstractExtension
20 | {
21 | protected function loadColumnTypes(): array
22 | {
23 | return [
24 | new ColumnType\Text(),
25 | new ColumnType\Number(),
26 | new ColumnType\Collection(),
27 | new ColumnType\DateTime(),
28 | new ColumnType\Action(),
29 | new ColumnType\Money(),
30 | new ColumnType\Action(),
31 | ];
32 | }
33 |
34 | protected function loadColumnTypesExtensions(): array
35 | {
36 | return [
37 | new ColumnTypeExtension\DefaultColumnOptionsExtension(),
38 | new ColumnTypeExtension\ValueFormatColumnOptionsExtension(),
39 | ];
40 | }
41 |
42 | protected function loadSubscribers(): array
43 | {
44 | return [
45 | new EventSubscriber\ColumnOrder(),
46 | ];
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/lib/Extension/Core/EventSubscriber/ColumnOrder.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Core\EventSubscriber;
13 |
14 | use FSi\Component\DataGrid\DataGridEventInterface;
15 | use FSi\Component\DataGrid\DataGridEvents;
16 | use FSi\Component\DataGrid\DataGridViewInterface;
17 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18 |
19 | class ColumnOrder implements EventSubscriberInterface
20 | {
21 | public static function getSubscribedEvents(): array
22 | {
23 | return [DataGridEvents::POST_BUILD_VIEW => ['postBuildView', 128]];
24 | }
25 |
26 | /**
27 | * {@inheritdoc}
28 | */
29 | public function postBuildView(DataGridEventInterface $event)
30 | {
31 | /** @var DataGridViewInterface $view */
32 | $view = $event->getData();
33 | $columns = $view->getColumns();
34 |
35 | if (count($columns)) {
36 | $positive = [];
37 | $negative = [];
38 | $neutral = [];
39 |
40 | $indexedColumns = [];
41 | foreach ($columns as $column) {
42 | if ($column->hasAttribute('display_order')) {
43 | if (($order = $column->getAttribute('display_order')) >= 0) {
44 | $positive[$column->getName()] = $order;
45 | } else {
46 | $negative[$column->getName()] = $order;
47 | }
48 | $indexedColumns[$column->getName()] = $column;
49 | } else {
50 | $neutral[] = $column;
51 | }
52 | }
53 |
54 | asort($positive);
55 | asort($negative);
56 |
57 | $columns = [];
58 | foreach ($negative as $name => $order) {
59 | $columns[] = $indexedColumns[$name];
60 | }
61 |
62 | $columns = array_merge($columns, $neutral);
63 | foreach ($positive as $name => $order) {
64 | $columns[] = $indexedColumns[$name];
65 | }
66 |
67 | $view->setColumns($columns);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/lib/Extension/Doctrine/ColumnType/Entity.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Doctrine\ColumnType;
13 |
14 | use Doctrine\Common\Collections\Collection;
15 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
16 |
17 | class Entity extends ColumnAbstractType
18 | {
19 | public function getId(): string
20 | {
21 | return 'entity';
22 | }
23 |
24 | public function getValue($object)
25 | {
26 | return $this->getDataMapper()->getData($this->getOption('relation_field'), $object);
27 | }
28 |
29 | public function filterValue($value)
30 | {
31 | if ($value instanceof Collection) {
32 | $value = $value->toArray();
33 | }
34 |
35 | $values = [];
36 | $objectValues = [];
37 | $mappingFields = $this->getOption('field_mapping');
38 |
39 | if (is_array($value)) {
40 | foreach ($value as $object) {
41 | foreach ($mappingFields as $field) {
42 | $objectValues[$field] = $this->getDataMapper()->getData($field, $object);
43 | }
44 |
45 | $values[] = $objectValues;
46 | }
47 | } else {
48 | foreach ($mappingFields as $field) {
49 | $objectValues[$field] = isset($value)
50 | ? $this->getDataMapper()->getData($field, $value)
51 | : null;
52 | }
53 |
54 | $values[] = $objectValues;
55 | }
56 |
57 | return $values;
58 | }
59 |
60 | public function initOptions(): void
61 | {
62 | $this->getOptionsResolver()->setDefaults([
63 | 'relation_field' => $this->getName(),
64 | ]);
65 |
66 | $this->getOptionsResolver()->setAllowedTypes('relation_field', 'string');
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/Extension/Doctrine/ColumnTypeExtension/ValueFormatColumnOptionsExtension.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Doctrine\ColumnTypeExtension;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
15 | use FSi\Component\DataGrid\Column\CellViewInterface;
16 | use FSi\Component\DataGrid\Column\ColumnAbstractTypeExtension;
17 | use FSi\Component\DataGrid\Exception\DataGridException;
18 |
19 | class ValueFormatColumnOptionsExtension extends ColumnAbstractTypeExtension
20 | {
21 | public function buildCellView(ColumnTypeInterface $column, CellViewInterface $view): void
22 | {
23 | $value = [];
24 | $values = $view->getValue();
25 | if (($emptyValue = $column->getOption('empty_value')) !== null) {
26 | $values = $this->populateValues($values, $emptyValue);
27 | }
28 | $glue = $column->getOption('value_glue');
29 | $format = $column->getOption('value_format');
30 |
31 | foreach ($values as $val) {
32 | $objectValue = null;
33 |
34 | if (isset($glue) && !isset($format)) {
35 | $objectValue = implode($glue, $val);
36 | }
37 |
38 | if (isset($format)) {
39 | if (isset($glue)) {
40 | $formattedValues = [];
41 | foreach ($val as $fieldValue) {
42 | $formattedValues[] = sprintf($format, $fieldValue);
43 | }
44 |
45 | $objectValue = implode($glue, $formattedValues);
46 | } else {
47 | $objectValue = vsprintf($format, $val);
48 | }
49 | }
50 |
51 | $value[] = $objectValue;
52 | }
53 |
54 | $value = implode($column->getOption('glue_multiple'), $value);
55 |
56 | $view->setValue($value);
57 | }
58 |
59 | public function getExtendedColumnTypes(): array
60 | {
61 | return [
62 | 'entity',
63 | ];
64 | }
65 |
66 | public function initOptions(ColumnTypeInterface $column): void
67 | {
68 | $column->getOptionsResolver()->setDefaults([
69 | 'glue_multiple' => ' ',
70 | 'value_glue' => ' ',
71 | 'value_format' => '%s',
72 | 'empty_value' => null
73 | ]);
74 |
75 | $column->getOptionsResolver()->setAllowedTypes('glue_multiple', ['string']);
76 | $column->getOptionsResolver()->setAllowedTypes('value_glue', ['string', 'null']);
77 | $column->getOptionsResolver()->setAllowedTypes('value_format', ['string', 'null']);
78 | $column->getOptionsResolver()->setAllowedTypes('empty_value', ['array', 'string', 'null']);
79 | }
80 |
81 | private function populateValues(array $values, $emptyValue): array
82 | {
83 | foreach ($values as &$val) {
84 | foreach ($val as $fieldKey => &$fieldValue) {
85 | if (!isset($fieldValue)) {
86 | $fieldValue = $this->populateValue($fieldKey, $fieldValue, $emptyValue);
87 | }
88 | }
89 | }
90 |
91 | return $values;
92 | }
93 |
94 | /**
95 | * @param string $key
96 | * @param mixed $value
97 | * @param mixed $emptyValue
98 | * @return mixed
99 | * @throws \FSi\Component\DataGrid\Exception\DataGridException
100 | */
101 | private function populateValue(string $key, $value, $emptyValue)
102 | {
103 | if (is_string($emptyValue)) {
104 | $value = $emptyValue;
105 | }
106 |
107 | if (is_array($emptyValue)) {
108 | if (isset($emptyValue[$key])) {
109 | $value = $emptyValue[$key];
110 | } else {
111 | throw new DataGridException(
112 | sprintf('Not found key "%s" in empty_value array', $key)
113 | );
114 | }
115 | }
116 |
117 | return $value;
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/lib/Extension/Doctrine/DoctrineExtension.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Doctrine;
13 |
14 | use FSi\Component\DataGrid\DataGridAbstractExtension;
15 | use FSi\Component\DataGrid\Extension\Doctrine\ColumnType;
16 |
17 | class DoctrineExtension extends DataGridAbstractExtension
18 | {
19 | protected function loadColumnTypes(): array
20 | {
21 | return [
22 | new ColumnType\Entity(),
23 | ];
24 | }
25 |
26 | protected function loadColumnTypesExtensions(): array
27 | {
28 | return [
29 | new ColumnTypeExtension\ValueFormatColumnOptionsExtension(),
30 | ];
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/Extension/Gedmo/ColumnType/Tree.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Gedmo\ColumnType;
13 |
14 | use Doctrine\Common\Persistence\ManagerRegistry;
15 | use Doctrine\Common\Persistence\ObjectManager;
16 | use Doctrine\ORM\EntityManager;
17 | use FSi\Component\DataGrid\Column\CellViewInterface;
18 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
19 | use FSi\Component\DataGrid\Exception\DataGridColumnException;
20 | use FSi\Component\DataIndexer\DoctrineDataIndexer;
21 | use Gedmo\Tree\RepositoryInterface as TreeRepositoryInterface;
22 | use Gedmo\Tree\Strategy;
23 | use Gedmo\Tree\TreeListener;
24 | use Symfony\Component\PropertyAccess\PropertyAccess;
25 |
26 | class Tree extends ColumnAbstractType
27 | {
28 | /**
29 | * @var ManagerRegistry
30 | */
31 | protected $registry;
32 |
33 | /**
34 | * @var array
35 | */
36 | protected $allowedStrategies;
37 |
38 | /**
39 | * @var array
40 | */
41 | private $viewAttributes;
42 |
43 | /**
44 | * @var array
45 | */
46 | private $classStrategies;
47 |
48 | public function __construct(ManagerRegistry $registry)
49 | {
50 | $this->registry = $registry;
51 | $this->viewAttributes = [];
52 | $this->classStrategies = [];
53 | $this->allowedStrategies = ['nested'];
54 | }
55 |
56 | public function getId(): string
57 | {
58 | return 'gedmo_tree';
59 | }
60 |
61 | public function getValue($object)
62 | {
63 | if (!is_object($object)) {
64 | throw new \InvalidArgumentException('Column "gedmo_tree" must read value from object.');
65 | }
66 |
67 | $value = parent::getValue($object);
68 | $objectManager = $this->registry->getManager($this->getOption('em'));
69 |
70 | // Check if tree listener is registred.
71 | $treeListener = $this->getTreeListener($objectManager);
72 |
73 | // Get Tree strategy.
74 | $strategy = $this->getClassStrategy($objectManager, $treeListener, get_class($object));
75 | $this->validateStrategy($object, $strategy);
76 |
77 | $config = $treeListener->getConfiguration($objectManager, get_class($object));
78 | $doctrineDataIndexer = new DoctrineDataIndexer($this->registry, get_class($object));
79 | $propertyAccessor = PropertyAccess::createPropertyAccessor();
80 |
81 | $this->viewAttributes = [
82 | 'id' => $doctrineDataIndexer->getIndex($object),
83 | 'root' => isset($config['root']) ? $propertyAccessor->getValue($object, $config['root']) : null,
84 | 'left' => isset($config['left']) ? $propertyAccessor->getValue($object, $config['left']) : null,
85 | 'right' => isset($config['right']) ? $propertyAccessor->getValue($object, $config['right']) : null,
86 | 'level' => (isset($config['level'])) ? $propertyAccessor->getValue($object, $config['level']) : null,
87 | 'children' => $this->getTreeRepository(get_class($object), $objectManager)->childCount($object),
88 | ];
89 |
90 | $parent = (isset($config['parent'])) ? $propertyAccessor->getValue($object, $config['parent']) : null;
91 | if (isset($parent)) {
92 | $this->viewAttributes['parent'] = $doctrineDataIndexer->getIndex($parent);
93 | }
94 |
95 | return $value;
96 | }
97 |
98 | /**
99 | * {@inheritdoc}
100 | */
101 | public function filterValue($value)
102 | {
103 | return $value;
104 | }
105 |
106 | public function buildCellView(CellViewInterface $view): void
107 | {
108 | foreach ($this->getViewAttributes() as $attrName => $attrValue) {
109 | $view->setAttribute($attrName, $attrValue);
110 | }
111 | }
112 |
113 | public function initOptions(): void
114 | {
115 | $this->getOptionsResolver()->setDefaults([
116 | 'em' => null,
117 | ]);
118 | }
119 |
120 | private function getViewAttributes(): array
121 | {
122 | return $this->viewAttributes;
123 | }
124 |
125 | private function getClassStrategy(ObjectManager $om, TreeListener $listener, string $class): Strategy
126 | {
127 | if (array_key_exists($class, $this->classStrategies)) {
128 | return $this->classStrategies[$class];
129 | }
130 |
131 | $this->classStrategies[$class] = null;
132 | $classParents = array_merge(
133 | [$class],
134 | class_parents($class)
135 | );
136 |
137 | foreach ($classParents as $parent) {
138 | try {
139 | $this->classStrategies[$class] = $listener->getStrategy($om, $parent);
140 | break;
141 | } catch (\Exception $e) {
142 | // we don't like to throw exception because there might be a strategy for class parents
143 | }
144 | }
145 |
146 | return $this->classStrategies[$class];
147 | }
148 |
149 | /**
150 | * @param ObjectManager $om
151 | * @throws \FSi\Component\DataGrid\Exception\DataGridColumnException
152 | * @return TreeListener
153 | */
154 | private function getTreeListener(ObjectManager $om)
155 | {
156 | $treeListener = null;
157 |
158 | if ($om instanceof EntityManager) {
159 | foreach ($om->getEventManager()->getListeners() as $listeners) {
160 | foreach ($listeners as $listener) {
161 | if ($listener instanceof TreeListener) {
162 | $treeListener = $listener;
163 | break;
164 | }
165 | }
166 | if ($treeListener) {
167 | break;
168 | }
169 | }
170 | }
171 |
172 | if (!isset($treeListener)) {
173 | throw new DataGridColumnException('Gedmo TreeListener was not found in your entity manager.');
174 | }
175 |
176 | return $treeListener;
177 | }
178 |
179 | /**
180 | * @param $class
181 | * @param \Doctrine\Common\Persistence\ObjectManager $em
182 | * @throws \RuntimeException
183 | * @return TreeRepositoryInterface
184 | */
185 | private function getTreeRepository($class, ObjectManager $em)
186 | {
187 | $repository = $em->getRepository($class);
188 | if (!$repository instanceof TreeRepositoryInterface) {
189 | throw new \RuntimeException(
190 | sprintf("%s must be an instance of Gedmo tree repository", get_class($repository))
191 | );
192 | }
193 |
194 | return $repository;
195 | }
196 |
197 | /**
198 | * @param $object
199 | * @param $strategy
200 | * @throws \FSi\Component\DataGrid\Exception\DataGridColumnException
201 | */
202 | private function validateStrategy($object, $strategy)
203 | {
204 | if (!isset($strategy) && !$strategy instanceof Strategy) {
205 | throw new DataGridColumnException(
206 | sprintf('"%s" is not implementing gedmo tree strategy. Maybe you should consider using a different column type?', get_class($object))
207 | );
208 | }
209 |
210 | if (!in_array($strategy->getName(), $this->allowedStrategies)) {
211 | throw new DataGridColumnException(
212 | sprintf('Strategy "%s" is not supported by "%s" column.', $strategy->getName(), $this->getId())
213 | );
214 | }
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/lib/Extension/Gedmo/GedmoDoctrineExtension.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Extension\Gedmo;
13 |
14 | use Doctrine\Common\Persistence\ManagerRegistry;
15 | use FSi\Component\DataGrid\DataGridAbstractExtension;
16 | use FSi\Component\DataGrid\Extension\Gedmo\ColumnType;
17 |
18 | class GedmoDoctrineExtension extends DataGridAbstractExtension
19 | {
20 | /**
21 | * @var ManagerRegistry
22 | */
23 | protected $registry;
24 |
25 | public function __construct(ManagerRegistry $registry)
26 | {
27 | $this->registry = $registry;
28 | }
29 |
30 | protected function loadColumnTypes(): array
31 | {
32 | return [
33 | new ColumnType\Tree($this->registry),
34 | ];
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | tests
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/tests/Data/DataRowsetTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Data;
13 |
14 | use FSi\Component\DataGrid\Tests\Fixtures\Entity;
15 | use FSi\Component\DataGrid\Data\DataRowset;
16 | use PHPUnit\Framework\TestCase;
17 | use TypeError;
18 |
19 | class DataRowsetTest extends TestCase
20 | {
21 | public function testCreateWithInvalidData()
22 | {
23 | $this->expectException(TypeError::class);
24 |
25 | new DataRowset('Invalid Data');
26 | }
27 |
28 | public function testCreateRowset()
29 | {
30 | $data = [
31 | 'e1' => new Entity('entity1'),
32 | 'e2' => new Entity('entity2')
33 | ];
34 |
35 | $rowset = new DataRowset($data);
36 |
37 | foreach ($rowset as $index => $row) {
38 | $this->assertSame($data[$index], $row);
39 | }
40 |
41 | $this->assertSame(2, $rowset->count());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/DataGridFactoryTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests;
13 |
14 | use FSi\Component\DataGrid\DataGridFactory;
15 | use FSi\Component\DataGrid\DataGridFactoryInterface;
16 | use FSi\Component\DataGrid\Tests\Fixtures\FooExtension;
17 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
18 | use FSi\Component\DataGrid\Exception\UnexpectedTypeException;
19 | use FSi\Component\DataGrid\Exception\DataGridColumnException;
20 | use FSi\Component\DataGrid\Tests\Fixtures\ColumnType\FooType;
21 | use PHPUnit\Framework\TestCase;
22 |
23 | class DataGridFactoryTest extends TestCase
24 | {
25 | /**
26 | * @var DataGridFactoryInterface
27 | */
28 | private $factory;
29 |
30 | protected function setUp()
31 | {
32 | $extensions = [
33 | new FooExtension(),
34 | ];
35 |
36 | $dataMapper = $this->createMock(DataMapperInterface::class);
37 |
38 | $this->factory = new DataGridFactory($extensions, $dataMapper);
39 | }
40 |
41 | public function testCreateGrids()
42 | {
43 | $grid = $this->factory->createDataGrid();
44 | $this->assertSame('grid',$grid->getName());
45 |
46 | $this->expectException(DataGridColumnException::class);
47 | $this->expectExceptionMessage('Datagrid name "grid" is not uniqe, it was used before to create datagrid');
48 | $this->factory->createDataGrid('grid');
49 | }
50 |
51 | public function testHasColumnType()
52 | {
53 | $this->assertTrue($this->factory->hasColumnType('foo'));
54 | $this->assertFalse($this->factory->hasColumnType('bar'));
55 | }
56 |
57 | public function testGetColumnType()
58 | {
59 | $this->assertInstanceOf(FooType::class, $this->factory->getColumnType('foo'));
60 |
61 | $this->expectException(UnexpectedTypeException::class);
62 | $this->expectExceptionMessage('There is no column with type "bar" registered in factory.');
63 | $this->factory->getColumnType('bar');
64 | }
65 |
66 | public function testGetDataMapper()
67 | {
68 | $this->assertInstanceOf(DataMapperInterface::class, $this->factory->getDataMapper());
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/tests/DataGridRowViewTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests;
13 |
14 | use FSi\Component\DataGrid\DataGridRowView;
15 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
16 | use FSi\Component\DataGrid\Column\CellViewInterface;
17 | use FSi\Component\DataGrid\DataGridViewInterface;
18 | use PHPUnit\Framework\TestCase;
19 |
20 | class DataGridRowViewTest extends TestCase
21 | {
22 | public function testCreateDataGridRowView()
23 | {
24 | $source = 'SOURCE';
25 |
26 | $dataGridView = $this->createMock(DataGridViewInterface::class);
27 |
28 | $cellView = $this->createMock(CellViewInterface::class);
29 |
30 | $column = $this->createMock(ColumnTypeInterface::class);
31 | $column->expects($this->atLeastOnce())
32 | ->method('createCellView')
33 | ->with($source, 0)
34 | ->will($this->returnValue($cellView));
35 |
36 | $columns = [
37 | 'foo' =>$column
38 | ];
39 |
40 | $gridRow = new DataGridRowView($dataGridView, $columns, $source, 0);
41 | $this->assertSame($gridRow->current(), $cellView);
42 |
43 | $this->assertSame($gridRow->getSource(), $source);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tests/DataGridTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests;
13 |
14 | use FSi\Component\DataGrid\DataGrid;
15 | use FSi\Component\DataGrid\Tests\Fixtures\FooExtension;
16 | use FSi\Component\DataGrid\Tests\Fixtures\ColumnType\FooType;
17 | use FSi\Component\DataGrid\Tests\Fixtures\Entity;
18 | use FSi\Component\DataGrid\DataGridViewInterface;
19 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
20 | use FSi\Component\DataGrid\DataGridFactoryInterface;
21 | use InvalidArgumentException;
22 | use PHPUnit\Framework\TestCase;
23 | use TypeError;
24 |
25 | class DataGridTest extends TestCase
26 | {
27 | /**
28 | * @var DataGridFactoryInterface
29 | */
30 | private $factory;
31 |
32 | /**
33 | * @var DataMapperInterface
34 | */
35 | private $dataMapper;
36 |
37 | /**
38 | * @var DataGrid
39 | */
40 | private $datagrid;
41 |
42 | protected function setUp()
43 | {
44 | $this->dataMapper = $this->createMock(DataMapperInterface::class);
45 | $this->dataMapper->expects($this->any())
46 | ->method('getData')
47 | ->will($this->returnCallback(function($field, $object){
48 | switch($field) {
49 | case 'name':
50 | return $object->getName();
51 | }
52 | }));
53 |
54 | $this->dataMapper->expects($this->any())
55 | ->method('setData')
56 | ->will($this->returnCallback(function($field, $object, $value){
57 | switch($field) {
58 | case 'name':
59 | $object->setName($value);
60 | break;
61 | }
62 | }));
63 |
64 | $this->factory = $this->createMock(DataGridFactoryInterface::class);
65 | $this->factory->expects($this->any())
66 | ->method('getExtensions')
67 | ->will($this->returnValue([
68 | new FooExtension(),
69 | ]));
70 |
71 | $this->factory->expects($this->any())
72 | ->method('getColumnType')
73 | ->with($this->equalTo('foo'))
74 | ->will($this->returnValue(
75 | new FooType()
76 | ));
77 |
78 | $this->factory->expects($this->any())
79 | ->method('hasColumnType')
80 | ->with($this->equalTo('foo'))
81 | ->will($this->returnValue(true));
82 |
83 | $this->datagrid = new DataGrid('grid', $this->factory, $this->dataMapper);
84 | }
85 |
86 | public function testGetName()
87 | {
88 | $this->assertSame('grid', $this->datagrid->getName());
89 | }
90 |
91 | public function testHasAddGetRemoveClearColumn()
92 | {
93 | $this->assertFalse($this->datagrid->hasColumn('foo1'));
94 | $this->datagrid->addColumn('foo1', 'foo');
95 | $this->assertTrue($this->datagrid->hasColumn('foo1'));
96 | $this->assertTrue($this->datagrid->hasColumnType('foo'));
97 | $this->assertFalse($this->datagrid->hasColumnType('this_type_cant_exists'));
98 |
99 | $this->assertInstanceOf(FooType::class, $this->datagrid->getColumn('foo1'));
100 |
101 | $this->assertTrue($this->datagrid->hasColumn('foo1'));
102 | $column = $this->datagrid->getColumn('foo1');
103 |
104 | $this->datagrid->removeColumn('foo1');
105 | $this->assertFalse($this->datagrid->hasColumn('foo1'));
106 |
107 | $this->datagrid->addColumn($column);
108 | $this->assertEquals($column, $this->datagrid->getColumn('foo1'));
109 |
110 | $this->assertCount(1, $this->datagrid->getColumns());
111 |
112 | $this->datagrid->clearColumns();
113 | $this->assertCount(0, $this->datagrid->getColumns());
114 |
115 | $this->expectException(InvalidArgumentException::class);
116 | $this->expectExceptionMessage('Column "bar" does not exist in data grid.');
117 | $this->datagrid->getColumn('bar');
118 | }
119 |
120 | public function testGetDataMapper()
121 | {
122 | $this->assertInstanceOf(DataMapperInterface::class, $this->datagrid->getDataMapper());
123 | }
124 |
125 | public function testSetData()
126 | {
127 | $gridData = [
128 | new Entity('entity1'),
129 | new Entity('entity2')
130 | ];
131 |
132 | $this->datagrid->setData($gridData);
133 |
134 | $this->assertEquals(count($gridData), count($this->datagrid->createView()));
135 |
136 | $gridData = [
137 | ['some', 'data'],
138 | ['next', 'data']
139 | ];
140 |
141 | $this->datagrid->setData($gridData);
142 |
143 | $this->assertEquals(count($gridData), count($this->datagrid->createView()));
144 |
145 | $gridBrokenData = false;
146 | $this->expectException(TypeError::class);
147 | $this->datagrid->setData($gridBrokenData);
148 | }
149 |
150 | public function testCreateView()
151 | {
152 | $this->datagrid->addColumn('foo1', 'foo');
153 | $gridData = [
154 | new Entity('entity1'),
155 | new Entity('entity2')
156 | ];
157 |
158 | $this->datagrid->setData($gridData);
159 | $this->assertInstanceOf(DataGridViewInterface::class,$this->datagrid->createView());
160 | }
161 |
162 | public function testSetDataForArray()
163 | {
164 | $gridData = [
165 | ['one'],
166 | ['two'],
167 | ['three'],
168 | ['four'],
169 | ['bazinga!'],
170 | ['five'],
171 | ];
172 |
173 | $this->datagrid->setData($gridData);
174 | $view = $this->datagrid->createView();
175 |
176 | $keys = [];
177 | foreach ($view as $row) {
178 | $keys[] = $row->getIndex();
179 | }
180 |
181 | $this->assertEquals(array_keys($gridData), $keys);
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/tests/DataGridViewTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests;
13 |
14 | use FSi\Component\DataGrid\DataGridView;
15 | use FSi\Component\DataGrid\Data\DataRowsetInterface;
16 | use FSi\Component\DataGrid\Column\HeaderViewInterface;
17 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
18 | use PHPUnit\Framework\TestCase;
19 |
20 | class DataGridViewTest extends TestCase
21 | {
22 | /**
23 | * @var DataRowsetInterface
24 | */
25 | private $rowset;
26 |
27 | /**
28 | * @var DataGridView
29 | */
30 | private $gridView;
31 |
32 | public function testAddHasGetRemoveColumn()
33 | {
34 | $self = $this;
35 |
36 | $column = $this->createMock(ColumnTypeInterface::class);
37 | $column->expects($this->any())
38 | ->method('createHeaderView')
39 | ->will($this->returnCallback(function() use ($self) {
40 | $headerView = $self->createMock(HeaderViewInterface::class);
41 | $headerView->expects($self->any())
42 | ->method('getName')
43 | ->will($self->returnValue('ColumnHeaderView'));
44 |
45 | $headerView->expects($self->any())
46 | ->method('getType')
47 | ->will($self->returnValue('foo-type'));
48 |
49 | return $headerView;
50 | }));
51 |
52 | $column->expects($this->any())
53 | ->method('getName')
54 | ->will($this->returnValue('foo'));
55 |
56 | $columnHeader = $this->createMock(HeaderViewInterface::class);
57 | $columnHeader->expects($this->any())
58 | ->method('getName')
59 | ->will($this->returnValue('foo'));
60 |
61 | $columnHeader->expects($this->any())
62 | ->method('getType')
63 | ->will($this->returnValue('foo-type'));
64 |
65 | $columnHeader->expects($this->any())
66 | ->method('setDataGridView');
67 |
68 | $this->rowset = $this->createMock(DataRowsetInterface::class);
69 | $this->gridView = new DataGridView('test-grid-view', [$column], $this->rowset);
70 |
71 | $this->assertSame('test-grid-view', $this->gridView->getName());
72 |
73 | $this->assertTrue($this->gridView->hasColumn('foo'));
74 | $this->assertTrue($this->gridView->hasColumnType('foo-type'));
75 | $this->assertCount(1, $this->gridView->getColumns());
76 | $this->assertSame($this->gridView->getColumn('foo')->getName(), 'ColumnHeaderView');
77 | $this->gridView->removeColumn('foo');
78 | $this->assertFalse($this->gridView->hasColumn('foo'));
79 |
80 | $this->gridView->addColumn($columnHeader);
81 | $this->assertTrue($this->gridView->hasColumn('foo'));
82 |
83 | $this->gridView->clearColumns();
84 | $this->assertFalse($this->gridView->hasColumn('foo'));
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/tests/DataMapper/ChainMapperTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\DataMapper;
13 |
14 | use FSi\Component\DataGrid\DataMapper\ChainMapper;
15 | use FSi\Component\DataGrid\Exception\DataMappingException;
16 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
17 | use InvalidArgumentException;
18 | use PHPUnit\Framework\TestCase;
19 |
20 | class ChainMapperTest extends TestCase
21 | {
22 | public function testMappersInChainWithInvalidMappers()
23 | {
24 | $this->expectException(InvalidArgumentException::class);
25 | $this->expectExceptionMessage(sprintf('Mapper needs to implement "%s"', DataMapperInterface::class));
26 | new ChainMapper([
27 | 'foo',
28 | 'bar'
29 | ]);
30 | }
31 |
32 | public function testMappersInChainWithEmptyMappersArray()
33 | {
34 | $this->expectException(InvalidArgumentException::class);
35 | $this->expectExceptionMessage(sprintf('Mapper needs to implement "%s"', DataMapperInterface::class));
36 | new ChainMapper([
37 | 'foo',
38 | 'bar'
39 | ]);
40 | }
41 |
42 | public function testGetDataFromTwoMappers()
43 | {
44 | $mapper = $this->createMock(DataMapperInterface::class);
45 | $mapper1 = $this->createMock(DataMapperInterface::class);
46 |
47 | $mapper->expects($this->once())
48 | ->method('getData')
49 | ->will($this->throwException(new DataMappingException));
50 |
51 | $mapper1->expects($this->once())
52 | ->method('getData')
53 | ->will($this->returnValue('foo'));
54 |
55 | $chain = new ChainMapper([$mapper, $mapper1]);
56 |
57 | $this->assertSame(
58 | 'foo',
59 | $chain->getData('foo', 'bar')
60 | );
61 | }
62 |
63 | public function testSetDataWithTwoMappers()
64 | {
65 | $mapper = $this->createMock(DataMapperInterface::class);
66 | $mapper1 = $this->createMock(DataMapperInterface::class);
67 |
68 | $mapper->expects($this->once())
69 | ->method('setData')
70 | ->will($this->throwException(new DataMappingException));
71 |
72 | $mapper1->expects($this->once())
73 | ->method('setData')
74 | ->with('foo', 'bar', 'test')
75 | ->will($this->returnValue(true));
76 |
77 | $chain = new ChainMapper([$mapper, $mapper1]);
78 |
79 | $chain->setData('foo', 'bar', 'test');
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/tests/DataMapper/ReflectionMapperTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\DataMapper;
13 |
14 | use FSi\Component\DataGrid\DataMapper\ReflectionMapper;
15 | use FSi\Component\DataGrid\Tests\Fixtures\EntityMapper;
16 | use FSi\Component\DataGrid\Exception\DataMappingException;
17 | use PHPUnit\Framework\TestCase;
18 |
19 | class ReflectionMapperTest extends TestCase
20 | {
21 | public function testGetter()
22 | {
23 | $mapper = new ReflectionMapper();
24 | $entity = new EntityMapper();
25 | $entity->setName('fooname');
26 |
27 | $this->assertSame('fooname',$mapper->getData('name', $entity));
28 | }
29 |
30 | public function testProtectedGetter()
31 | {
32 | $mapper = new ReflectionMapper();
33 | $entity = new EntityMapper();
34 | $entity->setSurname('foosurname');
35 |
36 | $this->expectException(DataMappingException::class);
37 | $this->expectExceptionMessage(sprintf('Method "getSurname()" is not public in class "%s"', EntityMapper::class));
38 | $mapper->getData('surname', $entity);
39 | }
40 |
41 | public function testHaser()
42 | {
43 | $mapper = new ReflectionMapper();
44 | $entity = new EntityMapper();
45 | $entity->setCollection('collection');
46 |
47 | $this->assertTrue($mapper->getData('collection', $entity));
48 | }
49 |
50 | public function testProtectedHaser()
51 | {
52 | $mapper = new ReflectionMapper();
53 | $entity = new EntityMapper();
54 | $entity->setPrivateCollection('collection');
55 |
56 | $this->expectException(DataMappingException::class);
57 | $this->expectExceptionMessage(sprintf('Method "hasPrivateCollection()" is not public in class "%s"', EntityMapper::class));
58 | $mapper->getData('private_collection', $entity);
59 | }
60 |
61 | public function testIser()
62 | {
63 | $mapper = new ReflectionMapper();
64 | $entity = new EntityMapper();
65 | $entity->setReady(true);
66 |
67 | $this->assertTrue($mapper->getData('ready', $entity));
68 | }
69 |
70 | public function testProtectedIser()
71 | {
72 | $mapper = new ReflectionMapper();
73 | $entity = new EntityMapper();
74 | $entity->setProtectedReady(true);
75 |
76 | $this->expectException(DataMappingException::class);
77 | $this->expectExceptionMessage(sprintf('Method "isProtectedReady()" is not public in class "%s"', EntityMapper::class));
78 | $mapper->getData('protected_ready', $entity);
79 | }
80 |
81 | public function testProperty()
82 | {
83 | $mapper = new ReflectionMapper();
84 | $entity = new EntityMapper();
85 | $entity->setId('bar');
86 |
87 | $this->assertSame('bar',$mapper->getData('id', $entity));
88 | }
89 |
90 | public function testPrivateProperty()
91 | {
92 | $mapper = new ReflectionMapper();
93 | $entity = new EntityMapper();
94 | $entity->setPrivateId('bar');
95 |
96 | $this->expectException(DataMappingException::class);
97 | $this->expectExceptionMessage(sprintf('Property "private_id" is not public in class "%s"', EntityMapper::class));
98 | $mapper->getData('private_id', $entity);
99 | }
100 |
101 | public function testSetter()
102 | {
103 | $mapper = new ReflectionMapper();
104 | $entity = new EntityMapper();
105 |
106 | $mapper->setData('name', $entity, 'fooname');
107 | $this->assertSame('fooname',$entity->getName());
108 | }
109 |
110 | public function testProtectedSetter()
111 | {
112 | $mapper = new ReflectionMapper();
113 | $entity = new EntityMapper();
114 |
115 | $this->expectException(DataMappingException::class);
116 | $this->expectExceptionMessage(sprintf('Method "setProtectedName()" is not public in class "%s"', EntityMapper::class));
117 | $mapper->setData('protected_name', $entity, 'fooname');
118 | }
119 |
120 | public function testAdder()
121 | {
122 | $mapper = new ReflectionMapper();
123 | $entity = new EntityMapper();
124 |
125 | $mapper->setData('tag', $entity, 'bar');
126 | $this->assertSame(['bar'],$entity->getTags());
127 | }
128 |
129 | public function testProtectedAdder()
130 | {
131 | $mapper = new ReflectionMapper();
132 | $entity = new EntityMapper();
133 |
134 | $this->expectException(DataMappingException::class);
135 | $this->expectExceptionMessage(sprintf('Method "addProtectedTag()" is not public in class "%s"', EntityMapper::class));
136 | $mapper->setData('protected_tag', $entity, 'bar');
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/tests/Extension/Core/ColumnType/ActionTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Core;
13 |
14 | use FSi\Component\DataGrid\Extension\Core\ColumnType\Action;
15 | use FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension\DefaultColumnOptionsExtension;
16 | use InvalidArgumentException;
17 | use PHPUnit\Framework\TestCase;
18 | use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
19 |
20 | class ActionTest extends TestCase
21 | {
22 | /**
23 | * @var Action
24 | */
25 | private $column;
26 |
27 | protected function setUp()
28 | {
29 | $column = new Action();
30 | $column->setName('action');
31 | $column->initOptions();
32 |
33 | $extension = new DefaultColumnOptionsExtension();
34 | $extension->initOptions($column);
35 |
36 | $this->column = $column;
37 | }
38 |
39 | public function testFilterValueEmptyActionsOptionType()
40 | {
41 | $this->expectException(InvalidOptionsException::class);
42 | $this->expectExceptionMessage('The option "actions" with value "boo" is expected to be of type "array", but is of type "string".');
43 | $this->column->setOption('actions', 'boo');
44 | $this->column->filterValue([]);
45 | }
46 |
47 | public function testFilterValueInvalidActionInActionsOption()
48 | {
49 | $this->expectException(InvalidArgumentException::class);
50 | $this->column->setOption('actions', ['edit' => 'asasdas']);
51 | $this->column->filterValue([]);
52 | }
53 |
54 | public function testFilterValueRequiredActionInActionsOption()
55 | {
56 | $this->column->setOption('actions', [
57 | 'edit' => [
58 | 'uri_scheme' => '/test/%s',
59 | ]
60 | ]);
61 |
62 | $this->assertSame(
63 | [
64 | 'edit' => [
65 | 'url' => '/test/bar',
66 | 'field_mapping_values' => [
67 | 'foo' => 'bar'
68 | ]
69 | ]
70 | ],
71 | $this->column->filterValue([
72 | 'foo' => 'bar'
73 | ])
74 | );
75 | }
76 |
77 | public function testFilterValueAvailableActionInActionsOption()
78 | {
79 | $this->column->setOption('actions', [
80 | 'edit' => [
81 | 'uri_scheme' => '/test/%s',
82 | 'domain' => 'fsi.pl',
83 | 'protocol' => 'https://',
84 | 'redirect_uri' => 'http://onet.pl/'
85 | ]
86 | ]);
87 |
88 | $this->assertSame(
89 | [
90 | 'edit' => [
91 | 'url' => 'https://fsi.pl/test/bar?redirect_uri=' . urlencode('http://onet.pl/'),
92 | 'field_mapping_values' => [
93 | 'foo' => 'bar'
94 | ]
95 | ]
96 | ],
97 | $this->column->filterValue([
98 | 'foo' => 'bar'
99 | ])
100 | );
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/tests/Extension/Core/ColumnType/BooleanTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Extension\Core\ColumnType\Boolean;
15 | use PHPUnit\Framework\TestCase;
16 |
17 | class BooleanTest extends TestCase
18 | {
19 | /**
20 | * @var Boolean
21 | */
22 | private $column;
23 |
24 | protected function setUp()
25 | {
26 | $column = new Boolean();
27 | $column->setName('available');
28 | $column->initOptions();
29 |
30 | $this->column = $column;
31 | }
32 |
33 | public function testBasicFilterValue()
34 | {
35 | $this->column->setOptions([
36 | 'true_value' => 'true',
37 | 'false_value'=> 'false'
38 | ]);
39 |
40 | $this->assertSame($this->column->filterValue(true), 'true');
41 | $this->assertNotSame($this->column->filterValue(true), 'false');
42 | }
43 |
44 | public function testFilterValueWithTrueValuesInArray()
45 | {
46 | $this->column->setOption('true_value', 'true');
47 |
48 | $this->assertSame(
49 | $this->column->filterValue([
50 | true,
51 | true
52 | ]),
53 | 'true'
54 | );
55 | }
56 |
57 | public function testFilterValueWithMixedValuesInArray()
58 | {
59 | $this->column->setOptions([
60 | 'true_value' => 'true',
61 | 'false_value'=> 'false'
62 | ]);
63 |
64 | $this->assertSame(
65 | $this->column->filterValue([
66 | true,
67 | 1,
68 | new \DateTime()
69 | ]),
70 | 'true'
71 | );
72 | }
73 |
74 |
75 | public function testFilterValueWithFalseValuesInArray()
76 | {
77 | $this->column->setOptions([
78 | 'true_value' => 'true',
79 | 'false_value'=> 'false'
80 | ]);
81 |
82 | $this->assertSame(
83 | $this->column->filterValue([
84 | false,
85 | false
86 | ]),
87 | 'false'
88 | );
89 | }
90 |
91 | public function testFilterValueWithMixedValuesAndFalseInArray()
92 | {
93 | $this->column->setOptions([
94 | 'true_value' => 'true',
95 | 'false_value'=> 'false'
96 | ]);
97 |
98 | $this->assertSame(
99 | $this->column->filterValue([
100 | true,
101 | 1,
102 | new \DateTime(),
103 | false
104 | ]),
105 | 'false'
106 | );
107 | }
108 |
109 | public function testFilterValueWithMixedValuesAndNullInArray()
110 | {
111 | $this->column->setOptions([
112 | 'true_value' => 'true',
113 | 'false_value'=> 'false'
114 | ]);
115 |
116 | $this->assertSame(
117 | $this->column->filterValue([
118 | true,
119 | 1,
120 | new \DateTime(),
121 | null
122 | ]),
123 | 'true'
124 | );
125 | }
126 |
127 | public function testFilterValueWithAllNullsInArray()
128 | {
129 | $this->column->setOptions([
130 | 'true_value' => 'true',
131 | 'false_value'=> 'false'
132 | ]);
133 |
134 | $this->assertSame(
135 | $this->column->filterValue([
136 | null,
137 | null
138 | ]),
139 | ''
140 | );
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/tests/Extension/Core/ColumnType/CollectionTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Extension\Core\ColumnType\Collection;
15 | use PHPUnit\Framework\TestCase;
16 |
17 | class CollectionTest extends TestCase
18 | {
19 | public function test_filter_value()
20 | {
21 | $column = new Collection();
22 | $column->initOptions();
23 | $column->setOption('collection_glue', ' ');
24 | $value = [
25 | ['foo', 'bar'],
26 | 'test'
27 | ];
28 |
29 | $this->assertSame(
30 | ['foo bar', 'test'],
31 | $column->filterValue($value)
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/Extension/Core/ColumnType/MoneyTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Extension\Core\ColumnType\Money;
15 | use FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension\DefaultColumnOptionsExtension;
16 | use PHPUnit\Framework\TestCase;
17 |
18 | class MoneyTest extends TestCase
19 | {
20 | /**
21 | * @var Money
22 | */
23 | private $column;
24 |
25 | protected function setUp()
26 | {
27 | $column = new Money();
28 | $column->setName('money');
29 | $column->initOptions();
30 |
31 | $extension = new DefaultColumnOptionsExtension();
32 | $extension->initOptions($column);
33 |
34 | $this->column = $column;
35 | }
36 |
37 | public function testCurrencyOption()
38 | {
39 | $value = [
40 | 'value' => 10,
41 | ];
42 |
43 | $this->column->setOption('currency', 'PLN');
44 |
45 | $this->assertSame(
46 | $this->column->filterValue($value),
47 | [
48 | 'value' => '10.00 PLN',
49 | ]
50 | );
51 | }
52 |
53 | public function testCurrencySeparatorOption()
54 | {
55 | $value = [
56 | 'value' => 10,
57 | ];
58 |
59 | $this->column->setOption('currency', 'PLN');
60 | $this->column->setOption('value_currency_separator', '$ ');
61 |
62 | $this->assertSame(
63 | $this->column->filterValue($value),
64 | [
65 | 'value' => '10.00$ PLN',
66 | ]
67 | );
68 | }
69 |
70 | public function testCurrencyDecPointOption()
71 | {
72 | $value = [
73 | 'value' => 10,
74 | ];
75 |
76 | $this->column->setOption('currency', 'PLN');
77 | $this->column->setOption('dec_point', '-');
78 |
79 | $this->assertSame(
80 | $this->column->filterValue($value),
81 | [
82 | 'value' => '10-00 PLN',
83 | ]
84 | );
85 | }
86 |
87 | public function testCurrencyDecimalsOption()
88 | {
89 | $value = [
90 | 'value' => 10,
91 | ];
92 |
93 | $this->column->setOption('currency', 'PLN');
94 | $this->column->setOption('decimals', 0);
95 |
96 | $this->assertSame(
97 | $this->column->filterValue($value),
98 | [
99 | 'value' => '10 PLN',
100 | ]
101 | );
102 |
103 | $this->column->setOption('currency', 'PLN');
104 | $this->column->setOption('decimals', 5);
105 |
106 | $this->assertSame(
107 | $this->column->filterValue($value),
108 | [
109 | 'value' => '10.00000 PLN',
110 | ]
111 | );
112 | }
113 |
114 | public function testCurrencyPrecisionOption()
115 | {
116 | $value = [
117 | 'value' => 10.326
118 | ];
119 |
120 | $this->column->setOption('currency', 'PLN');
121 | $this->column->setOption('precision', 2);
122 |
123 | $this->assertSame(
124 | $this->column->filterValue($value),
125 | [
126 | 'value' => '10.33 PLN',
127 | ]
128 | );
129 |
130 | $value = [
131 | 'value' => 10.324,
132 | ];
133 | $this->assertSame(
134 | $this->column->filterValue($value),
135 | [
136 | 'value' => '10.32 PLN',
137 | ]
138 | );
139 | }
140 |
141 | public function testCurrencyThousandsSepOption()
142 | {
143 | $value = [
144 | 'value' => 10000,
145 | ];
146 |
147 | $this->column->setOption('currency', 'PLN');
148 | $this->column->setOption('thousands_sep', '.');
149 |
150 | $this->assertSame(
151 | $this->column->filterValue($value),
152 | [
153 | 'value' => '10.000.00 PLN',
154 | ]
155 | );
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/tests/Extension/Core/ColumnType/NumberTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Extension\Core\ColumnType\Number;
15 | use FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension\DefaultColumnOptionsExtension;
16 | use PHPUnit\Framework\TestCase;
17 |
18 | class NumberTest extends TestCase
19 | {
20 | /**
21 | * @var Number
22 | */
23 | private $column;
24 |
25 | protected function setUp()
26 | {
27 | $column = new Number();
28 | $column->setName('number');
29 | $column->initOptions();
30 |
31 | $extension = new DefaultColumnOptionsExtension();
32 | $extension->initOptions($column);
33 |
34 | $this->column = $column;
35 | }
36 |
37 | public function testPrecision()
38 | {
39 | $value = [
40 | 'number' => 10.123,
41 | ];
42 |
43 | $this->column->setOption('precision', 2);
44 | $this->column->setOption('round_mode', Number::ROUND_HALF_UP);
45 |
46 | $this->assertSame(
47 | $this->column->filterValue($value),
48 | [
49 | 'number' => 10.12,
50 | ]
51 | );
52 | }
53 |
54 | public function testRoundMode()
55 | {
56 | $this->column->setOption('round_mode', Number::ROUND_HALF_UP);
57 | $this->assertSame(
58 | $this->column->filterValue([
59 | 'number' => 10.123,
60 | ]),
61 | [
62 | 'number' => 10.12,
63 | ]
64 | );
65 |
66 | $this->assertSame(
67 | $this->column->filterValue([
68 | 'number' => 10.126,
69 | ]),
70 | [
71 | 'number' => 10.13,
72 | ]
73 | );
74 | }
75 |
76 | public function testNumberFormat()
77 | {
78 | $this->assertEquals(
79 | [
80 | 'number' => 12345678.1,
81 | ],
82 | $this->column->filterValue([
83 | 'number' => 12345678.1,
84 | ])
85 | );
86 |
87 | $this->column->setOption('format', true);
88 |
89 | $this->assertEquals(
90 | [
91 | 'number' => '12,345,678.10',
92 | ],
93 | $this->column->filterValue([
94 | 'number' => 12345678.1,
95 | ])
96 | );
97 |
98 | $this->column->setOption('format_decimals', 0);
99 |
100 | $this->assertEquals(
101 | [
102 | 'number' => '12,345,678',
103 | ],
104 | $this->column->filterValue([
105 | 'number' => 12345678.1,
106 | ])
107 | );
108 |
109 | $this->column->setOption('format_decimals', 2);
110 |
111 | $this->assertEquals(
112 | [
113 | 'number' => '12,345,678.10',
114 | ],
115 | $this->column->filterValue([
116 | 'number' => 12345678.1,
117 | ])
118 | );
119 |
120 | $this->column->setOption('format_dec_point', ',');
121 | $this->column->setOption('format_thousands_sep', ' ');
122 |
123 | $this->assertEquals(
124 | [
125 | 'number' => '12 345 678,10',
126 | ],
127 | $this->column->filterValue([
128 | 'number' => 12345678.1,
129 | ])
130 | );
131 |
132 | $this->assertEquals(
133 | [
134 | 'number' => '1 000,00',
135 | ],
136 | $this->column->filterValue([
137 | 'number' => 1000,
138 | ])
139 | );
140 |
141 | $this->column->setOption('format_decimals', 0);
142 |
143 | $this->assertEquals(
144 | [
145 | 'number' => '1 000',
146 | ],
147 | $this->column->filterValue([
148 | 'number' => 1000,
149 | ])
150 | );
151 |
152 | $this->column->setOption('format', false);
153 | $this->assertEquals(
154 | [
155 | 'number' => '1000',
156 | ],
157 | $this->column->filterValue([
158 | 'number' => 1000,
159 | ])
160 | );
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/tests/Extension/Core/ColumnType/TextTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Core\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Extension\Core\ColumnType\Text;
15 | use PHPUnit\Framework\TestCase;
16 |
17 | class TextTest extends TestCase
18 | {
19 | public function testTrimOption()
20 | {
21 | $column = new Text();
22 | $column->initOptions();
23 | $column->setOption('trim', true);
24 |
25 | $value = [
26 | ' VALUE ',
27 | ];
28 |
29 | $this->assertSame(
30 | ['VALUE'],
31 | $column->filterValue($value)
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/Extension/Core/ColumnTypeExtension/DefaultColumnOptionsExtensionTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Core\ColumntypeExtension;
13 |
14 | use FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension\DefaultColumnOptionsExtension;
15 | use FSi\Component\DataGrid\Column\HeaderViewInterface;
16 | use FSi\Component\DataGrid\Column\ColumnTypeInterface;
17 | use PHPUnit\Framework\TestCase;
18 |
19 | class DefaultColumnOptionsExtensionTest extends TestCase
20 | {
21 | public function testBuildHeaderView()
22 | {
23 | $extension = new DefaultColumnOptionsExtension();
24 |
25 | $column = $this->createMock(ColumnTypeInterface::class);
26 | $view = $this->createMock(HeaderViewInterface::class);
27 |
28 | $column->expects($this->at(0))
29 | ->method('getOption')
30 | ->with('label')
31 | ->will($this->returnValue('foo'));
32 |
33 | $column->expects($this->at(1))
34 | ->method('getOption')
35 | ->with('display_order')
36 | ->will($this->returnValue(100));
37 |
38 | $view->expects($this->at(0))
39 | ->method('setLabel')
40 | ->with('foo');
41 |
42 | $view->expects($this->at(1))
43 | ->method('setAttribute')
44 | ->with('display_order', 100);
45 |
46 | $extension->buildHeaderView($column, $view);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/Extension/Core/CoreExtensionTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Core;
13 |
14 | use FSi\Component\DataGrid\Extension\Core\CoreExtension;
15 | use FSi\Component\DataGrid\Extension\Core\EventSubscriber\ColumnOrder;
16 | use FSi\Component\DataGrid\DataGridEventInterface;
17 | use FSi\Component\DataGrid\DataGridViewInterface;
18 | use FSi\Component\DataGrid\Column\HeaderViewInterface;
19 | use PHPUnit\Framework\TestCase;
20 |
21 | class CoreExtensionTest extends TestCase
22 | {
23 | public function testLoadedTypes()
24 | {
25 | $extension = new CoreExtension();
26 | $this->assertTrue($extension->hasColumnType('text'));
27 | $this->assertTrue($extension->hasColumnType('number'));
28 | $this->assertTrue($extension->hasColumnType('datetime'));
29 | $this->assertTrue($extension->hasColumnType('action'));
30 | $this->assertTrue($extension->hasColumnType('money'));
31 | $this->assertTrue($extension->hasColumnType('action'));
32 |
33 | $this->assertFalse($extension->hasColumnType('foo'));
34 | }
35 |
36 | public function testLoadedExtensions()
37 | {
38 | $extension = new CoreExtension();
39 | $this->assertTrue($extension->hasColumnTypeExtensions('text'));
40 | $this->assertTrue($extension->hasColumnTypeExtensions('text'));
41 | $this->assertTrue($extension->hasColumnTypeExtensions('number'));
42 | $this->assertTrue($extension->hasColumnTypeExtensions('datetime'));
43 | $this->assertTrue($extension->hasColumnTypeExtensions('action'));
44 | $this->assertTrue($extension->hasColumnTypeExtensions('money'));
45 | $this->assertTrue($extension->hasColumnTypeExtensions('gedmo_tree'));
46 | $this->assertTrue($extension->hasColumnTypeExtensions('entity'));
47 | }
48 |
49 | public function testColumnOrder()
50 | {
51 | $subscriber = new ColumnOrder();
52 |
53 | $cases = [
54 | [
55 | 'columns' => [
56 | 'negative2' => -2,
57 | 'neutral1' => null,
58 | 'negative1' => -1,
59 | 'neutral2' => null,
60 | 'positive1' => 1,
61 | 'neutral3' => null,
62 | 'positive2' => 2,
63 | ],
64 | 'sorted' => [
65 | 'negative2',
66 | 'negative1',
67 | 'neutral1',
68 | 'neutral2',
69 | 'neutral3',
70 | 'positive1',
71 | 'positive2',
72 | ]
73 | ],
74 | [
75 | 'columns' => [
76 | 'neutral1' => null,
77 | 'neutral2' => null,
78 | 'neutral3' => null,
79 | 'neutral4' => null,
80 | ],
81 | 'sorted' => [
82 | 'neutral1',
83 | 'neutral2',
84 | 'neutral3',
85 | 'neutral4',
86 | ]
87 | ]
88 | ];
89 |
90 | foreach ($cases as $case) {
91 | $columns = [];
92 |
93 | foreach ($case['columns'] as $name => $order) {
94 | $columnHeader = $this->createMock(HeaderViewInterface::class);
95 |
96 | $columnHeader
97 | ->expects($this->atLeastOnce())
98 | ->method('getName')
99 | ->will($this->returnValue($name));
100 |
101 | $columnHeader
102 | ->expects($this->atLeastOnce())
103 | ->method('hasAttribute')
104 | ->will($this->returnCallback(function ($attribute) use ($order) {
105 | if (($attribute == 'display_order') && isset($order)) {
106 | return true;
107 | } else {
108 | return false;
109 | }
110 | }));
111 |
112 | $columnHeader
113 | ->expects($this->any())
114 | ->method('getAttribute')
115 | ->will($this->returnCallback(function ($attribute) use ($order) {
116 | if (($attribute == 'display_order') && isset($order)) {
117 | return $order;
118 | } else {
119 | return null;
120 | }
121 | }));
122 |
123 | $columns[] = $columnHeader;
124 | }
125 |
126 | $view = $this->createMock(DataGridViewInterface::class);
127 |
128 | $self = $this;
129 |
130 | $view
131 | ->expects($this->once())
132 | ->method('getColumns')
133 | ->will($this->returnValue($columns));
134 |
135 | $view
136 | ->expects($this->once())
137 | ->method('setColumns')
138 | ->will($this->returnCallback(function (array $columns) use ($self, $case) {
139 | $sorted = [];
140 | foreach ($columns as $column) {
141 | $sorted[] = $column->getName();
142 | }
143 | $self->assertSame($case['sorted'], $sorted);
144 | }));
145 |
146 | $event = $this->createMock(DataGridEventInterface::class);
147 | $event
148 | ->expects($this->once())
149 | ->method('getData')
150 | ->will($this->returnValue($view));
151 |
152 | $subscriber->postBuildView($event);
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/tests/Extension/Doctrine/ColumnType/EntityTypeTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Doctrine\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Tests\Fixtures\Entity as Fixture;
15 | use FSi\Component\DataGrid\Extension\Doctrine\ColumnType\Entity;
16 | use FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension\DefaultColumnOptionsExtension;
17 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
18 | use FSi\Component\DataGrid\DataGridInterface;
19 | use PHPUnit\Framework\TestCase;
20 |
21 | class EntityTypeTest extends TestCase
22 | {
23 | public function testGetValue()
24 | {
25 | $column = new Entity();
26 | $column->setName('foo');
27 | $column->initOptions();
28 |
29 | $extension = new DefaultColumnOptionsExtension();
30 | $extension->initOptions($column);
31 |
32 | // Call resolve at OptionsResolver.
33 | $column->setOptions([]);
34 |
35 | $object = new Fixture('object');
36 |
37 | $dataGrid = $this->createMock(DataGridInterface::class);
38 | $dataMapper = $this->createMock(DataMapperInterface::class);
39 |
40 | $dataMapper->expects($this->once())
41 | ->method('getData')
42 | ->will($this->returnValue(['foo' => 'bar']));
43 |
44 | $dataGrid->expects($this->any())
45 | ->method('getDataMapper')
46 | ->will($this->returnValue($dataMapper));
47 |
48 | $column->setDataGrid($dataGrid);
49 |
50 | $column->getValue($object);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/Extension/Doctrine/DoctrineExtensionTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Doctrine;
13 |
14 | use FSi\Component\DataGrid\Extension\Doctrine\DoctrineExtension;
15 | use PHPUnit\Framework\TestCase;
16 |
17 | class DoctrineExtensionTest extends TestCase
18 | {
19 | public function testLoadedTypes()
20 | {
21 | $extension = new DoctrineExtension();
22 |
23 | $this->assertTrue($extension->hasColumnType('entity'));
24 | $this->assertFalse($extension->hasColumnType('foo'));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/Extension/Gedmo/ColumnType/Tree/TreeTypeTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Gedmo\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Tests\Fixtures\EntityTree;
15 | use FSi\Component\DataGrid\Tests\Fixtures\EntityManagerMock;
16 | use FSi\Component\DataGrid\Tests\Fixtures\EventManagerMock;
17 | use FSi\Component\DataGrid\Extension\Gedmo\ColumnType\Tree;
18 | use FSi\Component\DataGrid\Extension\Core\ColumnTypeExtension\DefaultColumnOptionsExtension;
19 | use FSi\Component\DataGrid\DataMapper\DataMapperInterface;
20 | use FSi\Component\DataGrid\DataGridInterface;
21 | use PHPUnit\Framework\TestCase;
22 | use Doctrine\Common\Persistence\ManagerRegistry;
23 | use Gedmo\Tree\TreeListener;
24 | use Doctrine\Common\Persistence\ObjectManager;
25 | use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory;
26 | use Doctrine\ORM\Mapping\ClassMetadataInfo;
27 | use Gedmo\Tree\Strategy;
28 |
29 | class TreeTypeTest extends TestCase
30 | {
31 | public function testWrongValue()
32 | {
33 | $registry = $this->createMock(ManagerRegistry::class);
34 | $column = new Tree($registry);
35 | $column->setName('tree');
36 | $column->initOptions();
37 |
38 | $extension = new DefaultColumnOptionsExtension();
39 | $extension->initOptions($column);
40 |
41 | $object = 'This is string, not object';
42 |
43 | $this->expectException(\InvalidArgumentException::class);
44 | $this->expectExceptionMessage('Column "gedmo_tree" must read value from object.');
45 | $column->getValue($object);
46 | }
47 |
48 | public function testGetValue()
49 | {
50 | $dataGrid = $this->createMock(DataGridInterface::class);
51 | $registry = $this->getManagerRegistry();
52 | $dataMapper = $this->createMock(DataMapperInterface::class);
53 |
54 | $dataMapper->expects($this->any())
55 | ->method('getData')
56 | ->will($this->returnValue(new EntityTree('foo')));
57 |
58 | $column = new Tree($registry);
59 | $column->setName('tree');
60 | $column->initOptions();
61 |
62 | $extension = new DefaultColumnOptionsExtension();
63 | $extension->initOptions($column);
64 |
65 | $column->setDataMapper($dataMapper);
66 | $column->setOption('field_mapping', ['foo']);
67 | $column->setDataGrid($dataGrid);
68 | $object = new EntityTree("foo");
69 |
70 | $column->getValue($object);
71 |
72 | $view = $column->createCellView($object, '0');
73 | $column->buildCellView($view);
74 |
75 | $this->assertSame(
76 | [
77 | "row" => "0",
78 | "id" => "foo",
79 | "root" => "root",
80 | "left" => "left",
81 | "right" => "right",
82 | "level" => "level",
83 | "children" => 2,
84 | "parent" => "bar",
85 | ],
86 | $view->getAttributes()
87 | );
88 | }
89 |
90 | protected function getManagerRegistry()
91 | {
92 | $managerRegistry = $this->createMock(ManagerRegistry::class);
93 | $managerRegistry->expects($this->any())
94 | ->method('getManagerForClass')
95 | ->will($this->returnCallback(function() {
96 | $manager = $this->createMock(ObjectManager::class);
97 | $manager->expects($this->any())
98 | ->method('getMetadataFactory')
99 | ->will($this->returnCallback(function() {
100 | $metadataFactory = $this->createMock(ClassMetadataFactory::class);
101 |
102 | $metadataFactory->expects($this->any())
103 | ->method('getMetadataFor')
104 | ->will($this->returnCallback(function($class) {
105 | switch ($class) {
106 | case EntityTree::class:
107 | $metadata = $this->createMock(ClassMetadataInfo::class);
108 | $metadata->expects($this->any())
109 | ->method('getIdentifierFieldNames')
110 | ->will($this->returnValue([
111 | 'id'
112 | ]));
113 | break;
114 | }
115 |
116 | return $metadata;
117 | }));
118 |
119 | return $metadataFactory;
120 | }));
121 |
122 | $manager->expects($this->any())
123 | ->method('getClassMetadata')
124 | ->will($this->returnCallback(function($class) {
125 | switch ($class) {
126 | case EntityTree::class:
127 | $metadata = $this->createMock(ClassMetadataInfo::class);
128 | $metadata->expects($this->any())
129 | ->method('getIdentifierFieldNames')
130 | ->will($this->returnValue([
131 | 'id'
132 | ]));
133 | $metadata->isMappedSuperclass = false;
134 | $metadata->rootEntityName = $class;
135 | break;
136 | }
137 |
138 | return $metadata;
139 | }));
140 |
141 | return $manager;
142 | }));
143 |
144 | $treeListener = $this->createMock(TreeListener::class);
145 | $strategy = $this->createMock(Strategy::class);
146 |
147 | $treeListener->expects($this->once())
148 | ->method('getStrategy')
149 | ->will($this->returnValue($strategy));
150 |
151 | $treeListener->expects($this->any())
152 | ->method('getConfiguration')
153 | ->will($this->returnValue(
154 | [
155 | 'left' => 'left',
156 | 'right' => 'right',
157 | 'root' => 'root',
158 | 'level' => 'level',
159 | 'parent' => 'parent'
160 | ]
161 | ));
162 |
163 | $strategy->expects($this->any())
164 | ->method('getName')
165 | ->will($this->returnValue('nested'));
166 |
167 | $evm = new EventManagerMock([$treeListener]);
168 | $em = new EntityManagerMock();
169 | $em->_setEventManager($evm);
170 |
171 | $managerRegistry->expects($this->any())
172 | ->method('getManager')
173 | ->will($this->returnValue($em));
174 |
175 | return $managerRegistry;
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/tests/Extension/Gedmo/GedmoDoctrineExtensionTest.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Extension\Doctrine;
13 |
14 | use FSi\Component\DataGrid\Extension\Gedmo\GedmoDoctrineExtension;
15 | use Doctrine\Common\Persistence\ManagerRegistry;
16 | use PHPUnit\Framework\TestCase;
17 |
18 | class GedmoDoctrineExtensionTest extends TestCase
19 | {
20 | public function testLoadedTypes()
21 | {
22 | $registry = $this->createMock(ManagerRegistry::class);
23 | $extension = new GedmoDoctrineExtension($registry);
24 |
25 | $this->assertTrue($extension->hasColumnType('gedmo_tree'));
26 | $this->assertFalse($extension->hasColumnType('foo'));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tests/Fixtures/ColumnType/FooType.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures\ColumnType;
13 |
14 | use FSi\Component\DataGrid\Column\ColumnAbstractType;
15 |
16 | class FooType extends ColumnAbstractType
17 | {
18 | public function getId(): string
19 | {
20 | return 'foo';
21 | }
22 |
23 | public function filterValue($value)
24 | {
25 | return $value;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/Fixtures/Entity.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures;
13 |
14 | class Entity
15 | {
16 | private $name;
17 |
18 | private $author;
19 |
20 | private $category;
21 |
22 | public function __construct($name)
23 | {
24 | $this->name = $name;
25 | }
26 |
27 | public function setName($name)
28 | {
29 | $this->name = $name;
30 | return $this;
31 | }
32 |
33 | public function getName()
34 | {
35 | return $this->name;
36 | }
37 |
38 | public function setAuthor($author)
39 | {
40 | $this->author = $author;
41 | return $this;
42 | }
43 |
44 | public function getAuthor()
45 | {
46 | return $this->author;
47 | }
48 |
49 | /**
50 | * @return EntityCategory
51 | */
52 | public function getCategory()
53 | {
54 | return $this->category;
55 | }
56 |
57 | public function setCategory($category)
58 | {
59 | $this->category = $category;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/tests/Fixtures/EntityCategory.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures;
13 |
14 | class EntityCategory
15 | {
16 | public $id;
17 | public $name;
18 |
19 | public function __construct($id, $name)
20 | {
21 | $this->name = $name;
22 | $this->id = $id;
23 | }
24 |
25 | public function getName()
26 | {
27 | return $this->name;
28 | }
29 |
30 | public function setName($name)
31 | {
32 | $this->name = $name;
33 | }
34 |
35 | public function __toString()
36 | {
37 | return $this->name;
38 | }
39 |
40 | public function getId()
41 | {
42 | return $this->id;
43 | }
44 |
45 | public function setId($id)
46 | {
47 | $this->id = $id;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/Fixtures/EntityManagerMock.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures;
13 |
14 | use Doctrine\ORM\EntityManager;
15 | use FSi\Component\DataGrid\Tests\Fixtures\EntityRepositoryMock;
16 |
17 | class EntityManagerMock extends EntityManager
18 | {
19 | protected $eventManager;
20 |
21 | protected $metadataFactory;
22 |
23 | public function __construct()
24 | {
25 | }
26 |
27 | public function _setEventManager($eventManager)
28 | {
29 | $this->eventManager = $eventManager;
30 | }
31 |
32 | public function _setMetadataFactory($metadataFactory)
33 | {
34 | $this->metadataFactory = $metadataFactory;
35 | }
36 |
37 | public function getMetadataFactory()
38 | {
39 | return $this->metadataFactory;
40 | }
41 |
42 | public function getEventManager()
43 | {
44 | return $this->eventManager;
45 | }
46 |
47 | public function getClassMetadata($className)
48 | {
49 | return null;
50 | }
51 |
52 | public function getRepository($entityName)
53 | {
54 | return new EntityRepositoryMock();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/Fixtures/EntityMapper.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures;
13 |
14 | class EntityMapper
15 | {
16 | public $id;
17 |
18 | private $private_id;
19 |
20 | private $name;
21 |
22 | private $surname;
23 |
24 | private $collection;
25 |
26 | private $private_collection;
27 |
28 | private $ready;
29 |
30 | private $protected_ready;
31 |
32 | private $tags = [];
33 |
34 | public function setId($id)
35 | {
36 | $this->id = $id;
37 | }
38 |
39 | public function setName($name)
40 | {
41 | $this->name = $name;
42 | return $this;
43 | }
44 |
45 | protected function setProtectedName($name)
46 | {
47 | $this->name = $name;
48 | return $this;
49 | }
50 |
51 | public function setPrivateId($id)
52 | {
53 | $this->private_id = $id;
54 | }
55 |
56 | public function getName()
57 | {
58 | return $this->name;
59 | }
60 |
61 | protected function getSurname()
62 | {
63 | return $this->surname;
64 | }
65 |
66 | public function setSurname($surname)
67 | {
68 | $this->surname = $surname;
69 | }
70 |
71 | public function hasCollection()
72 | {
73 | return isset($this->collection);
74 | }
75 |
76 | public function setCollection($collection)
77 | {
78 | $this->collection = $collection;
79 | }
80 |
81 | public function setPrivateCollection($collection)
82 | {
83 | $this->private_collection = $collection;
84 | }
85 |
86 | private function hasPrivateCollection()
87 | {
88 | return isset($this->privatecollection);
89 | }
90 |
91 | public function setReady($ready)
92 | {
93 | $this->ready = (boolean)$ready;
94 | }
95 |
96 | public function isReady()
97 | {
98 | return $this->ready;
99 | }
100 |
101 | public function setProtectedReady($ready)
102 | {
103 | $this->protected_ready = (boolean)$ready;
104 | }
105 |
106 | protected function isProtectedReady()
107 | {
108 | return $this->protected_ready;
109 | }
110 |
111 | public function addTag($tag)
112 | {
113 | $this->tags[] = $tag;
114 | }
115 |
116 | public function getTags()
117 | {
118 | return $this->tags;
119 | }
120 |
121 | protected function addProtectedTag($tag)
122 | {
123 | $this->tags[] = $tag;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/tests/Fixtures/EntityRepositoryMock.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures;
13 |
14 | use Gedmo\Tree\RepositoryInterface;
15 |
16 | class EntityRepositoryMock implements RepositoryInterface
17 | {
18 | public function getRootNodes($sortByField = null, $direction = 'asc')
19 | {
20 | }
21 |
22 | public function getNodesHierarchy($node = null, $direct = false, array $options = [], $includeNode = false)
23 | {
24 | }
25 |
26 | public function getChildren($node = null, $direct = false, $sortByField = null, $direction = 'ASC', $includeNode = false)
27 | {
28 | }
29 |
30 | public function childCount($node = null, $direct = false)
31 | {
32 | return 2;
33 | }
34 |
35 | public function childrenHierarchy($node = null, $direct = false, array $options = [], $includeNode = false)
36 | {
37 | }
38 |
39 | public function buildTree(array $nodes, array $options = [])
40 | {
41 | }
42 |
43 | public function buildTreeArray(array $nodes)
44 | {
45 | }
46 |
47 | public function setChildrenIndex($childrenIndex)
48 | {
49 | }
50 |
51 | public function getChildrenIndex()
52 | {
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/Fixtures/EntityTree.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures;
13 |
14 | class EntityTree
15 | {
16 | public $id;
17 | public $left = 'left';
18 | public $right = 'right';
19 | public $root = 'root';
20 | public $level = 'level';
21 | public $parent;
22 |
23 | public function __construct($id = null)
24 | {
25 | $this->id = $id;
26 | }
27 |
28 | public function getParent()
29 | {
30 | if (!isset($this->parent)) {
31 | $this->parent = new EntityTree("bar");
32 | }
33 |
34 | return $this->parent;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/tests/Fixtures/EventManagerMock.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures;
13 |
14 | class EventManagerMock
15 | {
16 | protected $listeners;
17 |
18 | public function __construct($listeners)
19 | {
20 | $this->listeners = $listeners;
21 | }
22 |
23 | public function getListeners()
24 | {
25 | return [$this->listeners];
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/Fixtures/FooExtension.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures;
13 |
14 | use FSi\Component\DataGrid\DataGridAbstractExtension;
15 | use FSi\Component\DataGrid\Tests\Fixtures\ColumnType;
16 |
17 | class FooExtension extends DataGridAbstractExtension
18 | {
19 | protected function loadColumnTypes(): array
20 | {
21 | return [
22 | new ColumnType\FooType(),
23 | ];
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/Fixtures/GedmoTreeListenerMock.php:
--------------------------------------------------------------------------------
1 |
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | declare(strict_types=1);
11 |
12 | namespace FSi\Component\DataGrid\Tests\Fixtures;
13 |
14 | class GedmoTreeListenerMock
15 | {
16 | }
17 |
--------------------------------------------------------------------------------