Skip to content

How to: creating “marketprice” module

zenmiu edited this page Nov 17, 2011 · 1 revision

Brief specification:

  • Administrator can set the so-called “Market price” for a product.

  • If the price specified in “Market price” is higher than the regular one, on the product details page, on the quick preview pop-up and all the lists, customers see the crossed out market price and the phrase “You save $x” and/or a shortcut with “You save in %”.

Step-by-step:

1) Create a folder named “classes/XLite/Module/CDev/MarketPrice/”. That folder contains the file Main.php, where we describe the module's main class. This has been covered earlier in this article.

2) In the model \XLite\Model\Product add a new field, “marketPrice”. This requires modifying the existing model, so we are going to "decorate" the class. In the module's main folder, we create a subfolder named “Model/” (so that the folder structure of the module repeats the structure of the core) and then add “Product.php” to it:

namespace XLite\Module\CDev\MarketPrice\Model;

/**
* Product
*
* @see   ____class_see____
* @since 1.0.0
*/
class Product extends \XLite\Model\Product implements \XLite\Base\IDecorator
{
    /**
    * Product market price
    *
    * @var   float
    * @see   ____var_see____
    * @since 1.0.0
    *
    * @Column (type="decimal", precision=14, scale=4)
    */
    protected $marketPrice = 0.0000;
}

The class implements the interface \XLite\Base\IDecorator and therefore will be embedded in the decorator chain for the main model.

3) On the product editor page, we need to add a new input box. To do so:

  • Review the list of templates for this page: “skins/admin/en/product/parts/*”.
  • In the “price.tpl” template, find the tag @ListChild, then in that tag find the template weight: 500.
  • In the “skins/admin/en/modules/CDev/MarketPrice/” folder, create a similar template “price.tpl” with an identical @LIstChild tag (the list names must match) but with a bit greater weight, 550.
  • The next time the cache is rebuilt, the module template will be included in the common list product.modify.list and will appear right below the “Price” field.

Note. The current implementation of the “Admin\Product” controller doesn't require modifying the PHP code when a new field is added to a template. Since the field name in the template matches the field name in the model (it's “marketPrice” in both these places), the field will be picked up automatically. In other controllers this may be implemented otherwise, so in that case you would need to additionally decode that controller class.

4) Display market price to buyers on the pages “Product Details Page”, “Quick Look Popup” and product lists of all kinds.

  • Since we do not add new pages and only modify the existing ones, we will need to do the decoding again.

  • In the module's main folder, create the “View/” subfolder (to ensure that the folder structure of the module repeats the structure of the core) and add the files Details.php and ItemsList.php to it. The names do not matter; they just need to match the names of the new classes.

  • Two viewers: details page and the base viewer that handles product lists:

      namespace XLite\Module\CDev\MarketPrice\View;
    
      /**
      * Details
      *
      * @see   ____class_see____
      * @since 1.0.0
      */
      abstract class Details extends \XLite\View\Product\Details\Customer\Page\APage implements \XLite\Base\IDecorator
    
      ------------------
    
      namespace XLite\Module\CDev\MarketPrice\View;
    
      /**
      * ItemsList
      *
      * @see   ____class_see____
      * @since 1.0.0
      */
      abstract class ItemsList extends \XLite\View\ItemsList\Product\Customer\ACustomer implements \XLite\Base\IDecorator
    
  • The need to decode is primarily caused by the fact that both the pages require a new logic: check whether to show market price (isShowMarketPrice() method), calculating the savings percentage (getSaveDifference() method), and getting the list of shortcuts (getLabels() method). These are the methods that are added to the encoded classes; after that, they can be called in templates. Taking logic to templates is highly discouraged.

5) Templates for the pages “Product Details Page”, “Quick Look Popup” and product lists. Complete analogy with the administrator zone templates:

  • Review the folders “skins/default/en/product/details/parts/” and “skins/default/en/items_list/product/parts/”.

  • In those folders, find the files “common.price.tpl” and “common.product-price.tpl” (in both the cases, we need to embed underneath the price block).

  • Create the “skins/default/en/modules/CDev/MarketPrice/” folder.

  • Copy the found files to it under any names you like; e.g., “details.tpl” and “list.tpl”.

  • Replace the template code with ours (not affecting the doc block). In the code, you can freely use the methods added to the respective viewers in 4).

  • In the doc block, slightly increase the weight for each @ListChild tag.

  • Just as for 3), the newly created templates will appear on all the required pages once the cache is rebuilt.

Example. The weight of the above template (price) is 40, of the next one is 50. Get in between them in both the lists (keeping both the tags) by setting their weight to 45.

{**
* Product market price
*
<...>
*
* @ListChild (list="product.details.page.info", weight="45")
* @ListChild (list="product.details.quicklook.info", weight="45")
*}

Note. The details.tpl template, in its turn, is split into lists. This is done for the convenience of customizing the very MarketPrice module, although that, of course, is not mandatory.

6) Including CSS. The Details class that decodes the viewer for “Product Details Page” overrides the function getCSSFiles(), because the details.tpl template uses the styles that are not included in LC by default.

namespace XLite\Module\CDev\MarketPrice\View;

/**
* Details
*
* @see   ____class_see____
* @since 1.0.0
*/
abstract class Details extends \XLite\View\Product\Details\Customer\Page\APage implements \XLite\Base\IDecorator
{
    /**
    * Register CSS files
    *
    * @return array
    * @see    ____func_see____
    * @since  1.0.0
    */
    public function getCSSFiles()
    {
          $list = parent::getCSSFiles();
          $list[] = 'modules/CDev/MarketPrice/style.css';

          return $list;
    }
}

Once the “style.css” file is added to the “skins/default/en/modules/CDev/MarketPrice/” folder, it loads automatically on the product details page (on that page only).

7) Add icon, the “icon.png” file, to the module's main directory. It will be picked up automatically during the installation of the module.

8) Pack module (this is covered at the end of the “Module structure” chapter). Using the “Upload add-on” button on the “Addons” -> “Manage addons”, upload your archive. Once the cache is rebuilt, the module should be enabled.

Clone this wiki locally