cancel
Showing results for 
Search instead for 
Did you mean: 

How to extends properly Cms Page and Block WebAPI

How to extends properly Cms Page and Block WebAPI

Hello Guys,

 

I would like to extends/override the APIs of CMS Pages and Blocks to add custom fields (for example, an array of store_ids to allow the creation of a CMS block on different stores with an webapi call, it's my main goal).

 

I tried many things, but this does not seem clean, standards-compliant. I have the impression of overloading the whole module CMS (data interface, repository interface, model, repository factory, etc..) just for adding new fields in webapi.

 

I will explain what I have done for now :

 

1/ I wrote an new data api \BlockInterface who extends the core interface to add my new field (store_id) and declare his getter and setter methods.

namespace Reflet\CmsExtension\Api\Data;

interface BlockInterface extends \Magento\Cms\Api\Data\BlockInterface{
    /**
     * New fields
     */
    const STORE_ID        = 'store_id';

    /**
     * Get Store Ids
     *
     * @return array
     */
    public function getStoreId();

    /**
     * Set Store Ids
     *
     * @param array $storeIds
     * @return \Reflet\CmsExtension\Api\Data\BlockInterface
     */
    public function setStoreId($storeIds);
}

2/ I implements the Data Interface in the new \Block model object.

3/ With many in the di.xml file, I override the block model type.

4/ I reimplement the api \BlockRepositoryInterface and the webapi.xml file to change the data type used in the repository.

5/ I testing the getById() and the save() methods for the block #1 with simple repository call and webapi.

 

Here, is my result :

 

1/ If, I get the block #1 with the repository, the store_id is load in the result object.

array (size=12)
  'row_id' => string '1' (length=1)
  'block_id' => string '1' (length=1)
  'created_in' => string '1' (length=1)
  'updated_in' => string '2147483647' (length=10)
  'title' => string 'Catalog Events Lister' (length=21)
  'identifier' => string 'catalog_events_lister' (length=21)
  'content' => string '{{block class="Magento\\CatalogEvent\\Block\\Event\\Lister" name="catalog.event.lister" template="lister.phtml"}}' (length=113)
  'creation_time' => string '2017-02-14 14:33:20' (length=19)
  'update_time' => string '2017-02-14 14:33:20' (length=19)
  'is_active' => string '1' (length=1)
  'store_id' => 
    array (size=1)
      0 => string '0' (length=1)
  'stores' => 
    array (size=1)
      0 => string '0' (length=1)

2/ If, I get the block #1 with the WebAPI, the store_id is also load in the result object.

public 'store_id' => 
    array (size=1)
      0 => string '0' (length=1)
  public 'id' => int 1
  public 'identifier' => string 'catalog_events_lister' (length=21)
  public 'title' => string 'Catalog Events Lister' (length=21)
  public 'content' => string '{{block class="Magento\\CatalogEvent\\Block\\Event\\Lister" name="catalog.event.lister" template="lister.phtml"}}' (length=113)
  public 'creation_time' => string '2017-02-14 14:33:20' (length=19)
  public 'update_time' => string '2017-02-14 14:33:20' (length=19)
  public 'active' => boolean true

3/ If, I save the block #1 with the WebAPI, an error occurs, he load the wrong BlockInterface. I need to reimplement the BlockRepository ? I don't think it's the good and cleaner method (...) ?

 public 'message' => string 'Property "StoreId" does not have corresponding setter in class "Magento\Cms\Api\Data\BlockInterface".' (length=101)
  public 'trace' => string '#0 /var/www/vhosts/reflet.com/storemanager/vendor/magento/framework/Reflection/NameFinder.php(59): Magento\Framework\Reflection\NameFinder->findAccessorMethodName(Object(Zend\Code\Reflection\ClassReflection), 'StoreId', 'getStoreId', 'isStoreId')
#1 /var/www/vhosts/reflet.com/storemanager/vendor/magento/framework/Webapi/ServiceInputProcessor.php(158): Magento\Framework\Reflection\NameFinder->getGetterMethodName(Object(Zend\Code\Reflection\ClassReflection), 'StoreId')
#2 /var/www/vhosts/reflet.com/storemanag'... (length=2239)

 

For this example, I use the 'store_id' only, but in the future, it's must be works with all custom fields in Page or Block object.

 

How do you recommend this modification to be as clean as possible and limit conflicts in the future ? Do you have an example ?

 

If you want to test, you can find in this archive, my two current Magento modules (Reflet_Api an simple adapter to call REST WebApi and Reflet_CmsExtension to override CMS Blocks) : https://drive.google.com/file/d/0B12trf96j0ALSjhZdmJPTzBPT0U/view

 

Thank you for your answers.

 

Best regards.

Jonathan