4

Long story short:
The CMS page admin form data provider class Magento\Cms\Model\Page\DataProvider, more specific the method getData always returns an array with a single element that contains the data for the page that I'm editing and the element key is the page id.
How does this happen? Where is the filter by page id applied?

Short story long:
At a first glance, what the method Magento\Cms\Model\Page\DataProvider::getData returns is not that obvious.
In the method there is this line

$items = $this->collection->getItems(); 

and the collection member var is initialized in __construct with

$this->collection = $pageCollectionFactory->create();`   

Where $pageCollectionFactory is an instance of Magento\Cms\Model\ResourceModel\Page\CollectionFactory.

So, when I first looked, I thought "why the hell is it loading the full collection since I am editing only one item? This doesn't scale.".
Upon a closer inspection, I saw that the collection returns one single item. The one I am editing. This is good, but how does it work?
If I print the collection query echo $this->collection->getSelect() I get back

SELECT `main_table`.* FROM `cms_page` AS `main_table` WHERE (`main_table`.`page_id` = '2')

where 2 is the id of the page that I am editing.
Now the curious part (if this was not curious enough) If I create my own entity, following the same guidelines for the data provider class, it works the same. I get back one single item.
This makes me think the filtering happens somewhere higher in the inheritance tree, but I have no idea where?

Note: Please don't explain how to make this work on my custom module. I know how to do that. I just need an explanation on how/why/where the magic happens.

  • magento\vendor\magento\module-cms\Controller\Adminhtml\Page\Edit.php & magento\vendor\magento\module-cms\Block\Page.php getPage() function – Ankit Shah May 9 '17 at 6:31
  • @AnkitShah This has nothing to do with the data provider class for the admin form. – Marius May 9 '17 at 6:38
2

Check following function


/**
 * {@inheritdoc}
 */
public function getDataSourceData()
{
    $dataSource = [];

    $id = $this->getContext()->getRequestParam($this->getContext()->getDataProvider()->getRequestFieldName(), null);
    $filter = $this->filterBuilder->setField($this->getContext()->getDataProvider()->getPrimaryFieldName())
        ->setValue($id)
        ->create();
    $this->getContext()->getDataProvider()
        ->addFilter($filter);

    $data = $this->getContext()->getDataProvider()->getData();

    if (isset($data[$id])) {
        $dataSource = [
            'data' => $data[$id]
        ];
    } elseif (isset($data['items'])) {
        foreach ($data['items'] as $item) {
            if ($item[$item['id_field_name']] == $id) {
                $dataSource = ['data' => ['general' => $item]];
            }
        }
    }
    return $dataSource;
}

Following line is make collection as a single item


$this->getContext()->getDataProvider()
        ->addFilter($filter);

[Edit by OP].
The trace is:

  • \Magento\Framework\View\Element\UiComponent\ContentType\Json::render()
  • \Magento\Framework\View\Element\UiComponent\Context::getDataSourceData()
  • \Magento\Ui\Component\Form::getDataSourceData()
  • Aha. This looks like a good place to start. Thanks. Now all I need to find out is what calls this method :). Will do some digging and get back to you. – Marius May 9 '17 at 7:10
  • magento\vendor\magento\framework\View\Element\UiComponent\Context.php this will help may be – Ankit Shah May 9 '17 at 7:17
  • 4
    Yep. Figured it out. Thanks. Now I can sleep peacefully at night. – Marius May 9 '17 at 7:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.