Clone component product

(apply for ideas shop, ideas cart need some adjustment)

Sometimes, you need to customize component to adapt what you need.

You shouldn't change code of plugin. Just clone component you want to customize

Here, i make a guide to clone component product.

This component display list of product in page category and product detail in page product detail.

 

- First, create a plugin. I create plugin 'test' in namespace (author name) 'october'

 public function registerComponents()
    {
        return [
            'October\Test\Components\Product' => 'Product',
        ];
    }

- Create file Product.php in /plugins/october/test/components : 

just copy code from file /plugins/ideas/shop/components/Product.php. Just change namespace:

<?php namespace October\Test\Components;

//....

class Product extends ComponentBase
{

    const PAGE_NOT_FOUND = 0;
    const PAGE_FOUND = 1;

    public function componentDetails()
    {
        return [
            'name' => 'clone component product',
            'description' => 'Get product list and product detail.'
        ];
    }

    /**
     * Pass params to component view
     */
    public function onRun()
    {
        $route = $this->getRouterBySlug();
        //.....
        if (empty($route)) {
            $this->page['found_result'] = self::PAGE_NOT_FOUND;
        } else {
            $seoInfo = self::getSeoInfo($route['entity_id'], $route['type']);
            //.....
        }
    }


    /**
     * Get seo info
     */
    public static function getSeoInfo($id, $type)
    {
        //....
    }

    /**
     * Cache route
     * Create event : ideas.shop.handle_slug to override handling route for product and category
     */
    public static function routeCache($slug)
    {
        //....
    }

    /**
     * Get router by current url
     */
    public function getRouterBySlug()
    {
        //....
        $data = self::routeCache($slug);
        return $data;
    }

    /**
     * Get data for category and product detail
     */
    public static function getProduct($id, $type)
    {
        if ($type == Route::ROUTE_PRODUCT) {
            return ProductFacades::getProductDetail($id);
        } else {
            //in case of one product belongs to many category
            Session::put('current_category', $id);
            $rs = CategoryFacades::getListProduct($id);
            return $rs;
        }
    }

    /**
     * Ajax Reload gallery of configurable product
     */
    public function onReloadGallery()
    {
        //....
    }

    /**
     * Generate captcha
     */
    public function onCaptcha()
    {
       //....
    }

    /**
     * save review
     */
    public function onSubmitReview()
    {
        //....
    }

}

=> the flow is:

- while there is a request to url http://your_web/:slug

=> function onRun() will run and call function getRouterBySlug() and getSeoInfo()

=> function getRouterBySlug() will run to handle slug, this function will call function routeCache($slug) to get record from table ideas_routes

=> function getRouterBySlug() will return a record to identify this route is category or product then in onRun(), function getProduct($id, $type) will be call

- next, you copy folder 'product' from /plugins/ideas/shop/components to /plugins/october/test/components

- You can modify js by copy 2 file category.js and productDetail.js in /plugins/ideas/shop/assets/components/js to /plugins/october/test/assets/components/js

- in page product.htm of your theme:

url = "/:slug"
layout = "default"

[October\Test\Components\Product Product]
==

{% if (type == type_category) %}
    {% component 'Product::category' %}
    {% put scripts %}
    <script type="text/javascript" src="/plugins/october/test/assets/components/js/category.js"></script>
    {% endput %}
{% else %}
    {% component 'Product::detail' %}
    {% put scripts %}
    <script type="text/javascript" src="/plugins/october/test/assets/components/js/productDetail.js"></script>
    {% endput %}
{% endif %}

=> here, we will load component Product of plugin 'test' of namespace 'october'

=> load file category.js and productDetail.js from /plugins/october/test/assets/components/js