From ba4af263328fe15a966dd9c85d90136581cbe3c3 Mon Sep 17 00:00:00 2001 From: "Gurzhyi, Andrii" Date: Tue, 17 Mar 2015 15:01:06 +0200 Subject: [PATCH 001/235] MAGETWO-31654: Magento Ui module code base clean up --- .../Magento/Cms/Model/Block/DataProvider.php | 159 ++++++ .../Magento/Cms/Model/Page/DataProvider.php | 167 ++++++ .../Cms/Model/Page/Source/IsActive.php | 47 ++ .../Cms/Model/Page/Source/PageLayout.php | 58 ++ .../Component/Listing/Column/BlockActions.php | 66 +++ .../Component/Listing/Column/PageActions.php | 86 +++ .../view/adminhtml/layout/cms_block_index.xml | 2 +- .../view/adminhtml/layout/cms_page_index.xml | 4 +- .../ui_component/cms_block_listing.xml | 312 ++++++++++ .../ui_component/cms_page_listing.xml | 319 +++++++++++ .../Customer/Model/Customer/DataProvider.php | 159 ++++++ app/code/Magento/Customer/etc/data_source.xml | 146 +++++ .../adminhtml/layout/customer_index_edit.xml | 5 +- .../view/base/ui_component/customer_form.xml | 100 ++++ .../Ui/Component/Listing/Column/Store.php | 103 ++++ .../Listing/Column/Store/Options.php | 99 ++++ .../Store/view/base/layout/ui_components.xml | 4 + .../Ui/Component/AbstractComponent.php | 252 +++++++++ .../Magento/Ui/Component/AbstractView.php | 252 +++++---- .../Magento/Ui/Component/Container/Block.php | 59 ++ .../Magento/Ui/Component/Control/Action.php | 15 +- .../Ui/Component/Control/ActionPool.php | 21 +- .../Component/Control/ActionPoolInterface.php | 8 + .../Control/ButtonProviderFactory.php | 2 +- .../Control/ButtonProviderInterface.php | 1 - .../Magento/Ui/Component/Control/Link.php | 16 +- app/code/Magento/Ui/Component/DataSource.php | 74 +++ .../Ui/Component/Filter/AbstractFilter.php | 47 ++ .../Ui/Component/Filter/DataProvider.php | 75 +++ .../Magento/Ui/Component/Filter/Type/Date.php | 156 +++-- .../Ui/Component/Filter/Type/Input.php | 69 ++- .../Ui/Component/Filter/Type/Range.php | 71 ++- .../Ui/Component/Filter/Type/Select.php | 111 +++- app/code/Magento/Ui/Component/Filters.php | 54 ++ app/code/Magento/Ui/Component/Form.php | 230 ++------ .../Magento/Ui/Component/Form/Collection.php | 16 +- .../Form/Element/AbstractFormElement.php | 4 +- .../Ui/Component/Form/Element/Checkbox.php | 12 +- .../Element/DataType/AbstractDataType.php | 14 +- .../Form/Element/DataType/Boolean.php | 12 +- .../Element/DataType/DataTypeInterface.php | 8 - .../Component/Form/Element/DataType/Date.php | 93 ++- .../Component/Form/Element/DataType/Email.php | 12 +- .../Component/Form/Element/DataType/Media.php | 12 +- .../Form/Element/DataType/Number.php | 12 +- .../Form/Element/DataType/Password.php | 12 +- .../Component/Form/Element/DataType/Price.php | 12 +- .../Component/Form/Element/DataType/Text.php | 12 +- .../Ui/Component/Form/Element/Input.php | 17 +- .../Ui/Component/Form/Element/Multiline.php | 12 + .../Ui/Component/Form/Element/Radio.php | 12 + .../Ui/Component/Form/Element/Range.php | 12 + .../Ui/Component/Form/Element/Select.php | 64 +++ .../Ui/Component/Form/Element/Textarea.php | 12 +- app/code/Magento/Ui/Component/Form/Field.php | 80 ++- .../Magento/Ui/Component/Form/Fieldset.php | 16 +- app/code/Magento/Ui/Component/Layout.php | 94 +++ .../Magento/Ui/Component/Layout/Generic.php | 78 +++ .../Magento/Ui/Component/Layout/Group.php | 16 +- .../Ui/Component/Layout/LayoutPool.php | 64 +++ app/code/Magento/Ui/Component/Layout/Tabs.php | 533 +++++++++++++++++- .../Magento/Ui/Component/Layout/Tabs/Nav.php | 6 +- .../Ui/Component/Layout/Tabs/TabInterface.php | 7 +- app/code/Magento/Ui/Component/Listing.php | 271 ++------- .../Magento/Ui/Component/Listing/Columns.php | 39 ++ .../Ui/Component/Listing/Columns/Column.php | 125 ++++ app/code/Magento/Ui/Component/MassAction.php | 44 +- app/code/Magento/Ui/Component/Paging.php | 36 +- .../Controller/Adminhtml/AbstractAction.php | 3 +- .../Ui/Controller/Adminhtml/Form/Fieldset.php | 21 +- .../Ui/Controller/Adminhtml/Form/Save.php | 3 - .../Ui/Controller/Adminhtml/Form/Validate.php | 4 +- .../Ui/Controller/UiActionInterface.php | 2 - .../Ui/DataProvider/Config/Converter.php | 38 +- .../Magento/Ui/DataProvider/Config/Data.php | 19 +- .../Ui/DataProvider/Config/FileResolver.php | 10 +- .../Magento/Ui/DataProvider/Config/Reader.php | 6 +- .../Ui/DataProvider/Config/SchemaLocator.php | 9 +- app/code/Magento/Ui/DataProvider/Metadata.php | 46 +- app/code/Magento/Ui/TemplateEngine/Xhtml.php | 93 +++ .../Ui/TemplateEngine/Xhtml/Compiler.php | 174 ++++++ .../Xhtml/Compiler/Attribute.php | 50 ++ .../Xhtml/Compiler/AttributeInterface.php | 23 + .../TemplateEngine/Xhtml/Compiler/Cdata.php | 26 + .../Xhtml/Compiler/CdataInterface.php | 23 + .../TemplateEngine/Xhtml/Compiler/Comment.php | 26 + .../Xhtml/Compiler/CommentInterface.php | 23 + .../Compiler/Directive/CallableMethod.php | 51 ++ .../Compiler/Directive/DirectiveInterface.php | 30 + .../Xhtml/Compiler/Directive/Variable.php | 36 ++ .../Xhtml/Compiler/Element/Content.php | 44 ++ .../Compiler/Element/ElementInterface.php | 33 ++ .../Xhtml/Compiler/Element/Form.php | 52 ++ .../Xhtml/Compiler/Element/Render.php | 45 ++ .../Ui/TemplateEngine/Xhtml/Compiler/Text.php | 54 ++ .../Xhtml/Compiler/TextInterface.php | 23 + .../Ui/TemplateEngine/Xhtml/Result.php | 118 ++++ .../Ui/TemplateEngine/Xhtml/Template.php | 70 +++ .../Ui/Test/Unit/Component/ListingTest.php | 10 +- app/code/Magento/Ui/etc/di.xml | 238 +++++++- app/code/Magento/Ui/etc/ui_components.xsd | 382 +++++++++++++ app/code/Magento/Ui/etc/ui_configuration.xsd | 75 +++ app/code/Magento/Ui/etc/ui_definition.xsd | 78 +++ app/code/Magento/Ui/etc/ui_template.xsd | 24 + .../Magento/Ui/view/base/layout/default.xml | 10 +- .../Ui/view/base/layout/ui_components.xml | 7 +- .../view/base/templates/context/default.phtml | 6 +- .../base/templates/filter_pool/default.phtml | 8 +- .../Ui/view/base/templates/form/default.phtml | 21 +- .../templates/listing/horizontal_grid.phtml | 15 +- .../listingcontainer/massaction/default.phtml | 10 +- .../massaction/page_actions.phtml | 10 +- .../view/base/templates/paging/default.phtml | 10 +- .../view/base/templates/sorting/default.phtml | 11 +- .../view/base/ui_component/etc/definition.xml | 214 +++++++ .../ui_component/templates/form/default.xhtml | 15 + .../templates/listing/default.xhtml | 12 + .../Magento/Ui/view/base/web/js/core/app.js | 22 +- .../web/js/core/renderer/components/layout.js | 106 ++-- .../base/web/js/core/renderer/renderer.js | 10 +- .../base/web/js/form/components/collection.js | 2 +- .../view/base/web/js/form/components/group.js | 49 +- .../view/base/web/js/form/element/abstract.js | 152 +++-- .../view/base/web/js/form/element/boolean.js | 13 +- .../Ui/view/base/web/js/form/element/date.js | 3 +- .../view/base/web/js/form/element/select.js | 105 ++-- .../view/base/web/js/grid/columns/select.js | 24 + .../Ui/view/base/web/js/grid/columns/text.js | 78 +++ .../view/base/web/js/grid/filters/filters.js | 80 +++ .../Ui/view/base/web/js/grid/filters/group.js | 28 + .../Ui/view/base/web/js/grid/listing.js | 1 + .../Ui/view/base/web/js/grid/massactions.js | 161 ++++++ .../Ui/view/base/web/js/grid/paging.js | 124 ++++ .../Ui/view/base/web/js/grid/provider.js | 86 +++ .../Magento/Ui/view/base/web/js/lib/class.js | 70 +-- .../base/web/js/lib/component/component.js | 21 + .../Ui/view/base/web/js/lib/component/core.js | 230 ++++++++ .../view/base/web/js/lib/component/links.js | 121 ++++ .../view/base/web/js/lib/component/manip.js | 157 ++++++ .../base/web/js/lib/component/traversal.js | 72 +++ .../Magento/Ui/view/base/web/js/lib/events.js | 35 +- .../Magento/Ui/view/base/web/js/lib/loader.js | 40 +- .../view/base/web/templates/grid/actions.html | 13 + .../web/templates/grid/cells/massactions.html | 5 + .../base/web/templates/grid/cells/select.html | 11 + .../base/web/templates/grid/cells/text.html | 11 + .../templates/grid/columns/massactions.html | 17 + .../base/web/templates/grid/columns/text.html | 9 + .../templates/grid/filters/elements/date.html | 17 + .../grid/filters/elements/group.html | 12 + .../grid/filters/elements/input.html | 23 + .../grid/filters/elements/select.html | 29 + .../web/templates/grid/filters/filters.html | 42 ++ .../view/base/web/templates/grid/listing.html | 34 ++ .../view/base/web/templates/grid/paging.html | 28 + .../adminhtml/layout/customer_index_edit.xml | 14 + .../Framework/Data/etc/argument/types.xsd | 15 + .../Interpreter/ConfigurableObject.php | 60 ++ .../UiComponent/ArrayObjectFactory.php | 21 + .../Element/UiComponent/Config/Converter.php | 123 ++++ .../Element/UiComponent/Config/DomMerger.php | 450 +++++++++++++++ .../UiComponent/Config/DomMergerInterface.php | 64 +++ .../FileCollector/AggregatedFileCollector.php | 86 +++ .../AggregatedFileCollectorFactory.php | 42 ++ .../Config/FileCollectorInterface.php | 20 + .../Element/UiComponent/Config/Manager.php | 330 +++++++++++ .../UiComponent/Config/ManagerInterface.php | 77 +++ .../Config/Provider/Component/Definition.php | 101 ++++ .../UiComponent/Config/Provider/Template.php | 111 ++++ .../Element/UiComponent/Config/Reader.php | 116 ++++ .../UiComponent/Config/ReaderFactory.php | 42 ++ .../UiComponent/Config/UiReaderInterface.php | 44 ++ .../Element/UiComponent/ConfigProvider.php | 115 ++++ .../UiComponent/ConfigProviderInterface.php | 62 ++ .../ContentType/AbstractContentType.php | 39 ++ .../ContentType/ContentTypeFactory.php | 63 +++ .../ContentType/ContentTypeInterface.php | 23 + .../Element/UiComponent/ContentType/Html.php | 49 ++ .../Element/UiComponent/ContentType/Json.php | 27 + .../Element/UiComponent/ContentType/Xml.php | 109 ++++ .../View/Element/UiComponent/Context.php | 249 ++++---- .../Element/UiComponent/ContextFactory.php | 42 ++ .../Element/UiComponent/ContextInterface.php | 101 ++++ .../DataProvider/DataProviderInterface.php | 90 +++ .../UiComponent/DataSourceInterface.php | 20 + .../Element/UiComponent/JsConfigInterface.php | 21 + .../Element/UiComponent/LayoutInterface.php | 30 + .../Element/UiComponent/TemplateAdapter.php | 69 +++ .../View/Element/UiComponentFactory.php | 224 ++++---- .../View/Element/UiComponentInterface.php | 82 +-- .../Framework/View/Layout/Argument/Parser.php | 8 +- .../View/Layout/Generator/UiComponent.php | 105 ++-- .../View/Layout/Reader/UiComponent.php | 41 +- .../Framework/View/Layout/etc/elements.xsd | 8 +- lib/web/mage/utils.js | 218 ++++--- 195 files changed, 11325 insertions(+), 1656 deletions(-) create mode 100644 app/code/Magento/Cms/Model/Block/DataProvider.php create mode 100644 app/code/Magento/Cms/Model/Page/DataProvider.php create mode 100644 app/code/Magento/Cms/Model/Page/Source/IsActive.php create mode 100644 app/code/Magento/Cms/Model/Page/Source/PageLayout.php create mode 100644 app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php create mode 100644 app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php create mode 100644 app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml create mode 100644 app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml create mode 100644 app/code/Magento/Customer/Model/Customer/DataProvider.php create mode 100644 app/code/Magento/Customer/etc/data_source.xml create mode 100644 app/code/Magento/Customer/view/base/ui_component/customer_form.xml create mode 100644 app/code/Magento/Store/Ui/Component/Listing/Column/Store.php create mode 100644 app/code/Magento/Store/Ui/Component/Listing/Column/Store/Options.php create mode 100644 app/code/Magento/Ui/Component/AbstractComponent.php create mode 100644 app/code/Magento/Ui/Component/Container/Block.php create mode 100644 app/code/Magento/Ui/Component/DataSource.php create mode 100644 app/code/Magento/Ui/Component/Filter/AbstractFilter.php create mode 100644 app/code/Magento/Ui/Component/Filter/DataProvider.php create mode 100644 app/code/Magento/Ui/Component/Filters.php create mode 100644 app/code/Magento/Ui/Component/Layout.php create mode 100644 app/code/Magento/Ui/Component/Layout/Generic.php create mode 100644 app/code/Magento/Ui/Component/Layout/LayoutPool.php create mode 100644 app/code/Magento/Ui/Component/Listing/Columns.php create mode 100644 app/code/Magento/Ui/Component/Listing/Columns/Column.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Cdata.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CdataInterface.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Comment.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CommentInterface.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/Variable.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Form.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php create mode 100644 app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php create mode 100644 app/code/Magento/Ui/etc/ui_components.xsd create mode 100644 app/code/Magento/Ui/etc/ui_configuration.xsd create mode 100644 app/code/Magento/Ui/etc/ui_definition.xsd create mode 100644 app/code/Magento/Ui/etc/ui_template.xsd create mode 100644 app/code/Magento/Ui/view/base/ui_component/etc/definition.xml create mode 100644 app/code/Magento/Ui/view/base/ui_component/templates/form/default.xhtml create mode 100644 app/code/Magento/Ui/view/base/ui_component/templates/listing/default.xhtml create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/columns/select.js create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/columns/text.js create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/filters/group.js create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/listing.js create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/massactions.js create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/paging.js create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/provider.js create mode 100644 app/code/Magento/Ui/view/base/web/js/lib/component/component.js create mode 100644 app/code/Magento/Ui/view/base/web/js/lib/component/core.js create mode 100644 app/code/Magento/Ui/view/base/web/js/lib/component/links.js create mode 100644 app/code/Magento/Ui/view/base/web/js/lib/component/manip.js create mode 100644 app/code/Magento/Ui/view/base/web/js/lib/component/traversal.js create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/actions.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/cells/massactions.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/cells/select.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/columns/massactions.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/columns/text.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/date.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/group.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/input.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/select.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/filters/filters.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/listing.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/paging.html create mode 100644 app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_edit.xml create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Argument/Interpreter/ConfigurableObject.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ArrayObjectFactory.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/Converter.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMerger.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMergerInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollector.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollectorFactory.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollectorInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/Manager.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Component/Definition.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/Reader.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/ReaderFactory.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/Config/UiReaderInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ConfigProvider.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ConfigProviderInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/AbstractContentType.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeFactory.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Html.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Json.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Xml.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ContextFactory.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ContextInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/DataProvider/DataProviderInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/DataSourceInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/JsConfigInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/LayoutInterface.php create mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/TemplateAdapter.php diff --git a/app/code/Magento/Cms/Model/Block/DataProvider.php b/app/code/Magento/Cms/Model/Block/DataProvider.php new file mode 100644 index 0000000000000..f39ee598fa309 --- /dev/null +++ b/app/code/Magento/Cms/Model/Block/DataProvider.php @@ -0,0 +1,159 @@ +primaryFieldName = $primaryFieldName; + $this->requestFieldName = $requestFieldName; + $this->collection = $collectionFactory->create(); + $this->meta = $meta; + } + + /** + * @return array + */ + public function getMeta() + { + return $this->meta; + } + + /** + * Get data + * + * @return array + */ + public function getData() + { + return $this->collection->toArray(); + } + + /** + * Get field name in request + * + * @return string + */ + public function getRequestFieldName() + { + return $this->requestFieldName; + } + + /** + * Get primary field name + * + * @return string + */ + public function getPrimaryFieldName() + { + return $this->primaryFieldName; + } + + /** + * @inheritdoc + */ + public function addFilter($field, $condition = null) + { + $this->collection->addFieldToFilter($field, $condition); + } + + /** + * Add field to select + * + * @param string|array $field + * @param string|null $alias + * @return void + */ + public function addField($field, $alias = null) + { + $this->collection->addFieldToSelect($field, $alias); + } + + /** + * self::setOrder() alias + * + * @param string $field + * @param string $direction + * @return void + */ + public function addOrder($field, $direction) + { + $this->collection->addOrder($field, $direction); + } + + /** + * Set Query limit + * + * @param int $offset + * @param int $size + * @return void + */ + public function setLimit($offset, $size) + { + $this->collection->setPageSize($size); + $this->collection->setCurPage($offset); + } + + /** + * Removes field from select + * + * @param string|null $field + * @param bool $isAlias Alias identifier + * @return void + */ + public function removeField($field, $isAlias = false) + { + $this->collection->removeFieldFromSelect($field, $isAlias); + } + + /** + * Removes all fields from select + * + * @return void + */ + public function removeAllFields() + { + $this->collection->removeAllFieldsFromSelect(); + } +} diff --git a/app/code/Magento/Cms/Model/Page/DataProvider.php b/app/code/Magento/Cms/Model/Page/DataProvider.php new file mode 100644 index 0000000000000..646973745b34e --- /dev/null +++ b/app/code/Magento/Cms/Model/Page/DataProvider.php @@ -0,0 +1,167 @@ +primaryFieldName = $primaryFieldName; + $this->requestFieldName = $requestFieldName; + + $this->collection = $collectionFactory->create(); + $this->collection->setFirstStoreFlag(true); + $this->meta = $meta; + } + + /** + * @return array + */ + public function getMeta() + { + return $this->meta; + } + + /** + * Get data + * + * @return array + */ + public function getData() + { + return $this->collection->toArray(); + } + + /** + * Get field name in request + * + * @return string + */ + public function getRequestFieldName() + { + return $this->requestFieldName; + } + + /** + * Get primary field name + * + * @return string + */ + public function getPrimaryFieldName() + { + return $this->primaryFieldName; + } + + /** + * @inheritdoc + */ + public function addFilter($field, $condition = null) + { + $this->collection->addFieldToFilter($field, $condition); + } + + /** + * Add field to select + * + * @param string|array $field + * @param string|null $alias + * @return void + */ + public function addField($field, $alias = null) + { + $this->collection->addFieldToSelect($field, $alias); + } + + /** + * self::setOrder() alias + * + * @param string $field + * @param string $direction + * @return void + */ + public function addOrder($field, $direction) + { + $this->collection->addOrder($field, $direction); + } + + /** + * Set Query limit + * + * @param int $offset + * @param int $size + * @return void + */ + public function setLimit($offset, $size) + { + $this->collection->setPageSize($size); + $this->collection->setCurPage($offset); + } + + /** + * Removes field from select + * + * @param string|null $field + * @param bool $isAlias Alias identifier + * @return void + */ + public function removeField($field, $isAlias = false) + { + $this->collection->removeFieldFromSelect($field, $isAlias); + } + + /** + * Removes all fields from select + * + * @return void + */ + public function removeAllFields() + { + $this->collection->removeAllFieldsFromSelect(); + } +} diff --git a/app/code/Magento/Cms/Model/Page/Source/IsActive.php b/app/code/Magento/Cms/Model/Page/Source/IsActive.php new file mode 100644 index 0000000000000..7c9d153e5a5a5 --- /dev/null +++ b/app/code/Magento/Cms/Model/Page/Source/IsActive.php @@ -0,0 +1,47 @@ +cmsPage = $cmsPage; + } + + /** + * Get options + * + * @return array + */ + public function toOptionArray() + { + $options = []; + $availableOptions = $this->cmsPage->getAvailableStatuses(); + foreach ($availableOptions as $key => $value) { + $options[$key] = [ + 'label' => $value, + 'value' => $key, + ]; + } + return $options; + } +} diff --git a/app/code/Magento/Cms/Model/Page/Source/PageLayout.php b/app/code/Magento/Cms/Model/Page/Source/PageLayout.php new file mode 100644 index 0000000000000..32e8878dbe5b2 --- /dev/null +++ b/app/code/Magento/Cms/Model/Page/Source/PageLayout.php @@ -0,0 +1,58 @@ +pageLayoutBuilder = $pageLayoutBuilder; + } + + /** + * Get options + * + * @return array + */ + public function toOptionArray() + { + if ($this->options !== null) { + return $this->options; + } + $options = []; + $configOptions = $this->pageLayoutBuilder->getPageLayoutsConfig()->getOptions(); + foreach ($configOptions as $key => $value) { + $options[$key] = [ + 'label' => $value, + 'value' => $key, + ]; + } + $this->options = $options; + + return $this->options; + } +} diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php new file mode 100644 index 0000000000000..ecdf19a805f4c --- /dev/null +++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/BlockActions.php @@ -0,0 +1,66 @@ +urlBuilder = $urlBuilder; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + /** + * @param array $items + * @return array + */ + public function prepareItems(array & $items) + { + foreach ($items as & $item) { + if (isset($item['block_id'])) { + $item[$this->getData('name')] = [ + 'edit' => [ + 'href' => $this->urlBuilder->getUrl(static::URL_PATH, ['block_id' => $item['block_id']]), + 'label' => __('Edit'), + ] + ]; + } + } + return $items; + } +} diff --git a/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php new file mode 100644 index 0000000000000..2a8140c0923cf --- /dev/null +++ b/app/code/Magento/Cms/Ui/Component/Listing/Column/PageActions.php @@ -0,0 +1,86 @@ +urlBuilder = $urlBuilder; + $this->actionUrlBuilder = $actionUrlBuilder; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + /** + * @param array $items + * @return array + */ + public function prepareItems(array & $items) + { + foreach ($items as & $item) { + if (isset($item['page_id'])) { + $item[$this->getData('name')]['edit'] = [ + 'href' => $this->urlBuilder->getUrl(static::URL_PATH, ['page_id' => $item['page_id']]), + 'label' => __('Edit'), + 'hidden' => true + ]; + } + if (isset($item['identifier'])) { + $item[$this->getData('name')]['preview'] = [ + 'href' => $this->actionUrlBuilder->getUrl( + $item['identifier'], + isset($item['_first_store_id']) ? $item['_first_store_id'] : null, + isset($item['store_code']) ? $item['store_code'] : null + ), + 'label' => __('Preview') + ]; + } + } + + return $items; + } +} diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml index 2e9d8a6ea0b25..dbf36016b5229 100644 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml +++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml index a63fe9f63f08d..f1d5e1ee7b1ae 100644 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml +++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml @@ -1,5 +1,5 @@ - ++ + Magento\Framework\View\Element\UiComponent\Context + cms_block_listing + + + + + cms_block_listing.cms_block_listing_data_source + + cms_block_listing.cms_block_listing_data_source + + 1 + + + add + Add New Block + primary + */*/new + + + + + true + true + true + + block_id + edit + + + + + + + + + Magento_Ui/js/grid/filters/filters + + + + + + Magento_Ui/js/grid/filters/group + + + ID + + + + + + From + From + + + + + + + To + To + + + + + + + + Title + + + + + + + Identifier + + + + + Magento\Store\Ui\Component\Listing\Column\Store\Options + + + ui/grid/filters/elements/select + Store View + + + + + + + ui/grid/filters/elements/select + Status + + + 0 + Disabled + + + 1 + Enabled + + + + + + + + + Magento_Ui/js/grid/filters/group + + + Created + + + + + + ui/grid/filters/elements/date + From + From + + + + + + + ui/grid/filters/elements/date + To + To + + + + + + + + Magento_Ui/js/grid/filters/group + + + Created + + + + + + ui/grid/filters/elements/date + From + From + + + + + + + ui/grid/filters/elements/date + To + To + + + + + + + + + + + + + + + + + + + + + + + Magento\Cms\Model\Block\DataProvider + block_id + id + + + + CMS Page + + + + + + + Magento_Ui/js/grid/provider + + + + + + + + + Magento_Ui/js/grid/columns/text + + + asc + left + ID + + + + + + + Magento_Ui/js/grid/columns/text + + + asc + left + Title + + + + + + + Magento_Ui/js/grid/columns/text + + + asc + left + Identifier + + + + + + + Magento_Ui/js/grid/columns/text + + + left + Store View + + + + + + + Magento_Ui/js/grid/columns/select + + + + 0 + Disabled + + + 1 + Enabled + + + + asc + left + Status + + + + + + + Magento_Ui/js/grid/columns/text + + + left + Created + + + + + + + Magento_Ui/js/grid/columns/text + + + left + Modified + + + + + + + left + Action + actions + false + false + false + + + + + diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml new file mode 100644 index 0000000000000..964100ae01835 --- /dev/null +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml @@ -0,0 +1,319 @@ + + ++ + Magento\Framework\View\Element\UiComponent\Context + cms_page_listing + + + + + cms_page_listing.cms_page_listing_data_source + + cms_page_listing.cms_page_listing_data_source + + 1 + + + add + Add New Page + primary + */*/new + + + + + true + true + true + + page_id + edit + + + + + + + + + + + + + + + + + + + Magento\Cms\Model\Page\DataProvider + block_id + id + + + + CMS Block + + + + + + + Magento_Ui/js/grid/provider + + + + + + + + Magento_Ui/js/grid/filters/filters + + + + + + Magento_Ui/js/grid/filters/group + + + ID + + + + + + From + From + + + + + + + To + To + + + + + + + + Title + + + + + + + URL Key + + + + + Magento\Cms\Model\Page\Source\PageLayout + + + ui/grid/filters/elements/select + Store View + + + + + Magento\Store\Ui\Component\Listing\Column\Store\Options + + + ui/grid/filters/elements/select + Store View + + + + + + + ui/grid/filters/elements/select + Status + + + 0 + Disabled + + + 1 + Enabled + + + + + + + + + Magento_Ui/js/grid/filters/group + + + Created + + + + + + ui/grid/filters/elements/date + From + From + + + + + + + ui/grid/filters/elements/date + To + To + + + + + + + + Magento_Ui/js/grid/filters/group + + + Created + + + + + + ui/grid/filters/elements/date + From + From + + + + + + + ui/grid/filters/elements/date + To + To + + + + + + + + + + Magento_Ui/js/grid/columns/text + + + asc + left + ID + + + + + + + Magento_Ui/js/grid/columns/text + + + asc + left + Title + + + + + + + Magento_Ui/js/grid/columns/text + + + left + URL Key + + + + + + Magento\Cms\Model\Page\Source\PageLayout + + Magento_Ui/js/grid/columns/select + + + left + Layout + + + + + + + Magento_Ui/js/grid/columns/text + + + left + Store View + + + + + + Magento\Cms\Model\Page\Source\IsActive + + Magento_Ui/js/grid/columns/select + + + asc + left + Status + + + + + + + Magento_Ui/js/grid/columns/text + + + left + Created + + + + + + + Magento_Ui/js/grid/columns/text + + + left + Modified + + + + + + + left + Action + actions + false + false + false + + + + + diff --git a/app/code/Magento/Customer/Model/Customer/DataProvider.php b/app/code/Magento/Customer/Model/Customer/DataProvider.php new file mode 100644 index 0000000000000..a5cc57dace990 --- /dev/null +++ b/app/code/Magento/Customer/Model/Customer/DataProvider.php @@ -0,0 +1,159 @@ +primaryFieldName = $primaryFieldName; + $this->requestFieldName = $requestFieldName; + $this->collection = $collectionFactory->create(); + $this->meta = $meta; + } + + /** + * @return array + */ + public function getMeta() + { + return $this->meta; + } + + /** + * Get data + * + * @return array + */ + public function getData() + { + return $this->collection->toArray(); + } + + /** + * Get field name in request + * + * @return string + */ + public function getRequestFieldName() + { + return $this->requestFieldName; + } + + /** + * Get primary field name + * + * @return string + */ + public function getPrimaryFieldName() + { + return $this->primaryFieldName; + } + + /** + * @inheritdoc + */ + public function addFilter($field, $condition = null) + { + $this->collection->addFieldToFilter($field, $condition); + } + + /** + * Add field to select + * + * @param string|array $field + * @param string|null $alias + * @return void + */ + public function addField($field, $alias = null) + { + $this->collection->addAttributeToSelect($field); + } + + /** + * self::setOrder() alias + * + * @param string $field + * @param string $direction + * @return void + */ + public function addOrder($field, $direction) + { + $this->collection->addOrder($field, $direction); + } + + /** + * Set Query limit + * + * @param int $offset + * @param int $size + * @return void + */ + public function setLimit($offset, $size) + { + $this->collection->setPageSize($size); + $this->collection->setCurPage($offset); + } + + /** + * Removes field from select + * + * @param string|null $field + * @param bool $isAlias Alias identifier + * @return void + */ + public function removeField($field, $isAlias = false) + { + $this->collection->removeAttributeToSelect($field); + } + + /** + * Removes all fields from select + * + * @return void + */ + public function removeAllFields() + { + $this->collection->removeAttributeToSelect(); + } +} diff --git a/app/code/Magento/Customer/etc/data_source.xml b/app/code/Magento/Customer/etc/data_source.xml new file mode 100644 index 0000000000000..b8dd7ac3e8185 --- /dev/null +++ b/app/code/Magento/Customer/etc/data_source.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + http://www.magentocommerce.com/knowledge-base/entry/understanding-store-scopes + If your Magento site has multiple views, you can set the scope to apply to a specific view. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml index 9d50ae75e0676..8f01263e954a8 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml @@ -5,10 +5,11 @@ * See COPYING.txt for license details. */ --> - + - + diff --git a/app/code/Magento/Customer/view/base/ui_component/customer_form.xml b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml new file mode 100644 index 0000000000000..13c16b63b89b7 --- /dev/null +++ b/app/code/Magento/Customer/view/base/ui_component/customer_form.xml @@ -0,0 +1,100 @@ + + +
+ + Customer Information + + + true + + + + tabs + left + + + + + Magento\Customer\Model\Customer\DataProvider + entity_id + id + + + + Account Information + + + + true + + Addresses + + + + + + + Magento_Ui/js/grid/provider + + + + +
+ + + + Magento_Ui/js/form/element/input + + + asc + left + Firstname + + + + + + + Magento_Ui/js/form/element/input + + + asc + left + Lastname + + + +
+ +
+ + + + Magento_Ui/js/form/element/input + + + asc + left + Firstname + + + + + + + Magento_Ui/js/form/element/input + + + asc + left + Lastname + + + +
+
diff --git a/app/code/Magento/Store/Ui/Component/Listing/Column/Store.php b/app/code/Magento/Store/Ui/Component/Listing/Column/Store.php new file mode 100644 index 0000000000000..08b0387396799 --- /dev/null +++ b/app/code/Magento/Store/Ui/Component/Listing/Column/Store.php @@ -0,0 +1,103 @@ +systemStore = $systemStore; + $this->escaper = $escaper; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + /** + * @param array $items + * @return array + */ + public function prepareItems(array & $items) + { + foreach ($items as & $item) { + $item[$this->getData('name')] = $this->prepareItem($item); + } + return $items; + } + + /** + * Get data + * + * @param array $item + * @return mixed + */ + public function prepareItem(array $item) + { + $content = ''; + $origStores = $item['store_id']; + + if (empty($origStores)) { + return ''; + } + if (!is_array($origStores)) { + $origStores = [$origStores]; + } + if (in_array(0, $origStores) && count($origStores) == 1) { + return __('All Store Views'); + } + + $data = $this->systemStore->getStoresStructure(false, $origStores); + + foreach ($data as $website) { + $content .= $website['label'] . "
"; + foreach ($website['children'] as $group) { + $content .= str_repeat(' ', 3) . $this->escaper->escapeHtml($group['label']) . "
"; + foreach ($group['children'] as $store) { + $content .= str_repeat(' ', 6) . $this->escaper->escapeHtml($store['label']) . "
"; + } + } + } + + return $content; + } +} diff --git a/app/code/Magento/Store/Ui/Component/Listing/Column/Store/Options.php b/app/code/Magento/Store/Ui/Component/Listing/Column/Store/Options.php new file mode 100644 index 0000000000000..4e29adfc9c040 --- /dev/null +++ b/app/code/Magento/Store/Ui/Component/Listing/Column/Store/Options.php @@ -0,0 +1,99 @@ +systemStore = $systemStore; + $this->escaper = $escaper; + } + + /** + * Get options + * + * @return array + */ + public function toOptionArray() + { + if ($this->options !== null) { + return $this->options; + } + $websiteCollection = $this->systemStore->getWebsiteCollection(); + $groupCollection = $this->systemStore->getGroupCollection(); + $storeCollection = $this->systemStore->getStoreCollection(); + + $currentOptions = [ + (string)__('All Store Views') => [ + 'label' => __('All Store Views'), + 'value' => 0, + ], + ]; + /** @var \Magento\Store\Model\Website $website */ + foreach ($websiteCollection as $website) { + $groups = []; + /** @var \Magento\Store\Model\Group $group */ + foreach ($groupCollection as $group) { + if ($group->getWebsiteId() == $website->getId()) { + $stores = []; + /** @var \Magento\Store\Model\Store $store */ + foreach ($storeCollection as $store) { + if ($store->getGroupId() == $group->getId()) { + $name = $this->escaper->escapeHtml($store->getName()); + $stores[$name]['label'] = str_repeat(' ', 8) . $name; + $stores[$name]['value'] = $store->getId(); + } + } + if (!empty($stores)) { + $name = $this->escaper->escapeHtml($group->getName()); + $groups[$name]['label'] = str_repeat(' ', 4) . $name; + $groups[$name]['value'] = $stores; + } + } + } + if (!empty($groups)) { + $name = $this->escaper->escapeHtml($website->getName()); + $currentOptions[$name]['label'] = $name; + $currentOptions[$name]['value'] = $groups; + } + } + $this->options = $currentOptions; + return $this->options; + } +} diff --git a/app/code/Magento/Store/view/base/layout/ui_components.xml b/app/code/Magento/Store/view/base/layout/ui_components.xml index 54811dfdf1f40..493ae30bba9ea 100644 --- a/app/code/Magento/Store/view/base/layout/ui_components.xml +++ b/app/code/Magento/Store/view/base/layout/ui_components.xml @@ -9,6 +9,10 @@ Magento_Ui::filter/type/select/default.phtml + + store + Magento_Store/js/listing/filter/store + diff --git a/app/code/Magento/Ui/Component/AbstractComponent.php b/app/code/Magento/Ui/Component/AbstractComponent.php new file mode 100644 index 0000000000000..54d186177e180 --- /dev/null +++ b/app/code/Magento/Ui/Component/AbstractComponent.php @@ -0,0 +1,252 @@ +context = $context; + $this->components = $components; + parent::__construct($data); + } + + /** + * Get component context + * + * @return ContextInterface + */ + public function getContext() + { + return $this->context; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + // + } + + /** + * Produce and return block's html output + * + * @return string + */ + public function toHtml() + { + $this->render(); + } + + /** + * Render component + * + * @return string + */ + public function render() + { + $result = $this->getContext()->getRenderEngine()->render($this, $this->getTemplate()); + return $result; + } + + /** + * Get component name + * + * @return string + */ + public function getName() + { + return $this->getData('name'); + } + + /** + * @param string $name + * @param UiComponentInterface $component + */ + public function addComponent($name, UiComponentInterface $component) + { + $this->components[$name] = $component; + } + + /** + * @param string $name + * @return UiComponentInterface + */ + public function getComponent($name) + { + return isset($this->components[$name]) ? $this->components[$name] : null; + } + + /** + * Get components + * + * @return UiComponentInterface[] + */ + public function getChildComponents() + { + return $this->components; + } + + /** + * Get template + * + * @return string + */ + public function getTemplate() + { + return $this->getData('template') . '.xhtml'; + } + + /** + * Render child component + * + * @param string $name + * @return string + */ + public function renderChildComponent($name) + { + $result = null; + if (isset($this->components[$name])) { + $result = $this->components[$name]->render(); + } + return $result; + } + + /** + * Component data setter + * + * @param string|array $key + * @param mixed $value + * @return void + */ + public function setData($key, $value = null) + { + parent::setData($key, $value); + } + + /** + * Component data getter + * + * @param string $key + * @param string|int $index + * @return mixed + */ + public function getData($key = '', $index = null) + { + return parent::getData($key, $index); + } + + /** + * Set component configuration + * + * @return void + */ + protected function prepareConfiguration() + { + $config = $this->getDefaultConfiguration(); + if ($this->hasData('config')) { + $config = array_merge($config, $this->getData('config')); + } + + $this->setData('config', $config); + } + + /** + * Get default parameters + * + * @return array + */ + protected function getDefaultConfiguration() + { + return []; + } + + /** + * Get JS configuration + * + * @param UiComponentInterface $component + * @return array + */ + protected function getJsConfiguration(UiComponentInterface $component) + { + $jsConfig = (array) $component->getData('js_config'); + if (!isset($jsConfig['extends'])) { + $jsConfig['extends'] = $component->getContext()->getNamespace(); + } + + return $jsConfig; + } + + /** + * Get JS config + * + * @return array + */ + public function getJsConfig() + { + return (array) $this->getData('config'); + } + + /** + * @return array + */ + public function getDataSourceData() + { + $dataSources = []; + foreach ($this->getChildComponents() as $component) { + if ($component instanceof DataSourceInterface) { + $dataSources[] = [ + 'type' => $component->getComponentName(), + 'name' => $component->getName(), + 'dataScope' => $component->getContext()->getNamespace(), + 'config' => [ + 'data' => $component->getDataProvider()->getData() + ] + ]; + } + } + return $dataSources; + } +} diff --git a/app/code/Magento/Ui/Component/AbstractView.php b/app/code/Magento/Ui/Component/AbstractView.php index e67d0e1ff40ee..7ef6bb68adb07 100644 --- a/app/code/Magento/Ui/Component/AbstractView.php +++ b/app/code/Magento/Ui/Component/AbstractView.php @@ -5,17 +5,16 @@ */ namespace Magento\Ui\Component; -use Magento\Framework\View\Asset\Repository; +use Magento\Ui\DataProvider\Manager; use Magento\Framework\View\Element\Template; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\ConfigInterface; -use Magento\Framework\View\Element\UiComponent\Context; +use \Magento\Ui\Component\Control\ActionPoolInterface; +use Magento\Ui\Component\Control\ButtonProviderFactory; use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; +use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\ArrayObjectFactory; +use Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeFactory; +use Magento\Framework\View\Element\Template\Context as TemplateContext; +use Magento\Framework\View\Element\UiComponent\Context as RenderContext; /** * Abstract class AbstractView @@ -24,34 +23,13 @@ */ abstract class AbstractView extends Template implements UiComponentInterface { - /** - * Config builder - * - * @var ConfigBuilderInterface - */ - protected $configBuilder; - - /** - * View configuration data - * - * @var ConfigInterface - */ - protected $config; - /** * Render context * - * @var Context + * @var RenderContext */ protected $renderContext; - /** - * Config factory - * - * @var ConfigFactory - */ - protected $configFactory; - /** * Content type factory * @@ -60,60 +38,61 @@ abstract class AbstractView extends Template implements UiComponentInterface protected $contentTypeFactory; /** - * Asset service - * - * @var Repository + * @var Manager */ - protected $assetRepo; + protected $dataManager; /** - * Data provider factory + * Layouts for the render * - * @var DataProviderFactory + * @var UiComponentInterface */ - protected $dataProviderFactory; + protected $uiLayout; /** - * @var \Magento\Ui\DataProvider\Manager + * @var \ArrayObject */ - protected $dataManager; + protected $componentData; /** - * Elements for the render - * - * @var ElementRendererInterface[] + * @var ButtonProviderFactory */ - protected $elements = []; + protected $buttonProviderFactory; + + /** + * @var ActionPoolInterface + */ + protected $actionPool; /** * Constructor * * @param TemplateContext $context - * @param Context $renderContext + * @param RenderContext $renderContext * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory * @param Manager $dataProviderManager + * @param ArrayObjectFactory $arrayObjectFactory + * @param ButtonProviderFactory $buttonProviderFactory + * @param ActionPoolInterface $actionPool * @param array $data */ public function __construct( TemplateContext $context, - Context $renderContext, + RenderContext $renderContext, ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, Manager $dataProviderManager, + ArrayObjectFactory $arrayObjectFactory, + ButtonProviderFactory $buttonProviderFactory, + ActionPoolInterface $actionPool, array $data = [] ) { $this->renderContext = $renderContext; $this->contentTypeFactory = $contentTypeFactory; - $this->assetRepo = $context->getAssetRepository(); - $this->configFactory = $configFactory; - $this->configBuilder = $configBuilder; - $this->dataProviderFactory = $dataProviderFactory; $this->dataManager = $dataProviderManager; + $this->componentData = $arrayObjectFactory->create(); + $this->actionPool = $actionPool; + $this->buttonProviderFactory = $buttonProviderFactory; + parent::__construct($context, $data); } @@ -151,8 +130,7 @@ public function render(array $data = []) $prevData = $this->getData(); $this->update($data); - $renderResult = $this->contentTypeFactory->get($this->renderContext->getAcceptType()) - ->render($this, $this->getContentTemplate()); + $renderResult = $this->getRenderEngine()->render($this, $this->getContentTemplate()); $this->setData($prevData); @@ -166,8 +144,7 @@ public function render(array $data = []) */ public function renderLabel() { - return $this->contentTypeFactory->get($this->renderContext->getAcceptType()) - ->render($this, $this->getLabelTemplate()); + return $this->getRenderEngine()->render($this, $this->getLabelTemplate()); } /** @@ -181,6 +158,7 @@ public function renderElement($elementName, array $arguments) { $element = $this->renderContext->getRender()->getUiElementView($elementName); $result = $element->render($arguments); + return $result; } @@ -198,6 +176,7 @@ public function renderElementLabel($elementName, array $arguments) $element->update($arguments); $result = $element->renderLabel(); $element->setData($prevData); + return $result; } @@ -247,92 +226,87 @@ public function getLayoutElement($fullName, $default = null) /** * Get name component instance * - * @return string + * @return string|null */ public function getName() { - return $this->config->getName(); + return isset($this->componentData['config']['name']) ? $this->componentData['config']['name'] : null; } /** * Get parent name component instance * - * @return string + * @return string|null */ public function getParentName() { - return $this->config->getParentName(); - } - - /** - * Get configuration builder - * - * @return ConfigBuilderInterface - */ - public function getConfigBuilder() - { - return $this->configBuilder; + return isset($this->componentData['config']['parent_name']) + ? $this->componentData['config']['parent_name'] + : null; } /** * Set component configuration * - * @param null $configData - * @param null $name - * @param null $parentName + * @param string|null $name + * @param string|null $parentName * @return void */ - public function prepareConfiguration($configData = null, $name = null, $parentName = null) + public function prepareConfiguration($name = null, $parentName = null) { - $arguments = []; - $arguments['name'] = $name ?: $this->renderContext->getNamespace() . '_' . $this->getNameInLayout(); - $arguments['parentName'] = $parentName ?: $this->renderContext->getNamespace(); - if ($configData) { - $arguments['configuration'] = $configData; + $defaultConfig = $this->getDefaultConfiguration(); + if ($this->hasData('config')) { + $defaultConfig = array_merge($defaultConfig, $this->getData('config')); } - $this->config = $this->configFactory->create($arguments); - $this->renderContext->getStorage()->addComponentsData($this->config); + $config = []; + $config['name'] = $name ?: $this->renderContext->getNamespace() . '_' . $this->getNameInLayout(); + $config['parent_name'] = $parentName ?: $this->renderContext->getNamespace(); + if (!empty($defaultConfig)) { + $config['configuration'] = $defaultConfig; + } + + $this->componentData['config'] = $config; } /** - * Get component configuration + * Get render context * - * @return ConfigInterface + * @return RenderContext */ - public function getConfig() + public function getRenderContext() { - return $this->config; + return $this->renderContext; } /** - * Get render context + * Set layout for the render * - * @return Context + * @return UiComponentInterface */ - public function getRenderContext() + public function getUiLayout() { - return $this->renderContext; + return $this->uiLayout; } /** - * Get elements to the render + * Set layout for the render * - * @return ElementRendererInterface[] + * @param UiComponentInterface $uiLayout + * @return void */ - public function getElements() + public function setUiLayout(UiComponentInterface $uiLayout) { - return $this->elements; + $this->uiLayout = $uiLayout; } /** - * Set elements for the render + * Component data * - * @param ElementRendererInterface[] $elements - * @return mixed|void + * @return \ArrayObject */ - public function setElements(array $elements) + public function getComponentData() { - $this->elements = $elements; + return $this->componentData; } /** @@ -356,20 +330,78 @@ protected function getRenderEngine() } /** - * Create data provider + * Add button in the actions toolbar * * @return void */ - protected function createDataProviders() + protected function addButtons() { - if ($this->hasData('data_provider_pool')) { - foreach ($this->getData('data_provider_pool') as $name => $config) { - $arguments = empty($config['arguments']) ? [] : $config['arguments']; - $arguments['params'] = $this->renderContext->getRequestParams(); + $buttons = $this->getData('buttons'); + if ($buttons) { + foreach ($buttons as $buttonId => $buttonData) { + if (is_array($buttonData)) { + $buttons[$buttonId] = $buttonData; + continue; + } + /** @var ButtonProviderInterface $button */ + $button = $this->buttonProviderFactory->create($buttonData); + $buttonData = $button->getButtonData(); + if (!$buttonData) { + unset($buttons[$buttonId]); + continue; + } + $buttons[$buttonId] = $buttonData; + } + uasort($buttons, [$this, 'sortButtons']); - $dataProvider = $this->dataProviderFactory->create($config['class'], $arguments); - $this->renderContext->getStorage()->addDataProvider($name, $dataProvider); + foreach ($buttons as $buttonId => $buttonData) { + $this->actionPool->add($buttonId, $buttonData, $this); } } } + + /** + * Sort buttons by sort order + * + * @param array $itemA + * @param array $itemB + * @return int + */ + public function sortButtons(array $itemA, array $itemB) + { + $sortOrderA = isset($itemA['sort_order']) ? intval($itemA['sort_order']) : 0; + $sortOrderB = isset($itemB['sort_order']) ? intval($itemB['sort_order']) : 0; + + return $sortOrderA - $sortOrderB; + } + + /** + * Method is called before rendering + * + * @return void + */ + public function beforeRender() + { + // + } + + /** + * Method is called after rendering + * + * @return void + */ + public function afterRender() + { + // + } + + /** + * Get component instance name + * + * @return string + */ + public function getComponentName() + { + // + } } diff --git a/app/code/Magento/Ui/Component/Container/Block.php b/app/code/Magento/Ui/Component/Container/Block.php new file mode 100644 index 0000000000000..f5ebb373aa462 --- /dev/null +++ b/app/code/Magento/Ui/Component/Container/Block.php @@ -0,0 +1,59 @@ +block = $block; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * @return string + */ + public function render() + { + return $this->block->toHtml(); + } +} diff --git a/app/code/Magento/Ui/Component/Control/Action.php b/app/code/Magento/Ui/Component/Control/Action.php index 5021b8f7c4817..6841e9f5c0e81 100644 --- a/app/code/Magento/Ui/Component/Control/Action.php +++ b/app/code/Magento/Ui/Component/Control/Action.php @@ -5,11 +5,22 @@ */ namespace Magento\Ui\Component\Control; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; /** * Class Action */ -class Action extends AbstractView implements ControlInterface +class Action extends AbstractComponent { + const NAME = 'action'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Control/ActionPool.php b/app/code/Magento/Ui/Component/Control/ActionPool.php index 97f5afdba9ed1..5ed4d4181a79d 100644 --- a/app/code/Magento/Ui/Component/Control/ActionPool.php +++ b/app/code/Magento/Ui/Component/Control/ActionPool.php @@ -5,6 +5,7 @@ */ namespace Magento\Ui\Component\Control; +use Magento\Framework\View\Element\BlockInterface; use Magento\Framework\View\Element\UiComponent\Context; use Magento\Framework\View\Element\UiComponentInterface; @@ -54,8 +55,18 @@ public function __construct(Context $context, ItemFactory $itemFactory) { $this->context = $context; $this->itemFactory = $itemFactory; - $this->toolbarBlock = $this->context->getPageLayout() - ? $this->context->getPageLayout()->getBlock(static::ACTIONS_PAGE_TOOLBAR) : false; + } + + /** + * Get toolbar block + * + * @return bool|BlockInterface + */ + public function getToolbar() + { + return $this->context->getPageLayout() + ? $this->context->getPageLayout()->getBlock(static::ACTIONS_PAGE_TOOLBAR) + : false; } /** @@ -70,11 +81,12 @@ public function add($key, array $data, UiComponentInterface $view) { $data['id'] = isset($data['id']) ? $data['id'] : $key; - if ($this->toolbarBlock !== false) { + $toolbar = $this->getToolbar(); + if ($toolbar !== false) { $this->items[$key] = $this->itemFactory->create(); $this->items[$key]->setData($data); $container = $this->createContainer($key, $view); - $this->toolbarBlock->setChild($key, $container); + $toolbar->setChild($key, $container); } } @@ -122,6 +134,7 @@ protected function createContainer($key, UiComponentInterface $view) ] ] ); + return $container; } } diff --git a/app/code/Magento/Ui/Component/Control/ActionPoolInterface.php b/app/code/Magento/Ui/Component/Control/ActionPoolInterface.php index 2a9d361a58f59..bfb561802d452 100644 --- a/app/code/Magento/Ui/Component/Control/ActionPoolInterface.php +++ b/app/code/Magento/Ui/Component/Control/ActionPoolInterface.php @@ -5,6 +5,7 @@ */ namespace Magento\Ui\Component\Control; +use Magento\Framework\View\Element\BlockInterface; use Magento\Framework\View\Element\UiComponentInterface; /** @@ -38,4 +39,11 @@ public function remove($key); * @return void */ public function update($key, array $data); + + /** + * Get toolbar block + * + * @return bool|BlockInterface + */ + public function getToolbar(); } diff --git a/app/code/Magento/Ui/Component/Control/ButtonProviderFactory.php b/app/code/Magento/Ui/Component/Control/ButtonProviderFactory.php index c30c7a0f9ced5..d872d762aa96e 100644 --- a/app/code/Magento/Ui/Component/Control/ButtonProviderFactory.php +++ b/app/code/Magento/Ui/Component/Control/ButtonProviderFactory.php @@ -9,7 +9,6 @@ /** * Class ButtonProviderFactory - * @package Magento\Ui\DataProvider */ class ButtonProviderFactory { @@ -43,6 +42,7 @@ public function create($providerClass, array $arguments = []) sprintf('"%s" must implement the interface ButtonProviderInterface.', $providerClass) ); } + return $object; } } diff --git a/app/code/Magento/Ui/Component/Control/ButtonProviderInterface.php b/app/code/Magento/Ui/Component/Control/ButtonProviderInterface.php index 508ae595faac9..ce5074013b056 100644 --- a/app/code/Magento/Ui/Component/Control/ButtonProviderInterface.php +++ b/app/code/Magento/Ui/Component/Control/ButtonProviderInterface.php @@ -7,7 +7,6 @@ /** * Interface ButtonProviderInterface - * @package Magento\Ui\Component\Control */ interface ButtonProviderInterface { diff --git a/app/code/Magento/Ui/Component/Control/Link.php b/app/code/Magento/Ui/Component/Control/Link.php index cdc3c166322a0..6b7d99eb243ef 100644 --- a/app/code/Magento/Ui/Component/Control/Link.php +++ b/app/code/Magento/Ui/Component/Control/Link.php @@ -5,12 +5,22 @@ */ namespace Magento\Ui\Component\Control; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; /** * Class Link */ -class Link extends AbstractView implements ControlInterface +class Link extends AbstractComponent { - // + const NAME = 'link'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/DataSource.php b/app/code/Magento/Ui/Component/DataSource.php new file mode 100644 index 0000000000000..d269b384e45d5 --- /dev/null +++ b/app/code/Magento/Ui/Component/DataSource.php @@ -0,0 +1,74 @@ +dataProvider = $dataProvider; + $context->setDataProvider($dataProvider); + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $jsConfig = $this->getJsConfiguration($this); + unset($jsConfig['extends']); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * @return DataProviderInterface + */ + public function getDataProvider() + { + return $this->dataProvider; + } +} diff --git a/app/code/Magento/Ui/Component/Filter/AbstractFilter.php b/app/code/Magento/Ui/Component/Filter/AbstractFilter.php new file mode 100644 index 0000000000000..a57bf0b24033e --- /dev/null +++ b/app/code/Magento/Ui/Component/Filter/AbstractFilter.php @@ -0,0 +1,47 @@ +dataProvider = $dataProvider; + $this->uiComponentFactory = $uiComponentFactory; + parent::__construct($context, $components, $data); + } +} diff --git a/app/code/Magento/Ui/Component/Filter/DataProvider.php b/app/code/Magento/Ui/Component/Filter/DataProvider.php new file mode 100644 index 0000000000000..433425cbe7748 --- /dev/null +++ b/app/code/Magento/Ui/Component/Filter/DataProvider.php @@ -0,0 +1,75 @@ +filterData = $this->prepareFilterString($request->getParam(static::FILTER_VAR)); + } + + /** + * Get filter data + * + * @param string $name + * @return string + */ + public function getData($name) + { + return isset($this->filterData[$name]) ? $this->filterData[$name] : null; + } + + /** + * Decode filter string + * + * @param string $filterString + * @return array + */ + protected function prepareFilterString($filterString) + { + $data = []; + $filterString = base64_decode($filterString); + parse_str($filterString, $data); + array_walk_recursive( + $data, + // @codingStandardsIgnoreStart + /** + * Decodes URL-encoded string and trims whitespaces from the beginning and end of a string + * + * @param string $value + */ + // @codingStandardsIgnoreEnd + function (&$value) { + $value = trim(rawurldecode($value)); + } + ); + + return $data; + } +} diff --git a/app/code/Magento/Ui/Component/Filter/Type/Date.php b/app/code/Magento/Ui/Component/Filter/Type/Date.php index 90b7e16a4aeeb..6b47ed8879d00 100644 --- a/app/code/Magento/Ui/Component/Filter/Type/Date.php +++ b/app/code/Magento/Ui/Component/Filter/Type/Date.php @@ -5,96 +5,95 @@ */ namespace Magento\Ui\Component\Filter\Type; -use Magento\Framework\Locale\ResolverInterface; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\Component\Filter\FilterAbstract; -use Magento\Ui\Component\Filter\FilterPool; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; +use Magento\Ui\Component\Filter\DataProvider; +use Magento\Ui\Component\Filter\AbstractFilter; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Ui\Component\Form\Element\DataType\Date as DataTypeDate; /** * Class Date - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Date extends FilterAbstract +class Date extends AbstractFilter { + const NAME = 'filter_date'; + + const COMPONENT = 'date'; + /** - * Timezone library + * Wrapped component * - * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface + * @var DataTypeDate */ - protected $localeDate; + protected $wrappedComponent; /** - * Scope config + * Get component name * - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @return string */ - protected $scopeConfig; + public function getComponentName() + { + return static::NAME; + } /** - * Locale resolver + * Prepare component configuration * - * @var \Magento\Framework\Locale\ResolverInterface + * @return void */ - protected $localeResolver; + public function prepare() + { + parent::prepare(); + + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + static::COMPONENT, + ['context' => $this->getContext()] + ); + $this->wrappedComponent->prepare(); + + $this->applyFilter(); + $jsConfig = array_replace_recursive( + $this->getJsConfiguration($this->wrappedComponent), + $this->getJsConfiguration($this) + ); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } /** - * Constructor + * Get JS config * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param FilterPool $filterPool - * @param ResolverInterface $localeResolver - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @return array */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - FilterPool $filterPool, - ResolverInterface $localeResolver, - array $data = [] - ) { - $this->localeDate = $context->getLocaleDate(); - $this->scopeConfig = $context->getScopeConfig(); - $this->localeResolver = $localeResolver; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $filterPool, - $data + public function getJsConfig() + { + return array_replace_recursive( + (array) $this->wrappedComponent->getData('config'), + (array) $this->getData('config') ); } /** - * Get condition by data type + * Apply filter + * + * @return void + */ + protected function applyFilter() + { + $condition = $this->getCondition(); + if ($condition !== null) { + $this->getContext()->getDataProvider()->addFilter($this->getName(), $condition); + } + } + + /** + * Get condition * - * @param string|array $value * @return array|null */ - public function getCondition($value) + protected function getCondition() { - return $this->convertValue($value); + return $this->convertValue($this->dataProvider->getData($this->getName())); } /** @@ -106,41 +105,26 @@ public function getCondition($value) protected function convertValue($value) { if (!empty($value['from']) || !empty($value['to'])) { - $locale = $this->localeResolver->getLocale(); if (!empty($value['from'])) { $value['orig_from'] = $value['from']; - $value['from'] = $this->convertDate(strtotime($value['from']), $locale); + $value['from'] = $this->wrappedComponent->convertDate( + strtotime($value['from']), + $this->wrappedComponent->getLocale() + ); } if (!empty($value['to'])) { $value['orig_to'] = $value['to']; - $value['to'] = $this->convertDate(strtotime($value['to']), $locale); + $value['to'] = $this->wrappedComponent->convertDate( + strtotime($value['to']), + $this->wrappedComponent->getLocale() + ); } $value['datetime'] = true; - $value['locale'] = $this->localeResolver->getLocale(); + $value['locale'] = $this->wrappedComponent->getLocale(); } else { $value = null; } return $value; } - - /** - * Convert given date to default (UTC) timezone - * - * @param int $date - * @param string $locale - * @return \DateTime|null - */ - protected function convertDate($date, $locale) - { - try { - $dateObj = $this->localeDate->date(new \DateTime($date), $locale, false); - $dateObj->setTime(0, 0, 0); - //convert store date to default date in UTC timezone without DST - $dateObj->setTimezone(new \DateTimeZone('UTC')); - return $dateObj; - } catch (\Exception $e) { - return null; - } - } } diff --git a/app/code/Magento/Ui/Component/Filter/Type/Input.php b/app/code/Magento/Ui/Component/Filter/Type/Input.php index 214ae8e8a671c..da2095cd606f3 100644 --- a/app/code/Magento/Ui/Component/Filter/Type/Input.php +++ b/app/code/Magento/Ui/Component/Filter/Type/Input.php @@ -5,21 +5,82 @@ */ namespace Magento\Ui\Component\Filter\Type; -use Magento\Ui\Component\Filter\FilterAbstract; +use Magento\Ui\Component\Filter\DataProvider; +use Magento\Ui\Component\Filter\AbstractFilter; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Ui\Component\Form\Element\Input as ElementInput; /** * Class Input */ -class Input extends FilterAbstract +class Input extends AbstractFilter { + const NAME = 'filter_input'; + + const COMPONENT = 'input'; + + /** + * Wrapped component + * + * @var ElementInput + */ + protected $wrappedComponent; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + static::COMPONENT, + ['context' => $this->getContext()] + ); + $this->wrappedComponent->prepare(); + + $this->applyFilter(); + $jsConfig = array_replace_recursive( + $this->getJsConfiguration($this->wrappedComponent), + $this->getJsConfiguration($this) + ); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Apply filter + * + * @return void + */ + protected function applyFilter() + { + $condition = $this->getCondition(); + if ($condition !== null) { + $this->getContext()->getDataProvider()->addFilter($this->getName(), $condition); + } + } + /** * Get condition by data type * - * @param string|array $value * @return array|null */ - public function getCondition($value) + public function getCondition() { + $value = $this->dataProvider->getData($this->getName()); $condition = null; if (!empty($value) || is_numeric($value)) { $condition = ['like' => sprintf('%%%s%%', $value)]; diff --git a/app/code/Magento/Ui/Component/Filter/Type/Range.php b/app/code/Magento/Ui/Component/Filter/Type/Range.php index 25583f994f400..b2705c7a8ab46 100644 --- a/app/code/Magento/Ui/Component/Filter/Type/Range.php +++ b/app/code/Magento/Ui/Component/Filter/Type/Range.php @@ -5,21 +5,84 @@ */ namespace Magento\Ui\Component\Filter\Type; -use Magento\Ui\Component\Filter\FilterAbstract; +use Magento\Ui\Component\AbstractComponent; +use Magento\Ui\Component\Filter\DataProvider; +use Magento\Framework\View\Element\UiComponent\ContextInterface; /** * Class Range */ -class Range extends FilterAbstract +class Range extends AbstractComponent { + const NAME = 'filter_range'; + + /** + * @var DataProvider + */ + protected $dataProvider; + + /** + * Constructor + * + * @param ContextInterface $context + * @param DataProvider $dataProvider + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + DataProvider $dataProvider, + array $components = [], + array $data = [] + ) { + $this->dataProvider = $dataProvider; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + $this->applyFilter(); + $jsConfig = $this->getJsConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Apply filter + * + * @return void + */ + protected function applyFilter() + { + $condition = $this->getCondition(); + if ($condition !== null) { + $this->getContext()->getDataProvider()->addFilter($this->getName(), $condition); + } + } + /** * Get condition by data type * - * @param array|string $value * @return array|null */ - public function getCondition($value) + public function getCondition() { + $value = $value = $this->dataProvider->getData($this->getName()); if (!empty($value['from']) || !empty($value['to'])) { if (isset($value['from']) && empty($value['from']) && $value['from'] !== '0') { $value['orig_from'] = $value['from']; diff --git a/app/code/Magento/Ui/Component/Filter/Type/Select.php b/app/code/Magento/Ui/Component/Filter/Type/Select.php index 309049fef6001..2084d7f9fd0f3 100644 --- a/app/code/Magento/Ui/Component/Filter/Type/Select.php +++ b/app/code/Magento/Ui/Component/Filter/Type/Select.php @@ -5,21 +5,111 @@ */ namespace Magento\Ui\Component\Filter\Type; -use Magento\Ui\Component\Filter\FilterAbstract; +use Magento\Ui\Component\Filter\DataProvider; +use Magento\Ui\Component\Filter\AbstractFilter; +use Magento\Framework\Data\OptionSourceInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Ui\Component\Form\Element\Select as ElementSelect; /** * Class Select */ -class Select extends FilterAbstract +class Select extends AbstractFilter { + const NAME = 'filter_select'; + + const COMPONENT = 'select'; + + /** + * Wrapped component + * + * @var ElementSelect + */ + protected $wrappedComponent; + + /** + * @var OptionSourceInterface + */ + protected $optionsProvider; + + /** + * Constructor + * + * @param ContextInterface $context + * @param DataProvider $dataProvider + * @param UiComponentFactory $uiComponentFactory + * @param OptionSourceInterface $optionsProvider + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + DataProvider $dataProvider, + UiComponentFactory $uiComponentFactory, + OptionSourceInterface $optionsProvider = null, + array $components = [], + array $data = [] + ) { + $this->optionsProvider = $optionsProvider; + parent::__construct($context, $dataProvider, $uiComponentFactory, $components, $data); + } + + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + static::COMPONENT, + ['context' => $this->getContext(), 'options' => $this->optionsProvider] + ); + $this->wrappedComponent->prepare(); + + $this->applyFilter(); + $jsConfig = array_replace_recursive( + $this->getJsConfiguration($this->wrappedComponent), + $this->getJsConfiguration($this) + ); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Get JS config + * + * @return array + */ + public function getJsConfig() + { + return array_replace_recursive( + (array) $this->wrappedComponent->getData('config'), + (array) $this->getData('config') + ); + } + /** * Get condition by data type * - * @param string|array $value * @return array|null */ - public function getCondition($value) + public function getCondition() { + $value = $this->dataProvider->getData($this->getName()); $condition = null; if (!empty($value) || is_numeric($value)) { $condition = ['eq' => $value]; @@ -27,4 +117,17 @@ public function getCondition($value) return $condition; } + + /** + * Apply filter + * + * @return void + */ + protected function applyFilter() + { + $condition = $this->getCondition(); + if ($condition !== null) { + $this->getContext()->getDataProvider()->addFilter($this->getName(), $condition); + } + } } diff --git a/app/code/Magento/Ui/Component/Filters.php b/app/code/Magento/Ui/Component/Filters.php new file mode 100644 index 0000000000000..3063e8fdad2b1 --- /dev/null +++ b/app/code/Magento/Ui/Component/Filters.php @@ -0,0 +1,54 @@ +getJsConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } +} diff --git a/app/code/Magento/Ui/Component/Form.php b/app/code/Magento/Ui/Component/Form.php index 4e4435b677363..234bbbfc7cd76 100644 --- a/app/code/Magento/Ui/Component/Form.php +++ b/app/code/Magento/Ui/Component/Form.php @@ -5,222 +5,70 @@ */ namespace Magento\Ui\Component; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Framework\View\Element\UiElementFactory; -use Magento\Ui\Component\Control\ActionPool; -use Magento\Ui\Component\Control\ButtonProviderFactory; -use Magento\Ui\Component\Control\ButtonProviderInterface; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; /** * Class Form - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Form extends AbstractView +class Form extends AbstractComponent { - /** - * Default form element - */ - const DEFAULT_FORM_ELEMENT = 'input'; - - /** - * From element map - * - * @var array - */ - protected $formElementMap = [ - 'text' => 'input', - 'number' => 'input', - ]; - - /** - * Ui element builder - * - * @var ElementRendererBuilder - */ - protected $elementRendererBuilder; - - /** - * @var UiElementFactory - */ - protected $factory; + const NAME = 'form'; /** - * @var ActionPool - */ - protected $actionPool; - - /** - * @var ButtonProviderFactory - */ - protected $buttonProviderFactory; - - /** - * Constructor + * Get component name * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param ElementRendererBuilder $elementRendererBuilder - * @param UiElementFactory $factory - * @param ActionPool $actionPool - * @param ButtonProviderFactory $buttonProviderFactory - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @return string */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - ElementRendererBuilder $elementRendererBuilder, - UiElementFactory $factory, - ActionPool $actionPool, - ButtonProviderFactory $buttonProviderFactory, - array $data = [] - ) { - $this->elementRendererBuilder = $elementRendererBuilder; - $this->factory = $factory; - $this->actionPool = $actionPool; - $this->buttonProviderFactory = $buttonProviderFactory; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); + public function getComponentName() + { + return static::NAME; } /** - * Prepare component data + * Prepare component configuration * * @return void */ public function prepare() { - $this->registerComponents(); - $buttons = $this->getData('buttons'); - if ($buttons) { - foreach ($buttons as $buttonId => $buttonClass) { - /** @var ButtonProviderInterface $button */ - $button = $this->buttonProviderFactory->create($buttonClass); - $buttonData = $button->getButtonData(); - if (!$buttonData) { - unset($buttons[$buttonId]); - continue; - } - $buttons[$buttonId] = $buttonData; - } - uasort($buttons, [$this, 'sortButtons']); - foreach ($buttons as $buttonId => $buttonData) { - $this->actionPool->add($buttonId, $buttonData, $this); - } - } + parent::prepare(); - $layoutSettings = (array) $this->getData('layout'); - $data = [ - 'name' => $this->getData('name'), - 'label' => $this->getData('label'), - 'data_sources' => $this->getData('data_sources'), - 'child_blocks' => $this->getLayout()->getChildBlocks($this->getNameInLayout()), - 'configuration' => isset($layoutSettings['configuration']) - ? $layoutSettings['configuration'] - : [], - ]; - $layoutType = isset($layoutSettings['type']) - ? $layoutSettings['type'] - : \Magento\Ui\Component\Layout\Tabs::NAME; - $layout = $this->factory->create( - $layoutType, - $data - ); - $layout->prepare(); - $this->elements[] = $layout; + $jsConfig = $this->getJsConfiguration($this); + unset($jsConfig['extends']); + $this->getContext()->addComponentDefinition($this->getContext()->getNamespace(), $jsConfig); } /** - * @return string + * @return array */ - public function getDataScope() + public function getDataSourceData() { - return $this->getData('name'); - } - - /** - * Register all UI Components configuration - * - * @return void - */ - protected function registerComponents() - { - $this->renderContext->getStorage()->addComponent( - $this->getData('name'), - [ - 'component' => 'Magento_Ui/js/form/component', - 'config' => [ - 'provider' => $this->getData('name'), - ], - 'deps' => [$this->getData('name')] - ] - ); - foreach ($this->getLayout()->getAllBlocks() as $name => $block) { - if ($block instanceof \Magento\Framework\View\Element\UiComponentInterface) { - $config = (array)$block->getData('js_config'); - if (!isset($config['extends'])) { - $config['extends'] = $this->getData('name'); + $namespace = $this->getContext()->getNamespace(); + $dataSources = []; + foreach ($this->getChildComponents() as $component) { + if ($component instanceof DataSourceInterface) { + $dataProvider = $component->getDataProvider(); + $id = $this->getContext()->getRequestParam($dataProvider->getRequestFieldName()); + if ($id) { + $dataProvider->addFilter($dataProvider->getPrimaryFieldName(), $id); + $preparedData = []; + $data = $dataProvider->getData(); + if (!empty($data['items'])) { + $preparedData[$namespace] = $data['items'][0]; + } + } else { + $preparedData = []; } - $this->renderContext->getStorage()->addComponent($name, $config); + $dataSources[] = [ + 'type' => $component->getComponentName(), + 'name' => $component->getName(), + 'dataScope' => $component->getContext()->getNamespace(), + 'config' => [ + 'data' => $preparedData + ] + ]; } - }; - } - - /** - * @return string - */ - public function getSaveAction() - { - return $this->getUrl('mui/form/save'); - } - - /** - * @return string - */ - public function getValidateAction() - { - return $this->getUrl('mui/form/validate'); - } - - /** - * Sort buttons by sort order - * - * @param array $itemA - * @param array $itemB - * @return int - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function sortButtons(array $itemA, array $itemB) - { - $sortOrderA = isset($itemA['sort_order']) ? intval($itemA['sort_order']) : 0; - $sortOrderB = isset($itemB['sort_order']) ? intval($itemB['sort_order']) : 0; - if ($sortOrderA == $sortOrderB) { - return 0; } - return ($sortOrderA < $sortOrderB) ? -1 : 1; + return $dataSources; } } diff --git a/app/code/Magento/Ui/Component/Form/Collection.php b/app/code/Magento/Ui/Component/Form/Collection.php index 09b67401aaced..c816843578c6b 100644 --- a/app/code/Magento/Ui/Component/Form/Collection.php +++ b/app/code/Magento/Ui/Component/Form/Collection.php @@ -5,13 +5,23 @@ */ namespace Magento\Ui\Component\Form; +use Magento\Ui\Component\AbstractComponent; use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\Component\AbstractView; /** * Class Collection */ -class Collection extends AbstractView implements UiComponentInterface +class Collection extends AbstractComponent implements UiComponentInterface { - // + const NAME = 'collection'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/AbstractFormElement.php b/app/code/Magento/Ui/Component/Form/Element/AbstractFormElement.php index e536143ab6b4a..9b8f81c7ca8ca 100644 --- a/app/code/Magento/Ui/Component/Form/Element/AbstractFormElement.php +++ b/app/code/Magento/Ui/Component/Form/Element/AbstractFormElement.php @@ -5,12 +5,12 @@ */ namespace Magento\Ui\Component\Form\Element; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; /** * Class AbstractFormElement */ -abstract class AbstractFormElement extends AbstractView implements ElementInterface +abstract class AbstractFormElement extends AbstractComponent implements ElementInterface { /** * @return string diff --git a/app/code/Magento/Ui/Component/Form/Element/Checkbox.php b/app/code/Magento/Ui/Component/Form/Element/Checkbox.php index df26d8c21bb31..61af55780c9c5 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Checkbox.php +++ b/app/code/Magento/Ui/Component/Form/Element/Checkbox.php @@ -10,5 +10,15 @@ */ class Checkbox extends AbstractFormElement { - // + const NAME = 'checkbox'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/AbstractDataType.php b/app/code/Magento/Ui/Component/Form/Element/DataType/AbstractDataType.php index cc196dea37d70..e36e3f3589ad6 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/AbstractDataType.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/AbstractDataType.php @@ -5,26 +5,20 @@ */ namespace Magento\Ui\Component\Form\Element\DataType; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; /** * Class AbstractDataType */ -abstract class AbstractDataType extends AbstractView implements DataTypeInterface +abstract class AbstractDataType extends AbstractComponent implements DataTypeInterface { /** + * Validate value + * * @return bool */ public function validate() { return true; } - - /** - * @return string - */ - public function getDataObjectValue() - { - return $this->getData('data_object')[$this->getData('name')]; - } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Boolean.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Boolean.php index 8fe4b24f502d9..d7865d61e608e 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Boolean.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Boolean.php @@ -10,5 +10,15 @@ */ class Boolean extends AbstractDataType { - // + const NAME = 'boolean'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/DataTypeInterface.php b/app/code/Magento/Ui/Component/Form/Element/DataType/DataTypeInterface.php index 63aefa0b72903..04bbecb0a8de5 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/DataTypeInterface.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/DataTypeInterface.php @@ -5,7 +5,6 @@ */ namespace Magento\Ui\Component\Form\Element\DataType; -use Magento\Framework\Object; use Magento\Framework\View\Element\UiComponentInterface; /** @@ -19,11 +18,4 @@ interface DataTypeInterface extends UiComponentInterface * @return bool */ public function validate(); - - /** - * Get data object value - * - * @return mixed - */ - public function getDataObjectValue(); } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php index 46bd9267d737c..db984f8abcd58 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php @@ -5,10 +5,101 @@ */ namespace Magento\Ui\Component\Form\Element\DataType; +use Magento\Framework\Locale\ResolverInterface; +use Magento\Framework\Stdlib\DateTime\TimezoneInterface; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + /** * Class Date */ class Date extends AbstractDataType { - // + const NAME = 'date'; + + /** + * Current locale + * + * @var string + */ + protected $locale; + + /** + * Wrapped component + * + * @var UiComponentInterface + */ + protected $wrappedComponent; + + /** + * Constructor + * + * @param ContextInterface $context + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + TimezoneInterface $localeDate, + ResolverInterface $localeResolver, + array $components = [], + array $data = [] + ) { + $this->locale = $localeResolver->getLocale(); + $this->localeDate = $localeDate; + parent::__construct($context, $components, $data); + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $jsConfig = $this->getJsConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + + /** + * Get locale + * + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Convert given date to default (UTC) timezone + * + * @param int $date + * @return \DateTime|null + */ + public function convertDate($date) + { + try { + $dateObj = $this->localeDate->date(new \DateTime($date), $this->getLocale(), false); + $dateObj->setTime(0, 0, 0); + //convert store date to default date in UTC timezone without DST + $dateObj->setTimezone(new \DateTimeZone('UTC')); + return $dateObj; + } catch (\Exception $e) { + return null; + } + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Email.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Email.php index 7dda21c016ae9..49b12bbf62770 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Email.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Email.php @@ -10,5 +10,15 @@ */ class Email extends AbstractDataType { - // + const NAME = 'email'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Media.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Media.php index 0f361470f944b..fda46d7b137a0 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Media.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Media.php @@ -10,5 +10,15 @@ */ class Media extends AbstractDataType { - // + const NAME = 'media'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Number.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Number.php index 4b5d7924e53c2..929a86ab19a8a 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Number.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Number.php @@ -10,5 +10,15 @@ */ class Number extends AbstractDataType { - // + const NAME = 'number'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Password.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Password.php index d58d74bd4c9d9..77a93da72288b 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Password.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Password.php @@ -10,5 +10,15 @@ */ class Password extends AbstractDataType { - // + const NAME = 'password'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Price.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Price.php index 138c224dea80d..a183fc4ad1760 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Price.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Price.php @@ -10,5 +10,15 @@ */ class Price extends AbstractDataType { - // + const NAME = 'price'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Text.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Text.php index 43c259b510bcd..c3187b92a7706 100644 --- a/app/code/Magento/Ui/Component/Form/Element/DataType/Text.php +++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Text.php @@ -10,5 +10,15 @@ */ class Text extends AbstractDataType { - // + const NAME = 'text'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Element/Input.php b/app/code/Magento/Ui/Component/Form/Element/Input.php index 9d149e9dd290f..eb3bc9dcc9af2 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Input.php +++ b/app/code/Magento/Ui/Component/Form/Element/Input.php @@ -10,19 +10,28 @@ */ class Input extends AbstractFormElement { + const NAME = 'input'; + /** - * @return mixed|string + * Get component name + * + * @return string */ - public function getType() + public function getComponentName() { - return $this->getData('input_type') ? $this->getData('input_type') : 'text'; + return static::NAME; } /** + * Prepare component configuration + * * @return void */ public function prepare() { - parent::prepare(); // TODO: Change the autogenerated stub + parent::prepare(); + + $jsConfig = $this->getJsConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); } } diff --git a/app/code/Magento/Ui/Component/Form/Element/Multiline.php b/app/code/Magento/Ui/Component/Form/Element/Multiline.php index 5e8b3b226dcb0..ade5dc6ab6f29 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Multiline.php +++ b/app/code/Magento/Ui/Component/Form/Element/Multiline.php @@ -10,6 +10,18 @@ */ class Multiline extends AbstractFormElement { + const NAME = 'multiline'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** * @return mixed|string */ diff --git a/app/code/Magento/Ui/Component/Form/Element/Radio.php b/app/code/Magento/Ui/Component/Form/Element/Radio.php index 1737d460db142..d7045895ec7f4 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Radio.php +++ b/app/code/Magento/Ui/Component/Form/Element/Radio.php @@ -10,6 +10,18 @@ */ class Radio extends AbstractFormElement { + const NAME = 'radio'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** * @return bool * @SuppressWarnings(PHPMD.BooleanGetMethodName) diff --git a/app/code/Magento/Ui/Component/Form/Element/Range.php b/app/code/Magento/Ui/Component/Form/Element/Range.php index 549b295108c33..c08d176144982 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Range.php +++ b/app/code/Magento/Ui/Component/Form/Element/Range.php @@ -10,6 +10,18 @@ */ class Range extends AbstractFormElement { + const NAME = 'range'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** * @return mixed */ diff --git a/app/code/Magento/Ui/Component/Form/Element/Select.php b/app/code/Magento/Ui/Component/Form/Element/Select.php index 59a366d3e4b2a..ff4a9d8f4f9c2 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Select.php +++ b/app/code/Magento/Ui/Component/Form/Element/Select.php @@ -5,11 +5,75 @@ */ namespace Magento\Ui\Component\Form\Element; +use Magento\Framework\Data\OptionSourceInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; + /** * Class Select */ class Select extends AbstractFormElement { + const NAME = 'select'; + + /** + * @var array|OptionSourceInterface|null + */ + protected $options; + + /** + * Constructor + * + * @param ContextInterface $context + * @param array|OptionSourceInterface|null $options + * @param array $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + $options = null, + array $components = [], + array $data = [] + ) { + $this->options = $options; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + $config = $this->getData('config'); + if (isset($this->options)) { + if (!isset($config['options'])) { + $config['options'] = []; + } + if ($this->options instanceof OptionSourceInterface) { + $options = $this->options->toOptionArray(); + } else { + $options = $this->options; + } + $config['options'] = array_values(array_merge_recursive($options, $config['options'])); + } + $this->setData('config', (array)$config); + + $jsConfig = $this->getJsConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + /** * Check if option value * diff --git a/app/code/Magento/Ui/Component/Form/Element/Textarea.php b/app/code/Magento/Ui/Component/Form/Element/Textarea.php index 0b7031ef8f6ce..47879dd5d1971 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Textarea.php +++ b/app/code/Magento/Ui/Component/Form/Element/Textarea.php @@ -10,5 +10,15 @@ */ class Textarea extends AbstractFormElement { - // + const NAME = 'textarea'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } } diff --git a/app/code/Magento/Ui/Component/Form/Field.php b/app/code/Magento/Ui/Component/Form/Field.php index 5f0c94dd42d76..2278d667c0d83 100644 --- a/app/code/Magento/Ui/Component/Form/Field.php +++ b/app/code/Magento/Ui/Component/Form/Field.php @@ -5,29 +5,89 @@ */ namespace Magento\Ui\Component\Form; +use Magento\Ui\Component\AbstractComponent; +use Magento\Framework\View\Element\UiComponentFactory; use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\Component\AbstractView; +use Magento\Framework\View\Element\UiComponent\ContextInterface; /** - * Class AbstractFormElement + * Class Field */ -class Field extends AbstractView implements UiComponentInterface +class Field extends AbstractComponent { + const NAME = 'field'; + + /** + * Wrapped component + * + * @var UiComponentInterface + */ + protected $wrappedComponent; + + /** + * UI component factory + * + * @var UiComponentFactory + */ + protected $uiComponentFactory; + + /** + * Constructor + * + * @param ContextInterface $context + * @param UiComponentFactory $uiComponentFactory + * @param UiComponentInterface[] $components + * @param array $data + */ + public function __construct( + ContextInterface $context, + UiComponentFactory $uiComponentFactory, + array $components = [], + array $data = [] + ) { + $this->uiComponentFactory = $uiComponentFactory; + parent::__construct($context, $components, $data); + } + /** - * @return mixed + * Get component name + * + * @return string */ - public function renderHeader() + public function getComponentName() { - return $this->getRenderEngine()->render($this, $this->getHeaderTemplate()); + return static::NAME; + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + $dataType = $this->getData('dataType'); + if ($dataType) { + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + $dataType, + ['context' => $this->getContext()] + ); + $this->wrappedComponent->prepare(); + } + + $jsConfig = $this->getJsConfiguration($this->wrappedComponent); + $this->getContext()->addComponentDefinition($this->wrappedComponent->getComponentName(), $jsConfig); } /** - * Getting template for field header section + * Get JS config * - * @return string|false + * @return array */ - public function getHeaderTemplate() + public function getJsConfig() { - return isset($this->configuration['header_template']) ? $this->configuration['header_template'] : false; + return $this->wrappedComponent->getJsConfig(); } } diff --git a/app/code/Magento/Ui/Component/Form/Fieldset.php b/app/code/Magento/Ui/Component/Form/Fieldset.php index 03fd8f62d6e84..31cb3b2511dbe 100644 --- a/app/code/Magento/Ui/Component/Form/Fieldset.php +++ b/app/code/Magento/Ui/Component/Form/Fieldset.php @@ -5,20 +5,32 @@ */ namespace Magento\Ui\Component\Form; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; /** * Class Fieldset */ -class Fieldset extends AbstractView +class Fieldset extends AbstractComponent { const UI_ELEMENT_FIELDSET = 'fieldset'; + const NAME = 'date'; + /** * @var bool */ protected $collapsible = false; + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** * @return string */ diff --git a/app/code/Magento/Ui/Component/Layout.php b/app/code/Magento/Ui/Component/Layout.php new file mode 100644 index 0000000000000..662881ffe120d --- /dev/null +++ b/app/code/Magento/Ui/Component/Layout.php @@ -0,0 +1,94 @@ +layoutPool = $layoutPool; + $this->type = $type; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + + /** + * Create Layout Navigation block and add to mane page layout + * + * @inheritdoc + */ + public function prepare() + { + $this->layoutTypeObject = $this->layoutPool->create($this->type); + $this->structure = $this->layoutTypeObject->build($this); + } + + /** + * @return array + */ + public function getStructure() + { + return $this->structure; + } +} diff --git a/app/code/Magento/Ui/Component/Layout/Generic.php b/app/code/Magento/Ui/Component/Layout/Generic.php new file mode 100644 index 0000000000000..7745229ca1392 --- /dev/null +++ b/app/code/Magento/Ui/Component/Layout/Generic.php @@ -0,0 +1,78 @@ +getContext(); + $this->addChildren($children, $component, $component->getName()); + $dataSources = $component->getDataSourceData(); + $configuration = [ + 'types' => array_reverse($context->getComponentsDefinitions()), + 'components' => [ + $context->getNamespace() => [ + 'children' => array_merge($children, $dataSources) + ] + ] + ]; + return $configuration; + } + + /** + * Add children data + * + * @param array $topNode + * @param UiComponentInterface $component + * @param string $componentType + */ + protected function addChildren( + array &$topNode, + UiComponentInterface $component, + $componentType + ) { + $childrenNode = []; + $childComponents = $component->getChildComponents(); + if (!empty($childComponents)) { + /** @var UiComponentInterface $child */ + foreach ($childComponents as $child) { + if ($child instanceof DataSourceInterface) { + continue; + } + $this->addChildren($childrenNode, $child, $child->getComponentName()); + } + } + /** @var JsConfigInterface $component */ + $config = $component->getJsConfig(); + $nodeData = [ + 'type' => $componentType, + 'name' => $component->getName(), + 'dataScope' => $component->getContext()->getNamespace(), + 'children' => $childrenNode + ]; + if (!empty($config)) { + $nodeData['config'] = $config; + } + $topNode[] = $nodeData; + } +} diff --git a/app/code/Magento/Ui/Component/Layout/Group.php b/app/code/Magento/Ui/Component/Layout/Group.php index 4b3eb842c56f9..6d97f6134c18b 100644 --- a/app/code/Magento/Ui/Component/Layout/Group.php +++ b/app/code/Magento/Ui/Component/Layout/Group.php @@ -5,13 +5,25 @@ */ namespace Magento\Ui\Component\Layout; -use Magento\Ui\Component\AbstractView; +use Magento\Ui\Component\AbstractComponent; /** * Class Group */ -class Group extends AbstractView +class Group extends AbstractComponent { + const NAME = 'group'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** * @return string */ diff --git a/app/code/Magento/Ui/Component/Layout/LayoutPool.php b/app/code/Magento/Ui/Component/Layout/LayoutPool.php new file mode 100644 index 0000000000000..b15a513ff42c6 --- /dev/null +++ b/app/code/Magento/Ui/Component/Layout/LayoutPool.php @@ -0,0 +1,64 @@ +objectManager = $objectManager; + $this->types = $types; + } + + /** + * Get layout by type + * + * @param string $layoutType + * @param array $arguments + * @return LayoutInterface + */ + public function create($layoutType, array $arguments = []) + { + if (!isset($this->types[$layoutType])) { + throw new \InvalidArgumentException(sprintf('Unknown layout type "%s"', $layoutType)); + } + $defArgs = $this->types[$layoutType]; + $class = isset($defArgs['class']) ? $defArgs['class'] : self::DEFAULT_CLASS; + unset($defArgs['class']); + if ($defArgs) { + $arguments = array_merge($defArgs, $arguments); + } + return $this->objectManager->create($class, $arguments); + } +} diff --git a/app/code/Magento/Ui/Component/Layout/Tabs.php b/app/code/Magento/Ui/Component/Layout/Tabs.php index d56881d3904c3..71031a8586d83 100644 --- a/app/code/Magento/Ui/Component/Layout/Tabs.php +++ b/app/code/Magento/Ui/Component/Layout/Tabs.php @@ -5,13 +5,536 @@ */ namespace Magento\Ui\Component\Layout; +use Magento\Framework\View\Element\BlockInterface; +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; +use Magento\Framework\View\Element\UiComponentInterface; + +use Magento\Ui\DataProvider\Metadata; +use Magento\Framework\View\Element\Template; +use Magento\Ui\Component\Layout\Tabs\TabInterface; +use Magento\Framework\View\Element\UiComponent\LayoutInterface; /** - * Class Tabs - * - * @package Magento\Ui\Component\Layout + * Class Layout */ -class Tabs extends AbstractStructure +class Tabs extends Generic implements LayoutInterface { - const NAME = 'tabs'; + /** + * @var string + */ + protected $navContainerName; + + /** + * @var UiComponentInterface + */ + protected $component; + + /** + * @var string + */ + protected $namespace; + + /** + * @var array + */ + protected $structure = []; + + /** + * @var int + */ + protected $sortIncrement = 10; + + public function __construct($navContainerName = null) + { + $this->navContainerName = $navContainerName; + } + + /** + * @param UiComponentInterface $component + * @return array + */ + public function build(UiComponentInterface $component) + { + $this->component = $component; + $this->namespace = $component->getContext()->getNamespace(); + + $this->addNavigationBlock(); + return parent::build($component); + } + + protected function addNavigationBlock() + { + $pageLayout = $this->component->getContext()->getPageLayout(); + /** @var \Magento\Ui\Component\Layout\Tabs\Nav $navBlock */ + if ($this->navContainerName) { + $navBlock = $pageLayout->addBlock('Magento\Ui\Component\Layout\Tabs\Nav', 'tabs_nav', $this->navContainerName); + } else { + $navBlock = $pageLayout->addBlock('Magento\Ui\Component\Layout\Tabs\Nav', 'tabs_nav', 'content'); + } + $navBlock->setTemplate('Magento_Ui::layout/tabs/nav/default.phtml'); + $navBlock->setData('data_scope', $this->namespace); + } + + /** + * Add children data + * + * @param array $topNode + * @param UiComponentInterface $component + * @param string $componentType + */ + protected function addChildren( + array &$topNode, + UiComponentInterface $component, + $componentType + ) { + $this->initSections(); + $this->initAreas(); + $this->initGroups(); + $this->initElements(); + + $this->processChildBlocks(); + + $topNode = $this->structure; + } + + /** + * Prepare initial structure for sections + * + * @return void + */ + protected function initSections() + { + $this->structure[static::SECTIONS_KEY] = [ + 'type' => 'nav', + 'config' => [ + 'label' => $this->component->getData('label'), + ], + 'children' => [], + ]; + } + + /** + * Prepare initial structure for areas + * + * @return void + */ + protected function initAreas() + { + $this->structure[static::AREAS_KEY] = [ + 'type' => 'form', + 'config' => [ + 'namespace' => $this->namespace, + ], + 'children' => [], + ]; + } + + /** + * Prepare initial structure for groups + * + * @return void + */ + protected function initGroups() + { + $this->structure[static::GROUPS_KEY] = [ + 'children' => [], + ]; + } + + /** + * Prepare initial structure for elements + * + * @return void + */ + protected function initElements() + { + $this->structure[static::ELEMENTS_KEY] = [ + 'children' => [], + ]; + } + + /** + * Process data source + * + * @return array + */ + protected function processDataSource() + { + $dataProvider = $this->component->getContext()->getDataProvider(); + + foreach ($dataProvider->getMeta() as $name => $meta) { + $areName = $name; + $areaConfig = $meta; + $areaConfig['insertTo'] = [ + "{$this->namespace}.sections" => ['position' => $this->getNextSortIncrement()] + ]; + $this->addArea($areName, $areaConfig); + + $groupName = $name; + $groupConfig = $meta; + $groupReferenceName = $this->addGroup($groupName, $groupConfig); + $this->addToArea($name, $groupReferenceName); + $fieldSet = $this->component->getComponent($name); + if (!$fieldSet) { + continue; + } + $elements = $fieldSet->getChildComponents(); + uasort($elements, [$this, 'sortChildren']); + + $collection = & $this->structure[static::ELEMENTS_KEY]; + + if (isset($meta['is_collection'])) { + $templateGroupName = $groupName . '_template'; + $groupConfig['type'] = 'collection'; + $groupConfig['dataScope'] = "{$this->namespace}.{$name}"; + $groupConfig['config']['active'] = 1; + $groupConfig['config']['removeLabel'] = __('Remove ' . $groupConfig['config']['label']); + $groupConfig['config']['removeMessage'] = __('Are you sure you want to delete this item?'); + $groupConfig['config']['addLabel'] = __('Add New ' . $groupConfig['config']['label']); + $groupConfig['config']['itemTemplate'] = 'item_template'; + + $itemTemplate = [ + 'type' => $this->namespace, + 'isTemplate' => true, + 'component' => 'Magento_Ui/js/form/components/collection/item', + 'childType' => 'group', + 'config' => [ + 'label' => __('New ' . $groupConfig['config']['label']), + ], + ]; + + $groupName = $templateGroupName; + + foreach ($elements as $elementName => $component) { + if ($component instanceof DataSourceInterface) { + continue; + } + $visibility = $component->getData('visible'); + if (isset($visibility) && $visibility === 'false') { + continue; + } + + $this->addToCollection($itemTemplate, $elementName, "{$this->namespace}.{$elementName}", $component->getData()); + + $referenceName = "{$name}.elements.{$elementName}"; + $this->addToGroup($groupName, $elementName, $referenceName, $component->getData()); + } + $groupConfig['children']['item_template'] = $itemTemplate; + $this->addGroup($templateGroupName, $groupConfig); + } else { + foreach ($elements as $elementName => $component) { + if ($component instanceof DataSourceInterface) { + continue; + } + $visibility = $component->getData('visible'); + if (isset($visibility) && $visibility === 'false') { + continue; + } + + $this->addToCollection($collection, $elementName, "{$this->namespace}.{$elementName}", $component->getData()); + + $referenceName = "{$name}.elements.{$elementName}"; + $this->addToGroup($groupName, $elementName, $referenceName, $component->getData()); + } + } + } + } + + /** + * Process child data source + * + * @param string $dataSource + * @param string $childName + * @param Metadata $childMeta + * @return void + */ + protected function processChildDataSource($dataSource, $childName, Metadata $childMeta) + { + $this->addArea( + $childName, + [ + 'insertTo' => [ + "{$this->namespace}.sections" => ['position' => $this->getNextSortIncrement()] + ], + 'config' => ['label' => $childMeta->getLabel()] + ] + ); + + $referenceChildGroupName = $this->addGroup($childName, [ + 'config' => [ + 'label' => $childMeta->getLabel() + ] + ]); + $this->addToArea($childName, $referenceChildGroupName); + + $itemTemplate = [ + 'type' => $this->namespace, + 'isTemplate' => true, + 'component' => 'Magento_Ui/js/form/components/collection/item', + 'childType' => 'group', + 'config' => [ + 'label' => __('New ' . $childMeta->getLabel()), + ], + ]; + + $elements = $childMeta->getFields(); + uasort($elements, [$this, 'sortChildren']); + foreach ($elements as $name => $element) { + if (isset($element['visible']) && $element['visible'] === 'false') { + continue; + } + $this->addToCollection($itemTemplate, $name, $name, $element); + } + + $referenceCollectionName = $this->addCollection( + "{$childName}Collection", + "{$dataSource}.{$childName}", + [ + 'active' => 1, + 'label' => $childMeta->getLabel(), + 'removeLabel' => __('Remove ' . $childMeta->getLabel()), + 'removeMessage' => __('Are you sure you want to delete this item?'), + 'addLabel' => __('Add New ' . $childMeta->getLabel()), + 'itemTemplate' => 'item_template' + ] + ); + $this->addTemplateToCollection("{$childName}Collection", 'item_template', $itemTemplate); + + $groups = & $this->structure[static::GROUPS_KEY]; + $groups['children'][$childName]['children'][] = $referenceCollectionName; + } + + /** + * Process child blocks + * + * @throws \Exception + * @return void + */ + protected function processChildBlocks() + { + // Add child blocks content + foreach ($this->component->getChildComponents() as $blockName => $childBlock) { + /** @var BlockInterface $childBlock */ + if ($childBlock instanceof UiComponentInterface) { + continue; + } + /** @var TabInterface $childBlock */ + if (!($childBlock instanceof TabInterface)) { + throw new \Exception(__('"%1" tab should implement TabInterface', $blockName)); + } + if (!$childBlock->canShowTab()) { + continue; + } + $childBlock->setData('target_form', $this->namespace); + $sortOrder = $childBlock->hasSortOrder() ? $childBlock->getSortOrder() : $this->getNextSortIncrement(); + $this->addArea( + $blockName, + [ + 'insertTo' => [ + "{$this->namespace}.sections" => ['position' => (int)$sortOrder] + ], + 'config' => ['label' => $childBlock->getTabTitle()] + ] + ); + + $config = [ + 'config' => [ + 'label' => $childBlock->getTabTitle() + ] + ]; + if ($childBlock->isAjaxLoaded()) { + $config['config']['source'] = $childBlock->getTabUrl(); + } else { + $config['config']['content'] = $childBlock->toHtml(); + } + $config['type'] = 'html_content'; + $referenceGroupName = $this->addGroup($blockName, $config); + $this->addToArea($blockName, $referenceGroupName); + } + } + + /** + * Add area + * + * @param string $name + * @param array $config + * @return string + */ + public function addArea($name, array $config = []) + { + $config['type'] = 'tab'; + $this->structure[static::AREAS_KEY]['children'][$name] = $config; + + return "{$this->namespace}.areas.{$name}"; + } + + /** + * Add item to area + * + * @param string $areaName + * @param string $itemName + * @return void + */ + public function addToArea($areaName, $itemName) + { + $this->structure[static::AREAS_KEY]['children'][$areaName]['children'][] = $itemName; + } + + /** + * Add group + * + * @param string $groupName + * @param array $config + * @return string + */ + public function addGroup($groupName, array $config = []) + { + $this->structure[static::GROUPS_KEY]['children'][$groupName] = $config; + + return "{$this->namespace}.groups.{$groupName}"; + } + + /** + * Add element to group + * + * @param string $groupName + * @param string $elementName + * @param string $referenceElementName + * @param array $element + * @return void + */ + public function addToGroup($groupName, $elementName, $referenceElementName, array $element = []) + { + $groups = & $this->structure[static::GROUPS_KEY]; + if (isset($element['fieldGroup'])) { + if ($elementName === $element['fieldGroup']) { + $groups['children'][$groupName]['children'][] = $referenceElementName; + } + } else { + $groups['children'][$groupName]['children'][] = $referenceElementName; + } + } + + /** + * Add collection + * + * @param string $collectionName + * @param string $dataScope + * @param array $config + * @return string + */ + public function addCollection($collectionName, $dataScope, array $config = []) + { + $this->structure[static::GROUPS_KEY]['children'][$collectionName] = [ + 'type' => 'collection', + 'dataScope' => $dataScope, + 'config' => $config, + ]; + + return "{$this->namespace}.groups.{$collectionName}"; + } + + /** + * Add element to collection + * + * @param array $collection + * @param string $elementName + * @param string $dataScope + * @param array $element + * @return void + */ + public function addToCollection(array & $collection, $elementName, $dataScope, array $element) + { + $collection['children'][$elementName] = ['type' => 'group']; + + if (isset($element['fieldGroup'])) { + $elementName = $element['fieldGroup']; + if (isset($element['displayArea']) && $elementName === $element['fieldGroup']) { + $collection['children'][$elementName]['config'] = ['displayArea' => $element['displayArea']]; + } + } else { + if (isset($element['displayArea'])) { + $collection['children'][$elementName]['config'] = ['displayArea' => $element['displayArea']]; + } + } + + if (isset($element['constraints'])) { + if (isset($element['constraints']['validate'])) { + $element['validation'] = $element['constraints']['validate']; + } + if (isset($element['constraints']['filter'])) { + foreach ($element['constraints']['filter'] as $filter) { + $element['listeners'] = [ + "data:{$filter['on']}" => ['filter' => [$filter['by']]], + ]; + } + } + unset($element['constraints']); + } + + if (isset($element['size'])) { + $collection['children'][$elementName]['dataScope'] = $dataScope; + $size = (int) @$element['size']; + for ($i = 0; $i < $size; ++$i) { + $collection['children'][$elementName]['children'][] = [ + 'type' => @$element['formElement'], + 'dataScope' => strval($i), + 'config' => $element, + ]; + if (isset($element['validation']['required-entry'])) { + unset($element['validation']['required-entry']); + } + } + } else { + $collection['children'][$elementName]['children'][] = [ + 'type' => @$element['formElement'], + 'dataScope' => $dataScope, + 'config' => $element, + ]; + } + } + + /** + * Add template to collection + * + * @param string $collectionName + * @param string $templateName + * @param array $template + * @return void + */ + protected function addTemplateToCollection($collectionName, $templateName, $template) + { + $groups = & $this->structure[static::GROUPS_KEY]; + $groups['children'][$collectionName]['children'][$templateName] = $template; + } + + /** + * Get next sort increment + * + * @return int + */ + protected function getNextSortIncrement() + { + $this->sortIncrement += 10; + + return $this->sortIncrement; + } + + /** + * Sort child elements + * + * @param UiComponentInterface $one + * @param UiComponentInterface $two + * @return int + */ + public function sortChildren(UiComponentInterface $one, UiComponentInterface $two) + { + if (!$one->getData('sortOrder')) { + return 1; + } + if (!$two->getData('sortOrder')) { + return -1; + } + return intval($one->getData('sortOrder')) - intval($two->getData('sortOrder')); + } } diff --git a/app/code/Magento/Ui/Component/Layout/Tabs/Nav.php b/app/code/Magento/Ui/Component/Layout/Tabs/Nav.php index 885eb69e277de..7c93e19f9a0d8 100644 --- a/app/code/Magento/Ui/Component/Layout/Tabs/Nav.php +++ b/app/code/Magento/Ui/Component/Layout/Tabs/Nav.php @@ -5,12 +5,12 @@ */ namespace Magento\Ui\Component\Layout\Tabs; -use Magento\Ui\Component\AbstractView; +use Magento\Framework\View\Element\Template; /** * Class Nav */ -class Nav extends AbstractView +class Nav extends Template { - const NAME = 'nav'; + // } diff --git a/app/code/Magento/Ui/Component/Layout/Tabs/TabInterface.php b/app/code/Magento/Ui/Component/Layout/Tabs/TabInterface.php index 1e65e984b0732..cb47ad3afabab 100644 --- a/app/code/Magento/Ui/Component/Layout/Tabs/TabInterface.php +++ b/app/code/Magento/Ui/Component/Layout/Tabs/TabInterface.php @@ -3,14 +3,11 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\Ui\Component\Layout\Tabs; /** - * Tab Interface - * - * @author Magento Core Team + * Interface TabInterface */ -namespace Magento\Ui\Component\Layout\Tabs; - interface TabInterface { /** diff --git a/app/code/Magento/Ui/Component/Listing.php b/app/code/Magento/Ui/Component/Listing.php index edc8d667758a7..c961a5b5c4262 100644 --- a/app/code/Magento/Ui/Component/Listing.php +++ b/app/code/Magento/Ui/Component/Listing.php @@ -5,89 +5,25 @@ */ namespace Magento\Ui\Component; -use Magento\Framework\View\Element\Template\Context as TemplateContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; -use Magento\Framework\View\Element\UiComponent\ConfigFactory; -use Magento\Framework\View\Element\UiComponent\Context; -use Magento\Ui\Component\Control\ActionPool; -use Magento\Ui\Component\Listing\OptionsFactory; -use Magento\Ui\Component\Listing\RowPool; -use Magento\Ui\ContentType\ContentTypeFactory; -use Magento\Ui\DataProvider\Factory as DataProviderFactory; -use Magento\Ui\DataProvider\Manager; +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; +use Magento\Ui\Component\Listing\Columns; +use Magento\Ui\Component\Listing\Columns\Column; /** * Class Listing - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Listing extends AbstractView +class Listing extends AbstractComponent { - /** - * Options provider key in data array - */ - const OPTIONS_PROVIDER_KEY = 'options_provider'; - - /** - * Row data provider key in data array - */ - const ROW_DATA_PROVIDER_KEY = 'row_data_provider'; - - /** - * Data provider row pool - * - * @var RowPool - */ - protected $dataProviderRowPool; + const NAME = 'listing'; /** - * Page action pool + * Get component name * - * @var ActionPool - */ - protected $actionPool; - - /** - * Constructor - * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param OptionsFactory $optionsFactory - * @param ActionPool $actionPool - * @param RowPool $dataProviderRowPool - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @return string */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - OptionsFactory $optionsFactory, - ActionPool $actionPool, - RowPool $dataProviderRowPool, - array $data = [] - ) { - $this->actionPool = $actionPool; - $this->optionsFactory = $optionsFactory; - $this->dataProviderRowPool = $dataProviderRowPool; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); + public function getComponentName() + { + return static::NAME; } /** @@ -97,170 +33,49 @@ public function __construct( */ public function prepare() { - $meta = $this->getMeta(); - $defaultConfigData = $this->getDefaultConfiguration(); - - if ($this->hasData('configuration')) { - $configData = $this->getData('configuration'); - if (!empty($configData['page_actions'])) { - foreach ($configData['page_actions'] as $key => $action) { - $defaultConfigData['page_actions'][$key] = isset($configData['page_actions']) - ? array_replace($defaultConfigData['page_actions'][$key], $configData['page_actions'][$key]) - : $defaultConfigData['page_actions'][$key]; - } - } - unset($configData['page_actions']); - $defaultConfigData = array_merge($defaultConfigData, $configData); - } - - foreach ($defaultConfigData['page_actions'] as $key => $action) { - $this->actionPool->add($key, $action, $this); - } - unset($defaultConfigData['page_actions']); - - $this->prepareConfiguration($defaultConfigData, $this->getData('name')); - $this->renderContext->getStorage()->addMeta($this->getData('name'), $meta); - $this->renderContext->getStorage()->addDataCollection($this->getData('name'), $this->getData('dataSource')); - } - - /** - * Render content - * - * @param array $data - * @return string - */ - public function render(array $data = []) - { - $this->initialConfiguration(); - - return parent::render($data); - } - - /** - * Get meta data - * - * @return array - */ - public function getMeta() - { - $meta = $this->getData('meta'); - foreach ($meta['fields'] as $key => $field) { - if ($field['data_type'] === 'date') { - $field['date_format'] = $this->_localeDate->getDateTimeFormat( - \IntlDateFormatter::MEDIUM - ); - } + $this->getContext()->addButtons($this->getData('buttons'), $this); - if (isset($field[static::OPTIONS_PROVIDER_KEY])) { - $field['options'] = $this->optionsFactory->create($field[static::OPTIONS_PROVIDER_KEY]) - ->getOptions(empty($field['options']) ? [] : $field['options']); - } - - unset($field[static::OPTIONS_PROVIDER_KEY]); - $meta['fields'][$key] = $field; - } - - return $meta; + $jsConfig = $this->getJsConfiguration($this); + unset($jsConfig['extends']); + $this->getContext()->addComponentDefinition($this->getContext()->getNamespace(), $jsConfig); } /** - * Apply data provider to row data - * - * @param array $dataRow - * @return array + * @inheritdoc */ - protected function getDataFromDataProvider(array $dataRow) + public function getDataSourceData() { - if ($this->hasData(static::ROW_DATA_PROVIDER_KEY)) { - foreach ($this->getData(static::ROW_DATA_PROVIDER_KEY) as $field => $data) { - $dataRow[$field] = $this->dataProviderRowPool->get($data['class'])->getData($dataRow); + /** @var Column[] $columns */ + $columns = []; + foreach ($this->getChildComponents() as $component) { + if ($component instanceof Columns) { + foreach ($component->getChildComponents() as $column) { + if ($column instanceof Column) { + $columns[] = $column; + } + } } } + $dataSources = []; + foreach ($this->getChildComponents() as $component) { + if ($component instanceof DataSourceInterface) { + $data = $component->getDataProvider()->getData(); + if (!empty($data['items']) && !empty($columns)) { + foreach ($columns as $column) { + $column->prepareItems($data['items']); + } + } - return $dataRow; - } - - /** - * Get collection items - * - * @return array - */ - public function getCollectionItems() - { - $items = []; - $collection = $this->getDataCollection()->getResultCollection(); - foreach ($collection->getItems() as $item) { - $actualFields = []; - $itemsData = $this->getDataFromDataProvider($item->getData()); - foreach (array_keys($this->getData('meta/fields')) as $field) { - $actualFields[$field] = $itemsData[$field]; + $dataSources[] = [ + 'type' => $component->getComponentName(), + 'name' => $component->getName(), + 'dataScope' => $component->getContext()->getNamespace(), + 'config' => [ + 'data' => $data + ] + ]; } - $items[] = $actualFields; } - - return $items; - } - - /** - * @return \Magento\Framework\Api\CriteriaInterface|\Magento\Framework\Data\CollectionDataSourceInterface - */ - protected function getDataCollection() - { - return $this->renderContext->getStorage()->getDataCollection($this->getName()); - } - - /** - * Configuration initialization - * - * @return void - */ - protected function initialConfiguration() - { - $url = $this->getUrl($this->getData('client_root')); - $this->renderContext->getStorage()->addGlobalData( - 'client', - [ - 'root' => $url, - 'ajax' => [ - 'data' => [ - 'component' => $this->getNameInLayout(), - ], - ] - ] - ); - $this->renderContext->getStorage()->addGlobalData('dump', ['extenders' => []]); - - $collection = $this->getDataCollection()->getResultCollection(); - $totalCount = $collection->getTotalCount(); - $this->renderContext->getStorage()->addDataSource( - $this->getName(), - [ - 'data' => [ - 'meta_reference' => $this->getName(), - 'items' => $this->getCollectionItems(), - 'pages' => ceil($totalCount / $this->renderContext->getRequestParam('limit', 20)), - 'totalCount' => $totalCount, - ] - ] - ); - } - - /** - * Get default parameters - * - * @return array - */ - public function getDefaultConfiguration() - { - return [ - 'page_actions' => [ - 'add' => [ - 'name' => 'add', - 'label' => __('Add New'), - 'class' => 'primary', - 'url' => $this->getUrl('*/*/new'), - ], - ] - ]; + return $dataSources; } } diff --git a/app/code/Magento/Ui/Component/Listing/Columns.php b/app/code/Magento/Ui/Component/Listing/Columns.php new file mode 100644 index 0000000000000..2cd8a5da3a0ec --- /dev/null +++ b/app/code/Magento/Ui/Component/Listing/Columns.php @@ -0,0 +1,39 @@ +getJsConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } +} diff --git a/app/code/Magento/Ui/Component/Listing/Columns/Column.php b/app/code/Magento/Ui/Component/Listing/Columns/Column.php new file mode 100644 index 0000000000000..a32ce95e43d8b --- /dev/null +++ b/app/code/Magento/Ui/Component/Listing/Columns/Column.php @@ -0,0 +1,125 @@ +uiComponentFactory = $uiComponentFactory; + parent::__construct($context, $components, $data); + } + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME . '.' . $this->getData('dataType'); + } + + /** + * Prepare component configuration + * + * @return void + */ + public function prepare() + { + parent::prepare(); + + $dataType = $this->getData('dataType'); + $wrappedComponentConfig = []; + if ($dataType) { + $this->wrappedComponent = $this->uiComponentFactory->create( + $this->getName(), + $dataType, + array_merge(['context' => $this->getContext()], (array) $this->getData()) + ); + $this->wrappedComponent->prepare(); + $wrappedComponentConfig = $this->getJsConfiguration($this->wrappedComponent); + } + + $this->applySorting(); + $jsConfig = array_replace_recursive($wrappedComponentConfig, $this->getJsConfiguration($this)); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); + } + + /** + * Get JS config + * + * @return array + */ + public function getJsConfig() + { + return array_replace_recursive( + (array) $this->wrappedComponent->getData('config'), + (array) $this->getData('config') + ); + } + + /** + * @param array $items + * @return array + */ + public function prepareItems(array & $items) + { + return $items; + } + + /** + * Apply sorting + * + * @return void + */ + protected function applySorting() + { + $direction = $this->getContext()->getRequestParam('dir', $this->getData('config/sorting')); + if (!empty($direction) ) { + $this->getContext()->getDataProvider()->addOrder( + $this->getName(), + strtoupper($direction) + ); + } + } +} diff --git a/app/code/Magento/Ui/Component/MassAction.php b/app/code/Magento/Ui/Component/MassAction.php index e892c9ed2793e..77b019fe05bd3 100644 --- a/app/code/Magento/Ui/Component/MassAction.php +++ b/app/code/Magento/Ui/Component/MassAction.php @@ -8,30 +8,44 @@ /** * Class MassAction */ -class MassAction extends AbstractView +class MassAction extends AbstractComponent { + const NAME = 'massaction'; + + /** + * Get component name + * + * @return string + */ + public function getComponentName() + { + return static::NAME; + } + /** * Prepare component data * - * @return $this|void + * @return void */ public function prepare() { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); + $this->prepareConfiguration(); + $config = $this->getData('config'); + if (isset($config['actions'])) { + array_walk_recursive( + $config, + function (&$item, $key, $object) { + if ($key === 'url') { + $item = $object->getUrl($item); + } + }, + $this + ); + $this->setData('config', $config); } - array_walk_recursive( - $configData, - function (&$item, $key, $object) { - if ($key === 'url') { - $item = $object->getUrl($item); - } - }, - $this - ); - $this->prepareConfiguration($configData); + $jsConfig = $this->getJsConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); } /** diff --git a/app/code/Magento/Ui/Component/Paging.php b/app/code/Magento/Ui/Component/Paging.php index 9a8f0a5ddd9b4..b255d5085b7ab 100644 --- a/app/code/Magento/Ui/Component/Paging.php +++ b/app/code/Magento/Ui/Component/Paging.php @@ -8,36 +8,36 @@ /** * Class Paging */ -class Paging extends AbstractView +class Paging extends AbstractComponent { + const NAME = 'paging'; + /** - * Prepare component data + * Get component name * - * @return void + * @return string */ - public function prepare() + public function getComponentName() { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); - } - - $this->prepareConfiguration($configData); - $this->updateDataCollection(); + return static::NAME; } /** - * Update data collection + * Prepare component data * * @return void */ - protected function updateDataCollection() + public function prepare() { - $defaultPage = $this->config->getData('current'); - $offset = $this->renderContext->getRequestParam('page', $defaultPage); - $defaultLimit = $this->config->getData('pageSize'); - $size = $this->renderContext->getRequestParam('limit', $defaultLimit); - $this->renderContext->getStorage()->getDataCollection($this->getParentName())->setLimit($offset, $size); + $this->prepareConfiguration(); + $defaultPage = $this->getData('config/current') ?: 1; + $offset = $this->getContext()->getRequestParam('page', $defaultPage); + $defaultLimit = $this->getData('config/pageSize') ?: 20; + $size = $this->getContext()->getRequestParam('limit', $defaultLimit); + $this->getContext()->getDataProvider()->setLimit($offset, $size); + + $jsConfig = $this->getJsConfiguration($this); + $this->getContext()->addComponentDefinition($this->getComponentName(), $jsConfig); } /** diff --git a/app/code/Magento/Ui/Controller/Adminhtml/AbstractAction.php b/app/code/Magento/Ui/Controller/Adminhtml/AbstractAction.php index 46a218025258c..0b8179b94a364 100644 --- a/app/code/Magento/Ui/Controller/Adminhtml/AbstractAction.php +++ b/app/code/Magento/Ui/Controller/Adminhtml/AbstractAction.php @@ -1,14 +1,13 @@ getComponent(); -// $name = $this->getName(); -// if ($component && $name) { -// $fieldset = $this->factory->createUiComponent($this->getComponent(), $this->getName())->getContainer($this->_request->getParam('container')); -// $fieldset->setNotLoadByAjax(); -// $this->_response->appendBody( -// $fieldset->render() -// ); -// } else { -// $this->_redirect('admin'); -// } -// $tabIndex = $this->getRequest()->getParam('container'); -// $this->getResponse()->appendBody( -// json_encode( -// ['layout' => ['customer_form_tabs' => [$tabIndex => ['label' => 'loaded', 'content' => 'content is loaded']]]] -// ) -// ); + // } } diff --git a/app/code/Magento/Ui/Controller/Adminhtml/Form/Save.php b/app/code/Magento/Ui/Controller/Adminhtml/Form/Save.php index 27bcd9d5096c5..402460330044c 100644 --- a/app/code/Magento/Ui/Controller/Adminhtml/Form/Save.php +++ b/app/code/Magento/Ui/Controller/Adminhtml/Form/Save.php @@ -1,6 +1,5 @@ nodeValue; } } else { - if ($source->hasChildNodes()) { - $groups = []; - foreach ($source->childNodes as $child) { - if ($child->nodeType == XML_TEXT_NODE || $child->nodeType == XML_COMMENT_NODE) { - continue; - } - if ($this->isTextNode($child)) { - $result[$child->nodeName] = $this->getTextNode($child)->data; + $groups = []; + foreach ($source->childNodes as $child) { + if ($child->nodeType == XML_TEXT_NODE || $child->nodeType == XML_COMMENT_NODE) { + continue; + } + if ($this->isTextNode($child)) { + $result[$child->nodeName] = $this->getTextNode($child)->data; + } else { + if (in_array($child->nodeName, ['validate', 'filter', 'readonly'])) { + if (!isset($result[$child->nodeName])) { + $result[$child->nodeName] = []; + } + $result[$child->nodeName][] = $this->toArray($child); } else { - if (in_array($child->nodeName, ['validate', 'filter', 'readonly'])) { - if (!isset($result[$child->nodeName])) { - $result[$child->nodeName] = []; + if (isset($result[$child->nodeName])) { + if (!isset($groups[$child->nodeName])) { + $result[$child->nodeName] = [$result[$child->nodeName]]; + $groups[$child->nodeName] = 1; } $result[$child->nodeName][] = $this->toArray($child); } else { - if (isset($result[$child->nodeName])) { - if (!isset($groups[$child->nodeName])) { - $result[$child->nodeName] = [$result[$child->nodeName]]; - $groups[$child->nodeName] = 1; - } - $result[$child->nodeName][] = $this->toArray($child); - } else { - $result[$child->nodeName] = $this->toArray($child); - } + $result[$child->nodeName] = $this->toArray($child); } } } diff --git a/app/code/Magento/Ui/DataProvider/Config/Data.php b/app/code/Magento/Ui/DataProvider/Config/Data.php index a975606507f0d..d61e3b83e142e 100644 --- a/app/code/Magento/Ui/DataProvider/Config/Data.php +++ b/app/code/Magento/Ui/DataProvider/Config/Data.php @@ -3,23 +3,26 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Ui\DataProvider\Config; +use Magento\Eav\Model\Entity\Attribute; +use Magento\Framework\Config\CacheInterface; +use Magento\Framework\Config\Data as ConfigData; + /** * Class Data */ -class Data extends \Magento\Framework\Config\Data +class Data extends ConfigData { /** + * Constructor + * * @param Reader $reader - * @param \Magento\Framework\Config\CacheInterface $cache + * @param CacheInterface $cache */ - public function __construct( - Reader $reader, - \Magento\Framework\Config\CacheInterface $cache - ) { - $this->cacheTags = [\Magento\Eav\Model\Entity\Attribute::CACHE_TAG]; + public function __construct(Reader $reader, CacheInterface $cache) + { + $this->cacheTags = [Attribute::CACHE_TAG]; parent::__construct($reader, $cache, 'data_source'); } diff --git a/app/code/Magento/Ui/DataProvider/Config/FileResolver.php b/app/code/Magento/Ui/DataProvider/Config/FileResolver.php index fbd093b8c1acd..5d329a5df7333 100644 --- a/app/code/Magento/Ui/DataProvider/Config/FileResolver.php +++ b/app/code/Magento/Ui/DataProvider/Config/FileResolver.php @@ -1,21 +1,19 @@ iteratorFactory->create( $this->directoryRead, - $this->directoryRead->search('/*/*/etc/data_source/' . $filename) + $this->directoryRead->search('/*/*/etc/' . $filename) ); return $iterator; } diff --git a/app/code/Magento/Ui/DataProvider/Config/Reader.php b/app/code/Magento/Ui/DataProvider/Config/Reader.php index 6360437f16eb3..f51828d6cfd53 100644 --- a/app/code/Magento/Ui/DataProvider/Config/Reader.php +++ b/app/code/Magento/Ui/DataProvider/Config/Reader.php @@ -3,15 +3,15 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Ui\DataProvider\Config; +use Magento\Framework\Config\Reader\Filesystem; use Magento\Framework\Config\ValidationStateInterface; /** * Class Reader */ -class Reader extends \Magento\Framework\Config\Reader\Filesystem +class Reader extends Filesystem { /** * List of id attributes for merge @@ -35,7 +35,7 @@ public function __construct( Converter $converter, SchemaLocator $schemaLocator, ValidationStateInterface $validationState, - $fileName = '*.xml', + $fileName = 'data_source.xml', $idAttributes = [], $domDocumentClass = 'Magento\Framework\Config\Dom', $defaultScope = '' diff --git a/app/code/Magento/Ui/DataProvider/Config/SchemaLocator.php b/app/code/Magento/Ui/DataProvider/Config/SchemaLocator.php index 02f64378eefe1..9574e80c80dd7 100644 --- a/app/code/Magento/Ui/DataProvider/Config/SchemaLocator.php +++ b/app/code/Magento/Ui/DataProvider/Config/SchemaLocator.php @@ -5,10 +5,13 @@ */ namespace Magento\Ui\DataProvider\Config; +use Magento\Framework\Config\SchemaLocatorInterface; +use Magento\Framework\Module\Dir\Reader as DirReader; + /** * Class SchemaLocator */ -class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface +class SchemaLocator implements SchemaLocatorInterface { /** * Path to corresponding XSD file with validation rules for both individual and merged configs @@ -18,9 +21,9 @@ class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface private $_schema; /** - * @param \Magento\Framework\Module\Dir\Reader $moduleReader + * @param DirReader $moduleReader */ - public function __construct(\Magento\Framework\Module\Dir\Reader $moduleReader) + public function __construct(DirReader $moduleReader) { $this->_schema = $moduleReader->getModuleDir('etc', 'Magento_Ui') . '/data_source.xsd'; } diff --git a/app/code/Magento/Ui/DataProvider/Metadata.php b/app/code/Magento/Ui/DataProvider/Metadata.php index 3606699e59b90..521a7bc4c555f 100644 --- a/app/code/Magento/Ui/DataProvider/Metadata.php +++ b/app/code/Magento/Ui/DataProvider/Metadata.php @@ -3,7 +3,6 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Ui\DataProvider; use Magento\Framework\ObjectManagerInterface; @@ -227,7 +226,7 @@ protected function initAttributes() { if (empty($this->attributes)) { foreach ($this->config['fields'] as $field) { - if (isset($field['source']) && $field['source'] == 'eav') { + if (isset($field['source']) && $field['source'] === 'eav') { $attribute = $this->dataSet->getEntity()->getAttribute($field['name']); if ($attribute) { $this->attributes[$field['name']] = $attribute->getData(); @@ -253,37 +252,26 @@ protected function initAttributes() */ protected function prepare($name, array & $field) { - if ($name == self::CHILD_DATA_SOURCES) { - foreach ($field as $childName => $childConfig) { - $field[$childName] = $this->manager->getMetadata($childName); - } - return; - } - $options = []; - if (isset($field['source'])) { - if ($field['source'] == 'option') { - $rawOptions = $this->manager->getData( - $field['reference']['target'] - ); + if (isset($field['source']) && $field['source'] === 'option') { + $rawOptions = $this->manager->getData( + $field['reference']['target'] + ); + $options[] = [ + 'label' => __('Please, select...'), + 'value' => null, + ]; + foreach ($rawOptions as $rawOption) { $options[] = [ - 'label' => __('Please, select...'), - 'value' => null, - ]; - foreach ($rawOptions as $rawOption) { - $options[] = [ - 'label' => $rawOption[$field['reference']['neededField']], - 'value' => $rawOption[$field['reference']['targetField']], + 'label' => $rawOption[$field['reference']['neededField']], + 'value' => $rawOption[$field['reference']['targetField']], - ]; - } - } - } else { - if (isset($field['optionProvider'])) { - list($source, $method) = explode('::', $field['optionProvider']); - $sourceModel = $this->universalFactory->create($source); - $options = $sourceModel->$method(); + ]; } + } else if (isset($field['optionProvider'])) { + list($source, $method) = explode('::', $field['optionProvider']); + $sourceModel = $this->universalFactory->create($source); + $options = $sourceModel->$method(); } $attributeCodes = [ diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml.php b/app/code/Magento/Ui/TemplateEngine/Xhtml.php new file mode 100644 index 0000000000000..9aa18889370bb --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml.php @@ -0,0 +1,93 @@ +templateProvider = $templateProvider; + $this->resultFactory = $resultFactory; + $this->templateFactory = $templateFactory; + $this->compilerFactory = $compilerFactory; + } + + /** + * Render template + * + * Render the named template in the context of a particular block and with + * the data provided in $vars. + * + * @param \Magento\Framework\View\Element\BlockInterface $block + * @param string $templateFile + * @param array $dictionary + * @return Result + */ + public function render(BlockInterface $block, $templateFile, array $dictionary = []) + { + /** @var Template $template */ + $template = $this->templateFactory->create(['content' => $this->templateProvider->getTemplate($templateFile)]); + + /** @var Result $result */ + $result = $this->resultFactory->create( + [ + 'template' => $template, + 'compiler' => $this->compilerFactory->create(), + 'component' => $block + ] + ); + + return $result; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php new file mode 100644 index 0000000000000..ffbafcb1d4a36 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php @@ -0,0 +1,174 @@ +compilerText = $compilerText; + $this->compilerAttribute = $compilerAttribute; + $this->compilerCdata = $compilerCdata; + $this->compilerComment = $compilerComment; + $this->elementCompilers = $elementCompilers; + } + + /** + * The compilation of the template and filling in the data + * + * @param \DOMNode $node + * @param UiComponentInterface $component + * @param Object $context + * @return void + */ + public function compile(\DOMNode $node, UiComponentInterface $component, Object $context) + { + switch ($node->nodeType) { + case XML_TEXT_NODE: + $this->compilerText->compile($node, $component); + break; + case XML_CDATA_SECTION_NODE: + $this->compilerCdata->compile($node, $component); + break; + case XML_COMMENT_NODE: + $this->compilerComment->compile($node, $component); + break; + default: + /** @var \DomElement $node */ + if ($node->hasAttributes()) { + foreach ($node->attributes as $attribute) { + $this->compilerAttribute->compile($attribute, $component); + } + } + $compiler = $this->getElementCompiler($node->nodeName); + if (null !== $compiler) { + $compiler->compile($this, $node, $component, $context); + } else if ($node->hasChildNodes()) { + foreach ($this->getChildNodes($node) as $child) { + $this->compile($child, $component, $context); + } + } + } + } + + /** + * Run postprocessing contents template + * + * @param $content + * @return string + */ + public function postprocessing($content) + { + return preg_replace_callback( + '#' . preg_quote(static::PATTERN_TAG) . '(.+?)' . preg_quote(static::PATTERN_TAG) . '#', + function ($match) { + return isset($this->data[$match[1]]) ? $this->data[$match[1]] : ''; + }, + $content + ); + } + + /** + * Set postprocessing data + * + * @param string $key + * @param string $content + */ + public function setPostprocessingData($key, $content) + { + $this->data[$key] = $content; + } + + /** + * Get child nodes + * + * @param \DOMElement $node + * @return \DOMElement[] + */ + protected function getChildNodes(\DOMElement $node) + { + $childNodes = []; + foreach ($node->childNodes as $child) { + $childNodes[] = $child; + } + + return $childNodes; + } + + /** + * Get element compiler by name + * + * @param string $name + * @return ElementInterface + */ + protected function getElementCompiler($name) + { + if (isset($this->elementCompilers[$name])) { + return $this->elementCompilers[$name]; + } + + return null; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php new file mode 100644 index 0000000000000..f1ab640960831 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php @@ -0,0 +1,50 @@ +directivePool = $directivePool; + } + + /** + * Compiles the Element node + * + * @param \DOMAttr $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMAttr $node, UiComponentInterface $component) + { + foreach ($this->directivePool as $directive) { + $node->value = preg_replace_callback( + $directive->getPattern(), + function ($match) use ($directive, $component) { + return $directive->execute($match, $component); + }, + $node->value + ); + } + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php new file mode 100644 index 0000000000000..274d43bcde56d --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php @@ -0,0 +1,23 @@ +$methodName(); + if (is_scalar($result)) { + break; + } + $object = $result; + continue; + } + break; + } + + return $result; + } + + /** + * Get regexp search pattern + * + * @return string + */ + public function getPattern() + { + return '#\{\{((?:[\w_0-9]+\(\)){1}(?:(?:\.[\w_0-9]+\(\))+)?)\}\}#'; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php new file mode 100644 index 0000000000000..b367a6b84f7b3 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php @@ -0,0 +1,30 @@ +getData($directive[1]); + } + + /** + * Get regexp search pattern + * + * @return string + */ + public function getPattern() + { + return '#\{\{([^\}\(]+)\}\}#'; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php new file mode 100644 index 0000000000000..91a84fc903fa5 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php @@ -0,0 +1,44 @@ +getAttribute('name'); + $content = (string)$component->renderChildComponent($name); + $name .= '_' . sprintf('%x', crc32(spl_object_hash($context))); + if (!empty($content)) { + $compiler->setPostprocessingData($name, $content); + $newNode = $node->ownerDocument->createTextNode( + Compiler::PATTERN_TAG . $name . Compiler::PATTERN_TAG); + $node->parentNode->replaceChild($newNode, $node); + } else { + $node->parentNode->removeChild($node); + } + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php new file mode 100644 index 0000000000000..df4e2f5c894da --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php @@ -0,0 +1,33 @@ +getChildNodes($node) as $child) { + $compiler->compile($child, $component, $context); + } + } + + /** + * Get child nodes + * + * @param \DOMElement $node + * @return \DOMElement[] + */ + protected function getChildNodes(\DOMElement $node) + { + $childNodes = []; + foreach ($node->childNodes as $child) { + $childNodes[] = $child; + } + + return $childNodes; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php new file mode 100644 index 0000000000000..9118a5e6b6aef --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php @@ -0,0 +1,45 @@ +renderChildComponent($node->getAttribute('name')); + if ($result instanceof Result) { + $node->parentNode->replaceChild($result->getDocumentElement(), $node); + } else if (!empty($result) && is_scalar($result)) { + $newFragment = $node->ownerDocument->createDocumentFragment(); + $newFragment->appendXML($result); + $node->parentNode->replaceChild($newFragment, $node); + $node->parentNode->removeChild($node); + } else { + $node->parentNode->removeChild($node); + } + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php new file mode 100644 index 0000000000000..5bdfe50622c2a --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php @@ -0,0 +1,54 @@ +directivePool = $directivePool; + } + + /** + * Compiles the Element node + * + * @param \DOMText $node + * @param UiComponentInterface $component + * @return void + */ + public function compile(\DOMText $node, UiComponentInterface $component) + { + $result = ''; + foreach ($this->directivePool as $directive) { + $result = preg_replace_callback( + $directive->getPattern(), + function ($match) use ($directive, $component) { + return $directive->execute($match, $component); + }, + $node->textContent + ); + } + + $newNode = $node->ownerDocument->createTextNode($result); + $node->parentNode->replaceChild($newNode, $node); + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php new file mode 100644 index 0000000000000..1f1ffc4158616 --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php @@ -0,0 +1,23 @@ +template = $template; + $this->compiler = $compiler; + $this->component = $component; + $this->layoutPool = $layoutPool; + } + + /** + * Get result document root element \DOMElement + * + * @return \DOMElement + */ + public function getDocumentElement() + { + return $this->template->getDocumentElement(); + } + + /** + * Append layout configuration + * + * @return void + */ + public function appendLayoutConfiguration() + { + /** @var LayoutInterface $layout */ + if (!$layoutDefinition = $this->component->getData('layout')) { + $layoutDefinition = [ + 'type' => 'generic' + ]; + } + + $layout = $this->layoutPool->create($layoutDefinition['type'], $layoutDefinition); + $layoutConfiguration = $this->wrapContent( + json_encode($layout->build($this->component)) + ); + $this->template->append($layoutConfiguration); + } + + /** + * Returns the string representation + * + * @return string + */ + public function __toString() + { + try { + $templateRootElement = $this->getDocumentElement(); + $this->compiler->compile($templateRootElement, $this->component, $this->component); + $this->appendLayoutConfiguration(); + $result = $this->compiler->postprocessing($this->template->__toString()); + } catch (\Exception $e) { + $result = ''; + } + return $result; + } + + /** + * Wrap content + * + * @param string $content + * @return string + */ + protected function wrapContent($content) + { + return ''; + } +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php new file mode 100644 index 0000000000000..8913621d2ae9c --- /dev/null +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php @@ -0,0 +1,70 @@ +loadXML($content); + $this->templateNode = $document->documentElement; + + } + + /** + * Get template root element + * + * @return \DOMElement + */ + public function getDocumentElement() + { + return $this->templateNode; + } + + /** + * @param string $content + */ + public function append($content) + { + $newFragment = $this->templateNode->ownerDocument->createDocumentFragment(); + $newFragment->appendXML($content); + $this->templateNode->appendChild($newFragment); + } + + /** + * Returns the string representation + * + * @return string + */ + public function __toString() + { + try { + $this->templateNode->ownerDocument->normalizeDocument(); + $result = $this->templateNode->ownerDocument->saveHTML(); + } catch (\Exception $e) { + $result = ''; + } + return $result; + } +} diff --git a/app/code/Magento/Ui/Test/Unit/Component/ListingTest.php b/app/code/Magento/Ui/Test/Unit/Component/ListingTest.php index e5f795227c825..e7aea723d6393 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/ListingTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/ListingTest.php @@ -11,7 +11,6 @@ use Magento\Framework\View\Element\Template\Context; use Magento\Ui\Component\Control\ActionPool; use Magento\Ui\Component\Listing\OptionsFactory; -use Magento\Ui\Component\Listing\RowPool; use Magento\Ui\Context\ConfigurationFactory; /** @@ -29,11 +28,6 @@ class ListingTest extends \PHPUnit_Framework_TestCase */ protected $optionsFactory; - /** - * @var RowPool|\PHPUnit_Framework_MockObject_MockObject - */ - protected $rowPool; - /** * @var Context */ @@ -89,7 +83,6 @@ public function setUp() $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->actionPool = $this->getMock('\Magento\Ui\Component\Control\ActionPool', [], [], '', false); $this->optionsFactory = $this->getMock('\Magento\Ui\Component\Listing\OptionsFactory', [], [], '', false); - $this->rowPool = $this->getMock('\Magento\Ui\Component\Listing\RowPool', [], [], '', false); $this->renderContext = $this->getMock('\Magento\Framework\View\Element\UiComponent\Context', [], [], '', false); $this->templateContext = $this->getMock( 'Magento\Framework\View\Element\Template\Context', @@ -142,8 +135,7 @@ public function setUp() 'configFactory' => $this->configurationFactory, 'configBuilder' => $configurationBuilder, 'optionsFactory' => $this->optionsFactory, - 'actionPool' => $this->actionPool, - 'dataProviderRowPool' => $this->rowPool + 'actionPool' => $this->actionPool ] ); } diff --git a/app/code/Magento/Ui/etc/di.xml b/app/code/Magento/Ui/etc/di.xml index 55a44cd9d4df7..471177efd4441 100644 --- a/app/code/Magento/Ui/etc/di.xml +++ b/app/code/Magento/Ui/etc/di.xml @@ -6,20 +6,252 @@ */ --> - - + + + + + + + + + + + Magento\Ui\TemplateEngine\Xhtml + + + + + + Magento\Ui\TemplateEngine\Xhtml\Compiler + + + + + + Magento\Framework\View\Element\UiComponent\ContentType\Html + Magento\Framework\View\Element\UiComponent\ContentType\Json + Magento\Framework\View\Element\UiComponent\ContentType\Xml + + + + + + + Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\Variable + Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\CallableMethod + + + + + + + Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\Variable + Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\CallableMethod + + + + + + Magento\Ui\TemplateEngine\Xhtml\Compiler\Text + Magento\Ui\TemplateEngine\Xhtml\Compiler\Attribute + Magento\Ui\TemplateEngine\Xhtml\Compiler\Cdata + Magento\Ui\TemplateEngine\Xhtml\Compiler\Comment + + Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Render + \Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Content + Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Form + + + + + + etc + Magento_Ui + ui_configuration.xsd + + / + + + name + + + + + + uiConfigurationDomMerger + + + + + etc + Magento_Ui + ui_template.xsd + + / + + + name + id + + + + + + uiTemplateDomMerger + + + + + etc + Magento_Ui + ui_definition.xsd + + /components + + + name + + true + + + + + etc/definition.xml + + + + + uiDefinitionFileCollector + uiDefinitionDomMerger + + + + + uiDefinitionReader + + Magento\Ui\Component\Filter\Type\Input Magento\Ui\Component\Filter\Type\Select Magento\Ui\Component\Filter\Type\Range - Magento\Ui\Component\Filter\Type\Date Magento\Ui\Component\Filter\Type\Store + + + + + Magento\Ui\Component\Layout\Generic + templates/layout/generic + + + Magento\Ui\Component\Layout\Tabs + templates/layout/tabs + + + + + + + Magento\Framework\Data\Argument\Interpreter\ArrayType + + + + + Magento\Framework\View\Element\UiComponent\Argument\Interpreter\ConfigurableObject + + + + + + Magento\Framework\Data\Argument\Interpreter\Object + configurableObjectArgumentInterpreterProxy + arrayArgumentInterpreterProxy + Magento\Framework\Data\Argument\Interpreter\Boolean + Magento\Framework\Data\Argument\Interpreter\Number + Magento\Framework\Data\Argument\Interpreter\String + Magento\Framework\Data\Argument\Interpreter\NullType + + xsi:type + + + + + uiComponentAggregatedCollector + + + + + uiComponentAggregatedSourceBaseSorted + uiComponentAggregatedSourceThemeSorted + uiComponentAggregatedSourceOverrideBaseSorted + uiComponentAggregatedSourceOverrideThemeSorted + + + + + ui_component + + + + + uiComponentAggregatedSourceBase + + + + + uiComponentAggregatedSourceBaseFiltered + + + + + ui_component + + + + + uiComponentAggregatedSourceTheme + + + + + uiComponentAggregatedSourceThemeFiltered + + + + + layout/override/base + + + + + uiComponentAggregatedSourceOverrideBase + + + + + uiComponentAggregatedSourceOverrideBaseFiltered + + + + + layout/override/theme + + + + + uiComponentAggregatedSourceOverrideTheme + + + + + uiComponentAggregatedSourceOverrideThemeFiltered + + diff --git a/app/code/Magento/Ui/etc/ui_components.xsd b/app/code/Magento/Ui/etc/ui_components.xsd new file mode 100644 index 0000000000000..42ef3a3f4787c --- /dev/null +++ b/app/code/Magento/Ui/etc/ui_components.xsd @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The value should only be {[a-z_-]+} since it is used as a reference to a database field. + + + + + + + + Any text value + + + + + + diff --git a/app/code/Magento/Ui/etc/ui_configuration.xsd b/app/code/Magento/Ui/etc/ui_configuration.xsd new file mode 100644 index 0000000000000..de27bdcbc5002 --- /dev/null +++ b/app/code/Magento/Ui/etc/ui_configuration.xsd @@ -0,0 +1,75 @@ + + + + + The definition of a configuration item components + The definition of a configuration item components + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Ui/etc/ui_definition.xsd b/app/code/Magento/Ui/etc/ui_definition.xsd new file mode 100644 index 0000000000000..b1fa91f1f36f9 --- /dev/null +++ b/app/code/Magento/Ui/etc/ui_definition.xsd @@ -0,0 +1,78 @@ + + + + + + + + + + + Registering components in the system and basic setup + Registering components in the system and basic setup + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Ui/etc/ui_template.xsd b/app/code/Magento/Ui/etc/ui_template.xsd new file mode 100644 index 0000000000000..ef5b731067363 --- /dev/null +++ b/app/code/Magento/Ui/etc/ui_template.xsd @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Ui/view/base/layout/default.xml b/app/code/Magento/Ui/view/base/layout/default.xml index 289b9006c48b5..fd5dc12088e9e 100644 --- a/app/code/Magento/Ui/view/base/layout/default.xml +++ b/app/code/Magento/Ui/view/base/layout/default.xml @@ -8,11 +8,11 @@ - - - Magento_Ui::context/default.phtml - - + + + + + diff --git a/app/code/Magento/Ui/view/base/layout/ui_components.xml b/app/code/Magento/Ui/view/base/layout/ui_components.xml index ac23d0fefa299..e8093ab26f67d 100644 --- a/app/code/Magento/Ui/view/base/layout/ui_components.xml +++ b/app/code/Magento/Ui/view/base/layout/ui_components.xml @@ -14,10 +14,9 @@ - - - - + + + diff --git a/app/code/Magento/Ui/view/base/templates/context/default.phtml b/app/code/Magento/Ui/view/base/templates/context/default.phtml index ecd62351fb8d0..247c493fc046f 100644 --- a/app/code/Magento/Ui/view/base/templates/context/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/context/default.phtml @@ -4,9 +4,9 @@ * See COPYING.txt for license details. */ /** - * @var \Magento\Ui\Context\DataProvider $block + * @var \Magento\Ui\Context\PageDataProvider $this */ ?> - diff --git a/app/code/Magento/Ui/view/base/templates/filter_pool/default.phtml b/app/code/Magento/Ui/view/base/templates/filter_pool/default.phtml index caec2660f677e..c81760ed4f8d4 100644 --- a/app/code/Magento/Ui/view/base/templates/filter_pool/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/filter_pool/default.phtml @@ -7,13 +7,7 @@ * @var \Magento\Ui\Component\FilterPool $block */ ?> - +
diff --git a/app/code/Magento/Ui/view/base/templates/form/default.phtml b/app/code/Magento/Ui/view/base/templates/form/default.phtml index f9510c9f9b387..f7ec8ba037f08 100644 --- a/app/code/Magento/Ui/view/base/templates/form/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/form/default.phtml @@ -6,22 +6,13 @@ /** * @var \Magento\Ui\Component\Form $block */ -$formConfig = $block->getRenderContext()->getConfigBuilder()->toJsonNew($block->getRenderContext()->getStorage()); +echo $block->renderChildComponent('before_form'); ?> - -
-
-
- -
+
+
-
-
+
+renderChildComponent('after_form'); diff --git a/app/code/Magento/Ui/view/base/templates/listing/horizontal_grid.phtml b/app/code/Magento/Ui/view/base/templates/listing/horizontal_grid.phtml index 32f2356edd984..f1e6048b9795b 100644 --- a/app/code/Magento/Ui/view/base/templates/listing/horizontal_grid.phtml +++ b/app/code/Magento/Ui/view/base/templates/listing/horizontal_grid.phtml @@ -3,24 +3,11 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -?> - - + getChildHtml('listing_head'); ?>
getChildHtml('listing_before'); ?> diff --git a/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/default.phtml b/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/default.phtml index f0e80904214fb..59bd107f158ed 100644 --- a/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/default.phtml @@ -3,19 +3,11 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -?> - - +
diff --git a/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/page_actions.phtml b/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/page_actions.phtml index 1bba18bb5ff43..1e74e194faed0 100644 --- a/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/page_actions.phtml +++ b/app/code/Magento/Ui/view/base/templates/listingcontainer/massaction/page_actions.phtml @@ -3,19 +3,11 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -?> - - +
diff --git a/app/code/Magento/Ui/view/base/templates/paging/default.phtml b/app/code/Magento/Ui/view/base/templates/paging/default.phtml index 6c710bdf1b154..ae8fdd1b1f440 100644 --- a/app/code/Magento/Ui/view/base/templates/paging/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/paging/default.phtml @@ -3,19 +3,11 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -?> - - +
diff --git a/app/code/Magento/Ui/view/base/templates/sorting/default.phtml b/app/code/Magento/Ui/view/base/templates/sorting/default.phtml index 1b85352c82b4e..91fb6edb157fb 100644 --- a/app/code/Magento/Ui/view/base/templates/sorting/default.phtml +++ b/app/code/Magento/Ui/view/base/templates/sorting/default.phtml @@ -3,17 +3,8 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -?> - - + diff --git a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml new file mode 100644 index 0000000000000..b6e474b30854e --- /dev/null +++ b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml @@ -0,0 +1,214 @@ + + + + + + + templates/listing/default + 1 + mui/index/render + + Magento_Ui/js/lib/component/component + + + + + + + + templates/paging/default + + Magento_Ui/js/grid/paging + + + + + + + + + + + templates/listingcontainer/massaction/default + + Magento_Ui/js/grid/massactions + + + + + + + Magento_Ui/js/grid/columns/select + + + + + + + Magento_Ui/js/form/element/abstract + + ui/grid/filters/elements/input + + + + + + + checkbox + + Magento_Ui/js/form/element/boolean + + checkbox + + + + + + + + + Magento_Ui/js/form/element/multiselect + + multiselect + ui/form/element/multiselect + + + + + + + + + Magento_Ui/js/form/element/text + + input + + + + + + + + + + input + + media + + + + + + + + input + Magento_Ui/js/form/element/date + + mm/dd/yyyy + + + + + + + + input + + select + + + + + + + + input + + email + @email: + + + + + + + + Magento_Ui/js/grid/listing + + + + +
+ + templates/form/default + mui/form/save + mui/form/validate + + Magento_Ui/js/form + + +
+
+ + Magento_Ui::form/fieldset/default + + Magento_Ui/js/form/components/fieldset + + +
+ + + + + + + templates/layout/tabs/tab/default + + Magento_Ui/js/form/components/area + + + + + + templates/layout/group/default + + Magento_Ui/js/form/components/group + + + + + +
diff --git a/app/code/Magento/Ui/view/base/ui_component/templates/form/default.xhtml b/app/code/Magento/Ui/view/base/ui_component/templates/form/default.xhtml new file mode 100644 index 0000000000000..2e997c4a0bd08 --- /dev/null +++ b/app/code/Magento/Ui/view/base/ui_component/templates/form/default.xhtml @@ -0,0 +1,15 @@ + + +
+
+
+
+
+ +
+
diff --git a/app/code/Magento/Ui/view/base/ui_component/templates/listing/default.xhtml b/app/code/Magento/Ui/view/base/ui_component/templates/listing/default.xhtml new file mode 100644 index 0000000000000..3f5a445a689f9 --- /dev/null +++ b/app/code/Magento/Ui/view/base/ui_component/templates/listing/default.xhtml @@ -0,0 +1,12 @@ + + +
+
+ +
diff --git a/app/code/Magento/Ui/view/base/web/js/core/app.js b/app/code/Magento/Ui/view/base/web/js/core/app.js index 9e8f5be7e0165..f3f5be33b222e 100644 --- a/app/code/Magento/Ui/view/base/web/js/core/app.js +++ b/app/code/Magento/Ui/view/base/web/js/core/app.js @@ -9,33 +9,19 @@ define([ ], function (_, Renderer, registry) { 'use strict'; - function load(config, name){ - require([config.path], function(constr){ - registry.set(name, new constr(config)); - }); - } - var global = { - init: function(data){ + init: function (data) { this.data = {}; this.register() - .initRenderer(data.renderer) - .initProviders(data.providers) - .register(); + .initRenderer(data); }, - initRenderer: function(data){ + initRenderer: function (data) { this.renderer = new Renderer(data); return this; }, - - initProviders: function(providers){ - _.each(providers, load); - - return this; - }, register: function () { registry.set('globalStorage', this); @@ -45,4 +31,4 @@ define([ }; return global.init.bind(global); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js b/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js index 6866bf0d0e644..bbffaa4acec27 100644 --- a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js +++ b/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js @@ -8,7 +8,7 @@ define([ 'mage/utils', 'Magento_Ui/js/lib/class', 'Magento_Ui/js/lib/registry/registry' -], function(_, $, utils, Class, registry) { +], function (_, $, utils, Class, registry) { 'use strict'; function getNodeName(parent, node, name) { @@ -25,56 +25,56 @@ define([ return name; } - function getNodeType(parent, node){ + function getNodeType(parent, node) { return node.type || (parent && parent.childType); } - function getDataScope(parent, node){ - var dataScope = node.dataScope, + function notEmpty(value) { + return !_.isUndefined(value) && value !== ''; + } + + function getDataScope(parent, node) { + var dataScope = node.dataScope, parentScope = parent && parent.dataScope; return notEmpty(parentScope) ? - ( notEmpty(dataScope) ? - (parentScope + '.' + dataScope) : - parentScope ) : - (dataScope || ''); - } - - function notEmpty(value){ - return !_.isUndefined(value) && value !== ''; + (notEmpty(dataScope) ? + (parentScope + '.' + dataScope) : + parentScope) : + (dataScope || ''); } - function mergeNode(node, config){ + function mergeNode(node, config) { return $.extend(true, {}, config, node); } - function additional(node){ + function additional(node) { return _.pick(node, 'name', 'index', 'dataScope'); } - function loadDeps(node){ + function loadDeps(node) { var loaded = $.Deferred(); - registry.get(node.deps, function(){ + registry.get(node.deps, function () { loaded.resolve(node); }); return loaded.promise(); } - function loadSource(node){ + function loadSource(node) { var loaded = $.Deferred(), source = node.component; - require([source], function(constr){ + require([source], function (constr) { loaded.resolve(node, constr); }); return loaded.promise(); } - function initComponent(node, constr){ - var component = new constr( + function initComponent(node, Constr) { + var component = new Constr( node.config, additional(node) ); @@ -82,21 +82,21 @@ define([ registry.set(node.name, component); } - function Layout(nodes, types){ - this.types = types; - this.registry = registry.create(); + function Layout(nodes, types) { + this.types = types; + this.registry = registry.create(); this.run(nodes); } _.extend(Layout.prototype, { - run: function(nodes, parent){ + run: function (nodes, parent) { _.each(nodes || [], this.iterator.bind(this, parent)); return this; }, - iterator: function(parent, node, name){ + iterator: function (parent, node) { var action = _.isString(node) ? this.addChild : this.process; @@ -104,18 +104,18 @@ define([ action.apply(this, arguments); }, - process: function(parent, node, name) { - if(!parent && node.parent){ + process: function (parent, node, name) { + if (!parent && node.parent) { return this.waitParent(node, name); } - if(node.template){ - return this.waitTemplate.apply(this, arguments); + if (node.template) { + return this.waitTemplate.apply(this, arguments); } node = this.build.apply(this, arguments); - if(node){ + if (node) { this.addChild(parent, node.name) .manipulate(node) .initComponent(node) @@ -125,15 +125,15 @@ define([ return this; }, - build: function(parent, node, name){ + build: function (parent, node, name) { var type; type = getNodeType.apply(null, arguments); node = mergeNode(node, this.types.get(type)); - node.index = node.name || name; - node.name = getNodeName(parent, node, name); - node.dataScope = getDataScope(parent, node); + node.index = node.name || name; + node.name = getNodeName(parent, node, name); + node.dataScope = getDataScope(parent, node); delete node.type; @@ -144,8 +144,8 @@ define([ node; }, - initComponent: function(node){ - if(!node.component){ + initComponent: function (node) { + if (!node.component) { return this; } @@ -156,31 +156,31 @@ define([ return this; } }); - + _.extend(Layout.prototype, { - waitTemplate: function(parent, node, name){ + waitTemplate: function (parent, node, name) { var args = _.toArray(arguments); - this.registry.get(node.template, function(){ + this.registry.get(node.template, function () { this.applyTemplate.apply(this, args); }.bind(this)); return this; }, - waitParent: function(node, name){ + waitParent: function (node, name) { var process = this.process.bind(this); - this.registry.get(node.parent, function(parent){ + this.registry.get(node.parent, function (parent) { process(parent, node, name); }); return this; }, - applyTemplate: function(parent, node, name){ + applyTemplate: function (parent, node, name) { var template = this.registry.get(node.template); - + node = mergeNode(node, template); delete node.template; @@ -190,7 +190,7 @@ define([ }); _.extend(Layout.prototype, { - manipulate: function(node) { + manipulate: function (node) { var name = node.name; if (node.appendTo) { @@ -201,41 +201,41 @@ define([ this.insert(name, node.prependTo, 0); } - if(node.insertTo){ + if (node.insertTo) { this.insertTo(name, node.insertTo); } return this; }, - insert: function(item, target, position){ - registry.get(target, function(target){ + insert: function (item, target, position) { + registry.get(target, function (target) { target.insert(item, position); }); return this; }, - insertTo: function(item, targets){ - _.each(targets, function(info, target){ + insertTo: function (item, targets) { + _.each(targets, function (info, target) { this.insert(item, target, info.position); }, this); return this; }, - addChild: function(parent, child){ - if(parent && parent.component){ + addChild: function (parent, child) { + if (parent && parent.component) { this.insert(child, parent.name); } return this; }, - clear: function(name){ + clear: function (name) { this.registry.remove(name); } }); return Layout; -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/core/renderer/renderer.js b/app/code/Magento/Ui/view/base/web/js/core/renderer/renderer.js index 5b7de47144ebb..fbe4cf977ba01 100644 --- a/app/code/Magento/Ui/view/base/web/js/core/renderer/renderer.js +++ b/app/code/Magento/Ui/view/base/web/js/core/renderer/renderer.js @@ -6,19 +6,19 @@ define([ './components/types', './components/layout', 'Magento_Ui/js/lib/class' -], function(Types, Layout, Class){ +], function (Types, Layout, Class) { 'use strict'; return Class.extend({ - initialize: function(data){ + initialize: function (data) { this.types = new Types(data.types); - this.layout = new Layout(data.layout, this.types); + this.layout = new Layout(data.components, this.types); return this; }, - render: function(data){ - this.layout.run(data.layout); + render: function (data) { + this.layout.run(data.components); this.types.set(data.types); } }); diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/collection.js b/app/code/Magento/Ui/view/base/web/js/form/components/collection.js index 0dd910f3e3ca3..6cef3d6c31d7f 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/collection.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/collection.js @@ -6,7 +6,7 @@ define([ 'underscore', 'mage/utils', 'Magento_Ui/js/lib/registry/registry', - 'Magento_Ui/js/form/component', + 'Magento_Ui/js/lib/component/component' ], function (_, utils, registry, Component) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/group.js b/app/code/Magento/Ui/view/base/web/js/form/components/group.js index 2a23cb48a54da..25b8d735d5f10 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/group.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/group.js @@ -4,45 +4,45 @@ */ define([ 'underscore', - '../component', + 'Magento_Ui/js/lib/component/component', 'mage/utils' -], function(_, Component, utils) { +], function (_, Component, utils) { 'use strict'; - - function extractData(container, field){ + + function extractData(container, field, orig) { var data, value; - container.some(function(item){ + container.some(function (item) { value = item[field]; - if(_.isFunction(value)){ + if (_.isFunction(value)) { value = value(); } return !item.hidden() && (data = value); }); - return data || ''; + return data || orig; } return Component.extend({ defaults: { - hidden: false, - label: '', - required: false, - template: 'ui/group/group', - fieldTemplate: 'ui/group/field', - breakLine: true + hidden: false, + label: '', + required: false, + template: 'ui/group/group', + fieldTemplate: 'ui/group/field', + breakLine: true }, /** * Extends this with defaults and config. * Then calls initObservable, iniListenes and extractData methods. - * + * * @param {Object} config */ - initialize: function() { + initialize: function () { _.bindAll(this, 'toggle'); return this._super(); @@ -51,12 +51,12 @@ define([ /** * Calls initObservable of parent class. * Defines observable properties of instance. - * + * * @return {Object} - reference to instance */ - initObservable: function(){ + initObservable: function () { this._super() - .observe('hidden label required'); + .observe('hidden required'); return this; }, @@ -67,7 +67,7 @@ define([ * @param {Object} element * @return {Object} - reference to instance */ - initElement: function(elem){ + initElement: function (elem) { this._super(); elem.on({ @@ -81,24 +81,23 @@ define([ /** * Extracts label and required properties from child elements - * + * * @return {Object} - reference to instance */ - extractData: function(){ + extractData: function () { var elems = this.elems(); - this.label(extractData(elems, 'label')); - this.required(extractData(elems, 'required')); + this.required(extractData(elems, 'required', this.required())); return this; }, /** * Sets incoming value to hidden observable, calls extractData method - * + * * @param {Boolean} value */ - toggle: function(value){ + toggle: function (value) { this.extractData() .hidden(value); }, diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js index e1d66754af628..3446210361d2e 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js @@ -5,58 +5,58 @@ define([ 'underscore', 'mage/utils', - 'Magento_Ui/js/form/component', + 'Magento_Ui/js/lib/component/component', 'Magento_Ui/js/lib/validation/validator' ], function (_, utils, Component, validator) { 'use strict'; - - /** - * Checks wether the incoming value is not empty, - * e.g. not 'null' or 'undefined' - * - * @param {*} value - Value to check. - * @returns {Boolean} - */ - function isEmpty(value){ - return _.isUndefined(value) || _.isNull(value); - } return Component.extend({ defaults: { - hidden: false, - preview: '', - focused: false, - required: false, - disabled: false, - tmpPath: 'ui/form/element/', - tooltipTpl: 'ui/form/element/helper/tooltip', - input_type: 'input', - placeholder: '', - description: '', - label: '', - error: '', - notice: '' + hidden: false, + preview: '', + focused: false, + required: false, + disabled: false, + tmpPath: 'ui/form/element/', + tooltipTpl: 'ui/form/element/helper/tooltip', + input_type: 'input', + placeholder: '', + description: '', + label: '', + error: '', + notice: '', + + listens: { + value: 'setPreview onUpdate', + hidden: 'setPreview' + }, + + links: { + value: '<%= provider %>:data.<%= dataScope %>' + }, + + exports: { + hidden: '<%= provider %>:params.<%= name %>.hidden' + } }, /** * Invokes initialize method of parent class, contains initialization * logic - * + * * @param {Object} config - form element configuration */ initialize: function () { - _.bindAll(this, 'onUpdate', 'reset'); + _.bindAll(this, 'reset'); - this._super() - .setHidden(this.hidden()) - .store(this.value()); + this._super(); return this; }, /** * Initializes observable properties of instance - * + * * @returns {Abstract} Chainable. */ initObservable: function () { @@ -68,7 +68,7 @@ define([ this.observe('error disabled focused preview hidden') .observe({ - 'value': this.initialValue, + 'value': this.initialValue, 'required': !!rules['required-entry'] }); @@ -77,7 +77,7 @@ define([ /** * Initializes regular properties of instance. - * + * * @returns {Abstract} Chainable. */ initProperties: function () { @@ -86,9 +86,9 @@ define([ this._super(); _.extend(this, { - 'uid': uid, - 'noticeId': 'notice-' + this.uid, - 'inputName': utils.serializeName(this.dataScope) + 'uid': uid, + 'noticeId': 'notice-' + this.uid, + 'inputName': utils.serializeName(this.dataScope) }); _.defaults(this, { @@ -100,45 +100,39 @@ define([ /** * Initializes instance's listeners. - * + * * @returns {Abstract} Chainable. */ - initListeners: function(){ - var provider = this.provider, - data = provider.data; - + initListeners: function () { this._super(); - data.on('reset', this.reset, this.name); - - this.value.subscribe(this.onUpdate); + this.source.on('reset', this.reset, this.name); return this; }, /** * Gets initial value of element - * + * * @returns {*} Elements' value. */ - getInititalValue: function(){ - var data = this.provider.data, - values = [data.get(this.dataScope), this.default], + getInititalValue: function () { + var values = [this.source.get('data.' + this.dataScope), this.default], value; - values.some(function(v){ - return !isEmpty(value = v); + values.some(function (v) { + return !utils.isEmpty(value = v); }); - return isEmpty(value) ? '': value; + return utils.isEmpty(value) ? '' : value; }, /** * Sets value to preview observable - * + * * @returns {Abstract} Chainable. */ - setPreview: function(value){ + setPreview: function (value) { this.preview(this.hidden() ? '' : value); return this; @@ -146,17 +140,17 @@ define([ /** * Returnes unwrapped preview observable. - * + * * @returns {String} Value of the preview observable. */ - getPreview: function(){ + getPreview: function () { return this.preview(); }, /** * Calls 'setHidden' passing true to it. */ - hide: function(){ + hide: function () { this.setHidden(true); return this; @@ -165,7 +159,7 @@ define([ /** * Calls 'setHidden' passing false to it. */ - show: function(){ + show: function () { this.setHidden(false); return this; @@ -175,25 +169,20 @@ define([ * Sets 'value' as 'hidden' propertie's value, triggers 'toggle' event, * sets instance's hidden identifier in params storage based on * 'value'. - * + * * @returns {Abstract} Chainable. */ - setHidden: function(isHidden){ - var params = this.provider.params; - + setHidden: function (isHidden) { this.hidden(isHidden); - - this.setPreview(this.value()) - .trigger('toggle', isHidden); - params.set(this.name + '.hidden', isHidden); + this.trigger('toggle', isHidden); return this; }, /** * Checkes if element has addons - * + * * @returns {Boolean} */ hasAddons: function () { @@ -205,29 +194,20 @@ define([ * * @returns {Boolean} */ - hasChanged: function(){ + hasChanged: function () { var notEqual = this.value() != this.initialValue; return this.hidden() ? false : notEqual; }, - /** - * Stores element's value to registry by element's path value - * @param {*} value - current value of form element - * @returns {Abstract} Chainable. - */ - store: function (value) { - var data = this.provider.data; - - data.set(this.dataScope, value); - - return this; + hasData: function () { + return !utils.isEmpty(this.value()); }, /** * Sets value observable to initialValue property. */ - reset: function(){ + reset: function () { this.value(this.initialValue); }, @@ -235,18 +215,18 @@ define([ * Validates itself by it's validation rules using validator object. * If validation of a rule did not pass, writes it's message to * 'error' observable property. - * + * * @returns {Boolean} True, if element is invalid. */ validate: function () { - var value = this.value(), - msg = validator(this.validation, value), + var value = this.value(), + msg = validator(this.validation, value), isValid = this.hidden() || !msg; this.error(msg); return { - valid: isValid, + valid: isValid, target: this }; }, @@ -254,10 +234,8 @@ define([ /** * Callback that fires when 'value' property is updated. */ - onUpdate: function (value) { - this.store(value) - .setPreview(value) - .trigger('update', this.hasChanged()); + onUpdate: function () { + this.trigger('update', this.hasChanged()); this.validate(); } diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js b/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js index 8b13f063ce205..c6fad500166a8 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js @@ -3,28 +3,29 @@ * See COPYING.txt for license details. */ define([ - './abstract' -], function (Abstract) { + './abstract', + 'mage/utils' +], function (Abstract, utils) { 'use strict'; return Abstract.extend({ /** * Converts the result of parent 'getInitialValue' call to boolean - * + * * @return {Boolean} */ - getInititalValue: function(){ + getInititalValue: function () { return !!+this._super(); }, /** * Calls 'store' method of parent, if value is defined and instance's * 'unique' property set to true, calls 'setUnique' method - * + * * @param {*} value * @return {Object} - reference to instance */ - store: function() { + store: function () { this._super(); if (this.hasUnique) { diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/date.js b/app/code/Magento/Ui/view/base/web/js/form/element/date.js index 6e53005137b69..0b2d1644ff3ac 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/date.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/date.js @@ -10,7 +10,8 @@ define([ return Abstract.extend({ defaults: { - dateFormat: 'MM/DD/YYYY' + dateFormat: 'MM/DD/YYYY', + options: {} }, /** diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/select.js b/app/code/Magento/Ui/view/base/web/js/form/element/select.js index bd2e6d6d13ca0..68e51325b7dc5 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/select.js @@ -10,7 +10,7 @@ define([ 'use strict'; var inputNode = { - name: '{index}_input', + name: '{index}_input', type: 'input', parent: '{parentName}', dataScope: '{customEntry}', @@ -18,7 +18,7 @@ define([ hidden: true, label: '{label}', listeners: { - "params:{parentName}.{index}.hidden":{ + "params:{parentName}.{index}.hidden": { "hide": { "conditions": false }, @@ -33,15 +33,15 @@ define([ /** * Parses incoming options, considers options with undefined value property * as caption - * + * * @param {Array} nodes * @return {Object} */ - function parseOptions(nodes){ + function parseOptions(nodes) { var caption, value; - nodes = _.map(nodes, function(node) { + nodes = _.map(nodes, function (node) { value = node.value; if (value == null || value === '') { @@ -55,24 +55,24 @@ define([ return { options: _.compact(nodes), - caption: caption + caption: caption || false }; } /** * Recursively loops over data to find non-undefined, non-array value - * + * * @param {Array} data * @return {*} - first non-undefined value in array */ - function findFirst(data){ + function findFirst(data) { var value; - data.some(function(node){ + data.some(function (node) { value = node.value; - if(Array.isArray(value)){ - value = findFirst(value); + if (Array.isArray(value)) { + value = findFirst(value); } return !_.isUndefined(value); @@ -91,11 +91,10 @@ define([ * and options, and invokes initialize method of AbstractElement class. * If instance's 'customEntry' property is set to true, calls 'initInput' */ - initialize: function (config) { - this.initOptions(config) - ._super(); - - if(this.customEntry){ + initialize: function () { + this._super(); + + if (this.customEntry) { this.initInput(); } @@ -103,42 +102,48 @@ define([ }, /** - * Calls 'initObservable' of parent, initializes 'options' and 'initialOptions' - * properties, calls 'setOptions' passing options to it - * + * Parses options and merges the result with instance + * + * @param {Object} config * @returns {Select} Chainable. */ - initObservable: function(){ - this._super(); + initConfig: function (config) { + var result = parseOptions(config.options); - this.initialOptions = this.options; + if (config.caption) { + delete result.caption; + } - this.observe('options') - .setOptions(this.options()); + _.extend(config, result); + + this._super(); return this; }, /** - * Parses options and merges the result with instance - * - * @param {Object} config + * Calls 'initObservable' of parent, initializes 'options' and 'initialOptions' + * properties, calls 'setOptions' passing options to it + * * @returns {Select} Chainable. */ - initOptions: function(config){ - var result = parseOptions(config.options); + initObservable: function () { + this._super(); - _.extend(config, result); + this.initialOptions = this.options; + + this.observe('options') + .setOptions(this.options()); return this; }, /** * Creates input from template, renders it via renderer. - * + * * @returns {Select} Chainable. */ - initInput: function(){ + initInput: function () { this.renderer.render({ layout: [ utils.template(inputNode, this) @@ -151,33 +156,33 @@ define([ /** * Calls 'getInitialValue' of parent and if the result of it is not empty * string, returs it, else returnes caption or first found option's value - * + * * @returns {Number|String} */ - getInititalValue: function(){ + getInititalValue: function () { var value = this._super(); - if(value !== ''){ + if (value !== '') { return value; } - - if(!this.caption){ + + if (!this.caption) { return findFirst(this.options); } }, /** * Filters 'initialOptions' property by 'field' and 'value' passed, - * calls 'setOptions' passing the result to it - * + * calls 'setOptions' passing the result to it + * * @param {String} field * @param {*} value */ - filter: function(field, value){ + filter: function (field, value) { var source = this.initialOptions, result; - result = _.filter(source, function(item){ + result = _.filter(source, function (item) { return item[field] === value; }); @@ -185,19 +190,19 @@ define([ }, /** - * Sets 'data' to 'options' observable array, if instance has + * Sets 'data' to 'options' observable array, if instance has * 'customEntry' property set to true, calls 'setHidden' method * passing !options.length as a parameter - * + * * @param {Array} data * @returns {Select} Chainable. */ - setOptions: function(data){ + setOptions: function (data) { this.indexedOptions = _.indexBy(data, 'value'); this.options(data); - - if(this.customEntry){ + + if (this.customEntry) { this.setHidden(!data.length); } @@ -207,14 +212,14 @@ define([ /** * Processes preview for option by it's value, and sets the result * to 'preview' observable - * + * * @param {String} value * @returns {Select} Chainable. */ - setPreview: function(value){ - var option = this.indexedOptions[value], + setPreview: function (value) { + var option = this.indexedOptions[value], preview = option ? option.label : ''; - + this.preview(preview); return this; diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js new file mode 100644 index 0000000000000..b6bc683790679 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js @@ -0,0 +1,24 @@ +define([ + './text' +], function (Text) { + 'use strict'; + + return Text.extend({ + defaults: { + bodyTmpl: 'ui/grid/cells/select' + }, + + getLabel: function (value) { + var label = '', + options = this.options || []; + + options.some(function (item) { + label = item.label; + + return item.value == value; + }); + + return label; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/text.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/text.js new file mode 100644 index 0000000000000..bc6e3f8d0ec7a --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/text.js @@ -0,0 +1,78 @@ +define([ + 'Magento_Ui/js/lib/component/component' +], function (Component) { + 'use strict'; + + return Component.extend({ + defaults: { + headerTmpl: 'ui/grid/columns/text', + bodyTmpl: 'ui/grid/cells/text', + sortable: true, + sorting: false, + classes: { + 'asc': 'sort-arrow-asc', + 'desc': 'sort-arrow-desc' + }, + + listens: { + '<%= provider %>:params.sorting.field': 'onSortUpdate', + sorting: 'setSortClass push' + } + }, + + initObservable: function () { + this._super() + .observe('sorting sortClass'); + + return this; + }, + + sort: function (enabled) { + var direction; + + direction = enabled !== false ? + this.sorting() ? + this.toggleDirection() : + 'asc' : + false; + + this.sorting(direction); + }, + + push: function () { + if (!this.sorting()) { + return; + } + + this.source.set('params.sorting.field', this.index); + this.source.set('params.sorting.direction', this.sorting()); + }, + + toggleDirection: function () { + return this.sorting() === 'asc' ? + 'desc' : + 'asc'; + }, + + setSortClass: function () { + var direction = this.sorting(), + sortClass = this.classes[direction] || ''; + + this.sortClass(sortClass); + }, + + onSortUpdate: function (field) { + if (field !== this.index) { + this.sort(false); + } + }, + + getHeader: function () { + return this.headerTmpl; + }, + + getBody: function () { + return this.bodyTmpl; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js new file mode 100644 index 0000000000000..08679e5235338 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js @@ -0,0 +1,80 @@ +define([ + 'underscore', + 'Magento_Ui/js/lib/component/component' +], function (_, Component) { + 'use strict'; + + function extractPreview(elem) { + return { + label: elem.label, + preview: elem.delegate('getPreview'), + elem: elem + }; + } + + function hasData(elem) { + return elem.delegate('hasData'); + } + + function resetValue(elem) { + return elem.delegate('reset'); + } + + return Component.extend({ + defaults: { + template: 'ui/grid/filters/filters', + isVisible: false, + + listens: { + active: 'extractPreviews' + } + }, + + initObservable: function () { + this._super() + .observe('isVisible') + .observe({ + active: [], + previews: [] + }); + + return this; + }, + + toggleVisible: function () { + this.isVisible(!this.isVisible()); + }, + + close: function () { + this.isVisible(false); + }, + + apply: function () { + this.extractActive(); + }, + + reset: function (filter) { + filter ? + resetValue(filter) : + this.active.each(resetValue); + + this.apply(); + }, + + extractActive: function () { + var active = this.elems.filter(hasData); + + this.active(active); + + return this; + }, + + extractPreviews: function (elems) { + var previews = elems.map(extractPreview); + + this.previews(_.compact(previews)); + + return this; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/group.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/group.js new file mode 100644 index 0000000000000..1b902e26cb8f6 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/group.js @@ -0,0 +1,28 @@ +define([ + 'underscore', + 'Magento_Ui/js/form/components/group' +], function (_, Group) { + 'use strict'; + + return Group.extend({ + defaults: { + template: 'ui/grid/filters/elements/group' + }, + + hasData: function () { + return this.elems.some(function (elem) { + return elem.delegate('hasData'); + }); + }, + + getPreview: function () { + var previews = this.elems.map(function (elem) { + if (elem.hasData()) { + return elem.label + ': ' + elem.getPreview(); + } + }); + + return _.compact(previews).join(' '); + } + }); +}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/grid/listing.js b/app/code/Magento/Ui/view/base/web/js/grid/listing.js new file mode 100644 index 0000000000000..855532e6f8e31 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/listing.js @@ -0,0 +1 @@ +define([ 'Magento_Ui/js/lib/component/component' ], function (Component) { 'use strict'; return Component.extend({ defaults: { template: 'ui/grid/listing', rows: [], imports: { rows: '<%= provider %>:data.items' } }, getColspan: function () { return this.elems().length; }, hasData: function () { return !!this.rows().length; } }); }); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js new file mode 100644 index 0000000000000..08cbabce16c22 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js @@ -0,0 +1,161 @@ +define([ + 'underscore', + 'Magento_Ui/js/lib/component/component' +], function (_, Component) { + 'use strict'; + + return Component.extend({ + defaults: { + headerTmpl: 'ui/grid/columns/massactions', + bodyTmpl: 'ui/grid/cells/massactions', + template: 'ui/grid/actions', + menuVisible: false, + allSelected: false, + selected: [], + excluded: [], + columnActions: [{ + value: 'selectAll', + label: 'Select all' + }, { + value: 'deselectAll', + label: 'Deselect all' + }, { + value: 'selectPage', + label: 'Select all on this page' + }, { + value: 'deselectPage', + label: 'Deselect all on this page' + }], + + exports: { + totalSelected: '<%= provider %>:params.totalSelected' + }, + + imports: { + totalRecords: '<%= provider %>:data.totalRecords', + rows: '<%= provider %>:data.cms_grid.listing' + }, + + listens: { + selected: 'onSelectedChange' + } + }, + + initObservable: function () { + this._super() + .observe('menuVisible selected excluded allSelected'); + + return this; + }, + + /** + * Sets isAllSelected observable to true and selects all items on current page. + */ + selectAll: function () { + this.allSelected(true); + + this.clearExcluded() + .selectPage(); + }, + + /** + * Sets isAllSelected observable to false and deselects all items on current page. + */ + deselectAll: function () { + this.allSelected(false); + this.deselectPage(); + }, + + /** + * If isAllSelected is true, deselects all, else selects all + */ + toggleSelectAll: function () { + var isAllSelected = this.allSelected(); + + isAllSelected ? this.deselectAll() : this.selectAll(); + }, + + /** + * Selects all items on current page, adding their ids to selected observable array. + */ + selectPage: function () { + this.selected(this.getIds()); + }, + + /** + * Deselects all items on current page, emptying selected observable array + */ + deselectPage: function () { + this.selected.removeAll(); + }, + + /** + * Clears the array of not selected records. + * @returns {MassActions} Chainable. + */ + clearExcluded: function () { + this.excluded.removeAll(); + + return this; + }, + + /** + * Retrieve all id's from available records. + * @param {Boolean} [exclude] - Whether to exclude not selected ids' from result. + * @returns {Array} An array of ids'. + */ + getIds: function (exclude) { + var items = this.rows(), + ids = _.pluck(items, this.indexField); + + return exclude ? + _.difference(ids, this.excluded()) : + ids; + }, + + updateExcluded: function (selected) { + var excluded = this.excluded(), + fromPage = _.difference(this.getIds(), selected); + + excluded = _.union(excluded, fromPage); + excluded = _.difference(excluded, selected); + + this.excluded(excluded); + + return this; + }, + + countSelected: function () { + var total = this.totalRecords(), + excluded = this.excluded().length, + count = this.selected().length; + + if (this.allSelected()) { + count = total - excluded; + } + + this.totalSelected(count); + }, + + toggleMenu: function () { + this.menuVisible(!this.menuVisible()); + }, + + hideMenu: function () { + this.menuVisible(false); + }, + + getHeader: function () { + return this.headerTmpl; + }, + + getBody: function () { + return this.bodyTmpl; + }, + + onSelectedChange: function (selected) { + this.updateExcluded(selected) + .countSelected(); + } + }); +}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/grid/paging.js b/app/code/Magento/Ui/view/base/web/js/grid/paging.js new file mode 100644 index 0000000000000..06d32b6ab5e8f --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/paging.js @@ -0,0 +1,124 @@ +define([ + 'ko', + 'Magento_Ui/js/lib/component/component' +], function (ko, Component) { + 'use strict'; + + /** + * Returns closest existing page number to page argument + * @param {Number} value + * @param {Number} max + * @returns {Number} closest existing page number + */ + function getInRange(value, max) { + return Math.min(Math.max(1, value), max); + } + + return Component.extend({ + defaults: { + template: 'ui/grid/paging', + pageSize: 20, + current: 1, + + imports: { + pages: '<%= provider %>:data.pages', + totalSelected: '<%= provider %>:params.totalSelected', + totalRecords: '<%= provider %>:data.totalRecords' + }, + + exports: { + pageSize: '<%= provider %>:data.paging.pageSize', + current: '<%= provider %>:data.paging.current' + }, + + listens: { + 'pageSize current': 'reload' + } + }, + + initObservable: function () { + this._super(); + + this._current = ko.pureComputed({ + read: function () { + return +this.current(); + }, + + /** + * Validates page change according to user's input. + * Sets current observable to result of validation. + * Calls reload method then. + */ + write: function (value) { + var valid; + + value = +value; + valid = !isNaN(value) ? getInRange(value, this.pages()) : 1; + + this.current(valid); + this._current.notifySubscribers(value); + }, + + owner: this + }); + + return this; + }, + + /** + * Increments current observable prop by val and call reload method + * @param {String} val + */ + go: function (val) { + var current = this.current; + + current(current() + val); + }, + + /** + * Calls go method with 1 as agrument + */ + next: function () { + this.go(1); + }, + + /** + * Calls go method with -1 as agrument + */ + prev: function () { + this.go(-1); + }, + + /** + * Compares current and pages observables and returns boolean result + * @return {Boolean} is current equal to pages property + */ + isLast: function () { + return this.current() === this.pages(); + }, + + /** + * Compares current observable to 1 + * @return {Boolean} is current page first + */ + isFirst: function () { + return this.current() === 1; + }, + + reload: function () { + this.source.reload(); + }, + + /** + * Is being triggered on user interaction with page size select. + * Resets current page to first if needed. + */ + onSizeChange: function () { + var size = this.pageSize(); + + if (size * this.current() > this.totalRecords()) { + this.current(1); + } + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/provider.js b/app/code/Magento/Ui/view/base/web/js/grid/provider.js new file mode 100644 index 0000000000000..7eb38796750e2 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/provider.js @@ -0,0 +1,86 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'mage/utils', + 'Magento_Ui/js/lib/class', + 'Magento_Ui/js/lib/events' +], function (_, utils, Class, EventsBus) { + 'use strict'; + + var Provider = { + /** + * Initializes DataProvider instance. + * @param {Object} config - Settings to initialize object with. + */ + initialize: function (config) { + _.extend(this.data = {}, config); + }, + + /** + * If path specified, returnes this.data[path], else returns this.data + * @param {String} path + * @return {*} this.data[path] or simply this.data + */ + get: function (path) { + return utils.nested(this.data, path); + }, + + /** + * Sets value property to path and triggers update by path, passing result + * @param {String|*} path + * @param {String|*} value + * @return {Object} reference to instance + */ + set: function (path, value) { + var result = this._override.apply(this, arguments); + + value = result.value; + path = result.path; + + this.trigger('update', value); + + if (path) { + this.trigger('update:' + path, value); + } + + return this; + }, + + remove: function (path) { + utils.nestedRemove(this.data, path); + + return this; + }, + + /** + * Assignes props to this.data based on incoming params + * @param {String|*} path + * @param {*} value + * @return {Object} + */ + _override: function (path, value) { + if (arguments.length > 1) { + utils.nested(this.data, path, value); + } else { + value = path; + path = false; + + this.data = value; + } + + return { + path: path, + value: value + }; + }, + + reload: function () { + + } + }; + + return Class.extend(_.extend(Provider, EventsBus)); +}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/class.js b/app/code/Magento/Ui/view/base/web/js/lib/class.js index 1cc6e8955cf81..16729f002d566 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/class.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/class.js @@ -3,8 +3,10 @@ * See COPYING.txt for license details. */ define([ - 'underscore' -], function(_) { + 'underscore', + 'mage/utils', + 'jquery' +], function (_, utils, $) { 'use strict'; var superReg = /\b_super\b/; @@ -15,7 +17,7 @@ define([ * @param {Function} method - Method to be checked. * @returns {Boolean} */ - function hasSuper(method){ + function hasSuper(method) { return _.isFunction(method) && superReg.test(method); } @@ -27,13 +29,13 @@ define([ * @param {Function} method - Method to be wrapped. * @returns {Function} Wrapped method. */ - function superWrapper(parent, name, method){ - return function(){ - var superTmp = this._super, - args = arguments, + function superWrapper(parent, name, method) { + return function () { + var superTmp = this._super, + args = arguments, result; - this._super = function(){ + this._super = function () { var superArgs = arguments.length ? arguments : args; return parent[name].apply(this, superArgs); @@ -44,52 +46,49 @@ define([ this._super = superTmp; return result; - } + }; } /** * Analogue of Backbone.extend function. * - * @param {Object} extender - - * Object, that describes the prototype of + * @param {Object} extender - Object, that describes the prototype of * created constructor. - * @param {...Object} Multiple amount of mixins. * @returns {Function} New constructor. */ - function extend(extender){ - var parent = this, + function extend(extender) { + var parent = this, + defaults = extender.defaults || {}, parentProto = parent.prototype, - defaults = extender.defaults || {}, - child, - childProto, - mixins; + child; - child = function(){ - _.defaults(this, defaults); - - parent.apply(this, arguments); - }; + defaults = defaults || {}; + extender = extender || {}; delete extender.defaults; - childProto = child.prototype = Object.create(parentProto); + if (extender.hasOwnProperty('constructor')) { + child = extender.constructor; + } else { + child = function () { + parent.apply(this, arguments); + }; + } + + defaults = $.extend(true, {}, parent.defaults, defaults); - childProto.constructor = child; + child.prototype = Object.create(parentProto); + child.prototype.constructor = child; - _.each(extender, function(method, name){ - childProto[name] = hasSuper(method) ? + _.each(extender, function (method, name) { + child.prototype[name] = hasSuper(method) ? superWrapper(parentProto, name, method) : method; }); - mixins = _.toArray(arguments).slice(1); - - mixins.forEach(function(mixin){ - _.extend(childProto, mixin); - }); - child.__super__ = parentProto; - child.extend = extend; + child.extend = extend; + child.defaults = defaults; return child; } @@ -101,9 +100,10 @@ define([ this.initialize.apply(this, arguments); } - Class.prototype.initialize = function(){}; + Class.prototype.initialize = function () {}; Class.extend = extend; + Class.defaults = {}; return Class; }); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/component.js b/app/code/Magento/Ui/view/base/web/js/lib/component/component.js new file mode 100644 index 0000000000000..9b5f99cf7cb89 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/component.js @@ -0,0 +1,21 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + './core', + './links', + './manip', + './traversal', + 'Magento_Ui/js/lib/class', + 'Magento_Ui/js/lib/ko/initialize' +], function (_, core, links, manip, traversal, Class) { + 'use strict'; + + var extenders; + + extenders = _.extend({}, core, links, manip, traversal); + + return Class.extend(extenders); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/core.js b/app/code/Magento/Ui/view/base/web/js/lib/component/core.js new file mode 100644 index 0000000000000..15873d85be8d4 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/core.js @@ -0,0 +1,230 @@ +define([ + 'ko', + 'mage/utils', + 'underscore', + 'Magento_Ui/js/lib/registry/registry' +], function (ko, utils, _, registry) { + 'use strict'; + + function getOffsetFor(elems, offset) { + if (typeof offset === 'undefined') { + offset = -1; + } + + if (offset < 0) { + offset += elems.length + 1; + } + + return offset; + } + + /** + * Wrapper for ko.observable and ko.observableArray. + * Assignes one or another ko property to obj[key] + * @param {Object} obj - object to store property to + * @param {String} key - key + * @param {*} value - initial value of observable + */ + function observe(obj, key, value) { + var method = Array.isArray(value) ? 'observableArray' : 'observable'; + + if (!ko.isObservable(obj[key])) { + obj[key] = ko[method](value); + } else { + obj[key](value); + } + } + + return { + initialize: function (options, additional) { + _.bindAll(this, '_insert'); + + this.initConfig(options, additional) + .initProperties() + .initObservable() + .initUnique() + .initLinks() + .setListners(this.listens); + + return this; + }, + + initConfig: function (options, additional) { + var defaults = this.constructor.defaults, + config = _.extend({}, defaults, options, additional); + + config = utils.template(config, this); + + _.extend(this, config); + + return this; + }, + + /** + * Defines various properties. + * + * @returns {Component} Chainable. + */ + initProperties: function () { + _.extend(this, { + 'parentName': this.getPart(this.name, -2), + 'parentScope': this.getPart(this.dataScope, -2), + 'source': registry.get(this.provider), + 'renderer': registry.get('globalStorage').renderer, + 'containers': [], + 'regions': [], + '_elems': [] + }); + + return this; + }, + + /** + * Initializes observable properties. + * + * @returns {Component} Chainable. + */ + initObservable: function () { + this.observe({ + 'elems': [] + }); + + this.regions.forEach(function (region) { + this.observe(region, []); + }, this); + + return this; + }, + + initLinks: function () { + _.each({ + both: this.links, + exports: this.exports, + imports: this.imports + }, this.setLinks, this); + + return this; + }, + + /** + * Initializes listeners of the unique property. + * + * @returns {Component} Chainable. + */ + initUnique: function () { + var update = this.onUniqueUpdate.bind(this), + uniqueNs = this.uniqueNs; + + this.hasUnique = this.uniqueProp && uniqueNs; + + if (this.hasUnique) { + this.source.on('update:params.' + uniqueNs, update, this.name); + } + + return this; + }, + + /** + * Called when current element was injected to another component. + * + * @param {Object} parent - Instance of a 'parent' component. + * @returns {Component} Chainable. + */ + initContainer: function (parent) { + this.containers.push(parent); + + return this; + }, + + /** + * Called when another element was added to current component. + * + * @param {Object} elem - Instance of an element that was added. + * @returns {Component} Chainable. + */ + initElement: function (elem) { + elem.initContainer(this); + + return this; + }, + + /** + * Splits incoming string and returns its' part specified by offset. + * + * @param {String} parts + * @param {Number} [offset] + * @param {String} [delimiter=.] + * @returns {String} + */ + getPart: function (parts, offset, delimiter) { + delimiter = delimiter || '.'; + parts = parts.split(delimiter); + offset = getOffsetFor(parts, offset); + + parts.splice(offset, 1); + + return parts.join(delimiter) || ''; + }, + + /** + * Returns path to components' template. + * @returns {String} + */ + getTemplate: function () { + return this.template || 'ui/collection'; + }, + + /** + * Updates property specified in uniqueNs + * if components' unique property is set to 'true'. + * + * @returns {Component} Chainable. + */ + setUnique: function () { + var params = this.provider.params, + property = this.uniqueProp; + + if (this[property]()) { + params.set(this.uniqueNs, this.name); + } + + return this; + }, + + /** + * If 2 params passed, path is considered as key. + * Else, path is considered as object. + * Assignes props to this based on incoming params + * @param {Object|String} path + */ + observe: function (path) { + var type = typeof path; + + if (type === 'string') { + path = path.split(' '); + } + + if (Array.isArray(path)) { + path.forEach(function (key) { + observe(this, key, this[key]); + }, this); + } else if (type === 'object') { + _.each(path, function (value, key) { + observe(this, key, value); + }, this); + } + + return this; + }, + + /** + * Callback which fires when property under uniqueNs has changed. + */ + onUniqueUpdate: function (name) { + var active = name === this.name, + property = this.uniqueProp; + + this[property](active); + } + }; +}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/links.js b/app/code/Magento/Ui/view/base/web/js/lib/component/links.js new file mode 100644 index 0000000000000..2ec17a3030c84 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/links.js @@ -0,0 +1,121 @@ +define([ + 'ko', + 'underscore', + 'mage/utils', + 'Magento_Ui/js/lib/registry/registry' +], function (ko, _, utils, registry) { + 'use strict'; + + function extractData(str) { + var data = str.split(':'); + + return { + component: data[0], + prop: data[1] + }; + } + + function update(target, prop, value) { + if (_.isFunction(target[prop])) { + target[prop](value); + } else if (target.set) { + target.set(prop, value); + } else { + target[prop] = value; + } + } + + function imports(owner, target, ownerProp, targetProp, auto) { + var from = update.bind(null, owner, ownerProp), + value; + + value = target.get ? + target.get(targetProp) : + utils.nested(target, targetProp); + + if (ko.isObservable(value)) { + value.subscribe(from); + value = value(); + } else if (target.on) { + target.on('update:' + targetProp, from); + } + + if (auto) { + from(value); + } + } + + function exports(owner, target, ownerProp, targetProp, auto) { + var to = update.bind(null, target, targetProp); + + ownerProp = owner[ownerProp]; + + ownerProp.subscribe(to); + + if (auto) { + to(ownerProp()); + } + } + + function links(owner, target, ownerProp, direction) { + if (!ko.isObservable(owner[ownerProp])) { + owner.observe(ownerProp); + } + + target = extractData(target); + + registry.get(target.component, function (component) { + var args = [owner, component, ownerProp, target.prop, true]; + + switch (direction) { + case 'imports': + case 'both': + imports.apply(null, args); + break; + + case 'exports': + case 'both': + exports.apply(null, args); + break; + } + }); + } + + function listen(owner, target, callback) { + target = extractData(target); + + if (!target.prop) { + target.prop = target.component; + target.component = owner.name; + } + + registry.get(target.component, function (component) { + imports(owner, component, callback, target.prop); + }); + } + + return { + setLinks: function (data, direction) { + var owner = this; + + _.each(data, function (target, prop) { + links(owner, target, prop, direction); + }); + }, + + setListners: function (listeners) { + var owner = this; + + _.each(listeners, function (callbacks, sources) { + sources = sources.split(' '); + callbacks = callbacks.split(' '); + + sources.forEach(function (target) { + callbacks.forEach(function (callback) { + listen(owner, target, callback); + }); + }); + }); + } + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js b/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js new file mode 100644 index 0000000000000..a00e03769cbaa --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js @@ -0,0 +1,157 @@ +define([ + 'underscore', + 'mage/utils', + 'Magento_Ui/js/lib/registry/registry' +], function (_, utils, registry) { + 'use strict'; + + function getOffsetFor(elems, offset) { + if (typeof offset === 'undefined') { + offset = -1; + } + + if (offset < 0) { + offset += elems.length + 1; + } + + return offset; + } + + return { + /** + * Requests specified components to insert + * them into 'elems' array starting from provided position. + * + * @param {String} elem - Name of the component to insert. + * @param {Number} [offset=-1] - Position at which to insert elements. + * @returns {Component} Chainable. + */ + insert: function (elem, offset) { + var _elems = this._elems, + insert = this._insert; + + offset = getOffsetFor(_elems, offset); + + _elems.splice(offset, 0, false); + + registry.get(elem, function (elem) { + insert(elem, offset); + }); + + return this; + }, + + /** + * Removes specified element from the 'elems' array. + * + * @param {Object} elem - Element to be removed. + * @returns {Component} Chainable. + */ + remove: function (elem) { + utils.remove(this._elems, elem); + this._update(); + + return this; + }, + + /** + * Destroys current instance along with all of its' children. + */ + destroy: function () { + this._dropHandlers() + ._clearData() + ._clearRefs(); + }, + + /** + * Removes events listeners. + * @private + * + * @returns {Component} Chainable. + */ + _dropHandlers: function () { + this.off(); + + this.source.off(this.name); + + return this; + }, + + /** + * Clears all data associated with component. + * @private + * + * @returns {Component} Chainable. + */ + _clearData: function () { + var layout = this.renderer.layout; + + this.source.remove('data.' + this.dataScope); + this.source.remove('params.' + this.name); + + layout.clear(this.name); + + return this; + }, + + /** + * Removes all references to current instance and + * calls 'destroy' method on all of its' children. + * @private + * + * @returns {Component} Chainable. + */ + _clearRefs: function () { + registry.remove(this.name); + + this.containers.forEach(function (parent) { + parent.remove(this); + }, this); + + this.elems().forEach(function (child) { + child.destroy(); + }); + + return this; + }, + + /** + * Inserts provided component into 'elems' array at a specified position. + * @private + * + * @param {Object} elem - Element to insert. + * @param {Number} index - Position of the element. + */ + _insert: function (elem, index) { + this._elems[index] = elem; + + this._update() + .initElement(elem); + }, + + /** + * Synchronizes multiple elements arrays with a core '_elems' container. + * Performs elemets grouping by theirs 'displayArea' property. + * @private + * + * @returns {Component} Chainable. + */ + _update: function () { + var _elems = _.compact(this._elems), + grouped = _.groupBy(_elems, 'displayArea'), + group; + + this.regions.forEach(function (region) { + group = grouped[region]; + + if (group) { + this[region](group); + } + }, this); + + this.elems(_elems); + + return this; + } + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/traversal.js b/app/code/Magento/Ui/view/base/web/js/lib/component/traversal.js new file mode 100644 index 0000000000000..e73a3cb7e7928 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/traversal.js @@ -0,0 +1,72 @@ +define([ + 'underscore', + 'Magento_Ui/js/lib/events' +], function (_, EventsBus) { + 'use strict'; + + return _.extend({}, EventsBus, { + /** + * Tries to call specified method of a current component, + * otherwise delegates attempt to its' children. + * + * @param {String} target - Name of the method. + * @param [...] Arguments that will be passed to method. + * @returns {*} Result of the method calls. + */ + delegate: function (target) { + var args = _.toArray(arguments); + + target = this[target]; + + if (_.isFunction(target)) { + return target.apply(this, args.slice(1)); + } + + return this._delegate(args); + }, + + /** + * Calls 'delegate' method of all of it's children components. + * @private + * + * @param {Array} args - An array of arguments to pass to the next delegation call. + * @returns {Array} An array of delegation resutls. + */ + _delegate: function (args) { + var result; + + result = this.elems.map(function (elem) { + return elem.delegate.apply(elem, args); + }); + + return _.flatten(result); + }, + + /** + * Overrides 'EventsBus.trigger' method to implement events bubbling. + * + * @param {String} name - Name of the event. + * @param [...] Any number of arguments that should be to the events' handler. + * @returns {Boolean} False if event bubbling was canceled. + */ + trigger: function () { + var args = _.toArray(arguments), + bubble = EventsBus.trigger.apply(this, args), + result; + + if (!bubble) { + return false; + } + + this.containers.forEach(function (parent) { + result = parent.trigger.apply(parent, args); + + if (result === false) { + bubble = false; + } + }); + + return !!bubble; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/events.js b/app/code/Magento/Ui/view/base/web/js/lib/events.js index 00cb428521225..7a8be3f5ad51a 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/events.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/events.js @@ -4,7 +4,7 @@ */ define([ 'underscore' -], function(_) { +], function (_) { 'use strict'; function addHandler(events, ns, callback, name) { @@ -20,19 +20,19 @@ define([ return name ? events[name] : events; } - function keepHandler(ns, handler){ - if(!ns){ + function keepHandler(ns, handler) { + if (!ns) { return false; } return handler.ns !== ns; } - function trigger(handlers, args){ - var bubble = true, + function trigger(handlers, args) { + var bubble = true, callback; - handlers.forEach(function(handler){ + handlers.forEach(function (handler) { callback = handler.callback; if (callback.apply(null, args) === false) { @@ -46,10 +46,9 @@ define([ return { /** * Calls callback when name event is triggered. - * @param {String} events - * @param {Function} callback - * @param {Function} ns - * @return {Object} reference to this + * @param {String} events + * @param {Function} callback + * @return {Object} reference to this */ on: function (events, callback, ns) { var storage = getEvents(this), @@ -69,20 +68,20 @@ define([ }, /** - * Removed callback from listening to target events + * Removed callback from listening to target event * @param {String} ns * @return {Object} reference to this */ off: function (ns) { var storage = getEvents(this), - filter = keepHandler.bind(null, ns); + filter = keepHandler.bind(null, ns); _.each(storage, function (handlers, name) { handlers = handlers.filter(filter); handlers.length ? - (storage[name] = handlers) : - (delete storage[name]); + storage[name] = handlers : + delete storage[name]; }); return this; @@ -95,9 +94,13 @@ define([ */ trigger: function (name) { var handlers = getEvents(this, name), - args = _.toArray(arguments).slice(1); + args = _.toArray(arguments).slice(1); + + if (_.isUndefined(handlers)) { + return true; + } - return _.isUndefined(handlers) || trigger(handlers, args); + return trigger(handlers, args); } }; }); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/loader.js b/app/code/Magento/Ui/view/base/web/js/lib/loader.js index 9949551220945..689882ebd7534 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/loader.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/loader.js @@ -5,13 +5,15 @@ define([ 'underscore', 'jquery' -], function (_, $) { +], function(_, $) { 'use strict'; + + var storage = window.localStorage; /** * Formats path of type "path.to.template" to RequireJS compatible * @param {String} path - * @returns {String} - formatted template path + * @return {String} - formatted template path */ function formatTemplatePath(path) { return 'text!' + path.replace(/^([^\/]+)/g, '$1/template') + '.html'; @@ -20,33 +22,33 @@ define([ /** * Waits for all items in passed array of promises to resolve. * @param {Array} promises - array of promises - * @returns {Deferred} - promise of promises to resolve + * @return {Deferred} - promise of promises to resolve */ function waitFor(promises) { - return $.when.apply($, promises); + return $.when.apply(this, promises); } /** * Removes license from incoming template - * + * * @param {String} tmpl - * @returns {String} - template without license + * @return {String} - template without license */ - function removeLicense(tmpl) { + function removeLicense(tmpl){ var regEx = //; - return tmpl.replace(regEx, function (match) { + return tmpl.replace(regEx, function(match){ return ~match.indexOf('/**') ? '' : match; }); } /** * Loads template by path, resolves promise with it if defined - * + * * @param {String} path - * @params {Deferred} promise + * @param {Deferred} promise */ - function load(path, promise) { + function load(path, promise){ require([path], function (template) { template = removeLicense(template); @@ -59,9 +61,9 @@ define([ * Loops over arguments and loads template for each. * @return {Deferred} - promise of templates to be loaded */ - loadTemplate: function () { - var isLoaded = $.Deferred(), - templates = _.toArray(arguments); + loadTemplate: function() { + var isLoaded = $.Deferred(), + templates = _.toArray(arguments); waitFor(templates.map(this._loadTemplate)).done(function () { isLoaded.resolve.apply(isLoaded, arguments); @@ -72,17 +74,17 @@ define([ /** * Loads template by it's name - * + * * @param {String} name * @return {Deferred} */ _loadTemplate: function (name) { - var isLoaded = $.Deferred(), - path = formatTemplatePath(name); + var isLoaded = $.Deferred(), + path = formatTemplatePath(name); load(path, isLoaded); return isLoaded.promise(); } - }; -}); + } +}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/actions.html b/app/code/Magento/Ui/view/base/web/templates/grid/actions.html new file mode 100644 index 0000000000000..eab4802c6e276 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/actions.html @@ -0,0 +1,13 @@ +
+ + + +
\ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/massactions.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/massactions.html new file mode 100644 index 0000000000000..ef2e70b47b6a2 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/massactions.html @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/select.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/select.html new file mode 100644 index 0000000000000..300a4fdbaf152 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/select.html @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html new file mode 100644 index 0000000000000..7a4530515763a --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/columns/massactions.html b/app/code/Magento/Ui/view/base/web/templates/grid/columns/massactions.html new file mode 100644 index 0000000000000..56627907635a9 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/columns/massactions.html @@ -0,0 +1,17 @@ + +
+ + +
    + +
  • + +
  • + +
+
+ \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/columns/text.html b/app/code/Magento/Ui/view/base/web/templates/grid/columns/text.html new file mode 100644 index 0000000000000..8a6eb7fd2a768 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/columns/text.html @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/date.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/date.html new file mode 100644 index 0000000000000..69bd8a45216ce --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/date.html @@ -0,0 +1,17 @@ +
+ +
+ +
+
diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/group.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/group.html new file mode 100644 index 0000000000000..dab3fc43ba4b0 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/group.html @@ -0,0 +1,12 @@ +
+ + +
+
+
+ + + +
+
+
\ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/input.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/input.html new file mode 100644 index 0000000000000..525982082b27a --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/input.html @@ -0,0 +1,23 @@ + +
+ +
+ +
+
diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/select.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/select.html new file mode 100644 index 0000000000000..490b84670a890 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/select.html @@ -0,0 +1,29 @@ + +
+ +
+ + per page. + + + + + Previous page + + + + of + + + + Next page + + +
\ No newline at end of file diff --git a/app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_edit.xml b/app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_edit.xml new file mode 100644 index 0000000000000..c2caa32651b37 --- /dev/null +++ b/app/code/Magento/Wishlist/view/adminhtml/layout/customer_index_edit.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Data/etc/argument/types.xsd b/lib/internal/Magento/Framework/Data/etc/argument/types.xsd index 5b6b6cedf73ce..065e8de3d1802 100644 --- a/lib/internal/Magento/Framework/Data/etc/argument/types.xsd +++ b/lib/internal/Magento/Framework/Data/etc/argument/types.xsd @@ -46,6 +46,21 @@ + + + + + + + + + + + + + + + diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Argument/Interpreter/ConfigurableObject.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Argument/Interpreter/ConfigurableObject.php new file mode 100644 index 0000000000000..1b92505e6028a --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Argument/Interpreter/ConfigurableObject.php @@ -0,0 +1,60 @@ +objectManager = $objectManager; + $this->argumentInterpreter = $argumentInterpreter; + } + + /** + * {@inheritdoc} + * @return object + * @throws \InvalidArgumentException + * @throws \UnexpectedValueException + */ + public function evaluate(array $data) + { + if (!isset($data['argument'])) { + throw new \InvalidArgumentException('Node "argument" required for this type.'); + } + foreach ($data['argument'] as $name => $argument) { + $arguments[$name] = $this->argumentInterpreter->evaluate($argument); + } + if (!isset($arguments['class'])) { + throw new \InvalidArgumentException('Node "argument" with name "class" is required for this type.'); + } + $className = $arguments['class']; + unset($arguments['class']); + + return $this->objectManager->create($className, $arguments); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ArrayObjectFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ArrayObjectFactory.php new file mode 100644 index 0000000000000..a9c933d8b4cd0 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ArrayObjectFactory.php @@ -0,0 +1,21 @@ +argumentParser = $argumentParser; + } + + /** + * Transform Xml to array + * + * @param \DOMNode $node + * @return array|string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function toArray(\DOMNode $node) + { + $result = []; + $attributes = []; + // Collect data from attributes + if ($node->hasAttributes()) { + foreach ($node->attributes as $attribute) { + $attributes[$attribute->name] = $attribute->value; + } + } + switch ($node->nodeType) { + case XML_TEXT_NODE: + case XML_COMMENT_NODE: + case XML_CDATA_SECTION_NODE: + break; + default: + if ($node->localName === static::ARGUMENT_KEY) { + if (!isset($attributes[static::NAME_ATTRIBUTE_KEY])) { + throw new \InvalidArgumentException( + 'Attribute "' . static::NAME_ATTRIBUTE_KEY . '" is absent in the attributes node.' + ); + } + $result[ $attributes[static::NAME_ATTRIBUTE_KEY] ] = $this->argumentParser->parse($node); + } else { + $arguments = []; + for ($i = 0, $iLength = $node->childNodes->length; $i < $iLength; ++$i) { + $itemNode = $node->childNodes->item($i); + if (empty($itemNode->localName)) { + continue; + } + if ($itemNode->nodeName === static::ARGUMENT_KEY) { + $arguments += $this->toArray($itemNode); + } else { + $result[$itemNode->localName][] = $this->toArray($itemNode); + } + } + if (!empty($arguments)) { + $result[static::DATA_ARGUMENTS_KEY] = $arguments; + } + if (!empty($attributes)) { + $result[static::DATA_ATTRIBUTES_KEY] = $attributes; + } + } + break; + } + + return $result; + } + + /** + * Convert configuration + * + * @param \DOMDocument|null $source + * @return array + */ + public function convert($source) + { + if ($source === null) { + return []; + } + + return $this->toArray($source); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMerger.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMerger.php new file mode 100644 index 0000000000000..2bbac74b2cdcf --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMerger.php @@ -0,0 +1,450 @@ +schemaFilePath = $directoryReader->getModuleDir($schemaFileType, $schemaFileModule) . '/' + . trim($schemaFileName, '/'); + $this->isMergeSimpleXMLElement = $isMergeSimpleXMLElement; + $this->contextXPath = $contextXPath; + $this->idAttributes = $idAttributes; + } + + /** + * Is id attribute + * + * @param string $attributeName + * @return bool + */ + protected function isIdAttribute($attributeName) + { + return in_array($attributeName, $this->idAttributes); + } + + /** + * Is merge context + * + * @param string $xPath + * @return bool + */ + protected function isMergeContext($xPath) + { + foreach ($this->contextXPath as $context) { + if (strpos($xPath, $context) === 0) { + return true; + } + } + return false; + } + + /** + * Is context XPath + * + * @param array $xPath + * @return bool + */ + protected function isContextXPath(array $xPath) + { + return count(array_intersect($xPath, $this->contextXPath)) === count($xPath); + } + + /** + * Merges attributes of the merge node to the base node + * + * @param \DOMElement $baseNode + * @param \DOMNode $mergeNode + * @return void + */ + protected function mergeAttributes(\DOMElement $baseNode, \DOMNode $mergeNode) + { + foreach ($mergeNode->attributes as $name => $attribute) { + $baseNode->setAttribute($name, $attribute->value); + } + } + + /** + * Create XPath + * + * @param \DOMNode $node + * @return string + */ + protected function createXPath(\DOMNode $node) + { + $parentXPath = ''; + $currentXPath = $node->getNodePath(); + if ($node->parentNode !== null && !$node->isSameNode($node->parentNode)) { + $parentXPath = $this->createXPath($node->parentNode); + $pathParts = explode('/', $currentXPath); + $currentXPath = '/' . end($pathParts); + } + $attributesXPath = ''; + if ($node->hasAttributes()) { + $attributes = []; + foreach ($node->attributes as $name => $attribute) { + if ($this->isIdAttribute($name)) { + $attributes[] = sprintf('@%s="%s"', $name, $attribute->value); + break; + } + } + if (!empty($attributes)) { + if (substr($currentXPath, -1) === ']') { + $currentXPath = substr($currentXPath, 0, strrpos($currentXPath, '[')); + } + $attributesXPath = '[' . implode(' and ', $attributes) . ']'; + } + } + return '/' . trim($parentXPath . $currentXPath . $attributesXPath, '/'); + } + + /** + * Merge nested xml nodes + * + * @param \DOMXPath $rootDomXPath + * @param \DOMNodeList $insertedNodes + * @param \DOMNode $contextNode + * @return void + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function nestedMerge(\DOMXPath $rootDomXPath, \DOMNodeList $insertedNodes, \DOMNode $contextNode) + { + for ($i = 0, $iLength = $insertedNodes->length; $i < $iLength; ++$i) { + $insertedItem = $insertedNodes->item($i); + switch ($insertedItem->nodeType) { + case XML_TEXT_NODE: + case XML_COMMENT_NODE: + case XML_CDATA_SECTION_NODE: + if (trim($insertedItem->textContent) !== '') { + $this->insertBefore($contextNode, $insertedItem); + } + break; + default: + $insertedXPath = $this->createXPath($insertedItem); + $rootMatchList = $rootDomXPath->query($insertedXPath, $contextNode); + $jLength = $rootMatchList->length; + if ($jLength > 0) { + for ($j = 0; $j < $jLength; ++$j) { + $rootItem = $rootMatchList->item($j); + $rootItemXPath = $this->createXPath($rootItem); + if ($this->isMergeContext($insertedXPath)) { + if ($this->isTextNode($insertedItem) && $this->isTextNode($rootItem)) { + $rootItem->nodeValue = $insertedItem->nodeValue; + } else if (!$this->isContextXPath([$rootItemXPath, $insertedXPath]) + && !$this->hasIdAttribute($rootItem) + && !$this->hasIdAttribute($insertedItem) + ) { + if ($this->isMergeSimpleXMLElement) { + $this->nestedMerge($rootDomXPath, $insertedItem->childNodes, $rootItem); + $this->mergeAttributes($rootItem, $insertedItem); + } else { + $this->appendChild($contextNode, $insertedItem); + } + } else { + $this->nestedMerge($rootDomXPath, $insertedItem->childNodes, $rootItem); + $this->mergeAttributes($rootItem, $insertedItem); + } + } else { + $this->appendChild($contextNode, $insertedItem); + } + } + } else { + $this->appendChild($contextNode, $insertedItem); + } + break; + } + } + } + + /** + * Append child node + * + * @param \DOMNode $parentNode + * @param \DOMNode $childNode + * @return void + */ + protected function appendChild(\DOMNode $parentNode, \DOMNode $childNode) + { + $importNode = $this->getDom()->importNode($childNode, true); + $parentNode->appendChild($importNode); + } + + /** + * Insert before + * + * @param \DOMNode $parentNode + * @param \DOMNode $childNode + * @return void + */ + protected function insertBefore(\DOMNode $parentNode, \DOMNode $childNode) + { + $importNode = $this->getDom()->importNode($childNode, true); + $parentNode->insertBefore($importNode); + } + + /** + * Check if the node content is text + * + * @param \DOMNode $node + * @return bool + */ + protected function isTextNode(\DOMNode $node) + { + return $node->childNodes->length == 1 && $node->childNodes->item(0) instanceof \DOMText; + } + + /** + * Has ID attribute + * + * @param \DOMNode $node + * @return bool + */ + protected function hasIdAttribute(\DOMNode $node) + { + if (!$node->hasAttributes()) { + return false; + } + + foreach ($node->attributes as $name => $attribute) { + if (in_array($name, $this->idAttributes)) { + return true; + } + } + + return false; + } + + /** + * Recursive merging of the \DOMElement into the original document + * + * Algorithm: + * 1. Find the same node in original document + * 2. Extend and override original document node attributes and scalar value if found + * 3. Append new node if original document doesn't have the same node + * + * @param \DOMElement $node + * @throws \Magento\Framework\Exception + * @return void + */ + public function mergeNode(\DOMElement $node) + { + $parentDoom = $this->getDom(); + $this->nestedMerge(new \DOMXPath($parentDoom), $node->childNodes, $parentDoom->documentElement); + } + + /** + * Create DOM document based on $xml parameter + * + * @param string $xml + * @return \DOMDocument + * @throws \Magento\Framework\Config\Dom\ValidationException + */ + public function createDomDocument($xml) + { + $domDocument = new \DOMDocument(); + $domDocument->loadXML($xml); + if ($this->schemaFilePath) { + $errors = $this->validateDomDocument($domDocument); + if (count($errors)) { + throw new \Magento\Framework\Config\Dom\ValidationException(implode("\n", $errors)); + } + } + + return $domDocument; + } + + /** + * Validate dom document + * + * @param \DOMDocument $domDocument + * @param string|null $schemaFilePath + * @return array of errors + * @throws \Exception + */ + protected function validateDomDocument(\DOMDocument $domDocument, $schemaFilePath = null) + { + $schemaFilePath = $schemaFilePath !== null ? $schemaFilePath : $this->schemaFilePath; + libxml_use_internal_errors(true); + try { + $result = $domDocument->schemaValidate($schemaFilePath); + $errors = []; + if (!$result) { + $validationErrors = libxml_get_errors(); + if (count($validationErrors)) { + foreach ($validationErrors as $error) { + $errors[] = $this->renderErrorMessage($error, static::ERROR_FORMAT_DEFAULT); + } + } else { + $errors[] = 'Unknown validation error'; + } + } + } catch (\Exception $exception) { + libxml_use_internal_errors(false); + throw $exception; + } + libxml_use_internal_errors(false); + + return $errors; + } + + /** + * Render error message string by replacing placeholders '%field%' with properties of \LibXMLError + * + * @param \LibXMLError $errorInfo + * @return string + * @throws \InvalidArgumentException + */ + protected function renderErrorMessage(\LibXMLError $errorInfo) + { + $result = static::ERROR_FORMAT_DEFAULT; + foreach ($errorInfo as $field => $value) { + $result = str_replace('%' . $field . '%', trim((string)$value), $result); + } + if (strpos($result, '%') !== false) { + throw new \InvalidArgumentException( + 'Error format "' . static::ERROR_FORMAT_DEFAULT . '" contains unsupported placeholders.' + ); + } + + return $result; + } + + /** + * Merge string $xml into DOM document + * + * @param string $xml + * @return void + */ + public function merge($xml) + { + if (!isset($this->domDocument)) { + $this->domDocument = $this->createDomDocument($xml); + } else { + $this->mergeNode($this->createDomDocument($xml)->documentElement); + } + } + + /** + * Get DOM document + * + * @return \DOMDocument + * @throws \Exception + */ + public function getDom() + { + if (!isset($this->domDocument)) { + throw new \Exception('Object DOMDocument should be created.'); + } + + return $this->domDocument; + } + + /** + * Set DOM document + * + * @param \DOMDocument $domDocument + * @return void + */ + public function setDom(\DOMDocument $domDocument) + { + $this->domDocument = $domDocument; + } + + /** + * Unset DOM document + * + * @return void + */ + public function unsetDom() + { + unset($this->domDocument); + } + + /** + * Validate self contents towards to specified schema + * + * @param string|null $schemaFilePath + * @return array + */ + public function validate($schemaFilePath = null) + { + return $this->validateDomDocument($this->getDom(), $schemaFilePath); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMergerInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMergerInterface.php new file mode 100644 index 0000000000000..b99af3f190c80 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/DomMergerInterface.php @@ -0,0 +1,64 @@ +searchPattern = $searchPattern; + $this->collectorAggregated = $collectorAggregated; + $this->design = $design; + $this->filesystem = $filesystem; + } + + /** + * Collect files + * + * @param string|null $searchPattern + * @return array + * @throws \Exception + */ + public function collectFiles($searchPattern = null) + { + $result = []; + if ($searchPattern === null) { + $searchPattern = $this->searchPattern; + } + if ($searchPattern === null) { + throw new \Exception('Search pattern cannot be empty.'); + } + $files = $this->collectorAggregated->getFiles($this->design->getDesignTheme(), $searchPattern); + $fileReader = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); + foreach ($files as $file) { + $filePath = $fileReader->getRelativePath($file->getFilename()); + $result[sprintf('%x', crc32($filePath))] = $fileReader->readFile($filePath); + } + + return $result; + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollectorFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollectorFactory.php new file mode 100644 index 0000000000000..609156211828e --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollectorFactory.php @@ -0,0 +1,42 @@ +objectManager = $objectManager; + } + + /** + * Create config reader + * + * @param array $arguments + * @return AggregatedFileCollector + */ + public function create(array $arguments = []) + { + return $this->objectManager->create(static::INSTANCE_NAME, $arguments); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollectorInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollectorInterface.php new file mode 100644 index 0000000000000..c2f74254bed42 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollectorInterface.php @@ -0,0 +1,20 @@ +componentConfigProvider = $componentConfigProvider; + $this->domMerger = $domMerger; + $this->readerFactory = $readerFactory; + $this->arrayObjectFactory = $arrayObjectFactory; + $this->componentsData = $this->arrayObjectFactory->create(); + $this->aggregatedFileCollectorFactory = $aggregatedFileCollectorFactory; + $this->cache = $cache; + } + + /** + * Get component data + * + * @param string $name + * @return array + */ + public function getData($name) + { + return (array) $this->componentsData->offsetGet($name); + } + + /** + * Has component data + * + * @param string $name + * @return bool + */ + protected function hasData($name) + { + return $this->componentsData->offsetExists($name); + } + + /** + * Prepare the initialization data of UI components + * + * @param string $name + * @return ManagerInterface + * @throws Exception + */ + public function prepareData($name) + { + if ($this->hasData($name)) { + throw new Exception('This component "' . $name . '" is already initialized.'); + } + $this->componentsPool = $this->arrayObjectFactory->create(); + + $cacheID = static::CACHE_ID . '_' . $name; + $cachedPool = $this->cache->load($cacheID); + if ($cachedPool === false) { + $this->prepare($name); + $this->cache->save($this->componentsPool->serialize(), $cacheID); + } else { + $this->componentsPool->unserialize($cachedPool); + } + $this->componentsData->offsetSet($name, $this->componentsPool); + + return $this; + } + + /** + * To create the raw data components + * + * @param string $component + * @return array + */ + public function createRawComponentData($component) + { + $componentData = $this->componentConfigProvider->getComponentData($component); + $componentData[Converter::DATA_ATTRIBUTES_KEY] = isset($componentData[Converter::DATA_ATTRIBUTES_KEY]) + ? $componentData[Converter::DATA_ATTRIBUTES_KEY] + : []; + $componentData[Converter::DATA_ARGUMENTS_KEY] = isset($componentData[Converter::DATA_ARGUMENTS_KEY]) + ? $componentData[Converter::DATA_ARGUMENTS_KEY] + : []; + + return [ + ManagerInterface::COMPONENT_ATTRIBUTES_KEY => $componentData[Converter::DATA_ATTRIBUTES_KEY], + ManagerInterface::COMPONENT_ARGUMENTS_KEY => $componentData[Converter::DATA_ARGUMENTS_KEY], + ]; + } + + /** + * Get UIReader and collect base files configuration + * + * @param $name + * @return UiReaderInterface + */ + public function getReader($name) + { + if (!isset($this->uiReader[$name])) { + $this->domMerger->unsetDom(); + $this->uiReader[$name] = $this->readerFactory->create( + [ + 'fileCollector' => $this->aggregatedFileCollectorFactory->create( + ['searchPattern' => sprintf(ManagerInterface::SEARCH_PATTERN, $name)] + ), + 'domMerger' => $this->domMerger + ] + ); + } + + return $this->uiReader[$name]; + } + + /** + * Initialize the new component data + * + * @param string $name + * @return void + */ + protected function prepare($name) + { + $componentData = $this->getReader($name)->read(); + $componentsPool = reset($componentData); + $componentsPool = reset($componentsPool); + $componentsPool[Converter::DATA_ATTRIBUTES_KEY] = array_merge( + ['name' => $name], + $componentsPool[Converter::DATA_ATTRIBUTES_KEY] + ); + $components = $this->createDataForComponent(key($componentData), [$componentsPool]); + $this->addComponentIntoPool($name, reset($components)); + } + + /** + * Create data for component instance + * + * @param string $name + * @param array $componentsPool + * @return array + */ + protected function createDataForComponent($name, array $componentsPool) + { + $createdComponents = []; + $rootComponent = $this->createRawComponentData($name); + foreach ($componentsPool as $key => $component) { + $resultConfiguration = [ManagerInterface::CHILDREN_KEY => []]; + $instanceName = $this->createName($component, $key, $name); + $resultConfiguration[ManagerInterface::COMPONENT_ARGUMENTS_KEY] = $this->mergeArguments( + $component, + $rootComponent + ); + unset($component[Converter::DATA_ARGUMENTS_KEY]); + $resultConfiguration[ManagerInterface::COMPONENT_ATTRIBUTES_KEY] = $this->mergeAttributes( + $component, + $rootComponent + ); + unset($component[Converter::DATA_ATTRIBUTES_KEY]); + // Create inner components + foreach ($component as $subComponentName => $subComponent) { + $resultConfiguration[ManagerInterface::CHILDREN_KEY] = array_merge( + $resultConfiguration[ManagerInterface::CHILDREN_KEY], + $this->createDataForComponent($subComponentName, $subComponent) + ); + } + $createdComponents[$instanceName] = $resultConfiguration; + } + + return $createdComponents; + } + + /** + * Add a component into pool + * + * @param string $instanceName + * @param $configuration + * @return void + */ + protected function addComponentIntoPool($instanceName, array $configuration) + { + $this->componentsPool->offsetSet($instanceName, $configuration); + } + + /** + * Merge component arguments + * + * @param array $componentData + * @param array $rootComponentData + * @return array + */ + protected function mergeArguments(array $componentData, array $rootComponentData) + { + $baseArguments = isset($rootComponentData[ManagerInterface::COMPONENT_ARGUMENTS_KEY]) + ? $rootComponentData[ManagerInterface::COMPONENT_ARGUMENTS_KEY] + : []; + $componentArguments = isset($componentData[Converter::DATA_ARGUMENTS_KEY]) + ? $componentData[Converter::DATA_ARGUMENTS_KEY] + : []; + + return array_replace_recursive($baseArguments, $componentArguments); + } + + /** + * Merge component attributes + * + * @param array $componentData + * @param array $rootComponentData + * @return array + */ + protected function mergeAttributes(array $componentData, array $rootComponentData) + { + $baseAttributes = isset($rootComponentData[ManagerInterface::COMPONENT_ATTRIBUTES_KEY]) + ? $rootComponentData[ManagerInterface::COMPONENT_ATTRIBUTES_KEY] + : []; + $componentAttributes = isset($componentData[Converter::DATA_ATTRIBUTES_KEY]) + ? $componentData[Converter::DATA_ATTRIBUTES_KEY] + : []; + unset($componentAttributes['noNamespaceSchemaLocation']); + + return array_replace_recursive($baseAttributes, $componentAttributes); + } + + /** + * Create name component instance + * + * @param array $componentData + * @param string|int $key + * @param string $componentName + * @return string + */ + protected function createName(array $componentData, $key, $componentName) + { + return isset($componentData[Converter::DATA_ATTRIBUTES_KEY][Converter::NAME_ATTRIBUTE_KEY]) + ? $componentData[Converter::DATA_ATTRIBUTES_KEY][Converter::NAME_ATTRIBUTE_KEY] + : sprintf(ManagerInterface::ANONYMOUS_TEMPLATE, $componentName, $key); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php new file mode 100644 index 0000000000000..908576f8f2239 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php @@ -0,0 +1,77 @@ +cache = $cache; + $this->componentData = $arrayObjectFactory->create(); + $cachedData = $this->cache->load(static::CACHE_ID); + if ($cachedData === false) { + $data = $uiReader->read(); + $this->cache->save(serialize($data), static::CACHE_ID); + } else { + $data = unserialize($cachedData); + } + $this->prepareComponentData($data); + } + + /** + * Get component data + * + * @param string $name + * @return array + */ + public function getComponentData($name) + { + return (array) $this->componentData->offsetGet($name); + } + + /** + * Set component data + * + * @param string $name + * @param array $data + * @return void + */ + public function setComponentData($name, array $data) + { + $this->componentData->offsetSet($name, $data); + } + + /** + * Prepare configuration data for the component + * + * @param array $componentsData + * @return void + */ + protected function prepareComponentData(array $componentsData) + { + $componentsData = reset($componentsData[static::COMPONENTS_KEY]); + unset($componentsData[Converter::DATA_ATTRIBUTES_KEY]); + foreach ($componentsData as $name => $data) { + $this->setComponentData($name, reset($data)); + } + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php new file mode 100644 index 0000000000000..1c47f39a1a993 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Provider/Template.php @@ -0,0 +1,111 @@ +aggregatedFileCollector = $aggregatedFileCollector; + $this->domMerger = $domMerger; + $this->cache = $cache; + $this->readerFactory = $readerFactory; + $this->aggregatedFileCollectorFactory = $aggregatedFileCollectorFactory; + + $cachedTemplates = $this->cache->load(static::CACHE_ID); + $this->cachedTemplates = $cachedTemplates === false ? [] : unserialize($cachedTemplates); + } + + /** + * Get template content + * + * @param string $template + * @return string + * @throws \Exception + */ + public function getTemplate($template) + { + $hash = sprintf('%x', crc32($template)); + if (isset($this->cachedTemplates[$hash])) { + return $this->cachedTemplates[$hash]; + } + + $this->cachedTemplates[$hash] = $this->readerFactory->create( + [ + 'fileCollector' => $this->aggregatedFileCollectorFactory->create(['searchPattern' => $template]), + 'domMerger' => $this->domMerger + ] + )->getContent(); + $this->cache->save(serialize($this->cachedTemplates), static::CACHE_ID); + + return $this->cachedTemplates[$hash]; + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Reader.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Reader.php new file mode 100644 index 0000000000000..0508cef4afc38 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/Reader.php @@ -0,0 +1,116 @@ +converter = $converter; + $this->domMerger = $domMerger; + $this->readFiles($fileCollector->collectFiles()); + } + + /** + * Read configuration files + * + * @param array $fileList + * @return array + * @throws \Magento\Framework\Exception + */ + protected function readFiles(array $fileList) + { + foreach ($fileList as $fileContent) { + $this->domMerger->merge($fileContent); + } + } + + /** + * Add xml content in the merged file + * + * @param string $xmlContent + * @return void + */ + public function addXMLContent($xmlContent) + { + $this->domMerger->merge($xmlContent); + } + + /** + * Add DOM node into DOM document + * + * @param \DOMNode $node + * @return void + */ + public function addNode(\DOMNode $node) + { + $this->domMerger->mergeNode($node); + } + + /** + * Load configuration scope + * + * @param string|null $scope + * @return array + */ + public function read($scope = null) + { + return $this->converter->convert($this->domMerger->getDom()); + } + + /** + * Get content from the merged files + * + * @return string + */ + public function getContent() + { + return $this->domMerger->getDom()->saveXML(); + } + + /** + * Get DOM document + * + * @return \DOMDocument + */ + public function getDOMDocument() + { + return $this->domMerger->getDom(); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ReaderFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ReaderFactory.php new file mode 100644 index 0000000000000..3efb30cb1141d --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ReaderFactory.php @@ -0,0 +1,42 @@ +objectManager = $objectManager; + } + + /** + * Create config reader + * + * @param array $arguments + * @return UiReaderInterface + */ + public function create(array $arguments = []) + { + return $this->objectManager->create(static::INSTANCE_NAME, $arguments); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/UiReaderInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/UiReaderInterface.php new file mode 100644 index 0000000000000..a9c1915131fab --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/UiReaderInterface.php @@ -0,0 +1,44 @@ +componentsData = $arrayObjectFactory->create(); + } + + /** + * Get all UI registered components + * + * @return UiComponentInterface[] + */ + public function getComponents() + { + return $this->components; + } + + /** + * Get UI component + * + * @param string|UiComponentInterface $uniqueKey + * @return UiComponentInterface + */ + public function getComponent($uniqueKey) + { + $uniqueKey = is_object($uniqueKey) ? $this->getHashKey($uniqueKey) : $uniqueKey; + return isset($this->components[$uniqueKey]) ? $this->components[$uniqueKey] : null; + } + + /** + * Add component + * + * @param UiComponentInterface $component + * @param string|null $uniqueKey + * @return void + */ + public function setComponent(UiComponentInterface $component, $uniqueKey = null) + { + $uniqueKey = $uniqueKey === null ? $this->getHashKey($component) : $uniqueKey; + $this->components[$uniqueKey] = $component; + } + + /** + * Get all components data + * + * @return \ArrayObject + */ + public function getComponentsData() + { + return $this->componentsData; + } + + /** + * Get component data + * + * @param string|UiComponentInterface $uniqueKey + * @return mixed + */ + public function getComponentData($uniqueKey) + { + $uniqueKey = is_object($uniqueKey) ? $this->getHashKey($uniqueKey) : $uniqueKey; + return isset($this->componentsData[$uniqueKey]) ? $this->componentsData[$uniqueKey] : null; + } + + /** + * Add component data + * + * @param mixed $data + * @param string|UiComponentInterface $uniqueKey + * @return void + */ + public function setComponentData($data, $uniqueKey) + { + $uniqueKey = is_object($uniqueKey) ? $this->getHashKey($uniqueKey) : $uniqueKey; + $this->componentsData[$uniqueKey] = $data; + } + + /** + * Get hash of object for the key + * + * @param object $object + * @return string + */ + protected function getHashKey($object) + { + return sprintf('%x', crc32(spl_object_hash($object))); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigProviderInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigProviderInterface.php new file mode 100644 index 0000000000000..ed5cda0722b22 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigProviderInterface.php @@ -0,0 +1,62 @@ +filesystem = $filesystem; + $this->templateEnginePool = $templateEnginePool; + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeFactory.php new file mode 100644 index 0000000000000..d15737e1b7eb9 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeFactory.php @@ -0,0 +1,63 @@ +types = $types; + $this->objectManager = $objectManager; + } + + /** + * Get content type object instance + * + * @param string $type + * @return ContentTypeInterface + * @throws \InvalidArgumentException + */ + public function get($type) + { + if (!isset($this->types[$type])) { + throw new \InvalidArgumentException(sprintf("Wrong content type '%s', renderer not exists.", $type)); + } + + $contentRender = $this->objectManager->get($this->types[$type]); + if (!$contentRender instanceof ContentTypeInterface) { + throw new \InvalidArgumentException( + sprintf('"%s" must implement the interface ContentTypeInterface.', $this->types[$type]) + ); + } + + return $contentRender; + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeInterface.php new file mode 100644 index 0000000000000..cbefd547d9caa --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/ContentTypeInterface.php @@ -0,0 +1,23 @@ +templateEnginePool->get($extension); + $result = $templateEngine->render($component, $this->getTemplate($extension, $template)); + } + return $result; + } + + /** + * Get template path + * + * @param string $extension + * @param string $template + * @return string + */ + protected function getTemplate($extension, $template) + { + switch ($extension) { + case 'xhtml': + return $template; + default: + return $this->filesystem->getTemplateFileName($template); + } + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Json.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Json.php new file mode 100644 index 0000000000000..9732a8abac2b9 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Json.php @@ -0,0 +1,27 @@ + 'TODO fix me']); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Xml.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Xml.php new file mode 100644 index 0000000000000..ce4915347f6be --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContentType/Xml.php @@ -0,0 +1,109 @@ +generator = $generator; + parent::__construct($filesystem, $templateEnginePool); + } + + /** + * Render data + * + * @param UiComponentInterface $view + * @param string $template + * @return string + * @throws \Exception + */ + public function render(UiComponentInterface $view, $template = '') + { + $templateEngine = false; + if ($template) { + $extension = pathinfo($template, PATHINFO_EXTENSION); + $templateEngine = $this->templateEnginePool->get($extension); + } + if ($templateEngine) { + $path = $this->filesystem->getTemplateFileName($template); + $result = $templateEngine->render($view, $path); + } else { + $result = $this->getDataXml($view); + } + + throw new \Exception('Please implement XML renderer'); + } + + /** + * @param UiComponentInterface $view + * @return string + */ + protected function getDataXml(UiComponentInterface $view) + { + $result = [ + 'configuration' => $view->getRenderContext()->getStorage()->getComponentsData($view->getName())->getData(), + 'data' => [], + ]; + foreach ($view->getRenderContext()->getStorage()->getData($view->getName()) as $key => $value) { + if (is_object($value)) { + if (method_exists($value, 'toXml')) { + $result['data'][$key] = $value->toXml(); + } else { + $result['data'][$key] = $this->objectToXml($value); + } + } else { + $result['data'][$key] = $value; + } + } + return $this->generator->arrayToXml($result); + } + + /** + * Convert object to xml format + * + * @param \Magento\Framework\Object $object + * @return string + */ + protected function objectToXml(\Magento\Framework\Object $object) + { + return (string)$object; + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php index 582fad08370f4..8c053561ef9c3 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php @@ -6,28 +6,30 @@ namespace Magento\Framework\View\Element\UiComponent; use Magento\Framework\App\RequestInterface; -use Magento\Framework\Registry; -use Magento\Framework\View\Element\UiComponentFactory; -use Magento\Framework\View\LayoutInterface; +use Magento\Ui\Component\Control\ActionPoolFactory; +use Magento\Ui\Component\Control\ActionPoolInterface; +use Magento\Ui\Component\Control\ButtonProviderFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Ui\Component\Control\ButtonProviderInterface; +use Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeFactory; +use Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeInterface; +use Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface; +use Magento\Framework\View\LayoutInterface as PageLayoutInterface; /** * Class Context */ -class Context extends Registry +class Context implements ContextInterface { /** - * Configuration storage builder - * - * @var ConfigStorageBuilderInterface + * @var string */ - protected $configStorageBuilder; + protected $namespace; /** - * Configuration storage - * - * @var ConfigStorageInterface + * @var DataProviderInterface */ - protected $configStorage; + protected $dataProvider; /** * Application request @@ -36,6 +38,13 @@ class Context extends Registry */ protected $request; + /** + * Factory renderer for a content type + * + * @var ContentTypeFactory + */ + protected $contentTypeFactory; + /** * Accept type * @@ -44,191 +53,233 @@ class Context extends Registry protected $acceptType; /** - * @var LayoutInterface + * Config provider + * + * @var ConfigProviderInterface + */ + protected $configProvider; + + /** + * @var PageLayoutInterface */ protected $pageLayout; /** - * @var LayoutInterface + * @var ButtonProviderFactory */ - protected $layout; + protected $buttonProviderFactory; /** - * @var UiComponentFactory + * @var ActionPoolInterface */ - protected $factory; + protected $actionPool; /** - * Data Namespace + * Registry components * - * @var string + * @var array */ - protected $namespace; + protected $componentsDefinitions = []; /** - * Constructor - * - * @param ConfigStorageInterface $configStorage - * @param ConfigStorageBuilderInterface $configStorageBuilder + * @param PageLayoutInterface $pageLayout * @param RequestInterface $request + * @param ButtonProviderFactory $buttonProviderFactory + * @param ActionPoolFactory $actionPoolFactory + * @param ContentTypeFactory $contentTypeFactory + * @param DataProviderInterface|null $dataProvider + * @param string $namespace */ public function __construct( - ConfigStorageInterface $configStorage, - ConfigStorageBuilderInterface $configStorageBuilder, - RequestInterface $request + PageLayoutInterface $pageLayout, + RequestInterface $request, + ButtonProviderFactory $buttonProviderFactory, + ActionPoolFactory $actionPoolFactory, + ContentTypeFactory $contentTypeFactory, + DataProviderInterface $dataProvider = null, + $namespace = null ) { - $this->configStorage = $configStorage; - $this->configStorageBuilder = $configStorageBuilder; + $this->namespace = $namespace; $this->request = $request; + $this->buttonProviderFactory = $buttonProviderFactory; + $this->dataProvider = $dataProvider; + $this->pageLayout = $pageLayout; + $this->actionPool = $actionPoolFactory->create( + [ + 'context' => $this + ] + ); + $this->contentTypeFactory = $contentTypeFactory; + $this->setAcceptType(); } /** - * Getting requested accept type + * Add component into registry * + * @param string $name + * @param array $config * @return void */ - protected function setAcceptType() + public function addComponentDefinition($name, array $config) { - $this->acceptType = 'xml'; - - $rawAcceptType = $this->request->getHeader('Accept'); - if (strpos($rawAcceptType, 'json') !== false) { - $this->acceptType = 'json'; - } elseif (strpos($rawAcceptType, 'html') !== false) { - $this->acceptType = 'html'; + if (!isset($this->componentsDefinitions[$name])) { + $this->componentsDefinitions[$name] = $config; } } /** - * Getting accept type + * To get the registry components * - * @return string + * @return array */ - public function getAcceptType() + public function getComponentsDefinitions() { - return $this->acceptType; + return $this->componentsDefinitions; } /** - * Set Ui Components Factory + * Get render engine * - * @param UiComponentFactory $render - * @return void + * @return ContentTypeInterface */ - public function setRender(UiComponentFactory $render) + public function getRenderEngine() { - $this->factory = $render; + return $this->contentTypeFactory->get($this->getAcceptType()); } /** - * Get Ui Components Factory - * - * @return UiComponentFactory + * @return string */ - public function getRender() + public function getNamespace() { - return $this->factory; + return $this->namespace; } /** - * Set root layout + * Getting accept type * - * @param LayoutInterface $layout - * @return void + * @return string */ - public function setPageLayout(LayoutInterface $layout) + public function getAcceptType() { - $this->pageLayout = $layout; + return $this->acceptType; } /** - * Get root layout + * Getting all request data * - * @return LayoutInterface + * @return mixed */ - public function getPageLayout() + public function getRequestParams() { - return $this->pageLayout; + return $this->request->getParams(); } /** - * Set root view + * Getting data according to the key * - * @param string $namespace - * @return void + * @param string $key + * @param mixed|null $defaultValue + * @return mixed */ - public function setNamespace($namespace) + public function getRequestParam($key, $defaultValue = null) { - $this->namespace = $namespace; + return $this->request->getParam($key, $defaultValue); } /** - * Get root view + * Get data provider * - * @return string + * @return DataProviderInterface */ - public function getNamespace() + public function getDataProvider() { - return $this->namespace; + return $this->dataProvider; } /** - * Getting all request data + * Get page layout * - * @return mixed + * @return PageLayoutInterface */ - public function getRequestParams() + public function getPageLayout() { - return $this->request->getParams(); + return $this->pageLayout; } /** - * Getting data according to the key + * Add button in the actions toolbar * - * @param string $key - * @param mixed|null $defaultValue - * @return mixed + * @param array $buttons + * @param UiComponentInterface $component + * @return void */ - public function getRequestParam($key, $defaultValue = null) + public function addButtons(array $buttons, UiComponentInterface $component) { - return $this->request->getParam($key, $defaultValue); - } + if (!empty($buttons)) { + foreach ($buttons as $buttonId => $buttonData) { + if (is_array($buttonData)) { + $buttons[$buttonId] = $buttonData; + continue; + } + /** @var ButtonProviderInterface $button */ + $button = $this->buttonProviderFactory->create($buttonData); + $buttonData = $button->getButtonData(); + if (!$buttonData) { + unset($buttons[$buttonId]); + continue; + } + $buttons[$buttonId] = $buttonData; + } + uasort($buttons, [$this, 'sortButtons']); - /** - * Get storage configuration - * - * @return ConfigStorageInterface - */ - public function getStorage() - { - return $this->configStorage; + foreach ($buttons as $buttonId => $buttonData) { + $this->actionPool->add($buttonId, $buttonData, $component); + } + } } /** - * Get configuration builder + * Sort buttons by sort order * - * @return ConfigStorageBuilderInterface + * @param array $itemA + * @param array $itemB + * @return int */ - public function getConfigBuilder() + public function sortButtons(array $itemA, array $itemB) { - return $this->configStorageBuilder; + $sortOrderA = isset($itemA['sort_order']) ? intval($itemA['sort_order']) : 0; + $sortOrderB = isset($itemB['sort_order']) ? intval($itemB['sort_order']) : 0; + + return $sortOrderA - $sortOrderB; } /** - * @param LayoutInterface $layout + * Getting requested accept type + * * @return void */ - public function setLayout(LayoutInterface $layout) + protected function setAcceptType() { - $this->layout = $layout; + $this->acceptType = 'xml'; + + $rawAcceptType = $this->request->getHeader('Accept'); + if ($this->request->getParam('isAjax') === 'true' || strpos($rawAcceptType, 'json') !== false) { + $this->acceptType = 'json'; + } elseif (strpos($rawAcceptType, 'html') !== false) { + $this->acceptType = 'html'; + } } /** - * @return LayoutInterface + * Set data provider + * + * @param DataProviderInterface $dataProvider + * @return void */ - public function getLayout() + public function setDataProvider(DataProviderInterface $dataProvider) { - return $this->layout; + $this->dataProvider = $dataProvider; } } diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContextFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContextFactory.php new file mode 100644 index 0000000000000..5708da5d21278 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContextFactory.php @@ -0,0 +1,42 @@ +objectManager = $objectManager; + } + + /** + * Create context + * + * @param array $arguments + * @return ContextInterface + */ + public function create(array $arguments = []) + { + return $this->objectManager->create(static::INSTANCE_NAME, $arguments); + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ContextInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ContextInterface.php new file mode 100644 index 0000000000000..ab934866621d6 --- /dev/null +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/ContextInterface.php @@ -0,0 +1,101 @@ +component = $component; + $this->containerFactory = $containerFactory; + parent::__construct($context, $data); + } + + /** + * Render block HTML + * + * @return string + */ + protected function _toHtml() + { + foreach ($this->getChildNames() as $childName) { + $childBlock = $this->getLayout()->getBlock($childName); + if ($childBlock) { + $container = $this->containerFactory->create([ + 'block' => $childBlock + ]); + $this->component->addComponent('block_' . $childName, $container); + } + } + + $result = $this->component->render(); + return (string)$result; + } +} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php b/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php index 48239e9c92261..dc0204aa3c066 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponentFactory.php @@ -6,9 +6,12 @@ namespace Magento\Framework\View\Element; use Magento\Framework\Object; -use Magento\Framework\View\Element\UiComponent\Context as RenderContext; -use Magento\Framework\View\LayoutFactory; +use Magento\Framework\Exception; use Magento\Framework\View\LayoutInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Data\Argument\InterpreterInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; +use Magento\Framework\View\Element\UiComponent\Config\ManagerInterface; /** * Class UiComponentFactory @@ -16,172 +19,149 @@ class UiComponentFactory extends Object { /** - * Ui element view + * Object manager * - * @var UiComponentInterface + * @var ObjectManagerInterface */ - protected $view; + protected $objectManager; /** - * Render context + * UI component manager * - * @var RenderContext + * @var ManagerInterface */ - protected $renderContext; + protected $componentManager; /** - * Layout Interface + * Argument interpreter * - * @var \Magento\Framework\View\LayoutFactory + * @var InterpreterInterface */ - protected $layoutFactory; - - /** - * @var LayoutInterface - */ - protected $layout; - - /** - * @var bool - */ - protected $layoutLoaded = false; + protected $argumentInterpreter; /** * Constructor * - * @param RenderContext $renderContext - * @param LayoutFactory $layoutFactory + * @param ObjectManagerInterface $objectManager + * @param ManagerInterface $componentManager + * @param InterpreterInterface $argumentInterpreter * @param array $data */ public function __construct( - RenderContext $renderContext, - LayoutFactory $layoutFactory, + ObjectManagerInterface $objectManager, + ManagerInterface $componentManager, + InterpreterInterface $argumentInterpreter, array $data = [] ) { - $this->renderContext = $renderContext; - $this->renderContext->setRender($this); - $this->layoutFactory = $layoutFactory; + $this->objectManager = $objectManager; + $this->componentManager = $componentManager; + $this->argumentInterpreter = $argumentInterpreter; parent::__construct($data); } /** - * Get component name - * - * @return string - */ - public function getComponent() - { - return $this->getData('configuration/component'); - } - - /** - * Get layout handle - * - * @return string - */ - public function getLayoutHandle() - { - return $this->getData('configuration/name'); - } - - /** - * @param LayoutInterface $layout - * @return void - */ - public function setLayout(LayoutInterface $layout) - { - if (!$this->renderContext->getPageLayout()) { - $this->renderContext->setPageLayout($layout); - } - } - - /** - * Create Ui Component instance + * Create child components * - * @param string $componentName - * @param string $handleName - * @param array $arguments + * @param array $bundleComponents + * @param ContextInterface $renderContext + * @param string $identifier * @return UiComponentInterface */ - public function createUiComponent($componentName, $handleName, array $arguments = []) - { - if (!$this->layout) { - $this->renderContext->setNamespace($handleName); - $this->layout = $this->layoutFactory->create(); - $this->renderContext->setLayout($this->layout); - $this->layout->getUpdate()->addHandle('ui_components'); - $this->layout->getUpdate()->addHandle($handleName); - $this->loadLayout(); - $this->layoutLoaded = true; + protected function createChildComponent( + array $bundleComponents, + ContextInterface $renderContext, + $identifier + ) { + list($className, $arguments) = $this->argumentsResolver($identifier, $bundleComponents); + $components = []; + foreach ($bundleComponents['children'] as $childrenIdentifier => $childrenData) { + $children = $this->createChildComponent( + $childrenData, + $renderContext, + $childrenIdentifier + ); + $components[$childrenIdentifier] = $children; } - $view = $this->getUiElementView($componentName); - $view->update($arguments); - if ($this->layoutLoaded) { - $this->prepare($view); + $arguments['components'] = $components; + if (!isset($arguments['context'])) { + $arguments['context'] = $renderContext; } - return $view; + return $this->objectManager->create($className, $arguments); } /** - * Prepare UI Component data + * Resolve arguments * - * @param object $view - * @return void + * @param string $identifier + * @param array $componentData + * @return array */ - protected function prepare($view) + protected function argumentsResolver($identifier, array $componentData) { - if ($view instanceof UiComponentInterface) { - $view->prepare(); + $attributes = $componentData[ManagerInterface::COMPONENT_ATTRIBUTES_KEY]; + $className = $attributes['class']; + unset($attributes['class']); + $arguments = []; + foreach ($componentData[ManagerInterface::COMPONENT_ARGUMENTS_KEY] as $name => $argument) { + $arguments[$name] = $this->argumentInterpreter->evaluate($argument); } - foreach ($view->getLayout()->getChildNames($view->getNameInLayout()) as $childAlias) { - $name = $view->getLayout()->getChildName($view->getNameInLayout(), $childAlias); - if ($view->getLayout()->isContainer($name)) { - foreach ($view->getLayout()->getChildNames($name) as $childName) { - $child = $view->getLayout()->getBlock($childName); - $this->prepare($child); - } - } else { - $child = $view->getChildBlock($childAlias); - if ($child) { - $this->prepare($child); - } - } + + if (!isset($arguments['data'])) { + $arguments['data'] = []; } + + $arguments['data'] = array_merge($arguments['data'], ['name' => $identifier], $attributes); + return [$className, $arguments]; } /** - * Get UI Element View + * Create component object * - * @param string $uiElementName + * @param string $identifier + * @param string $name + * @param array $arguments * @return UiComponentInterface - * @throws \InvalidArgumentException + * @throws Exception */ - public function getUiElementView($uiElementName) + public function create($identifier, $name = null, array $arguments = []) { - /** @var UiComponentInterface $view */ - $view = $this->layout->getBlock($uiElementName); - if (!$view instanceof UiComponentInterface) { - throw new \InvalidArgumentException( - sprintf( - 'UI Element "%s" must implement \Magento\Framework\View\Element\UiComponentInterface', - $uiElementName - ) + if ($name === null) { + $bundleComponents = $this->componentManager->prepareData($identifier)->getData($identifier); + if (empty($bundleComponents)) { + throw new Exception('You use an empty set.'); + } + list($className, $componentArguments) = $this->argumentsResolver( + $identifier, + $bundleComponents[$identifier] ); - } - return $view; - } + if (!isset($arguments['context'])) { + throw new Exception('Context, is required argument.'); + } + $componentContext = $arguments['context']; + $components = []; + foreach ($bundleComponents[$identifier]['children'] as $childrenIdentifier => $childrenData) { + $children = $this->createChildComponent( + $childrenData, + $componentContext, + $childrenIdentifier + ); + $components[$childrenIdentifier] = $children; + } + $componentArguments['components'] = $components; - /** - * Load layout - * - * @return void - */ - protected function loadLayout() - { - $this->layout->getUpdate()->load(); - $this->layout->generateXml(); - $this->layout->generateElements(); + /** @var \Magento\Framework\View\Element\UiComponentInterface $component */ + $component = $this->objectManager->create($className, array_merge($componentArguments, $arguments)); + + return $component; + } else { + $defaultData = $this->componentManager->createRawComponentData($name); + list($className, $componentArguments) = $this->argumentsResolver($identifier, $defaultData); + /** @var \Magento\Framework\View\Element\UiComponentInterface $component */ + $component = $this->objectManager->create($className, array_merge($componentArguments, $arguments)); + + return $component; + } } } diff --git a/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php index 343f82b40d49e..14de3f577bbae 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php @@ -5,98 +5,102 @@ */ namespace Magento\Framework\View\Element; -use Magento\Framework\View\Element\UiComponent\Context as RenderContext; -use Magento\Framework\View\Element\UiComponent\ConfigBuilderInterface; +use Magento\Framework\View\Element\UiComponent\ContextInterface; /** - * Class UiComponentInterface + * Interface UiComponentInterface */ interface UiComponentInterface extends BlockInterface { /** - * Update component data + * Get component instance name * - * @param array $arguments * @return string */ - public function update(array $arguments = []); + public function getName(); /** - * Prepare component data + * Get component name * - * @return void + * @return string */ - public function prepare(); + public function getComponentName(); /** * Render component * - * @param array $data * @return string */ - public function render(array $data = []); + public function render(); /** - * Render label - * - * @return mixed|string + * @param string $name + * @param UiComponentInterface $component */ - public function renderLabel(); + public function addComponent($name, UiComponentInterface $component); /** - * Getting template for rendering content - * - * @return string|false + * @param string $name + * @return UiComponentInterface */ - public function getContentTemplate(); + public function getComponent($name); /** - * Getting template for rendering label + * Get child components * - * @return string|false + * @return UiComponentInterface[] */ - public function getLabelTemplate(); + public function getChildComponents(); /** - * Getting instance name + * Get template * * @return string */ - public function getName(); + public function getTemplate(); /** - * Getting parent name component instance + * Get component context * - * @return string + * @return ContextInterface */ - public function getParentName(); + public function getContext(); /** - * Get render context + * Render child component * - * @return RenderContext + * @param string $name + * @return string */ - public function getRenderContext(); + public function renderChildComponent($name); /** - * Get elements + * Component data setter * - * @return UiComponentInterface[] + * @param string|array $key + * @param mixed $value + * @return void */ - public function getElements(); + public function setData($key, $value = null); /** - * Set elements + * Component data getter * - * @param array $elements + * @param string $key + * @param string|int $index * @return mixed */ - public function setElements(array $elements); + public function getData($key = '', $index = null); + + /** + * @return array + */ + public function getDataSourceData(); /** - * Get configuration builder + * Prepare component configuration * - * @return ConfigBuilderInterface + * @return void */ - public function getConfigBuilder(); + public function prepare(); } diff --git a/lib/internal/Magento/Framework/View/Layout/Argument/Parser.php b/lib/internal/Magento/Framework/View/Layout/Argument/Parser.php index 7697660afc02f..fd4bca2122cda 100644 --- a/lib/internal/Magento/Framework/View/Layout/Argument/Parser.php +++ b/lib/internal/Magento/Framework/View/Layout/Argument/Parser.php @@ -41,7 +41,13 @@ protected function getConverter() if (!$this->converter) { $arrayNodeConfig = new ArrayNodeConfig( new NodePathMatcher(), - ['argument/param' => 'name', 'argument(/item)+' => 'name', 'argument(/item)+/param' => 'name'], + [ + 'argument/param' => 'name', + 'argument(/item)+' => 'name', + 'argument(/item)+/param' => 'name', + 'argument(/argument)+' => 'name', + 'argument((/argument)+(/item)+)+' => 'name', + ], ['argument/updater'] ); $this->converter = new FlatConverter($arrayNodeConfig); diff --git a/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php b/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php index 0356d93d04c86..d1c8b75f7ed7c 100644 --- a/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php +++ b/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php @@ -5,11 +5,22 @@ */ namespace Magento\Framework\View\Layout\Generator; -use Magento\Framework\Data\Argument\InterpreterInterface; -use Magento\Framework\View\Element\UiComponentFactory; use Magento\Framework\View\Layout; +use Magento\Framework\View\Element\BlockFactory; +use Magento\Framework\View\Layout\Data\Structure; +use Magento\Framework\View\Layout\GeneratorInterface; +use Magento\Framework\View\Element\UiComponentFactory; +use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Data\Argument\InterpreterInterface; +use Magento\Framework\View\Layout\Reader\Context as ReaderContext; +use Magento\Framework\View\Layout\Generator\Context as GeneratorContext; +use Magento\Framework\View\Element\UiComponent\ContextFactory as UiComponentContextFactory; +use Magento\Framework\View\LayoutInterface; -class UiComponent implements Layout\GeneratorInterface +/** + * Class UiComponent + */ +class UiComponent implements GeneratorInterface { /** * Generator type @@ -17,33 +28,39 @@ class UiComponent implements Layout\GeneratorInterface const TYPE = 'ui_component'; /** - * @var \Magento\Framework\View\Element\UiComponentFactory + * Block adapter + */ + const ADAPTER = 'Magento\Framework\View\Element\UiComponent\TemplateAdapter'; + + /** + * @var UiComponentFactory */ protected $uiComponentFactory; /** - * @var \Magento\Framework\Data\Argument\InterpreterInterface + * @var UiComponentContextFactory */ - protected $argumentInterpreter; + protected $contextFactory; /** * Constructor * * @param UiComponentFactory $uiComponentFactory - * @param \Magento\Framework\Data\Argument\InterpreterInterface $argumentInterpreter + * @param BlockFactory $blockFactory + * @param UiComponentContextFactory $contextFactory */ public function __construct( UiComponentFactory $uiComponentFactory, - InterpreterInterface $argumentInterpreter + BlockFactory $blockFactory, + UiComponentContextFactory $contextFactory ) { $this->uiComponentFactory = $uiComponentFactory; - $this->argumentInterpreter = $argumentInterpreter; + $this->blockFactory = $blockFactory; + $this->contextFactory = $contextFactory; } /** * {@inheritdoc} - * - * @return string */ public function getType() { @@ -53,11 +70,11 @@ public function getType() /** * Creates UI Component object based on scheduled data and add it to the layout * - * @param Layout\Reader\Context $readerContext - * @param Context $generatorContext + * @param ReaderContext $readerContext + * @param GeneratorContext $generatorContext * @return $this */ - public function process(Layout\Reader\Context $readerContext, Layout\Generator\Context $generatorContext) + public function process(ReaderContext $readerContext, GeneratorContext $generatorContext) { $scheduledStructure = $readerContext->getScheduledStructure(); $scheduledElements = $scheduledStructure->getElements(); @@ -66,18 +83,16 @@ public function process(Layout\Reader\Context $readerContext, Layout\Generator\C } $structure = $generatorContext->getStructure(); $layout = $generatorContext->getLayout(); - $this->uiComponentFactory->setLayout($layout); + + // Instantiate blocks and collect all actions data /** @var $blocks \Magento\Framework\View\Element\AbstractBlock[] */ $blocks = []; - // Instantiate blocks and collect all actions data foreach ($scheduledElements as $elementName => $element) { - list($type, $data) = $element; - if ($type === self::TYPE) { - $block = $this->generateComponent($structure, $elementName, $data); - $blocks[$elementName] = $block; - $layout->setBlock($elementName, $block); - $scheduledStructure->unsetElement($elementName); - } + list(, $data) = $element; + $block = $this->generateComponent($structure, $elementName, $data, $layout); + $blocks[$elementName] = $block; + $layout->setBlock($elementName, $block); + $scheduledStructure->unsetElement($elementName); } return $this; @@ -86,35 +101,49 @@ public function process(Layout\Reader\Context $readerContext, Layout\Generator\C /** * Create component object * - * @param \Magento\Framework\View\Layout\Data\Structure $structure + * @param Structure $structure * @param string $elementName * @param string $data - * @return \Magento\Framework\View\Element\UiComponentInterface + * @param LayoutInterface $layout + * @return UiComponentInterface */ - protected function generateComponent(Layout\Data\Structure $structure, $elementName, $data) + protected function generateComponent(Structure $structure, $elementName, $data, LayoutInterface $layout) { $attributes = $data['attributes']; if (!empty($attributes['group'])) { $structure->addToParentGroup($elementName, $attributes['group']); } - $arguments = empty($data['arguments']) ? [] : $this->evaluateArguments($data['arguments']); - $componentName = isset($attributes['component']) ? $attributes['component'] : ''; - $uiComponent = $this->uiComponentFactory->createUiComponent($componentName, $elementName, $arguments); - return $uiComponent; + + $context = $this->contextFactory->create([ + 'namespace' => $elementName, + 'pageLayout' => $layout + ]); + + $component = $this->uiComponentFactory->create($elementName, null, [ + 'context' => $context + ]); + $this->prepareComponent($component); + + /** @var \Magento\Framework\View\Element\UiComponent\TemplateAdapter $adapterBlock */ + $adapterBlock = $this->blockFactory->createBlock(static::ADAPTER, ['component' => $component]); + + return $adapterBlock; } /** - * Compute and return argument values + * Call prepare method in the component UI * - * @param array $arguments - * @return array + * @param UiComponentInterface $component + * @return void */ - protected function evaluateArguments(array $arguments) + protected function prepareComponent(UiComponentInterface $component) { - $result = []; - foreach ($arguments as $argumentName => $argumentData) { - $result[$argumentName] = $this->argumentInterpreter->evaluate($argumentData); + $childComponents = $component->getChildComponents(); + if (!empty($childComponents)) { + foreach ($childComponents as $child) { + $this->prepareComponent($child); + } } - return $result; + $component->prepare(); } } diff --git a/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php b/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php index ae986912df95d..f9b5e5c977c19 100644 --- a/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php +++ b/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php @@ -6,8 +6,13 @@ namespace Magento\Framework\View\Layout\Reader; use Magento\Framework\App; +use Magento\Framework\Exception; use Magento\Framework\View\Layout; +use Magento\Framework\View\Element\UiComponent\Config\ManagerInterface; +/** + * Class UiComponent + */ class UiComponent implements Layout\ReaderInterface { /**#@+ @@ -28,29 +33,45 @@ class UiComponent implements Layout\ReaderInterface */ protected $layoutHelper; + /** + * UI component manager + * + * @var ManagerInterface + */ + protected $componentManager; + /** * @var string|null */ protected $scopeType; + /** + * @var \Magento\Framework\View\Layout\Argument\Parser + */ + protected $argumentParser; + /** * Constructor * * @param Layout\ScheduledStructure\Helper $helper + * @param Layout\Argument\Parser $argumentParser + * @param ManagerInterface $componentManager * @param string|null $scopeType */ public function __construct( Layout\ScheduledStructure\Helper $helper, + Layout\Argument\Parser $argumentParser, + ManagerInterface $componentManager, $scopeType = null ) { $this->layoutHelper = $helper; + $this->componentManager = $componentManager; + $this->argumentParser = $argumentParser; $this->scopeType = $scopeType; } /** * {@inheritdoc} - * - * @return string[] */ public function getSupportedNodes() { @@ -59,27 +80,24 @@ public function getSupportedNodes() /** * {@inheritdoc} - * - * @param Context $readerContext - * @param Layout\Element $currentElement - * @return $this */ public function interpret(Context $readerContext, Layout\Element $currentElement) { + $attributes = $this->getAttributes($currentElement); $scheduledStructure = $readerContext->getScheduledStructure(); $referenceName = $this->layoutHelper->scheduleStructure( - $readerContext->getScheduledStructure(), + $scheduledStructure, $currentElement, $currentElement->getParent(), - ['attributes' => $this->getAttributes($currentElement)] + ['attributes' => $attributes] ); - $scheduledStructure->setStructureElementData($referenceName, [ - 'attributes' => $this->getAttributes($currentElement) - ]); + + $scheduledStructure->setStructureElementData($referenceName, ['attributes' => $attributes]); $configPath = (string)$currentElement->getAttribute('ifconfig'); if (!empty($configPath)) { $scheduledStructure->setElementToIfconfigList($referenceName, $configPath, $this->scopeType); } + return $this; } @@ -95,6 +113,7 @@ protected function getAttributes(Layout\Element $element) foreach ($this->attributes as $attributeName) { $attributes[$attributeName] = (string)$element->getAttribute($attributeName); } + return $attributes; } } diff --git a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd index 02fe8da728aa2..655955ff47393 100644 --- a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd +++ b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd @@ -115,8 +115,8 @@ - - + + @@ -238,8 +238,8 @@ Part of view that can generate appropriate content. - - + + diff --git a/lib/web/mage/utils.js b/lib/web/mage/utils.js index 239fca6d918ea..641c1ce8ccae2 100644 --- a/lib/web/mage/utils.js +++ b/lib/web/mage/utils.js @@ -4,30 +4,56 @@ */ //TODO: assemble all util methods in this module define([ - 'underscore' -], function (_) { + 'underscore', + 'jquery' +], function (_, jQuery) { 'use strict'; - var tplRegxp = /\{(\w*)\}/g; - /** @namespace */ - var utils = {}; + var utils = {}, + opener = '<%'; - /** - * Replaces matches of '{*}' pattern with a matched property in 'data' object. - * @private - * - * @param {String} tpl - String to process. - * @param {Object} data - Data to match with pattern. - * @returns {String} Modified string. - * - * @example - * template('Hello {one}!', {one: 'World'}); - * => 'Hello World!'; - */ - function template(tpl, data){ - return tpl.replace(tplRegxp, function(match, key){ - return data.hasOwnProperty(key) ? data[key] : ''; + function template(tmpl, data) { + var last = tmpl; + + data = Object.create(data); + + while (~tmpl.indexOf(opener)) { + tmpl = _.template(tmpl)(data); + + if (tmpl === last) { + break; + } + + last = tmpl; + } + + return tmpl; + } + + function hasTemplate(value) { + return _.isString(value) && ~value.indexOf(opener); + } + + function process(initial, raw) { + raw = raw || initial; + + _.each(raw, function (value, key) { + if (hasTemplate(key)) { + delete raw[key]; + + key = template(key, initial); + raw[key] = value; + } + + if (hasTemplate(value)) { + value = template(value, initial); + raw[key] = value; + } + + if (typeof value === 'object') { + process(initial, value); + } }); } @@ -40,10 +66,10 @@ define([ * @param {*} value - Value of the last property in 'path' array. * returns {*} New value for the property. */ - function setNested(parent, path, value){ + function setNested(parent, path, value) { var last = path.pop(); - path.forEach(function(part) { + path.forEach(function (part) { if (_.isUndefined(parent[part])) { parent[part] = {}; } @@ -51,7 +77,9 @@ define([ parent = parent[part]; }); - return (parent[last] = value); + parent[last] = value; + + return value; } /** @@ -62,16 +90,16 @@ define([ * @param {Array} path - Splitted path the property. * @returns {*} Value of the property. */ - function getNested(parent, path){ + function getNested(parent, path) { var exists; - exists = path.every(function(part) { + exists = path.every(function (part) { parent = parent[part]; return !_.isUndefined(parent); }); - if(exists){ + if (exists) { return parent; } } @@ -80,7 +108,7 @@ define([ * Removes property from a specified object. * @private * - * @param {Object} parent - Object from which to remove property. + * @param {Object} parent - Object from which to remove property. * @param {Array} path - Splitted path to the propery. */ function removeNested(parent, path) { @@ -109,7 +137,7 @@ define([ * utils.nested({}, 'one.two', 3); * => { one: {two: 3} } */ - nested: function(data, path, value){ + nested: function (data, path, value) { var action = arguments.length > 2 ? setNested : getNested; path = path ? path.split('.') : []; @@ -123,7 +151,7 @@ define([ * @param {Object} data - Data source. * @param {String} path - Path to the property e.g. 'one.two.three' */ - nestedRemove: function(data, path) { + nestedRemove: function (data, path) { path = path.split('.'); removeNested(data, path); @@ -144,18 +172,18 @@ define([ * utils.flatten({one: { two: { three: 'value'} }}, '=>'); * => {'one=>two=>three': 'value'}; */ - flatten: function(data, separator, parent, result){ - separator = separator || '.'; - result = result || {}; + flatten: function (data, separator, parent, result) { + separator = separator || '.'; + result = result || {}; - _.each(data, function(node, name){ - if(parent){ + _.each(data, function (node, name) { + if (parent) { name = parent + separator + name; } typeof node === 'object' ? this.flatten(node, separator, name, result) : - (result[name] = node); + result[name] = node; }, this); @@ -173,14 +201,14 @@ define([ * utils.unflatten({'one=>two': 'value'}, '=>'); * => { * one: { two: 'value' } - * }; + * }; */ - unflatten: function(data, separator){ + unflatten: function (data, separator) { var result = {}; separator = separator || '.'; - _.each(data, function(value, nodes){ + _.each(data, function (value, nodes) { nodes = nodes.split(separator); setNested(result, nodes, value); @@ -200,14 +228,14 @@ define([ * utils.serialize({one: { two: { three: 'value'} }}); * => { 'one[two][three]': 'value' } */ - serialize: function(data){ + serialize: function (data) { var result = {}; data = this.flatten(data); - _.each(data, function(value, keys){ - keys = this.serializeName(keys); - value = _.isUndefined(value) ? '' : value; + _.each(data, function (value, keys) { + keys = this.serializeName(keys); + value = _.isUndefined(value) ? '' : value; result[keys] = value; }, this); @@ -218,13 +246,13 @@ define([ /** * Applies provided data to the template. * - * @param {(String|Object)} template - * @param {Object} source - Data object to match with template. - * @returns {String|Object} + * @param {Object} tmpl + * @param {Object} [$data] - Data object to match with template. + * @returns {Object} * * @example Template defined as a string. * var source = { foo: 'Random Stuff', bar: 'Some' }; - * + * * utils.template('{bar} {foo}', source); * => 'Some Random Stuff'; * @@ -234,21 +262,19 @@ define([ * utils.template(tpl, source); * => { key: { 'Some_Baz': 'Random Stuff' } }; */ - template: function(templ, source){ - var result, - parse; + template: function (tmpl, $data) { + tmpl = jQuery.extend(true, {}, tmpl); - if(_.isObject(templ)){ - templ = JSON.stringify(templ); - parse = true; - } + tmpl.$data = $data || {}; - result = template(templ, source); + process(tmpl); - return parse ? JSON.parse(result) : result; + delete tmpl.$data; + + return tmpl; } }); - + /** * Helpers for working with strings. */ @@ -257,11 +283,11 @@ define([ * Splits string by separator if it's possible, * otherwise returns the incoming value. * - * @param {(String|Array|*)} str - String to split. - * @param {String} [separator=' '] - Seperator based on which to split the string. + * @param {(String|Array|*)} str - String to split. + * @param {String} [separator=' '] - Seperator based on which to split the string. * @returns {Array|*} Splitted string or the incoming value. */ - stringToArray: function(str, separator){ + stringToArray: function (str, separator) { separator = separator || ' '; return typeof str === 'string' ? @@ -281,22 +307,33 @@ define([ * utils.serializeName('one.two.three'); * => 'one[two][three]'; */ - serializeName: function(name, separator){ + serializeName: function (name, separator) { var result; - separator = separator || '.'; - name = name.split(separator); + separator = separator || '.'; + name = name.split(separator); result = name.shift(); - name.forEach(function(part){ + name.forEach(function (part) { result += '[' + part + ']'; }); return result; + }, + + /** + * Checks wether the incoming value is not empty, + * e.g. not 'null' or 'undefined' + * + * @param {*} value - Value to check. + * @returns {Boolean} + */ + isEmpty: function (value) { + return value === '' || _.isUndefined(value) || _.isNull(value); } }); - + /** * Array manipulation methods. */ @@ -305,13 +342,13 @@ define([ * Facade method to remove/add value from/to array * without creating a new instance. * - * @param {Array} arr - Array to be modified. + * @param {Array} arr - Array to be modified. * @param {*} value - Value to add/remove. * @param {Boolean} add - Flag that specfies operation. * @returns {Utils} Chainable. */ - toggle: function(arr, value, add){ - return add ? + toggle: function (arr, value, add) { + return add ? this.add(arr, value) : this.remove(arr, value); }, @@ -324,10 +361,10 @@ define([ * @param {*} value - Value to be removed. * @returns {Utils} Chainable. */ - remove: function(arr, value){ + remove: function (arr, value) { var index = arr.indexOf(value); - if(~index){ + if (~index) { arr.splice(index, 1); } @@ -338,15 +375,15 @@ define([ * Adds the incoming value to array if * it's not alredy present in there. * - * @param {Array} arr - Array to be modifed. + * @param {Array} arr - Array to be modifed. * @param {...*} Values to be added. * @returns {Utils} Chainable. */ - add: function(arr){ + add: function (arr) { var values = _.toArray(arguments).slice(1); - values.forEach(function(value){ - if(!~arr.indexOf(value)){ + values.forEach(function (value) { + if (!~arr.indexOf(value)) { arr.push(value); } }); @@ -363,7 +400,7 @@ define([ * @param {Number} [offset=0] - Position at which to start inserting values. * @returns {Array} Modified array. */ - reserve: function(container, size, offset){ + reserve: function (container, size, offset) { container.splice(offset || 0, 0, new Array(size)); return _.flatten(container); @@ -375,15 +412,13 @@ define([ * @param {...Array} Multiple arrays to compare. * @returns {Bollean} True if arrays are identical to each other. */ - identical: function(){ - var arrays = _.toArray(arguments), - first = arrays.shift(); - - return arrays.every(function(arr) { - return ( - arr.length === first.length && - !_.difference(arr, first).length - ); + identical: function () { + var arrays = _.toArray(arguments), + first = arrays.shift(); + + return arrays.every(function (arr) { + return arr.length === first.length && + !_.difference(arr, first).length; }); } }); @@ -399,13 +434,13 @@ define([ * @returns {String} */ uniqueid: function (size) { - var code = (Math.random() * 25 + 65) | 0, - idstr = String.fromCharCode(code); + var code = Math.random() * 25 + 65 | 0, + idstr = String.fromCharCode(code); size = size || 7; while (idstr.length < size) { - code = Math.floor((Math.random() * 42) + 48); + code = Math.floor(Math.random() * 42 + 48); if (code < 58 || code > 64) { idstr += String.fromCharCode(code); @@ -418,11 +453,10 @@ define([ /** * Serializes and sends data via POST request. * - * @param {Object} options - - * Options object that consists of - * a 'url' and 'data' properties. + * @param {Object} options - Options object that consists of + * a 'url' and 'data' properties. */ - submit: function(options){ + submit: function (options) { var form = document.createElement('form'), data = this.serialize(options.data), field; @@ -430,7 +464,7 @@ define([ form.setAttribute('action', options.url); form.setAttribute('method', 'post'); - _.each(data, function(value, name){ + _.each(data, function (value, name) { field = document.createElement('input'); field.setAttribute('name', name); @@ -448,4 +482,4 @@ define([ }); return utils; -}); \ No newline at end of file +}); From 023d7cb8f2f73d6d7a13d498ba78769d6cd8c01e Mon Sep 17 00:00:00 2001 From: Vitalii Korotun Date: Tue, 17 Mar 2015 15:23:00 +0200 Subject: [PATCH 002/235] MAGETWO-31654: Magento Ui module code base clean up -rename "ui_component" to "uiComponent" --- .../view/adminhtml/layout/cms_block_index.xml | 2 +- .../view/adminhtml/layout/cms_page_index.xml | 2 +- .../adminhtml/layout/customer_index_edit.xml | 2 +- .../Magento/Ui/view/base/layout/default.xml | 18 -- .../Ui/view/base/layout/ui_components.xml | 235 ------------------ app/etc/di.xml | 14 +- .../UiComponent/Config/ManagerInterface.php | 5 - .../Magento/Framework/View/Layout/Element.php | 2 +- .../View/Layout/Generator/UiComponent.php | 2 +- .../View/Layout/Reader/UiComponent.php | 2 +- .../Framework/View/Layout/etc/body.xsd | 2 +- .../Framework/View/Layout/etc/elements.xsd | 10 +- .../Unit/Layout/Reader/UiComponentTest.php | 4 +- 13 files changed, 21 insertions(+), 279 deletions(-) delete mode 100644 app/code/Magento/Ui/view/base/layout/default.xml delete mode 100644 app/code/Magento/Ui/view/base/layout/ui_components.xml diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml index dbf36016b5229..4a66ae566db92 100644 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml +++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_index.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml index f1d5e1ee7b1ae..02204211c1e52 100644 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml +++ b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_index.xml @@ -8,7 +8,7 @@ - + diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml index 8f01263e954a8..eaaa2bba52ade 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_edit.xml @@ -9,7 +9,7 @@ xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> - + diff --git a/app/code/Magento/Ui/view/base/layout/default.xml b/app/code/Magento/Ui/view/base/layout/default.xml deleted file mode 100644 index fd5dc12088e9e..0000000000000 --- a/app/code/Magento/Ui/view/base/layout/default.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - diff --git a/app/code/Magento/Ui/view/base/layout/ui_components.xml b/app/code/Magento/Ui/view/base/layout/ui_components.xml deleted file mode 100644 index e8093ab26f67d..0000000000000 --- a/app/code/Magento/Ui/view/base/layout/ui_components.xml +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - Magento_Ui::listing/horizontal_grid.phtml - 1 - mui/index/render - - - - - - - - - - - Magento_Ui::paging/default.phtml - - - - - Magento_Ui::filter_pool/default.phtml - - - - mm/dd/yyyy - - - - - - - - - - - - - - - - Magento_Ui::sorting/default.phtml - - asc - - - - - - - Magento_Ui::listingcontainer/massaction/default.phtml - - - - - - - - - Magento_Ui/js/form/element/abstract - - input - - - - - - - checkbox - - Magento_Ui/js/form/element/boolean - - checkbox - - - - - - - - Magento_Ui/js/form/element/select - - select - - - - - - - - Magento_Ui/js/form/element/multiselect - - multiselect - ui/form/element/multiselect - - - - - - - - Magento_Ui/js/form/element/textarea - - textarea - - - - - - - - - - - - input - - media - - - - - - - - input - Magento_Ui/js/form/element/date - - date - - - - - - - - input - - select - - - - - - - - input - - email - - - - - - - - Magento_Ui::form/default.phtml - mui/form/save - mui/form/validate - - tabs - - - Magento_Ui/js/form - - - - - - Magento_Ui::form/fieldset/default.phtml - - Magento_Ui/js/form/components/fieldset - - - - - - Magento_Ui::layout/tabs/default.phtml - - Magento_Ui/js/form/components/tabs - - - - - - Magento_Ui::layout/tabs/tab/default.phtml - - Magento_Ui/js/form/components/area - - - - - - Magento_Ui::layout/group/default.phtml - - Magento_Ui/js/form/components/group - - - - - - Magento_Ui::layout/tabs/nav/default.phtml - - Magento_Ui/js/form/components/tab_group - - ui/tab - - - - - - - Magento_Ui::container/content/default.phtml - - Magento_Ui/js/form/components/html - - - - - - - Magento_Ui::form/collection/default.phtml - - Magento_Ui/js/form/components/collection - - - - diff --git a/app/etc/di.xml b/app/etc/di.xml index fe752e71c2253..2e36681447f71 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -401,7 +401,7 @@ Magento\Framework\View\Layout\Reader\Container Magento\Framework\View\Layout\Reader\Block - Magento\Framework\View\Layout\Reader\UiComponent + Magento\Framework\View\Layout\Reader\UiComponent @@ -417,7 +417,7 @@ Magento\Framework\View\Layout\Reader\Block Magento\Framework\View\Layout\Reader\Move Magento\Framework\View\Layout\Reader\Remove - Magento\Framework\View\Layout\Reader\UiComponent + Magento\Framework\View\Layout\Reader\UiComponent @@ -441,7 +441,7 @@ Magento\Framework\View\Layout\Reader\Block Magento\Framework\View\Layout\Reader\Move Magento\Framework\View\Layout\Reader\Remove - Magento\Framework\View\Layout\Reader\UiComponent + Magento\Framework\View\Layout\Reader\UiComponent @@ -460,7 +460,7 @@ Magento\Framework\View\Layout\Reader\Block Magento\Framework\View\Layout\Reader\Move Magento\Framework\View\Layout\Reader\Remove - Magento\Framework\View\Layout\Reader\UiComponent + Magento\Framework\View\Layout\Reader\UiComponent @@ -477,7 +477,7 @@ Magento\Framework\View\Layout\Reader\Block Magento\Framework\View\Layout\Reader\Move Magento\Framework\View\Layout\Reader\Remove - Magento\Framework\View\Layout\Reader\UiComponent + Magento\Framework\View\Layout\Reader\UiComponent @@ -502,7 +502,7 @@ Magento\Framework\View\Page\Config\Generator\Body Magento\Framework\View\Layout\Generator\Block Magento\Framework\View\Layout\Generator\Container - Magento\Framework\View\Layout\Generator\UiComponent + Magento\Framework\View\Layout\Generator\UiComponent @@ -513,7 +513,7 @@ Magento\Framework\View\Page\Config\Generator\Body Magento\Framework\View\Layout\Generator\Block Magento\Framework\View\Layout\Generator\Container - Magento\Framework\View\Layout\Generator\UiComponent + Magento\Framework\View\Layout\Generator\UiComponent diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php index 908576f8f2239..f373b15181c37 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/ManagerInterface.php @@ -17,11 +17,6 @@ interface ManagerInterface */ const SEARCH_PATTERN = '%s.xml'; - /** - * The name of the root node UI components - */ - const UI_COMPONENTS_ROOT_NODE = 'ui_components'; - /** * The anonymous template name */ diff --git a/lib/internal/Magento/Framework/View/Layout/Element.php b/lib/internal/Magento/Framework/View/Layout/Element.php index 01e58372cec32..3ea80ec098168 100644 --- a/lib/internal/Magento/Framework/View/Layout/Element.php +++ b/lib/internal/Magento/Framework/View/Layout/Element.php @@ -37,7 +37,7 @@ class Element extends \Magento\Framework\Simplexml\Element const TYPE_MOVE = 'move'; - const TYPE_UI_COMPONENT = 'ui_component'; + const TYPE_UI_COMPONENT = 'uiComponent'; const TYPE_HEAD = 'head'; diff --git a/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php b/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php index d1c8b75f7ed7c..f2f11fe8e8657 100644 --- a/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php +++ b/lib/internal/Magento/Framework/View/Layout/Generator/UiComponent.php @@ -25,7 +25,7 @@ class UiComponent implements GeneratorInterface /** * Generator type */ - const TYPE = 'ui_component'; + const TYPE = 'uiComponent'; /** * Block adapter diff --git a/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php b/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php index f9b5e5c977c19..d90e886305f3b 100644 --- a/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php +++ b/lib/internal/Magento/Framework/View/Layout/Reader/UiComponent.php @@ -18,7 +18,7 @@ class UiComponent implements Layout\ReaderInterface /**#@+ * Supported types */ - const TYPE_UI_COMPONENT = 'ui_component'; + const TYPE_UI_COMPONENT = 'uiComponent'; /**#@-*/ /** diff --git a/lib/internal/Magento/Framework/View/Layout/etc/body.xsd b/lib/internal/Magento/Framework/View/Layout/etc/body.xsd index a8d5a75f795b0..3b187137d61fc 100644 --- a/lib/internal/Magento/Framework/View/Layout/etc/body.xsd +++ b/lib/internal/Magento/Framework/View/Layout/etc/body.xsd @@ -17,7 +17,7 @@ - + diff --git a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd index 655955ff47393..fc44f93df682b 100644 --- a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd +++ b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd @@ -108,7 +108,7 @@ - + Argument name must be unique in scope of all Blocks, Containers and other UI Components. @@ -185,7 +185,7 @@ - + @@ -216,7 +216,7 @@ - + @@ -311,7 +311,7 @@ - + @@ -322,7 +322,7 @@ - + diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/UiComponentTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/UiComponentTest.php index 145c8f6992e91..1c573b9a2a891 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/UiComponentTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Layout/Reader/UiComponentTest.php @@ -82,8 +82,8 @@ public function interpretDataProvider() return [ [ $this->getElement( - '', - 'ui_component' + '', + 'uiComponent' ), ] ]; From a0818c31c05f03ef6b33b8dd40cc14e0530cfc8e Mon Sep 17 00:00:00 2001 From: "Gurzhyi, Andrii" Date: Tue, 17 Mar 2015 16:03:07 +0200 Subject: [PATCH 003/235] MAGETWO-31654: Magento Ui module code base clean up --- .../Magento/Ui/Component/AbstractView.php | 407 ------------- .../Ui/Component/Container/Content.php | 29 - .../Magento/Ui/Component/ElementRenderer.php | 50 -- .../Ui/Component/ElementRendererBuilder.php | 51 -- .../Ui/Component/ElementRendererInterface.php | 19 - .../Ui/Component/Filter/FilterAbstract.php | 97 --- .../Ui/Component/Filter/FilterInterface.php | 21 - .../Ui/Component/Filter/FilterPool.php | 64 -- .../Magento/Ui/Component/Filter/Type/Date.php | 1 - .../Ui/Component/Filter/Type/Input.php | 3 - .../Ui/Component/Filter/Type/Store.php | 15 - app/code/Magento/Ui/Component/FilterPool.php | 193 ------ .../Ui/Component/Form/Element/Multiline.php | 2 +- .../Ui/Component/Layout/AbstractStructure.php | 564 ------------------ app/code/Magento/Ui/Component/Layout/Tabs.php | 7 +- .../Magento/Ui/Component/Layout/Tabs/Tab.php | 25 - .../Ui/Component/Listing/OptionsFactory.php | 49 -- .../Ui/Component/Listing/OptionsInterface.php | 20 - .../Magento/Ui/Component/Listing/RowPool.php | 56 -- .../Ui/Component/RenderLayoutInterface.php | 15 - app/code/Magento/Ui/Component/Search.php | 14 - .../Ui/ContentType/Builder/ConfigJson.php | 30 - .../ContentType/Builder/ConfigStorageJson.php | 73 --- .../Ui/ContentType/ContentTypeFactory.php | 72 --- .../Ui/ContentType/ContentTypeInterface.php | 23 - app/code/Magento/Ui/ContentType/Html.php | 61 -- app/code/Magento/Ui/ContentType/Json.php | 52 -- app/code/Magento/Ui/ContentType/Xml.php | 102 ---- app/code/Magento/Ui/Context/Configuration.php | 109 ---- .../Ui/Context/ConfigurationStorage.php | 340 ----------- app/code/Magento/Ui/Context/DataProvider.php | 22 - .../DataProviderCollectionInterface.php | 29 - .../DataProviderEntityInterface.php | 16 - app/code/Magento/Ui/DataProvider/Factory.php | 41 -- .../UiComponent/ConfigBuilderInterface.php | 20 - .../Element/UiComponent/ConfigFactory.php | 53 -- .../Element/UiComponent/ConfigInterface.php | 52 -- .../ConfigStorageBuilderInterface.php | 21 - .../UiComponent/ConfigStorageInterface.php | 222 ------- .../UiComponent/DataProviderInterface.php | 27 - .../View/Element/UiElementFactory.php | 59 -- 41 files changed, 4 insertions(+), 3122 deletions(-) delete mode 100644 app/code/Magento/Ui/Component/AbstractView.php delete mode 100644 app/code/Magento/Ui/Component/Container/Content.php delete mode 100644 app/code/Magento/Ui/Component/ElementRenderer.php delete mode 100644 app/code/Magento/Ui/Component/ElementRendererBuilder.php delete mode 100644 app/code/Magento/Ui/Component/ElementRendererInterface.php delete mode 100644 app/code/Magento/Ui/Component/Filter/FilterAbstract.php delete mode 100644 app/code/Magento/Ui/Component/Filter/FilterInterface.php delete mode 100644 app/code/Magento/Ui/Component/Filter/FilterPool.php delete mode 100644 app/code/Magento/Ui/Component/Filter/Type/Store.php delete mode 100644 app/code/Magento/Ui/Component/FilterPool.php delete mode 100644 app/code/Magento/Ui/Component/Layout/AbstractStructure.php delete mode 100644 app/code/Magento/Ui/Component/Layout/Tabs/Tab.php delete mode 100644 app/code/Magento/Ui/Component/Listing/OptionsFactory.php delete mode 100644 app/code/Magento/Ui/Component/Listing/OptionsInterface.php delete mode 100644 app/code/Magento/Ui/Component/Listing/RowPool.php delete mode 100644 app/code/Magento/Ui/Component/RenderLayoutInterface.php delete mode 100644 app/code/Magento/Ui/Component/Search.php delete mode 100644 app/code/Magento/Ui/ContentType/Builder/ConfigJson.php delete mode 100644 app/code/Magento/Ui/ContentType/Builder/ConfigStorageJson.php delete mode 100644 app/code/Magento/Ui/ContentType/ContentTypeFactory.php delete mode 100644 app/code/Magento/Ui/ContentType/ContentTypeInterface.php delete mode 100644 app/code/Magento/Ui/ContentType/Html.php delete mode 100644 app/code/Magento/Ui/ContentType/Json.php delete mode 100644 app/code/Magento/Ui/ContentType/Xml.php delete mode 100644 app/code/Magento/Ui/Context/Configuration.php delete mode 100644 app/code/Magento/Ui/Context/ConfigurationStorage.php delete mode 100644 app/code/Magento/Ui/Context/DataProvider.php delete mode 100644 app/code/Magento/Ui/DataProvider/DataProviderCollectionInterface.php delete mode 100644 app/code/Magento/Ui/DataProvider/DataProviderEntityInterface.php delete mode 100644 app/code/Magento/Ui/DataProvider/Factory.php delete mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ConfigBuilderInterface.php delete mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ConfigFactory.php delete mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ConfigInterface.php delete mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ConfigStorageBuilderInterface.php delete mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/ConfigStorageInterface.php delete mode 100644 lib/internal/Magento/Framework/View/Element/UiComponent/DataProviderInterface.php delete mode 100644 lib/internal/Magento/Framework/View/Element/UiElementFactory.php diff --git a/app/code/Magento/Ui/Component/AbstractView.php b/app/code/Magento/Ui/Component/AbstractView.php deleted file mode 100644 index 7ef6bb68adb07..0000000000000 --- a/app/code/Magento/Ui/Component/AbstractView.php +++ /dev/null @@ -1,407 +0,0 @@ -renderContext = $renderContext; - $this->contentTypeFactory = $contentTypeFactory; - $this->dataManager = $dataProviderManager; - $this->componentData = $arrayObjectFactory->create(); - $this->actionPool = $actionPool; - $this->buttonProviderFactory = $buttonProviderFactory; - - parent::__construct($context, $data); - } - - /** - * Update data - * - * @param array $data - * @return void - */ - public function update(array $data = []) - { - if (!empty($data)) { - $this->_data = array_merge_recursive($this->_data, $data); - } - } - - /** - * Prepare component data - * - * @return void - */ - public function prepare() - { - // - } - - /** - * Render content - * - * @param array $data - * @return string - */ - public function render(array $data = []) - { - $prevData = $this->getData(); - $this->update($data); - - $renderResult = $this->getRenderEngine()->render($this, $this->getContentTemplate()); - - $this->setData($prevData); - - return $renderResult; - } - - /** - * Render label - * - * @return mixed|string - */ - public function renderLabel() - { - return $this->getRenderEngine()->render($this, $this->getLabelTemplate()); - } - - /** - * Render element - * - * @param string $elementName - * @param array $arguments - * @return mixed|string - */ - public function renderElement($elementName, array $arguments) - { - $element = $this->renderContext->getRender()->getUiElementView($elementName); - $result = $element->render($arguments); - - return $result; - } - - /** - * Render component label - * - * @param string $elementName - * @param array $arguments - * @return string - */ - public function renderElementLabel($elementName, array $arguments) - { - $element = $this->renderContext->getRender()->getUiElementView($elementName); - $prevData = $element->getData(); - $element->update($arguments); - $result = $element->renderLabel(); - $element->setData($prevData); - - return $result; - } - - /** - * Shortcut for rendering as HTML - * (used for backward compatibility with standard rendering mechanism via layout interface) - * - * @return string - */ - public function toHtml() - { - return $this->render(); - } - - /** - * Getting label template - * - * @return string|false - */ - public function getLabelTemplate() - { - return 'Magento_Ui::label/default.phtml'; - } - - /** - * Getting content template - * - * @return string|false - */ - public function getContentTemplate() - { - return $this->getData('content_template'); - } - - /** - * Get Layout Node - * - * @param string $fullName - * @param mixed $default - * @return array - */ - public function getLayoutElement($fullName, $default = null) - { - return $this->renderContext->getStorage()->getLayoutNode($fullName, $default); - } - - /** - * Get name component instance - * - * @return string|null - */ - public function getName() - { - return isset($this->componentData['config']['name']) ? $this->componentData['config']['name'] : null; - } - - /** - * Get parent name component instance - * - * @return string|null - */ - public function getParentName() - { - return isset($this->componentData['config']['parent_name']) - ? $this->componentData['config']['parent_name'] - : null; - } - - /** - * Set component configuration - * - * @param string|null $name - * @param string|null $parentName - * @return void - */ - public function prepareConfiguration($name = null, $parentName = null) - { - $defaultConfig = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $defaultConfig = array_merge($defaultConfig, $this->getData('config')); - } - $config = []; - $config['name'] = $name ?: $this->renderContext->getNamespace() . '_' . $this->getNameInLayout(); - $config['parent_name'] = $parentName ?: $this->renderContext->getNamespace(); - if (!empty($defaultConfig)) { - $config['configuration'] = $defaultConfig; - } - - $this->componentData['config'] = $config; - } - - /** - * Get render context - * - * @return RenderContext - */ - public function getRenderContext() - { - return $this->renderContext; - } - - /** - * Set layout for the render - * - * @return UiComponentInterface - */ - public function getUiLayout() - { - return $this->uiLayout; - } - - /** - * Set layout for the render - * - * @param UiComponentInterface $uiLayout - * @return void - */ - public function setUiLayout(UiComponentInterface $uiLayout) - { - $this->uiLayout = $uiLayout; - } - - /** - * Component data - * - * @return \ArrayObject - */ - public function getComponentData() - { - return $this->componentData; - } - - /** - * Get default parameters - * - * @return array - */ - protected function getDefaultConfiguration() - { - return []; - } - - /** - * Get render engine - * - * @return \Magento\Ui\ContentType\ContentTypeInterface - */ - protected function getRenderEngine() - { - return $this->contentTypeFactory->get($this->renderContext->getAcceptType()); - } - - /** - * Add button in the actions toolbar - * - * @return void - */ - protected function addButtons() - { - $buttons = $this->getData('buttons'); - if ($buttons) { - foreach ($buttons as $buttonId => $buttonData) { - if (is_array($buttonData)) { - $buttons[$buttonId] = $buttonData; - continue; - } - /** @var ButtonProviderInterface $button */ - $button = $this->buttonProviderFactory->create($buttonData); - $buttonData = $button->getButtonData(); - if (!$buttonData) { - unset($buttons[$buttonId]); - continue; - } - $buttons[$buttonId] = $buttonData; - } - uasort($buttons, [$this, 'sortButtons']); - - foreach ($buttons as $buttonId => $buttonData) { - $this->actionPool->add($buttonId, $buttonData, $this); - } - } - } - - /** - * Sort buttons by sort order - * - * @param array $itemA - * @param array $itemB - * @return int - */ - public function sortButtons(array $itemA, array $itemB) - { - $sortOrderA = isset($itemA['sort_order']) ? intval($itemA['sort_order']) : 0; - $sortOrderB = isset($itemB['sort_order']) ? intval($itemB['sort_order']) : 0; - - return $sortOrderA - $sortOrderB; - } - - /** - * Method is called before rendering - * - * @return void - */ - public function beforeRender() - { - // - } - - /** - * Method is called after rendering - * - * @return void - */ - public function afterRender() - { - // - } - - /** - * Get component instance name - * - * @return string - */ - public function getComponentName() - { - // - } -} diff --git a/app/code/Magento/Ui/Component/Container/Content.php b/app/code/Magento/Ui/Component/Container/Content.php deleted file mode 100644 index 94c43012e2eac..0000000000000 --- a/app/code/Magento/Ui/Component/Container/Content.php +++ /dev/null @@ -1,29 +0,0 @@ -getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); - } - - $this->prepareConfiguration($configData); - } -} diff --git a/app/code/Magento/Ui/Component/ElementRenderer.php b/app/code/Magento/Ui/Component/ElementRenderer.php deleted file mode 100644 index 3d3e2857aa61b..0000000000000 --- a/app/code/Magento/Ui/Component/ElementRenderer.php +++ /dev/null @@ -1,50 +0,0 @@ -element = $element; - $this->data = $data; - } - - /** - * Render element - * - * @return string - */ - public function render() - { - return $this->element->render($this->data); - } -} diff --git a/app/code/Magento/Ui/Component/ElementRendererBuilder.php b/app/code/Magento/Ui/Component/ElementRendererBuilder.php deleted file mode 100644 index 4672866fc6299..0000000000000 --- a/app/code/Magento/Ui/Component/ElementRendererBuilder.php +++ /dev/null @@ -1,51 +0,0 @@ -objectManager = $objectManager; - } - - /** - * Create element to the render - * - * @param UiComponentInterface $element - * @param array $renderData - * @return ElementRendererInterface - */ - public function create(UiComponentInterface $element, array $renderData) - { - return $this->objectManager->create($this->instanceClass, ['element' => $element, 'data' => $renderData]); - } -} diff --git a/app/code/Magento/Ui/Component/ElementRendererInterface.php b/app/code/Magento/Ui/Component/ElementRendererInterface.php deleted file mode 100644 index 2cffde7c86465..0000000000000 --- a/app/code/Magento/Ui/Component/ElementRendererInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -filterPool = $filterPool; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); - } - - /** - * Prepare component data - * - * @return void - */ - public function prepare() - { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); - } - - $this->prepareConfiguration($configData); - } - - /** - * Get condition by data type - * - * @param string|array $value - * @return array|null - */ - public function getCondition($value) - { - return $value; - } -} diff --git a/app/code/Magento/Ui/Component/Filter/FilterInterface.php b/app/code/Magento/Ui/Component/Filter/FilterInterface.php deleted file mode 100644 index aa1ccfe73e37b..0000000000000 --- a/app/code/Magento/Ui/Component/Filter/FilterInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -objectManager = $objectManager; - $this->filterTypes = $filters; - } - - /** - * Get filter by type - * - * @param string $filterName - * @return FilterInterface - * @throws \InvalidArgumentException - */ - public function getFilter($filterName) - { - if (!isset($this->filters[$filterName])) { - if (!isset($this->filterTypes[$filterName])) { - throw new \InvalidArgumentException(sprintf('Unknown filter type "%s"', $filterName)); - } - $this->filters[$filterName] = $this->objectManager->create($this->filterTypes[$filterName]); - } - - return $this->filters[$filterName]; - } -} diff --git a/app/code/Magento/Ui/Component/Filter/Type/Date.php b/app/code/Magento/Ui/Component/Filter/Type/Date.php index 6b47ed8879d00..75483cfa10f55 100644 --- a/app/code/Magento/Ui/Component/Filter/Type/Date.php +++ b/app/code/Magento/Ui/Component/Filter/Type/Date.php @@ -5,7 +5,6 @@ */ namespace Magento\Ui\Component\Filter\Type; -use Magento\Ui\Component\Filter\DataProvider; use Magento\Ui\Component\Filter\AbstractFilter; use Magento\Framework\Stdlib\DateTime\TimezoneInterface; use Magento\Ui\Component\Form\Element\DataType\Date as DataTypeDate; diff --git a/app/code/Magento/Ui/Component/Filter/Type/Input.php b/app/code/Magento/Ui/Component/Filter/Type/Input.php index da2095cd606f3..ca27a41c07487 100644 --- a/app/code/Magento/Ui/Component/Filter/Type/Input.php +++ b/app/code/Magento/Ui/Component/Filter/Type/Input.php @@ -5,10 +5,7 @@ */ namespace Magento\Ui\Component\Filter\Type; -use Magento\Ui\Component\Filter\DataProvider; use Magento\Ui\Component\Filter\AbstractFilter; -use Magento\Framework\View\Element\UiComponentFactory; -use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Ui\Component\Form\Element\Input as ElementInput; /** diff --git a/app/code/Magento/Ui/Component/Filter/Type/Store.php b/app/code/Magento/Ui/Component/Filter/Type/Store.php deleted file mode 100644 index aa0495336a281..0000000000000 --- a/app/code/Magento/Ui/Component/Filter/Type/Store.php +++ /dev/null @@ -1,15 +0,0 @@ -filterPoolProvider = $filterPoolProvider; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); - } - - /** - * Prepare component data - * - * @return void - */ - public function prepare() - { - $configData = $this->getDefaultConfiguration(); - if ($this->hasData('config')) { - $configData = array_merge($configData, $this->getData('config')); - } - $this->prepareConfiguration($configData); - $this->updateDataCollection(); - } - - /** - * Get fields - * - * @return array - */ - public function getFields() - { - $meta = $this->renderContext->getStorage()->getMeta($this->getParentName()); - $fields = []; - if (isset($meta['fields'])) { - foreach ($meta['fields'] as $name => $config) { - if (isset($config['filterable']) && $config['filterable'] === false) { - continue; - } - $fields[$name] = $config; - } - } - return $fields; - } - - /** - * Get active filters - * - * @return array - */ - public function getActiveFilters() - { - $metaData = $this->renderContext->getStorage()->getMeta($this->getParentName()); - $metaData = $metaData['fields']; - $filters = []; - $filterData = $this->prepareFilterString( - $this->renderContext->getRequestParam(FilterAbstract::FILTER_VAR) - ); - foreach ($filterData as $field => $value) { - if (isset($metaData[$field]['filter_type'])) { - $filters[$field] = [ - 'label' => $metaData[$field]['label'], - 'current_display_value' => $value, - ]; - } - } - - return $filters; - } - - /** - * Update data collection - * - * @return void - */ - protected function updateDataCollection() - { - $collection = $this->renderContext->getStorage()->getDataCollection($this->getParentName()); - - $metaData = $this->renderContext->getStorage()->getMeta($this->getParentName()); - $metaData = $metaData['fields']; - $filterData = $this->prepareFilterString( - $this->renderContext->getRequestParam(FilterAbstract::FILTER_VAR) - ); - foreach ($filterData as $field => $value) { - if (!isset($metaData[$field]['filter_type'])) { - continue; - } - $condition = $this->filterPoolProvider->getFilter($metaData[$field]['filter_type'])->getCondition($value); - if ($condition !== null) { - $collection->addFilter($field, $field, $condition); - } - } - } - - /** - * Get list of required filters - * - * @return array - */ - protected function getListOfRequiredFilters() - { - $result = []; - foreach ($this->getFields() as $field) { - $result[] = isset($field['filter_type']) ? $field['filter_type'] : $field['input_type']; - } - - return $result; - } - - /** - * Decode filter string - * - * @param string $filterString - * @return array - */ - protected function prepareFilterString($filterString) - { - $data = []; - $filterString = base64_decode($filterString); - parse_str($filterString, $data); - array_walk_recursive( - $data, - // @codingStandardsIgnoreStart - /** - * Decodes URL-encoded string and trims whitespaces from the beginning and end of a string - * - * @param string $value - */ - // @codingStandardsIgnoreEnd - function (&$value) { - $value = trim(rawurldecode($value)); - } - ); - return $data; - } -} diff --git a/app/code/Magento/Ui/Component/Form/Element/Multiline.php b/app/code/Magento/Ui/Component/Form/Element/Multiline.php index ade5dc6ab6f29..8c1ab2b93fab8 100644 --- a/app/code/Magento/Ui/Component/Form/Element/Multiline.php +++ b/app/code/Magento/Ui/Component/Form/Element/Multiline.php @@ -35,6 +35,6 @@ public function getType() */ public function prepare() { - parent::prepare(); // TODO: Change the autogenerated stub + parent::prepare(); } } diff --git a/app/code/Magento/Ui/Component/Layout/AbstractStructure.php b/app/code/Magento/Ui/Component/Layout/AbstractStructure.php deleted file mode 100644 index 8fdd8616b7c8b..0000000000000 --- a/app/code/Magento/Ui/Component/Layout/AbstractStructure.php +++ /dev/null @@ -1,564 +0,0 @@ - [], - 'areas' => [], - 'groups' => [], - 'elements' => [], - ]; - - /** - * @var UiElementFactory - */ - protected $factory; - - /** - * Layout Namespace - * - * @var string - */ - protected $ns; - - /** - * @var int - */ - protected $sortInc = 10; - - /** - * Constructor - * - * @param TemplateContext $context - * @param Context $renderContext - * @param ContentTypeFactory $contentTypeFactory - * @param ConfigFactory $configFactory - * @param ConfigBuilderInterface $configBuilder - * @param DataProviderFactory $dataProviderFactory - * @param Manager $dataProviderManager - * @param UiElementFactory $factory - * @param array $data - */ - public function __construct( - TemplateContext $context, - Context $renderContext, - ContentTypeFactory $contentTypeFactory, - ConfigFactory $configFactory, - ConfigBuilderInterface $configBuilder, - DataProviderFactory $dataProviderFactory, - Manager $dataProviderManager, - UiElementFactory $factory, - array $data = [] - ) { - $this->factory = $factory; - parent::__construct( - $context, - $renderContext, - $contentTypeFactory, - $configFactory, - $configBuilder, - $dataProviderFactory, - $dataProviderManager, - $data - ); - } - - /** - * @inheritdoc - * @SuppressWarnings(PHPMD.UnusedLocalVariable) - */ - public function prepare() - { - $this->ns = $this->getData('name'); - - $this->initSections(); - $this->initAreas(); - $this->initGroups(); - $this->initElements(); - - foreach ($this->getDataSources() as $name => $dataSourceConfig) { - $this->processDataSource($dataSourceConfig); - } - - $this->processChildBLocks(); - - $this->renderContext->getStorage()->addLayoutStructure( - $this->getDataScope(), - [ - 'children' => $this->structure - ] - ); - - $navBlock = $this->factory->create( - \Magento\Ui\Component\Layout\Tabs\Nav::NAME, - [ - 'data_scope' => $this->ns - ] - ); - if ($this->getData('configuration/tabs_container_name')) { - $this->getRenderContext()->getPageLayout() - ->addBlock($navBlock, 'tabs_nav', $this->getData('configuration/tabs_container_name')); - } else { - $this->getRenderContext()->getPageLayout() - ->addBlock($navBlock, 'tabs_nav', 'content'); - } - } - - /** - * @return string - */ - public function getDataScope() - { - return $this->ns; - } - - /** - * Prepare initial structure for sections - * - * @return void - */ - protected function initSections() - { - $this->structure['sections'] = [ - 'type' => \Magento\Ui\Component\Layout\Tabs\Nav::NAME, - 'config' => [ - 'label' => $this->getData('label'), - ], - 'children' => [], - ]; - } - - /** - * Prepare initial structure for areas - * - * @return void - */ - protected function initAreas() - { - $this->structure['areas'] = [ - 'type' => 'form', - 'config' => [ - 'namespace' => $this->ns, - ], - 'children' => [], - ]; - } - - /** - * Prepare initial structure for groups - * - * @return void - */ - protected function initGroups() - { - $this->structure['groups'] = [ - 'children' => [], - ]; - } - - /** - * Prepare initial structure for elements - * - * @return void - */ - protected function initElements() - { - $this->structure['elements'] = [ - 'children' => [], - ]; - } - - /** - * Get registered Data Sources - * - * @return array - */ - protected function getDataSources() - { - return $this->getData('data_sources'); - } - - /** - * @param array $dataSourceConfig - * @return void - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - protected function processDataSource(array $dataSourceConfig) - { - $id = $this->renderContext->getRequestParam('id'); - $dataSource = $dataSourceConfig['name']; - - $meta = $this->dataManager->getMetadata($dataSource); - - $this->addArea( - $dataSource, - [ - 'insertTo' => [ - $this->ns . '.sections' => [ - 'position' => $this->getNextSortInc(), - ], - ], - 'config' => [ - 'label' => $meta->getLabel(), - ] - ] - ); - $referenceGroupName = $this->addGroup( - $dataSource, - [ - 'label' => $meta->getLabel() - ] - ); - - $elements = $meta->getFields(); - uasort($elements, [$this, 'sortChildren']); - foreach ($elements as $name => $element) { - if (isset($element['visible']) && $element['visible'] === 'false') { - continue; - } - if ($name != Metadata::CHILD_DATA_SOURCES) { - $collection = & $this->structure['elements']; - $this->addElementToCollection($collection, $name, "{$dataSource}.{$name}", $element); - - $referenceName = "{$this->ns}.elements.{$name}"; - $this->addElementToGroup($dataSource, $name, $referenceName, $element); - } - } - - $this->addToArea($dataSource, $referenceGroupName); - - $children = $meta->get(Metadata::CHILD_DATA_SOURCES); - foreach ($children as $childName => $childMeta) { - $this->processChildDataSource($dataSource, $childName, $childMeta); - } - - $preparedData = []; - $data = $id ? $this->dataManager->getData($dataSource, ['entity_id' => $id]) : []; - if ($data) { - $preparedData[$dataSource] = []; - foreach (array_shift($data) as $key => $value) { - $preparedData[$dataSource][$key] = $value; - } - } - - $this->renderContext->getStorage()->addDataSource( - $this->getData('name'), - [ - 'data' => $preparedData, - 'config' => $dataSourceConfig, - ] - ); - } - - /** - * @param string $dataSource - * @param string $childName - * @param \Magento\Ui\DataProvider\Metadata $childMeta - * @return void - */ - protected function processChildDataSource($dataSource, $childName, \Magento\Ui\DataProvider\Metadata $childMeta) - { - $this->addArea( - $childName, - [ - 'insertTo' => [ - $this->ns . '.sections' => [ - 'position' => $this->getNextSortInc(), - ], - ], - 'config' => [ - 'label' => $childMeta->getLabel(), - ] - ] - ); - $referenceChildGroupName = $this->addGroup( - $childName, - [ - 'label' => $childMeta->getLabel() - ] - ); - $this->addToArea($childName, $referenceChildGroupName); - - $itemTemplate = [ - 'type' => $this->ns, - 'isTemplate' => true, - 'component' => 'Magento_Ui/js/form/components/collection/item', - 'childType' => 'group', - 'config' => [ - 'label' => __('New ' . $childMeta->getLabel()), - ], - ]; - - $elements = $childMeta->getFields(); - uasort($elements, [$this, 'sortChildren']); - foreach ($elements as $name => $element) { - if (isset($element['visible']) && $element['visible'] === 'false') { - continue; - } - $this->addElementToCollection($itemTemplate, $name, $name, $element); - } - - $referenceCollectionName = $this->addCollection( - $childName . 'Collection', - "{$dataSource}.{$childName}", - [ - 'active' => 1, - 'label' => $childMeta->getLabel(), - 'removeLabel' => __('Remove ' . $childMeta->getLabel()), - 'removeMessage' => __('Are you sure you want to delete this item?'), - 'addLabel' => __('Add New ' . $childMeta->getLabel()), - 'itemTemplate' => 'item_template' - ] - ); - $this->addTemplateToCollection($childName . 'Collection', 'item_template', $itemTemplate); - - $this->structure['groups']['children'][$childName]['children'][] = $referenceCollectionName; - } - - /** - * @throws \Exception - * @return void - */ - protected function processChildBlocks() - { - //Add child blocks content - foreach ($this->getData('child_blocks') as $blockName => $childBlock) { - /** @var TabInterface $childBlock */ - if (!($childBlock instanceof TabInterface)) { - throw new \Exception(__('"%1" tab should implement TabInterface', $blockName)); - } - if (!$childBlock->canShowTab()) { - continue; - } - $childBlock->setData('target_form', $this->getDataScope()); - $sortOrder = $childBlock->hasSortOrder() ? $childBlock->getSortOrder() : $this->getNextSortInc(); - $this->addArea( - $blockName, - [ - 'insertTo' => [ - $this->ns . '.sections' => [ - 'position' => (int)$sortOrder, - ], - ], - 'config' => [ - 'label' => $childBlock->getTabTitle(), - ] - ] - ); - - $config = [ - 'label' => $childBlock->getTabTitle(), - ]; - if ($childBlock->isAjaxLoaded()) { - $config['source'] = $childBlock->getTabUrl(); - } else { - $config['content'] = $childBlock->toHtml(); - } - $referenceGroupName = $this->addGroup($blockName, $config, 'html_content'); - $this->addToArea($blockName, $referenceGroupName); - } - } - - /** - * @param string $name - * @param array $config - * @return string - */ - protected function addArea($name, array $config = []) - { - $config['type'] = 'tab'; - $this->structure['areas']['children'][$name] = $config; - return "{$this->ns}.areas.{$name}"; - } - - /** - * @param string $areaName - * @param string $itemName - * @return void - */ - protected function addToArea($areaName, $itemName) - { - $this->structure['areas']['children'][$areaName]['children'][] = $itemName; - } - - /** - * @param string $groupName - * @param array $config - * @param string $type - * @return string - */ - protected function addGroup($groupName, array $config = [], $type = 'fieldset') - { - $this->structure['groups']['children'][$groupName] = [ - 'type' => $type, - 'config' => $config, - ]; - return "{$this->ns}.groups.{$groupName}"; - } - - /** - * @param string $groupName - * @param string $elementName - * @param string $referenceElementName - * @param array $element - * @return void - */ - protected function addElementToGroup($groupName, $elementName, $referenceElementName, array $element) - { - if (isset($element['fieldGroup'])) { - if ($elementName === $element['fieldGroup']) { - $this->structure['groups']['children'][$groupName]['children'][] = $referenceElementName; - } - } else { - $this->structure['groups']['children'][$groupName]['children'][] = $referenceElementName; - } - } - - /** - * @param array $collection - * @param string $elementName - * @param string $dataScope - * @param array $element - * @return string - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function addElementToCollection(array & $collection, $elementName, $dataScope, array $element) - { - $collection['children'][$elementName] = [ - 'type' => 'group', - ]; - if (isset($element['fieldGroup'])) { - $elementName = $element['fieldGroup']; - if ($elementName === $element['fieldGroup']) { - $collection['children'][$elementName]['config'] = [ - 'displayArea' => $element['displayArea'], - ]; - } - } else { - $collection['children'][$elementName]['config'] = [ - 'displayArea' => $element['displayArea'], - ]; - } - - if (isset($element['constraints'])) { - if (isset($element['constraints']['validate'])) { - $element['validation'] = $element['constraints']['validate']; - } - if (isset($element['constraints']['filter'])) { - foreach ($element['constraints']['filter'] as $filter) { - $element['listeners'] = [ - "data:" . $filter['on'] => [ - 'filter' => [$filter['by']], - ], - ]; - } - } - unset($element['constraints']); - } - if (isset($element['size'])) { - $collection['children'][$elementName]['dataScope'] = $dataScope; - $size = (int)$element['size']; - for ($i = 0; $i < $size; $i++) { - $collection['children'][$elementName]['children'][] = [ - 'type' => $element['formElement'], - 'dataScope' => (string)$i, - 'config' => $element, - ]; - if (isset($element['validation']['required-entry'])) { - unset($element['validation']['required-entry']); - } - } - } else { - $collection['children'][$elementName]['children'][] = [ - 'type' => $element['formElement'], - 'dataScope' => $dataScope, - 'config' => $element, - ]; - } - } - - /** - * @param string $collectionName - * @param string $dataScope - * @param array $config - * @return string - */ - protected function addCollection($collectionName, $dataScope, array $config = []) - { - $this->structure['groups']['children'][$collectionName] = [ - 'type' => 'collection', - 'dataScope' => $dataScope, - 'config' => $config, - ]; - return "{$this->ns}.groups.{$collectionName}"; - } - - /** - * @param string $collectionName - * @param string $templateName - * @param array $template - * @return void - */ - protected function addTemplateToCollection($collectionName, $templateName, $template) - { - $this->structure['groups']['children'][$collectionName]['children'][$templateName] = $template; - } - - /** - * @return int - */ - protected function getNextSortInc() - { - $this->sortInc += 10; - return $this->sortInc; - } - - /** - * Sort child elements - * - * @param array $one - * @param array $two - * @return int - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function sortChildren(array $one, array $two) - { - if (!isset($one['sortOrder'])) { - return 1; - } - if (!isset($two['sortOrder'])) { - return -1; - } - $sortOrderA = isset($one['sortOrder']) ? intval($one['sortOrder']) : -1; - $sortOrderB = isset($two['sortOrder']) ? intval($two['sortOrder']) : -1; - if ($sortOrderA == $sortOrderB) { - return 0; - } - return ($sortOrderA < $sortOrderB) ? -1 : 1; - } -} diff --git a/app/code/Magento/Ui/Component/Layout/Tabs.php b/app/code/Magento/Ui/Component/Layout/Tabs.php index 71031a8586d83..fdc92d1fc54b7 100644 --- a/app/code/Magento/Ui/Component/Layout/Tabs.php +++ b/app/code/Magento/Ui/Component/Layout/Tabs.php @@ -5,14 +5,13 @@ */ namespace Magento\Ui\Component\Layout; -use Magento\Framework\View\Element\BlockInterface; -use Magento\Framework\View\Element\UiComponent\DataSourceInterface; -use Magento\Framework\View\Element\UiComponentInterface; - use Magento\Ui\DataProvider\Metadata; use Magento\Framework\View\Element\Template; +use Magento\Framework\View\Element\BlockInterface; use Magento\Ui\Component\Layout\Tabs\TabInterface; +use Magento\Framework\View\Element\UiComponentInterface; use Magento\Framework\View\Element\UiComponent\LayoutInterface; +use Magento\Framework\View\Element\UiComponent\DataSourceInterface; /** * Class Layout diff --git a/app/code/Magento/Ui/Component/Layout/Tabs/Tab.php b/app/code/Magento/Ui/Component/Layout/Tabs/Tab.php deleted file mode 100644 index 4428717e8bc07..0000000000000 --- a/app/code/Magento/Ui/Component/Layout/Tabs/Tab.php +++ /dev/null @@ -1,25 +0,0 @@ -objectManager = $objectManager; - } - - /** - * Getting provider object - * - * @param string $class - * @param array $arguments - * @return OptionsInterface - * @throws \InvalidArgumentException - */ - public function create($class, array $arguments = []) - { - $object = $this->objectManager->create($class, $arguments); - if (!($object instanceof OptionsInterface)) { - throw new \InvalidArgumentException( - sprintf('"%s" must implement the interface \Magento\Ui\Component\Listing\OptionsInterface', $class) - ); - } - - return $object; - } -} diff --git a/app/code/Magento/Ui/Component/Listing/OptionsInterface.php b/app/code/Magento/Ui/Component/Listing/OptionsInterface.php deleted file mode 100644 index 97ffc3d9c15f1..0000000000000 --- a/app/code/Magento/Ui/Component/Listing/OptionsInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -objectManager = $objectManager; - } - - /** - * Getting provider object - * - * @param string $class - * @param array $arguments - * @return RowInterface - * @throws \InvalidArgumentException - */ - public function get($class, array $arguments = []) - { - if (!isset($this->classPool[$class])) { - $this->classPool[$class] = $this->objectManager->create($class, $arguments); - if (!($this->classPool[$class] instanceof RowInterface)) { - throw new \InvalidArgumentException( - sprintf('"%s" must implement the interface \Magento\Ui\Component\Listing\RowInterface', $class) - ); - } - } - - return $this->classPool[$class]; - } -} diff --git a/app/code/Magento/Ui/Component/RenderLayoutInterface.php b/app/code/Magento/Ui/Component/RenderLayoutInterface.php deleted file mode 100644 index 34bb85e8d7469..0000000000000 --- a/app/code/Magento/Ui/Component/RenderLayoutInterface.php +++ /dev/null @@ -1,15 +0,0 @@ -getData(); - $result['name'] = $configuration->getName(); - $result['parent_name'] = $configuration->getParentName(); - - return json_encode($result); - } -} diff --git a/app/code/Magento/Ui/ContentType/Builder/ConfigStorageJson.php b/app/code/Magento/Ui/ContentType/Builder/ConfigStorageJson.php deleted file mode 100644 index 99eca8d299434..0000000000000 --- a/app/code/Magento/Ui/ContentType/Builder/ConfigStorageJson.php +++ /dev/null @@ -1,73 +0,0 @@ - [], - ]; - $result['meta'] = $storage->getMeta($parentName); - $dataSource = $storage->getDataSource($parentName); - $data = isset($dataSource['data']) ? $dataSource['data'] : null; - if ($parentName !== null) { - $rootComponent = $storage->getComponentsData($parentName); - $result['name'] = $rootComponent->getName(); - $result['parent_name'] = $rootComponent->getParentName(); - $result['data'] = $data; - $result['config']['components'][$rootComponent->getName()] = $rootComponent->getData(); - } else { - $components = $storage->getComponentsData(); - if (!empty($components)) { - /** @var ConfigInterface $component */ - foreach ($components as $name => $component) { - $result['config']['components'][$name] = $component->getData(); - } - } - $result['data'] = $data; - } - $result['config'] += $storage->getGlobalData(); - $result['dump']['extenders'] = []; - - return json_encode($result); - } - - /** - * Config storage data to JSON by output - * - * @param ConfigStorageInterface $storage - * @return string - */ - public function toJsonNew(ConfigStorageInterface $storage) - { - $result = []; - foreach ($storage->getDataSource() as $name => $dataSource) { - $dataSource['path'] = 'Magento_Ui/js/form/provider'; - $result['providers'][$name] = $dataSource; - } - $result['renderer'] = [ - 'types' => $storage->getComponents(), - 'layout' => $storage->getLayoutStructure(), - ]; - return json_encode($result); - } -} diff --git a/app/code/Magento/Ui/ContentType/ContentTypeFactory.php b/app/code/Magento/Ui/ContentType/ContentTypeFactory.php deleted file mode 100644 index 5bdda92584f66..0000000000000 --- a/app/code/Magento/Ui/ContentType/ContentTypeFactory.php +++ /dev/null @@ -1,72 +0,0 @@ - 'Magento\Ui\ContentType\Html', - 'json' => 'Magento\Ui\ContentType\Json', - 'xml' => 'Magento\Ui\ContentType\Xml', - ]; - - /** - * Object manager - * - * @var \Magento\Framework\ObjectManagerInterface - */ - protected $objectManager; - - /** - * Constructor - * - * @param ObjectManagerInterface $objectManager - * @param array $types - */ - public function __construct(ObjectManagerInterface $objectManager, array $types = []) - { - $this->types = array_merge($this->types, $types); - $this->objectManager = $objectManager; - } - - /** - * Get content type object instance - * - * @param string $type - * @return ContentTypeInterface - * @throws \InvalidArgumentException - */ - public function get($type = ContentTypeFactory::DEFAULT_TYPE) - { - if (!isset($this->types[$type])) { - throw new \InvalidArgumentException(sprintf("Wrong content type '%s', renderer not exists.", $type)); - } - - $contentRender = $this->objectManager->get($this->types[$type]); - if (!$contentRender instanceof ContentTypeInterface) { - throw new \InvalidArgumentException( - sprintf('"%s" must implement the interface ContentTypeInterface.', $this->types[$type]) - ); - } - - return $contentRender; - } -} diff --git a/app/code/Magento/Ui/ContentType/ContentTypeInterface.php b/app/code/Magento/Ui/ContentType/ContentTypeInterface.php deleted file mode 100644 index 575c42e77d1dd..0000000000000 --- a/app/code/Magento/Ui/ContentType/ContentTypeInterface.php +++ /dev/null @@ -1,23 +0,0 @@ -filesystem = $filesystem; - $this->templateEnginePool = $templateEnginePool; - } - - /** - * Render data - * - * @param UiComponentInterface $view - * @param string $template - * @return string - */ - public function render(UiComponentInterface $view, $template = '') - { - $templateEngine = false; - if ($template) { - $extension = pathinfo($template, PATHINFO_EXTENSION); - $templateEngine = $this->templateEnginePool->get($extension); - } - if ($templateEngine) { - $path = $this->filesystem->getTemplateFileName($template); - $result = $templateEngine->render($view, $path); - } else { - $result = ''; - } - return $result; - } -} diff --git a/app/code/Magento/Ui/ContentType/Json.php b/app/code/Magento/Ui/ContentType/Json.php deleted file mode 100644 index 4eb26e619a831..0000000000000 --- a/app/code/Magento/Ui/ContentType/Json.php +++ /dev/null @@ -1,52 +0,0 @@ -filesystem = $filesystem; - $this->templateEnginePool = $templateEnginePool; - } - - /** - * Render data - * - * @param UiComponentInterface $view - * @param string $template - * @return string - */ - public function render(UiComponentInterface $view, $template = '') - { - return $view->getRenderContext() - ->getConfigBuilder() - ->toJson($view->getRenderContext()->getStorage(), $view->getName()); - } -} diff --git a/app/code/Magento/Ui/ContentType/Xml.php b/app/code/Magento/Ui/ContentType/Xml.php deleted file mode 100644 index 065a34d73a17f..0000000000000 --- a/app/code/Magento/Ui/ContentType/Xml.php +++ /dev/null @@ -1,102 +0,0 @@ -filesystem = $filesystem; - $this->templateEnginePool = $templateEnginePool; - $this->generator = $generator; - } - - /** - * Render data - * - * @param UiComponentInterface $view - * @param string $template - * @return string - */ - public function render(UiComponentInterface $view, $template = '') - { - $templateEngine = false; - if ($template) { - $extension = pathinfo($template, PATHINFO_EXTENSION); - $templateEngine = $this->templateEnginePool->get($extension); - } - if ($templateEngine) { - $path = $this->filesystem->getTemplateFileName($template); - $result = $templateEngine->render($view, $path); - } else { - $result = $this->getDataXml($view); - } - return $result; - } - - /** - * @param UiComponentInterface $view - * @return string - */ - protected function getDataXml(UiComponentInterface $view) - { - $result = [ - 'configuration' => $view->getRenderContext()->getStorage()->getComponentsData($view->getName())->getData(), - 'data' => [], - ]; - foreach ($view->getRenderContext()->getStorage()->getData($view->getName()) as $key => $value) { - if (is_object($value)) { - if (method_exists($value, 'toXml')) { - $result['data'][$key] = $value->toXml(); - } else { - $result['data'][$key] = $this->objectToXml($value); - } - } else { - $result['data'][$key] = $value; - } - } - return $this->generator->arrayToXml($result); - } - - /** - * Convert object to xml format - * - * @param \Magento\Framework\Object $object - * @return string - */ - protected function objectToXml(\Magento\Framework\Object $object) - { - return (string)$object; - } -} diff --git a/app/code/Magento/Ui/Context/Configuration.php b/app/code/Magento/Ui/Context/Configuration.php deleted file mode 100644 index 7711fec456f00..0000000000000 --- a/app/code/Magento/Ui/Context/Configuration.php +++ /dev/null @@ -1,109 +0,0 @@ -name = $name; - $this->parentName = $parentName; - $this->configuration = $configuration; - } - - /** - * Get configuration data - * - * @param string|null $key - * @return mixed - */ - public function getData($key = null) - { - if ($key === null) { - return (array)$this->configuration; - } - return isset($this->configuration[$key]) ? $this->configuration[$key] : null; - } - - /** - * Add configuration data - * - * @param string $key - * @param mixed $data - * @return mixed - */ - public function addData($key, $data) - { - if (!isset($this->configuration[$key])) { - $this->configuration[$key] = $data; - } - } - - /** - * Update configuration data - * - * @param string $key - * @param mixed $data - * @return mixed - */ - public function updateData($key, $data) - { - $this->configuration[$key] = $data; - } - - /** - * Get owner name - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Get owner parent name - * - * @return string - */ - public function getParentName() - { - return $this->parentName; - } -} diff --git a/app/code/Magento/Ui/Context/ConfigurationStorage.php b/app/code/Magento/Ui/Context/ConfigurationStorage.php deleted file mode 100644 index 91218f496e010..0000000000000 --- a/app/code/Magento/Ui/Context/ConfigurationStorage.php +++ /dev/null @@ -1,340 +0,0 @@ -components[$name] = $data; - } - - /** - * @inheritdoc - */ - public function addComponentsData(ConfigInterface $config) - { - if (!isset($this->componentStorage[$config->getName()])) { - $this->componentStorage[$config->getName()] = $config; - } - } - - /** - * @return array - */ - public function getComponents() - { - return $this->components; - } - - /** - * @return array - */ - public function getMetaKeys() - { - return array_keys($this->metaStorage); - } - - /** - * @inheritdoc - */ - public function removeComponentsData(ConfigInterface $configuration) - { - unset($this->componentStorage[$configuration->getName()]); - } - - /** - * @inheritdoc - */ - public function getComponentsData($name = null) - { - if ($name === null) { - return $this->componentStorage; - } - return isset($this->componentStorage[$name]) ? $this->componentStorage[$name] : null; - } - - /** - * @inheritdoc - */ - public function addDataSource($name, array $dataSource) - { - if (!isset($this->dataStorage[$name])) { - $this->dataStorage[$name] = $dataSource; - } - } - - /** - * @inheritdoc - */ - public function removeDataSource($name) - { - unset($this->dataStorage[$name]); - } - - /** - * @inheritdoc - */ - public function getDataSource($name = null) - { - if ($name === null) { - return $this->dataStorage; - } - return isset($this->dataStorage[$name]) ? $this->dataStorage[$name] : null; - } - - /** - * @inheritdoc - */ - public function updateDataSource($name, array $dataSource) - { - if (isset($this->dataStorage[$name])) { - $this->dataStorage[$name] = $dataSource; - } - } - - /** - * @inheritdoc - */ - public function addMeta($key, array $data) - { - if (!isset($this->metaStorage[$key])) { - $this->metaStorage[$key] = $data; - } - } - - /** - * @inheritdoc - */ - public function removeMeta($key) - { - unset($this->metaStorage[$key]); - } - - /** - * @inheritdoc - */ - public function getMeta($key = null) - { - if ($key === null) { - return $this->metaStorage; - } - return isset($this->metaStorage[$key]) ? $this->metaStorage[$key] : null; - } - - /** - * @inheritdoc - */ - public function updateMeta($key, array $data) - { - if (isset($this->metaStorage[$key])) { - $this->metaStorage[$key] = $data; - } - } - - /** - * @inheritdoc - */ - public function addDataCollection($key, CollectionDataSourceInterface $dataCollection) - { - if (!isset($this->collectionStorage[$key])) { - $this->collectionStorage[$key] = $dataCollection; - } - } - - /** - * @inheritdoc - */ - public function getDataCollection($key = null) - { - if ($key === null) { - return $this->collectionStorage; - } - return isset($this->collectionStorage[$key]) ? $this->collectionStorage[$key] : null; - } - - /** - * @inheritdoc - */ - public function updateDataCollection($key, CollectionDataSourceInterface $dataCollection) - { - if (isset($this->collectionStorage[$key])) { - $this->collectionStorage[$key] = $dataCollection; - } - } - - /** - * @inheritdoc - */ - public function addGlobalData($key, array $data) - { - if (!isset($this->globalDataStorage[$key])) { - $this->globalDataStorage[$key] = $data; - } - } - - /** - * @inheritdoc - */ - public function removeGlobalData($key) - { - unset($this->globalDataStorage[$key]); - } - - /** - * @inheritdoc - */ - public function getGlobalData($key = null) - { - if ($key === null) { - return $this->globalDataStorage; - } - return isset($this->globalDataStorage[$key]) ? $this->globalDataStorage[$key] : null; - } - - /** - * @inheritdoc - */ - public function addDataProvider($key, DataProviderInterface $dataProvider) - { - if (!isset($this->dataProviderStorage[$key])) { - $this->dataProviderStorage[$key] = $dataProvider; - } - } - - /** - * @inheritdoc - */ - public function removeDataProvider($key) - { - if (isset($this->dataProviderStorage[$key])) { - unset($this->dataProviderStorage[$key]); - } - } - - /** - * @inheritdoc - */ - public function getDataProvider($key = null) - { - if ($key === null) { - return $this->dataProviderStorage; - } - return isset($this->dataProviderStorage[$key]) ? $this->dataProviderStorage[$key] : null; - } - - /** - * @inheritdoc - */ - public function updateDataProvider($key, DataProviderInterface $dataProvider) - { - if (isset($this->dataProviderStorage[$key])) { - $this->dataProviderStorage[$key] = $dataProvider; - } - } - - /** - * @inheritdoc - */ - public function addLayoutStructure($dataScope, array $structure) - { - $this->layoutStructure[$dataScope] = $structure; - } - - /** - * @inheritdoc - */ - public function getLayoutStructure() - { - return $this->layoutStructure; - } - - /** - * @inheritdoc - */ - public function getLayoutNode($name, $default = null) - { - if (strpos($name, '.') !== false) { - $nameParts = explode('.', $name); - $firstChunk = array_shift($nameParts); - $node = isset($this->layoutStructure[$firstChunk]) ? $this->layoutStructure[$firstChunk] : []; - foreach ($nameParts as $nodeName) { - if (isset($node['children'][$nodeName])) { - $node = $node['children'][$nodeName]; - } else { - $node = $default; - break; - } - } - } else { - $node = isset($this->layoutStructure[$name]) ? $this->layoutStructure[$name] : []; - } - return $node; - } -} diff --git a/app/code/Magento/Ui/Context/DataProvider.php b/app/code/Magento/Ui/Context/DataProvider.php deleted file mode 100644 index 1621470ec5752..0000000000000 --- a/app/code/Magento/Ui/Context/DataProvider.php +++ /dev/null @@ -1,22 +0,0 @@ -renderContext->getConfigBuilder()->toJson($this->renderContext->getStorage()); - } -} diff --git a/app/code/Magento/Ui/DataProvider/DataProviderCollectionInterface.php b/app/code/Magento/Ui/DataProvider/DataProviderCollectionInterface.php deleted file mode 100644 index b6cc0da7753b1..0000000000000 --- a/app/code/Magento/Ui/DataProvider/DataProviderCollectionInterface.php +++ /dev/null @@ -1,29 +0,0 @@ -objectManager = $objectManager; - } - - /** - * Create data provider - * - * @param string $providerClass - * @param array $arguments - * @return mixed - */ - public function create($providerClass, array $arguments = []) - { - return $this->objectManager->create($providerClass, ['arguments' => $arguments]); - } -} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigBuilderInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigBuilderInterface.php deleted file mode 100644 index bba2e86556c49..0000000000000 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigBuilderInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -objectManager = $objectManager; - $this->instanceName = $instanceName; - } - - /** - * Create class instance with specified parameters - * - * @param array $data - * @return \Magento\Framework\View\Element\UiComponent\ConfigInterface - */ - public function create(array $data = []) - { - return $this->objectManager->create($this->instanceName, $data); - } -} diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigInterface.php deleted file mode 100644 index ad665bc3de14e..0000000000000 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/ConfigInterface.php +++ /dev/null @@ -1,52 +0,0 @@ -objectManager = $objectManager; - $this->context = $context; - } - - /** - * Create data provider - * - * @param string $elementName - * @param array $data - * @return bool|BlockInterface - * @throws \Exception - */ - public function create($elementName, array $data = []) - { - if ('text' == $elementName) { - $elementName = 'input'; - } - $block = $this->context->getLayout()->getBlock($elementName); - if (!$block) { - throw new \Exception('Can not find block of element ' . $elementName); - } - $newBlock = clone $block; - $newBlock->addData($data); - return $newBlock; - } -} From 224c2f4f6a22dbd3cc9ee6a132019c7c0db31cbb Mon Sep 17 00:00:00 2001 From: Denys Rul Date: Tue, 17 Mar 2015 18:05:07 +0200 Subject: [PATCH 004/235] MAGETWO-31654: Magento Ui module code base clean up - Sync up --- .../ui_component/cms_page_listing.xml | 59 ++- .../Theme/view/base/requirejs-config.js | 5 + .../Magento/Ui/Component/Layout/Generic.php | 4 +- .../Magento/Ui/view/base/requirejs-config.js | 5 + .../view/base/ui_component/etc/definition.xml | 2 +- .../web/js/core/renderer/components/layout.js | 4 +- .../web/js/core/renderer/components/types.js | 32 +- app/code/Magento/Ui/view/base/web/js/form.js | 11 +- .../Ui/view/base/web/js/form/client.js | 2 +- .../Ui/view/base/web/js/form/component.js | 473 ----------------- .../base/web/js/form/components/collection.js | 4 +- .../web/js/form/components/collection/item.js | 2 +- .../view/base/web/js/form/components/group.js | 11 +- .../view/base/web/js/form/element/abstract.js | 6 +- .../view/base/web/js/form/element/boolean.js | 2 +- .../base/web/js/form/element/multiselect.js | 8 +- .../view/base/web/js/form/element/select.js | 2 +- .../Ui/view/base/web/js/grid/columns/date.js | 16 + .../view/base/web/js/grid/columns/select.js | 12 +- .../Ui/view/base/web/js/grid/columns/text.js | 25 +- .../view/base/web/js/grid/filters/filters.js | 2 +- .../Ui/view/base/web/js/grid/listing.js | 23 +- .../Ui/view/base/web/js/grid/massactions.js | 36 +- .../Ui/view/base/web/js/grid/paging.js | 2 +- .../Ui/view/base/web/js/grid/provider.js | 18 +- .../Magento/Ui/view/base/web/js/lib/class.js | 7 +- .../Ui/view/base/web/js/lib/component.js | 51 -- .../Ui/view/base/web/js/lib/component/core.js | 2 +- .../view/base/web/js/lib/component/links.js | 10 +- .../lib/component/{component.js => main.js} | 0 .../view/base/web/js/lib/component/manip.js | 2 +- .../view/base/web/js/lib/deferred_events.js | 78 --- .../Ui/view/base/web/js/lib/ko/scope.js | 104 ---- .../Ui/view/base/web/js/lib/provider.js | 45 -- .../view/base/web/js/lib/registry/events.js | 2 +- .../view/base/web/js/lib/registry/registry.js | 30 +- .../Ui/view/base/web/js/lib/storage/dump.js | 10 - .../Ui/view/base/web/js/lib/storage/index.js | 22 - .../Ui/view/base/web/js/lib/storage/meta.js | 186 ------- .../view/base/web/js/lib/storage/storage.js | 82 --- .../Magento/Ui/view/base/web/js/lib/utils.js | 79 --- .../view/base/web/templates/grid/actions.html | 10 +- .../base/web/templates/grid/cells/select.html | 11 - .../base/web/templates/grid/cells/text.html | 2 +- .../templates/grid/columns/massactions.html | 2 +- lib/web/mage/utils.js | 485 ------------------ lib/web/mage/utils/arrays.js | 91 ++++ lib/web/mage/utils/compare.js | 129 +++++ lib/web/mage/utils/main.js | 20 + lib/web/mage/utils/misc.js | 60 +++ lib/web/mage/utils/objects.js | 224 ++++++++ lib/web/mage/utils/strings.js | 61 +++ lib/web/mage/utils/template.js | 85 +++ 53 files changed, 895 insertions(+), 1761 deletions(-) delete mode 100644 app/code/Magento/Ui/view/base/web/js/form/component.js create mode 100644 app/code/Magento/Ui/view/base/web/js/grid/columns/date.js delete mode 100644 app/code/Magento/Ui/view/base/web/js/lib/component.js rename app/code/Magento/Ui/view/base/web/js/lib/component/{component.js => main.js} (100%) delete mode 100644 app/code/Magento/Ui/view/base/web/js/lib/deferred_events.js delete mode 100644 app/code/Magento/Ui/view/base/web/js/lib/ko/scope.js delete mode 100644 app/code/Magento/Ui/view/base/web/js/lib/provider.js delete mode 100644 app/code/Magento/Ui/view/base/web/js/lib/storage/dump.js delete mode 100644 app/code/Magento/Ui/view/base/web/js/lib/storage/index.js delete mode 100644 app/code/Magento/Ui/view/base/web/js/lib/storage/meta.js delete mode 100644 app/code/Magento/Ui/view/base/web/js/lib/storage/storage.js delete mode 100644 app/code/Magento/Ui/view/base/web/js/lib/utils.js delete mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/cells/select.html delete mode 100644 lib/web/mage/utils.js create mode 100644 lib/web/mage/utils/arrays.js create mode 100644 lib/web/mage/utils/compare.js create mode 100644 lib/web/mage/utils/main.js create mode 100644 lib/web/mage/utils/misc.js create mode 100644 lib/web/mage/utils/objects.js create mode 100644 lib/web/mage/utils/strings.js create mode 100644 lib/web/mage/utils/template.js diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml index 964100ae01835..60818fe9ccdfa 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml @@ -37,19 +37,6 @@ - - - - - - - - - - - - - Magento\Cms\Model\Page\DataProvider @@ -75,6 +62,9 @@ Magento_Ui/js/grid/filters/filters + + params.filters + @@ -88,7 +78,7 @@ - From + from From @@ -96,7 +86,7 @@ - To + to To @@ -105,6 +95,7 @@ + title Title @@ -116,12 +107,13 @@ - + Magento\Cms\Model\Page\Source\PageLayout ui/grid/filters/elements/select - Store View + Layout + Select... @@ -129,6 +121,7 @@ Magento\Store\Ui\Component\Listing\Column\Store\Options + Select... ui/grid/filters/elements/select Store View @@ -139,6 +132,7 @@ ui/grid/filters/elements/select Status + Select... 0 @@ -165,7 +159,7 @@ ui/grid/filters/elements/date - From + from From @@ -174,7 +168,7 @@ ui/grid/filters/elements/date - To + to To @@ -186,14 +180,14 @@ Magento_Ui/js/grid/filters/group - Created + Modified ui/grid/filters/elements/date - From + from From @@ -202,13 +196,26 @@ ui/grid/filters/elements/date - To + to To + + + + + + + + + + + + + @@ -228,7 +235,6 @@ Magento_Ui/js/grid/columns/text - asc left Title @@ -275,7 +281,6 @@ Magento_Ui/js/grid/columns/select - asc left Status @@ -284,22 +289,24 @@ - Magento_Ui/js/grid/columns/text + Magento_Ui/js/grid/columns/date left Created + MMM d, YYYY h:mm:ss A - Magento_Ui/js/grid/columns/text + Magento_Ui/js/grid/columns/date left Modified + MMM d, YYYY h:mm:ss A diff --git a/app/code/Magento/Theme/view/base/requirejs-config.js b/app/code/Magento/Theme/view/base/requirejs-config.js index 637568a9c357c..58dbd2b841a66 100644 --- a/app/code/Magento/Theme/view/base/requirejs-config.js +++ b/app/code/Magento/Theme/view/base/requirejs-config.js @@ -5,6 +5,11 @@ var config = { "waitSeconds": 0, + "map": { + "*": { + "mageUtils": "mage/utils/main" + } + }, "shim": { "jquery/jquery-migrate": ["jquery"], "jquery/jquery.hashchange": ["jquery", "jquery/jquery-migrate"], diff --git a/app/code/Magento/Ui/Component/Layout/Generic.php b/app/code/Magento/Ui/Component/Layout/Generic.php index 7745229ca1392..6783ddf51086c 100644 --- a/app/code/Magento/Ui/Component/Layout/Generic.php +++ b/app/code/Magento/Ui/Component/Layout/Generic.php @@ -67,7 +67,9 @@ protected function addChildren( $nodeData = [ 'type' => $componentType, 'name' => $component->getName(), - 'dataScope' => $component->getContext()->getNamespace(), + 'dataScope' => isset($config['dataScope']) + ? $config['dataScope'] + : $component->getContext()->getNamespace(), 'children' => $childrenNode ]; if (!empty($config)) { diff --git a/app/code/Magento/Ui/view/base/requirejs-config.js b/app/code/Magento/Ui/view/base/requirejs-config.js index 8f1227f8bf264..ab04a98d63815 100644 --- a/app/code/Magento/Ui/view/base/requirejs-config.js +++ b/app/code/Magento/Ui/view/base/requirejs-config.js @@ -7,5 +7,10 @@ var config = { paths: { 'ui/template': 'Magento_Ui/templates', 'i18n': 'Magento_Ui/js/lib/i18n' + }, + map: { + '*': { + uiComponent: 'Magento_Ui/js/lib/component/main' + } } }; \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml index b6e474b30854e..3330e30fd28d9 100644 --- a/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml +++ b/app/code/Magento/Ui/view/base/ui_component/etc/definition.xml @@ -13,7 +13,7 @@ 1 mui/index/render - Magento_Ui/js/lib/component/component + uiComponent diff --git a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js b/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js index bbffaa4acec27..aac0784ecb4e1 100644 --- a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js +++ b/app/code/Magento/Ui/view/base/web/js/core/renderer/components/layout.js @@ -5,7 +5,7 @@ define([ 'underscore', 'jquery', - 'mage/utils', + 'mageUtils', 'Magento_Ui/js/lib/class', 'Magento_Ui/js/lib/registry/registry' ], function (_, $, utils, Class, registry) { @@ -45,7 +45,7 @@ define([ } function mergeNode(node, config) { - return $.extend(true, {}, config, node); + return utils.extend({}, config, node); } function additional(node) { diff --git a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/types.js b/app/code/Magento/Ui/view/base/web/js/core/renderer/components/types.js index 461bd8332cfd4..ba10463bc2447 100644 --- a/app/code/Magento/Ui/view/base/web/js/core/renderer/components/types.js +++ b/app/code/Magento/Ui/view/base/web/js/core/renderer/components/types.js @@ -4,15 +4,13 @@ */ define([ 'underscore', - 'jquery', - 'mage/utils', - 'Magento_Ui/js/lib/class', - 'Magento_Ui/js/lib/registry/registry' -], function(_, $, utils, Class, registry) { + 'mageUtils', + 'Magento_Ui/js/lib/class' +], function (_, utils, Class) { 'use strict'; return Class.extend({ - initialize: function(types){ + initialize: function (types) { this.types = {}; this.set(types); @@ -20,37 +18,37 @@ define([ return this; }, - set: function(types){ + set: function (types) { types = types || []; - - _.each(types, function(data, type){ + + _.each(types, function (data, type) { this.types[type] = this.flatten(data); }, this); }, - get: function(type){ + get: function (type) { return this.types[type] || {}; }, - flatten: function(data){ + flatten: function (data) { var extender = data.extends || [], - result = {}; + result = {}; extender = utils.stringToArray(extender); extender.push(data); - extender.forEach(function(item){ - if(_.isString(item)){ + extender.forEach(function (item) { + if (_.isString(item)) { item = this.get(item); } - $.extend(true, result, item); + utils.extend(result, item); }, this); delete result.extends; - return result + return result; } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form.js b/app/code/Magento/Ui/view/base/web/js/form.js index ef54b43da9039..2fec472c353c6 100644 --- a/app/code/Magento/Ui/view/base/web/js/form.js +++ b/app/code/Magento/Ui/view/base/web/js/form.js @@ -3,19 +3,20 @@ * See COPYING.txt for license details. */ define([ - 'jquery', 'underscore', 'Magento_Ui/js/form/component', 'Magento_Ui/js/lib/spinner', './form/adapter' -], function ($, _, Component, loader, adapter) { +], function (_, Component, loader, adapter) { 'use strict'; - function collectData(selector) { - var data = $(selector).serializeArray(), + function collectData(selector){ + var items = document.querySelectorAll(selector), result = {}; - data.forEach(function (item) { + items = Array.prototype.slice.call(items); + + items.forEach(function(item){ result[item.name] = item.value; }); diff --git a/app/code/Magento/Ui/view/base/web/js/form/client.js b/app/code/Magento/Ui/view/base/web/js/form/client.js index 4526c775a39f6..11bce6e68eb3e 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/client.js +++ b/app/code/Magento/Ui/view/base/web/js/form/client.js @@ -5,7 +5,7 @@ define([ 'jquery', 'underscore', - 'mage/utils', + 'mageUtils', 'Magento_Ui/js/lib/class' ], function($, _, utils, Class){ 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/form/component.js b/app/code/Magento/Ui/view/base/web/js/form/component.js deleted file mode 100644 index 5b207bfc22205..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/form/component.js +++ /dev/null @@ -1,473 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'mage/utils', - 'Magento_Ui/js/lib/ko/scope', - 'Magento_Ui/js/lib/events', - 'Magento_Ui/js/lib/registry/registry' -], function(_, utils, Scope, EventsBus, registry) { - 'use strict'; - - function getOffsetFor(elems, offset){ - if(typeof offset === 'undefined'){ - offset = -1; - } - - if(offset < 0){ - offset += elems.length + 1; - } - - return offset; - } - - function getProxy(callback, data){ - if(_.isArray(data)){ - data = { - additional: data - } - } - - _.defaults(data, { - conditions: '*', - additional: [], - callback: callback - }); - - return proxy.bind(null, data); - } - - function proxy(data, value){ - var conditions = data.conditions, - args; - - if(conditions === value || conditions === '*'){ - args = data.additional.slice(); - - args.push(value); - - data.callback.apply(null, args); - } - } - - function parseSource(source, storages, data){ - var storage; - - source = utils.template(source, data); - source = source.split(':'); - - storage = source.shift(); - - return { - source: source[0], - storage: storages[storage] - } - } - - var Component = Scope.extend({ - initialize: function(config, additional){ - _.extend(this, config, additional); - - _.bindAll(this, '_insert'); - - this.initProperties() - .initObservable() - .initListeners() - .initUnique(); - - return this; - }, - - /** - * Defines various properties. - * - * @returns {Component} Chainable. - */ - initProperties: function () { - _.extend(this,{ - 'parentName': this.getPart(this.name, -2), - 'parentScope': this.getPart(this.dataScope, -2), - 'provider': registry.get(this.provider), - 'renderer': registry.get('globalStorage').renderer, - 'containers': [], - 'regions': [], - '_elems': [] - }); - - return this; - }, - - /** - * Initializes observable properties. - * - * @returns {Component} Chainable. - */ - initObservable: function(){ - this.observe({ - 'elems': [] - }); - - this.regions.forEach(function(region){ - this.observe(region, []); - }, this); - - return this; - }, - - /** - * Initializes storages listeners. - * - * @returns {Component} Chainable. - */ - initListeners: function(){ - var listeners = this.listeners || {}, - params, - iterator; - - _.each(listeners, function(handlers, source){ - params = parseSource(source, this.provider, this); - iterator = this.initListener.bind(this, params); - - _.each(handlers, iterator); - }, this); - - return this; - }, - - /** - * Initializes listeners of the unique property. - * - * @returns {Component} Chainable. - */ - initUnique: function(){ - var update = this.onUniqueUpdate.bind(this), - params = this.provider.params, - uniqueNs = this.uniqueNs; - - this.hasUnique = this.uniqueProp && uniqueNs; - - if(this.hasUnique){ - params.on('update:' + uniqueNs, update, this.name); - } - - return this; - }, - - /** - * Used as iterator for the listeners object. - * Creates callbacks and assigns it to the specified storage. - * - * @param {Object} data - - Data object that contains storage object and - it's property name that should be listened. - * @param {Object} params - Parameters of the callback. - * @param {String} callback - Callback's name. - */ - initListener: function(data, params, callback){ - var storage = data.storage, - source = data.source; - - callback = this[callback].bind(this); - callback = getProxy(callback, params); - - callback(storage.get(source)); - - storage.on('update:' + source, callback, this.name); - }, - - /** - * Called when current element was injected to another component. - * - * @param {Object} parent - Instance of a 'parent' component. - * @returns {Component} Chainable. - */ - initContainer: function(parent){ - this.containers.push(parent); - - return this; - }, - - /** - * Called when another element was added to current component. - * - * @param {Object} elem - Instance of an element that was added. - * @returns {Component} Chainable. - */ - initElement: function(elem){ - elem.initContainer(this); - - return this; - }, - - /** - * Splits incoming string and returns its' part specified by offset. - * - * @param {String} parts - * @param {Number} [offset] - * @param {String} [delimiter=.] - * @returns {String} - */ - getPart: function(parts, offset, delimiter){ - delimiter = delimiter || '.'; - parts = parts.split(delimiter); - offset = getOffsetFor(parts, offset); - - parts.splice(offset, 1); - - return parts.join(delimiter) || ''; - }, - - /** - * Returns path to components' template. - * @returns {String} - */ - getTemplate: function(){ - return this.template || 'ui/collection'; - }, - - /** - * Updates property specified in uniqueNs - * if components' unique property is set to 'true'. - * - * @returns {Component} Chainable. - */ - setUnique: function () { - var params = this.provider.params, - property = this.uniqueProp; - - if (this[property]()) { - params.set(this.uniqueNs, this.name); - } - - return this; - }, - - /** - * Callback which fires when property under uniqueNs has changed. - */ - onUniqueUpdate: function(name){ - var active = name === this.name, - property = this.uniqueProp; - - this[property](active); - } - }, EventsBus); - - - /** - * Elements manipulation methods. - */ - _.extend(Component.prototype, { - /** - * Requests specified components to insert - * them into 'elems' array starting from provided position. - * - * @param {String} elem - Name of the component to insert. - * @param {Number} [offset=-1] - Position at which to insert elements. - * @returns {Component} Chainable. - */ - insert: function(elem, offset){ - var _elems = this._elems, - insert = this._insert; - - offset = getOffsetFor(_elems, offset); - - _elems.splice(offset, 0, false); - - registry.get(elem, function(elem){ - insert(elem, offset); - }); - - return this; - }, - - /** - * Removes specified element from the 'elems' array. - * - * @param {Object} elem - Element to be removed. - * @returns {Component} Chainable. - */ - remove: function(elem) { - utils.remove(this._elems, elem); - this._update(); - - return this; - }, - - /** - * Destroys current instance along with all of its' children. - */ - destroy: function(){ - this._dropHandlers() - ._clearData() - ._clearRefs(); - }, - - /** - * Removes events listeners. - * @private - * - * @returns {Component} Chainable. - */ - _dropHandlers: function(){ - var provider = this.provider; - - this.off(); - - provider.data.off(this.name); - provider.params.off(this.name); - - return this; - }, - - /** - * Clears all data associated with component. - * @private - * - * @returns {Component} Chainable. - */ - _clearData: function(){ - var provider = this.provider, - layout = this.renderer.layout; - - provider.data.remove(this.dataScope); - provider.params.remove(this.name); - - layout.clear(this.name); - - return this; - }, - - /** - * Removes all references to current instance and - * calls 'destroy' method on all of its' children. - * @private - * - * @returns {Component} Chainable. - */ - _clearRefs: function(){ - registry.remove(this.name); - - this.containers.forEach(function(parent){ - parent.remove(this); - }, this); - - this.elems().forEach(function(child){ - child.destroy(); - }); - - return this; - }, - - /** - * Inserts provided component into 'elems' array at a specified position. - * @private - * - * @param {Object} elem - Element to insert. - * @param {Number} index - Position of the element. - */ - _insert: function(elem, index){ - this._elems[index] = elem; - - this._update() - .initElement(elem); - }, - - /** - * Synchronizes multiple elements arrays with a core '_elems' container. - * Performs elemets grouping by theirs 'displayArea' property. - * @private - * - * @returns {Component} Chainable. - */ - _update: function(){ - var _elems = _.compact(this._elems), - grouped = _.groupBy(_elems, 'displayArea'), - group; - - this.regions.forEach(function(region) { - if ((group = grouped[region])) { - this[region](group); - } - }, this); - - this.elems(_elems); - - return this; - }, - }); - - - /** - * Elements traversing methods. - */ - _.extend(Component.prototype, { - /** - * Tries to call specified method of a current component, - * otherwise delegates attempt to its' children. - * - * @param {String} target - Name of the method. - * @param [...] Arguments that will be passed to method. - * @returns {*} Result of the method calls. - */ - delegate: function(target){ - var args = _.toArray(arguments); - - target = this[target]; - - if(_.isFunction(target)){ - return target.apply(this, args.slice(1)); - } - - return this._delegate(args); - }, - - /** - * Calls 'delegate' method of all of it's children components. - * @private - * - * @param {Array} args - An array of arguments to pass to the next delegation call. - * @returns {Array} An array of delegation resutls. - */ - _delegate: function(args){ - var result; - - result = this.elems.map(function(elem){ - return elem.delegate.apply(elem, args); - }); - - return _.flatten(result); - }, - - /** - * Overrides 'EventsBus.trigger' method to implement events bubbling. - * - * @param {String} name - Name of the event. - * @param [...] Any number of arguments that should be to the events' handler. - * @returns {Boolean} False if event bubbling was canceled. - */ - trigger: function(){ - var args = _.toArray(arguments), - bubble = EventsBus.trigger.apply(this, args), - result; - - if(!bubble){ - return false; - } - - this.containers.forEach(function(parent) { - result = parent.trigger.apply(parent, args); - - if (result === false) { - bubble = false; - } - }); - - return !!bubble; - } - }); - - return Component; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/collection.js b/app/code/Magento/Ui/view/base/web/js/form/components/collection.js index 6cef3d6c31d7f..2a2a39adc5d48 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/collection.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/collection.js @@ -4,9 +4,9 @@ */ define([ 'underscore', - 'mage/utils', + 'mageUtils', 'Magento_Ui/js/lib/registry/registry', - 'Magento_Ui/js/lib/component/component' + 'uiComponent' ], function (_, utils, registry, Component) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/collection/item.js b/app/code/Magento/Ui/view/base/web/js/form/components/collection/item.js index 44413dd455597..ef74c75977918 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/collection/item.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/collection/item.js @@ -4,7 +4,7 @@ */ define([ 'underscore', - 'mage/utils', + 'mageUtils', '../tab' ], function (_, utils, Tab) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/form/components/group.js b/app/code/Magento/Ui/view/base/web/js/form/components/group.js index 25b8d735d5f10..78bbf41c879c4 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/components/group.js +++ b/app/code/Magento/Ui/view/base/web/js/form/components/group.js @@ -4,9 +4,8 @@ */ define([ 'underscore', - 'Magento_Ui/js/lib/component/component', - 'mage/utils' -], function (_, Component, utils) { + 'uiComponent' +], function (_, Component) { 'use strict'; function extractData(container, field, orig) { @@ -39,8 +38,6 @@ define([ /** * Extends this with defaults and config. * Then calls initObservable, iniListenes and extractData methods. - * - * @param {Object} config */ initialize: function () { _.bindAll(this, 'toggle'); @@ -64,7 +61,7 @@ define([ /** * Assignes onUpdate callback to update event of incoming element. * Calls extractData method. - * @param {Object} element + * @param {Object} elem * @return {Object} - reference to instance */ initElement: function (elem) { @@ -118,4 +115,4 @@ define([ return this.elems.getLength() > 1; } }); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js index 3446210361d2e..56f1b3db1a21f 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js @@ -4,8 +4,8 @@ */ define([ 'underscore', - 'mage/utils', - 'Magento_Ui/js/lib/component/component', + 'mageUtils', + 'uiComponent', 'Magento_Ui/js/lib/validation/validator' ], function (_, utils, Component, validator) { 'use strict'; @@ -32,7 +32,7 @@ define([ }, links: { - value: '<%= provider %>:data.<%= dataScope %>' + value: '<%= provider %>:<%= dataScope %>' }, exports: { diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js b/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js index c6fad500166a8..adf089b68aeeb 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/boolean.js @@ -4,7 +4,7 @@ */ define([ './abstract', - 'mage/utils' + 'mageUtils' ], function (Abstract, utils) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js index 1afc75a8837ef..a6dc9e3b3afe6 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js @@ -4,7 +4,7 @@ */ define([ 'underscore', - 'mage/utils', + 'mageUtils', './select' ], function (_, utils, Select) { 'use strict'; @@ -17,10 +17,10 @@ define([ /** * Calls 'getInitialValue' of parent and if the result of it is not empty * string, returs it, else returnes caption or first found option's value - * + * * @returns {Number|String} */ - getInititalValue: function(){ + getInititalValue: function () { var value = this._super(); return _.isString(value) ? value.split(',') : value; @@ -31,7 +31,7 @@ define([ * @returns {Boolean} */ hasChanged: function () { - var value = this.value(), + var value = this.value(), initial = this.initialValue; return !utils.identical(value, initial); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/select.js b/app/code/Magento/Ui/view/base/web/js/form/element/select.js index 68e51325b7dc5..8fd34793bf0e3 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/select.js @@ -4,7 +4,7 @@ */ define([ 'underscore', - 'mage/utils', + 'mageUtils', './abstract' ], function (_, utils, Abstract) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js new file mode 100644 index 0000000000000..3cca7c666960a --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js @@ -0,0 +1,16 @@ +define([ + './text', + 'moment' +], function (Text, moment) { + 'use strict'; + + return Text.extend({ + defaults: { + dateFormat: 'MMM d, YYYY h:mm:ss A' + }, + + getLabel: function (data) { + return moment(data).format(this.dateFormat); + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js index b6bc683790679..5c6e592ced7a1 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/select.js @@ -4,18 +4,14 @@ define([ 'use strict'; return Text.extend({ - defaults: { - bodyTmpl: 'ui/grid/cells/select' - }, - - getLabel: function (value) { - var label = '', - options = this.options || []; + getLabel: function (data) { + var options = this.options || [], + label = ''; options.some(function (item) { label = item.label; - return item.value == value; + return item.value == data; }); return label; diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/text.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/text.js index bc6e3f8d0ec7a..08e15be228c8b 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/text.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/text.js @@ -1,5 +1,5 @@ define([ - 'Magento_Ui/js/lib/component/component' + 'uiComponent' ], function (Component) { 'use strict'; @@ -24,6 +24,8 @@ define([ this._super() .observe('sorting sortClass'); + this.setSortClass(this.sorting()); + return this; }, @@ -39,13 +41,15 @@ define([ this.sorting(direction); }, - push: function () { - if (!this.sorting()) { + push: function (sorting) { + if (!sorting) { return; } - - this.source.set('params.sorting.field', this.index); - this.source.set('params.sorting.direction', this.sorting()); + + this.source.set('params.sorting', { + field: this.index, + direction: sorting + }); }, toggleDirection: function () { @@ -54,9 +58,8 @@ define([ 'asc'; }, - setSortClass: function () { - var direction = this.sorting(), - sortClass = this.classes[direction] || ''; + setSortClass: function (sorting) { + var sortClass = this.classes[sorting] || ''; this.sortClass(sortClass); }, @@ -67,6 +70,10 @@ define([ } }, + getLabel: function (data) { + return data; + }, + getHeader: function () { return this.headerTmpl; }, diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js index 08679e5235338..31b0f7737da9a 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js @@ -1,6 +1,6 @@ define([ 'underscore', - 'Magento_Ui/js/lib/component/component' + 'uiComponent' ], function (_, Component) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/grid/listing.js b/app/code/Magento/Ui/view/base/web/js/grid/listing.js index 855532e6f8e31..fe925e4d39731 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/listing.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/listing.js @@ -1 +1,22 @@ -define([ 'Magento_Ui/js/lib/component/component' ], function (Component) { 'use strict'; return Component.extend({ defaults: { template: 'ui/grid/listing', rows: [], imports: { rows: '<%= provider %>:data.items' } }, getColspan: function () { return this.elems().length; }, hasData: function () { return !!this.rows().length; } }); }); \ No newline at end of file +define([ + 'uiComponent' +], function (Component) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'ui/grid/listing', + imports: { + rows: '<%= provider %>:data.items' + } + }, + + getColspan: function () { + return this.elems().length; + }, + + hasData: function () { + return !!this.rows().length; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js index 08cbabce16c22..f058d5e9716b9 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js @@ -1,6 +1,6 @@ define([ 'underscore', - 'Magento_Ui/js/lib/component/component' + 'uiComponent' ], function (_, Component) { 'use strict'; @@ -10,6 +10,7 @@ define([ bodyTmpl: 'ui/grid/cells/massactions', template: 'ui/grid/actions', menuVisible: false, + actionsVisible: false, allSelected: false, selected: [], excluded: [], @@ -43,7 +44,7 @@ define([ initObservable: function () { this._super() - .observe('menuVisible selected excluded allSelected'); + .observe('menuVisible actionsVisible selected excluded allSelected'); return this; }, @@ -137,14 +138,30 @@ define([ this.totalSelected(count); }, + applyAction: function (action) { + var confirmed = true; + + if (action.confirm) { + confirmed = window.confirm(action.confirm); + } + }, + toggleMenu: function () { this.menuVisible(!this.menuVisible()); }, + toggleActions: function () { + this.actionsVisible(!this.actionsVisible()); + }, + hideMenu: function () { this.menuVisible(false); }, + hideActions: function () { + this.actionsVisible(false); + }, + getHeader: function () { return this.headerTmpl; }, @@ -153,6 +170,21 @@ define([ return this.bodyTmpl; }, + isSelectVisible: function (action) { + var onPage = this.getIds().length, + total = this.totalRecords(); + + switch (action) { + case 'selectPage': + case 'deselectPage': + return onPage < total; + break; + + default: + return true; + } + }, + onSelectedChange: function (selected) { this.updateExcluded(selected) .countSelected(); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/paging.js b/app/code/Magento/Ui/view/base/web/js/grid/paging.js index 06d32b6ab5e8f..85dc650174ef2 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/paging.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/paging.js @@ -1,6 +1,6 @@ define([ 'ko', - 'Magento_Ui/js/lib/component/component' + 'uiComponent' ], function (ko, Component) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/grid/provider.js b/app/code/Magento/Ui/view/base/web/js/grid/provider.js index 7eb38796750e2..5eb689c579730 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/provider.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/provider.js @@ -4,7 +4,7 @@ */ define([ 'underscore', - 'mage/utils', + 'mageUtils', 'Magento_Ui/js/lib/class', 'Magento_Ui/js/lib/events' ], function (_, utils, Class, EventsBus) { @@ -35,16 +35,18 @@ define([ * @return {Object} reference to instance */ set: function (path, value) { - var result = this._override.apply(this, arguments); + var data = utils.nested(this.data, path), + diffs = utils.compare(data, value, path); - value = result.value; - path = result.path; + utils.nested(this.data, path, value); - this.trigger('update', value); + diffs.changes.forEach(function (change) { + this.trigger(change.name, change.value, change); + }, this); - if (path) { - this.trigger('update:' + path, value); - } + _.each(diffs.containers, function (changes, name) { + this.trigger(name, changes); + }, this); return this; }, diff --git a/app/code/Magento/Ui/view/base/web/js/lib/class.js b/app/code/Magento/Ui/view/base/web/js/lib/class.js index 16729f002d566..be53c19ea135f 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/class.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/class.js @@ -4,9 +4,8 @@ */ define([ 'underscore', - 'mage/utils', - 'jquery' -], function (_, utils, $) { + 'mageUtils' +], function (_, utils) { 'use strict'; var superReg = /\b_super\b/; @@ -75,7 +74,7 @@ define([ }; } - defaults = $.extend(true, {}, parent.defaults, defaults); + defaults = utils.extend({}, parent.defaults, defaults); child.prototype = Object.create(parentProto); child.prototype.constructor = child; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component.js b/app/code/Magento/Ui/view/base/web/js/lib/component.js deleted file mode 100644 index 7d179bcf36633..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/component.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'Magento_Ui/js/lib/registry/registry' -], function(registry) { - 'use strict'; - - /** - * Extends configuration that will be retrieved from the data provider - * with configuration that is stored in a 'baseConfig' object. - * @param {Object} provider - DataProvider instance. - * @param {Object} baseConfig - Basic configuration. - * @returns {Object} Resulting configurational object. - */ - function getConfig(provider, baseConfig) { - var configs = provider.config.get('components'), - storeConfig = configs[baseConfig.name] || {}; - - return _.extend({ - provider: provider - }, storeConfig, baseConfig); - } - - /** - * Creates new instance of a grids' component. - * @param {Object} data - - Data object that was passed while creating component initializer. - * @param {Object} base - - Basic configuration. - */ - function init(data, base) { - var providerName = base.parent_name, - component = providerName + ':' + base.name; - - if (registry.has(component)) { - return; - } - - registry.get(providerName, function(provider) { - var config = getConfig(provider, base); - - registry.set(component, new data.constr(config)); - }); - } - - return function(data) { - return init.bind(this, data); - }; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/core.js b/app/code/Magento/Ui/view/base/web/js/lib/component/core.js index 15873d85be8d4..5738241751db6 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/component/core.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/core.js @@ -1,6 +1,6 @@ define([ 'ko', - 'mage/utils', + 'mageUtils', 'underscore', 'Magento_Ui/js/lib/registry/registry' ], function (ko, utils, _, registry) { diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/links.js b/app/code/Magento/Ui/view/base/web/js/lib/component/links.js index 2ec17a3030c84..a313dfec93546 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/component/links.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/links.js @@ -1,7 +1,7 @@ define([ 'ko', 'underscore', - 'mage/utils', + 'mageUtils', 'Magento_Ui/js/lib/registry/registry' ], function (ko, _, utils, registry) { 'use strict'; @@ -26,7 +26,7 @@ define([ } function imports(owner, target, ownerProp, targetProp, auto) { - var from = update.bind(null, owner, ownerProp), + var callback = update.bind(null, owner, ownerProp), value; value = target.get ? @@ -34,14 +34,14 @@ define([ utils.nested(target, targetProp); if (ko.isObservable(value)) { - value.subscribe(from); + value.subscribe(callback); value = value(); } else if (target.on) { - target.on('update:' + targetProp, from); + target.on(targetProp, callback); } if (auto) { - from(value); + callback(value); } } diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/component.js b/app/code/Magento/Ui/view/base/web/js/lib/component/main.js similarity index 100% rename from app/code/Magento/Ui/view/base/web/js/lib/component/component.js rename to app/code/Magento/Ui/view/base/web/js/lib/component/main.js diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js b/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js index a00e03769cbaa..63b19d6cf2db4 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/manip.js @@ -1,6 +1,6 @@ define([ 'underscore', - 'mage/utils', + 'mageUtils', 'Magento_Ui/js/lib/registry/registry' ], function (_, utils, registry) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/deferred_events.js b/app/code/Magento/Ui/view/base/web/js/lib/deferred_events.js deleted file mode 100644 index 3b9dbd9042592..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/deferred_events.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'jquery', - './events' -], function ($, EventBus) { - 'use strict'; - - var events = {}; - - function isResolved(promise) { - return promise.state() === 'resolved'; - }; - - function toArray(obj, from) { - return Array.prototype.slice.call(obj, from || 0); - }; - - function on(context, name, callback) { - return EventBus.on.call(context, name, callback); - }; - - function trigger(name) { - return EventBus.trigger.apply(this, toArray(arguments)); - }; - - function getStorage(name) { - return events[name] || {}; - }; - - function getCallbacks(name) { - var storage = getStorage(name); - return storage.callbacks || []; - }; - - return { - when: function (name, callback) { - var storage = events[name] = getStorage(name), - callbacks = storage.callbacks = getCallbacks(name), - promise = storage.promise = storage.promise || $.Deferred(), - args = toArray(arguments), - resolveArgs; - - if (isResolved(promise)) { - return on(this, name, callback); - } - - if (~!callbacks.indexOf(callback)) { - callbacks.push(callback); - } - - promise.done(function () { - - callback.apply(this, arguments); - on(this, name, callback); - - }.bind(this)); - - return this; - }, - - resolve: function (name) { - var args = toArray(arguments, 1), - storage = events[name] = getStorage(name), - promise = storage.promise = storage.promise || $.Deferred(); - - if (isResolved(promise)) { - return trigger.bind(this, name).apply(this, args); - } - - promise.resolve.apply(promise, args); - - return this; - } - } -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/scope.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/scope.js deleted file mode 100644 index 65ee522bc2af1..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/ko/scope.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'ko', - 'underscore', - '../class', - './initialize' -], function(ko, _, Class) { - 'use strict'; - - /** - * Wrapper for ko.observable and ko.observableArray. - * Assignes one or another ko property to obj[key] - * @param {Object} obj - object to store property to - * @param {String} key - key - * @param {*} value - initial value of observable - */ - function observe(obj, key, value){ - var method = Array.isArray(value) ? 'observableArray' : 'observable'; - - obj[key] = ko[method](value); - } - - return Class.extend({ - - /** - * If 2 params passed, path is considered as key. - * Else, path is considered as object. - * Assignes props to this based on incoming params - * @param {Object|String} path - * @param {*} value - */ - observe: function(path, value) { - var type = typeof path; - - if(arguments.length === 1){ - if(type === 'string'){ - path = path.split(' '); - } - - if(Array.isArray(path)){ - path.forEach(function(key){ - observe(this, key, this[key]); - }, this); - } - else if(type==='object'){ - _.each(path, function(value, key){ - observe(this, key, value); - }, this); - } - } - else if(type === 'string') { - observe(this, path, value); - } - - return this; - }, - - /** - * Reads it's params from provider and stores it into its params object - * @return {Object} reference to instance - */ - pushParams: function(){ - var params = this.params, - provider = this.provider.params, - data = {}; - - params.items.forEach(function(name) { - data[name] = this[name](); - }, this); - - provider.set(params.dir, data); - - return this; - }, - - /** - * Loops over params.items and writes it's corresponding {key: value} - * pairs to this as observables. - * @return {Object} reference to instance - */ - pullParams: function(){ - var params = this.params, - provider = this.provider.params, - data = provider.get(params.dir); - - params.items.forEach(function(name) { - this[name](data[name]); - }, this); - - return this; - }, - - /** - * Calls pushParams and calls refresh on this.provider - */ - reload: function() { - this.pushParams() - .provider.refresh(); - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/provider.js b/app/code/Magento/Ui/view/base/web/js/lib/provider.js deleted file mode 100644 index 66454fee11c9b..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/provider.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'jquery', - './data_provider', - 'Magento_Ui/js/lib/registry/registry' -], function($, DataProvider, registry) { - 'use strict'; - - /** - * Merges passed settings with preset ajax properties - * @param {Object} settings - * @returns {Object} - mutated settings - */ - function getConfig(settings) { - var config = settings.config, - client = config.client = config.client || {}; - - $.extend(true, client, { - ajax: { - data: { - name: settings.name, - form_key: FORM_KEY - } - } - }); - - return settings; - } - - /** - * Creates new data provider and register it by settings.name - * @param {Object} settings - */ - function init(settings) { - var name = settings.name, - config = getConfig(settings); - - registry.set(name, new DataProvider(config)); - } - - return init; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js b/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js index 21969f43dc852..cf4b3b13d1093 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js @@ -4,7 +4,7 @@ */ define([ 'underscore', - 'mage/utils' + 'mageUtils' ], function (_, utils) { 'use strict'; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js b/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js index db002ca2a3cf7..8c0448aaa49b3 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/registry/registry.js @@ -3,10 +3,10 @@ * See COPYING.txt for license details. */ define([ - 'mage/utils', + 'mageUtils', './storage', './events' -], function (utils, Storage, Events) { +], function(utils, Storage, Events) { 'use strict'; function Registry() { @@ -20,21 +20,22 @@ define([ /** * Retrieves data from registry. * - * @param {(String|Array)} elems - An array of elements' names or - * a string of names divided by spaces. - * @param {Function} [callback] - Callback function that will be triggered + * @params {(String|Array)} elems - + * An array of elements' names or a string of names divided by spaces. + * @params {Function} [callback] - + * Callback function that will be triggered * when all of the elements are registered. * @returns {Array|*|Undefined} * Returns either an array of elements * or an element itself if only is requested. * If callback function is specified then returns 'undefined'. */ - get: function (elems, callback) { + get: function(elems, callback) { var records; elems = utils.stringToArray(elems) || []; - if (typeof callback == 'function') { + if (typeof callback !== 'undefined') { this.events.wait(elems, callback); } else { records = this.storage.get(elems); @@ -45,11 +46,12 @@ define([ } }, - /** + + /** * Sets data to registry. * - * @param {String} elem - Elements' name. - * @param {*} value - Value that will be assigned to the element. + * @params {String} elems - Elements' name. + * @params {*} value - Value that will be assigned to the element. * @returns {registry} Chainable. */ set: function (elem, value) { @@ -61,8 +63,8 @@ define([ /** * Removes specified elements from a storage. - * @param {(String|Array)} elems - An array of elements' names or - * a string of names divided by spaces. + * @params {(String|Array)} elems - + * An array of elements' names or a string of names divided by spaces. * @returns {registry} Chainable. */ remove: function (elems) { @@ -76,8 +78,8 @@ define([ /** * Checks whether specified elements has been registered. * - * @param {(String|Array)} elems - An array of elements' names or - * a string of names divided by spaces. + * @params {(String|Array)} elems - + * An array of elements' names or a string of names divided by spaces. * @returns {Boolean} */ has: function (elems) { diff --git a/app/code/Magento/Ui/view/base/web/js/lib/storage/dump.js b/app/code/Magento/Ui/view/base/web/js/lib/storage/dump.js deleted file mode 100644 index 8c904764da3fd..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/storage/dump.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - './storage', - 'Magento_Ui/js/lib/deferred_events' -], function (Storage, DeferredEvents) { - return Storage.extend({}, DeferredEvents); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/storage/index.js b/app/code/Magento/Ui/view/base/web/js/lib/storage/index.js deleted file mode 100644 index ca58235fa19b4..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/storage/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/** - * Assembles storages returning storage mapping - */ -define([ - './storage', - './meta', - './dump' -], function(Storage, MetaStorage, DumpStorage){ - 'use strict'; - - return { - meta: MetaStorage, - params: Storage, - config: Storage, - data: Storage, - dump: DumpStorage - } -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/storage/meta.js b/app/code/Magento/Ui/view/base/web/js/lib/storage/meta.js deleted file mode 100644 index d3cee2931c4d6..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/storage/meta.js +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - './storage' -], function(_, Storage) { - 'use strict'; - - /** - * Loops over first level of object looking for valueKey of typeof object values - * to be typeof object as well. Breaks loop on first entry on one. - * @param {Object} target - * @param {String} valueKey - complex to look for - * @return {Boolean} - */ - function hasComplexValue(target, valueKey) { - var result = false, - key, - object; - - - for (key in target) { - object = target[key]; - - if (typeof object === 'object' && typeof object[valueKey] === 'object') { - result = true; - break; - } - } - - return result; - } - - /** - * Recursively loops over object's properties and converts it to array ignoring keys. - * If typeof 'value' properties is 'object', creates 'items' property and assigns - * execution of nestedObjectToArray on 'value' to it. - * If typeof 'value' key is not an 'object', is simply writes an object itself to result array. - * @param {Object} obj - * @return {Array} result array - */ - function nestedObjectToArray(obj, valueKey) { - var target, - items = []; - - for (var prop in obj) { - - target = obj[prop]; - if (typeof target[valueKey] === 'object') { - - target.items = nestedObjectToArray(target[valueKey], valueKey); - delete target[valueKey]; - } - items.push(target); - } - - return items; - } - - return Storage.extend({ - - /** - * Initializes data prop based on data argument. - * Calls initFields and initColspan methods - * @param {Object} config - */ - initialize: function(data) { - this.data = data || {}; - - this.initFields() - .initColspan(); - }, - - /** - * Formats fields property to compatible format. - * Processes those. Assignes fiedls to data.fields. - * @return {Object} - reference to instance - */ - initFields: function(){ - var data = this.data, - fields = data.fields; - - fields = this._fieldsToArray(fields); - - fields.forEach(this._processField, this); - - data.fields = fields; - - return this; - }, - - /** - * Assigns data.colspan to this.getVisible().length - * @return {Object} - reference to instance - */ - initColspan: function(){ - var visible = this.getVisible(); - - this.data.colspan = visible.length; - - return this; - }, - - /** - * Assignes default params to field - * @param {Object} field - * @return {Object} reference to instance - */ - applyDefaults: function(field) { - var defaults = this.data.defaults; - - if (defaults) { - _.defaults(field, defaults); - } - - return this; - }, - - /** - * Format options based on those being nested - * @param {Object} field - * @return {Object} reference to instance - */ - formatOptions: function(field) { - var result, - options, - isNested; - - options = field.options; - - if (options) { - result = {}; - isNested = hasComplexValue(options, 'value'); - - if(isNested){ - result = nestedObjectToArray(options, 'value'); - } - else{ - _.each(options, function(option){ - result[option.value] = option.label; - }); - } - - field.options = result; - } - - return this; - }, - - /** - * Returns filted by visible property fields array. - * @return {Array} filted by visible property fields array - */ - getVisible: function(){ - var fields = this.data.fields; - - return fields.filter(function(field){ - return field.visible; - }); - }, - - /** - * Convertes fields object to array, assigning key to index property. - * @param {Object} fields - * @return {Array} array of fields - */ - _fieldsToArray: function(fields){ - return _.map(fields, function(field, id){ - field.index = id; - - return field; - }); - }, - - /** - * Calls applyDefaults and formatOptions on field - * @param {Object} field - */ - _processField: function(field){ - this.applyDefaults(field) - .formatOptions(field); - } - }); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/storage/storage.js b/app/code/Magento/Ui/view/base/web/js/lib/storage/storage.js deleted file mode 100644 index e0075c746b546..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/storage/storage.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - '../class', - '../events', - 'mage/utils' -], function(_, Class, EventsBus, utils) { - 'use strict'; - - return Class.extend({ - - /** - * Inits this.data to incoming data - * @param {Object} data - */ - initialize: function(data) { - this.data = data || {}; - }, - - /** - * If path specified, returnes this.data[path], else returns this.data - * @param {String} path - * @return {*} this.data[path] or simply this.data - */ - get: function(path) { - return utils.nested(this.data, path); - }, - - /** - * Sets value property to path and triggers update by path, passing result - * @param {String|*} path - * @param {String|*} value - * @return {Object} reference to instance - */ - set: function(path, value){ - var result = this._override.apply(this, arguments); - - value = result.value; - path = result.path; - - this.trigger('update', value); - - if (path) { - this.trigger('update:' + path, value); - } - - return this; - }, - - remove: function (path) { - utils.nestedRemove(this.data, path); - - return this; - }, - - /** - * Assignes props to this.data based on incoming params - * @param {String|*} path - * @param {*} value - * @return {Object} - */ - _override: function(path, value) { - if (arguments.length > 1) { - utils.nested(this.data, path, value); - } else { - value = path; - path = false; - - this.data = value; - } - - return { - path: path, - value: value - }; - } - - }, EventsBus); -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/js/lib/utils.js b/app/code/Magento/Ui/view/base/web/js/lib/utils.js deleted file mode 100644 index dcc7c65e3255f..0000000000000 --- a/app/code/Magento/Ui/view/base/web/js/lib/utils.js +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'mage/utils' -], function(_, utils) { - 'use strict'; - - var utils = {}, - atobSupport, - btoaSupport; - - atobSupport = typeof atob === 'function'; - btoaSupport = typeof btoa === 'function'; - - /** - * Base64 encoding/decoding methods. - * First check for native support. - */ - if( btoaSupport && atobSupport ){ - _.extend(utils, { - atob: function(input){ - return window.atob(input); - }, - - btoa: function(input){ - return window.btoa(input); - } - }); - } - else{ - _.extend(utils, { - atob: function(input){ - return Base64.decode(input) - }, - - btoa: function(input){ - return Base64.encode(input); - } - }); - } - - /** - * Submits specified data as a form object. - * @param {Object} params - Parameters of form. - */ - utils.submitAsForm = function(params){ - var form, - field; - - form = document.createElement('form'); - - form.setAttribute('method', params.method); - form.setAttribute('action', params.action); - - _.each(params.data, function(value, name){ - field = document.createElement('input'); - - if(typeof value === 'object'){ - value = JSON.stringify(value); - } - - field.setAttribute('name', name); - field.setAttribute('type', 'hidden'); - - field.value = value; - - form.appendChild(field); - }); - - document.body.appendChild(form); - - form.submit(); - }; - - return utils; -}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/actions.html b/app/code/Magento/Ui/view/base/web/templates/grid/actions.html index eab4802c6e276..cf743a3ba0512 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/actions.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/actions.html @@ -1,13 +1,13 @@ -
+
- -
\ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/select.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/select.html deleted file mode 100644 index 300a4fdbaf152..0000000000000 --- a/app/code/Magento/Ui/view/base/web/templates/grid/cells/select.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html index 7a4530515763a..300a4fdbaf152 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/text.html @@ -6,6 +6,6 @@ --> - + \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/columns/massactions.html b/app/code/Magento/Ui/view/base/web/templates/grid/columns/massactions.html index 56627907635a9..ac0fbf0db5b2c 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/columns/massactions.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/columns/massactions.html @@ -8,7 +8,7 @@