Xlite counterpath
Author: v | 2025-04-24
Bria Solo Free is also the renamed and updated version of XLite. Users of XLite will now have to upgrade to Bria Solo as well as provide CounterPath the details of their session Users of XLite will now have to upgrade to Bria Solo as well as provide CounterPath the details of their session initiation protocol or SIP
Counterpath Xlite Soft Phone and the IPitomy PBX
Is a guide explaining how to add new property to product.Basic plan to this task is:change DTO class \XLite\Model\DTO\Product\Info;change \XLite\View\FormModel\Product\Info class that renders product details form.We decorate \XLite\Model\DTO\Product\Info class, so we create the classes/XLite/Module/XCExample/ImageWidgetDemo/Model/DTO/Product/Info.php file with the following content: // vim: set ts=4 sw=4 sts=4 et:namespace XLite\Module\XCExample\ImageWidgetDemo\Model\DTO\Product;/** * Abstract widget */abstract class Info extends \XLite\Model\DTO\Product\Info implements \XLite\Base\IDecorator{ protected function init($object) { parent::init($object); $secondaryImages = $object->getSecondaryImages(); $dtoImages = [ 0 => [ 'delete' => false, 'position' => '', 'alt' => '', 'temp_id' => '', ] ]; foreach ($secondaryImages as $image) { $dtoImages[$image->getId()] = [ 'delete' => false, 'position' => '', 'alt' => '', 'temp_id' => '', ]; } $this->default->secondary_images = $dtoImages; } public function populateTo($object, $rawData = null) { parent::populateTo($object, $rawData); $object->processFiles('secondaryImages', $this->default->secondary_images); }}We implement two methods in this class:init() is used to populate data-transfer object (DTO) with secondary images' data;populateTo() is used to apply changes to product object based on submitted data. In this case, all needed routines for handling images are defined in processFiles() method, so we just call it with first parameter as name of our product's property (secondaryImages) and with second parameter as data submitted in the form ($this->default->secondary_images).Now we should apply changes to our product details' form. We decorate \XLite\View\FormModel\Product\Info class and create the classes/XLite/Module/XCExample/ImageWidgetDemo/View/FormModel/Product/Info.php file with the following content:// vim: set ts=4 sw=4 sts=4 et:namespace XLite\Module\XCExample\ImageWidgetDemo\View\FormModel\Product;/** * Product form model */abstract class Info extends \XLite\View\FormModel\Product\Info implements \XLite\Base\IDecorator{ protected function defineFields() { $schema = parent::defineFields(); $product = \XLite\Core\Database::getRepo('XLite\Model\Product')->find($this->getDataObject()->default->identity); $secondaryImages = []; if ($product) { $secondaryImages = $product->getSecondaryImages(); } $schema[self::SECTION_DEFAULT]['secondary_images'] = [ 'label' => static::t('Secondary Images'), 'type' => 'XLite\View\FormModel\Type\UploaderType', 'imageClass' => 'XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage', 'files' => $secondaryImages, 'multiple' => true, 'position' => 350, ]; return $schema; }}Essentially, we only have one defineFields() method here and inside it we define our 'secondary_images' field as follows:$schema[self::SECTION_DEFAULT]['secondary_images'] = [ 'label' => static::t('Secondary Images'), 'type' => 'XLite\View\FormModel\Type\UploaderType', 'imageClass' => 'XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage', 'files' => $secondaryImages, 'multiple' => true, 'position' => 350,];label of this field is 'Secondary Images';widget used for rendering this field is \XLite\View\FormModel\Type\UploaderType;this widget will work with images of \XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage class;existing secondary images are passed into 'files' parameter;this widget allows to specify multiple images for a product, not a single one ('multiple' => true).Besides that, we need to display secondary images in store-front. For that we create a template that will be shown on product details page. We createskins/customer/modules/XCExample/ImageWidgetsDemo/product/details/secondary-images.twig template with the following content: {## # @ListChild (list="product.details.page", weight="80") #} Secondary images {% for Bria Solo Free is also the renamed and updated version of XLite. Users of XLite will now have to upgrade to Bria Solo as well as provide CounterPath the details of their session GetSecondaryImages(){ return $this->secondaryImages;}public function addSecondaryImages($image){ $this->secondaryImages[] = $image; return $this;} Creating SecondaryImage classWe create the classes/XLite/Module/XCExample/ImageWidgetDemo/Model/Image/Product/SecondaryImage.php file with the following content: // vim: set ts=4 sw=4 sts=4 et:namespace XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product;/** * @Entity * @Table (name="product_secondary_images") */class SecondaryImage extends \XLite\Model\Base\Image{ /** * @Column (type="integer") */ protected $orderby = 0; /** * @ManyToOne (targetEntity="\XLite\Model\Product", inversedBy="secondary_images") * @JoinColumn (name="product_id", referencedColumnName="product_id") */ protected $product; /** * @Column (type="string", length=255) */ protected $alt = '';}Let us have a look at each important moment of this SecondaryImage class:The directive: means that this class defines a new entity.We define the name of the table where info about these objects will be stored: @Table (name="product_secondary_images")In our case, this table will be 'xc_product_secondary_images', assuming you have not changed table prefix in config.We create our SecondaryImage class based on standard \XLite\Model\Base\Image image class: class SecondaryImage extends \XLite\Model\Base\ImageOur image class will have three additional properties: $orderby field for sorting, $product property as a link to parent product's object and $alt field that will define a text for HTML's 'alt' property.Implementation of $orderby and $alt properties is quite straight-forwart, while $product is more complex: /** * @ManyToOne (targetEntity="\XLite\Model\Product", inversedBy="secondaryImages") * @JoinColumn (name="product_id", referencedColumnName="product_id") */We create a backward relation to \XLite\Model\Product class similar to $secondaryImages property in \XLite\Module\XCExample\ImageWidgetDemo\Model\Product class.We define $product property as @ManyToOne, because one secondary image can be assigned to one and only one product, while a product can have multiple secondary images assigned. Then we link $product property to $secondaryImages property of the \XLite\Model\Product class:@ManyToOne (targetEntity="\XLite\Model\Product", inversedBy="secondaryImages") We also specify that MySQL table, where secondary images are stored must contain the product_id column with value of parent image's ID in order to create this relation: @JoinColumn (name="product_id", referencedColumnName="product_id")Now it is time to create the repository class that will handled requests to database about SecondaryImage objects. We create the classes/XLite/Module/XCExample/ImageWidgetDemo/Model/Repo/Image/Product/SecondaryImage.php file with the following content: // vim: set ts=4 sw=4 sts=4 et:namespace XLite\Module\XCExample\ImageWidgetDemo\Model\Repo\Image\Product;class SecondaryImage extends \XLite\Model\Repo\Base\Image{ /** * Returns the name of the directory within '/images' where images are stored */ public function getStorageName() { return 'product_secondary'; }}We extend the standard \XLite\Model\Repo\Base\Image repository class and use it as a template: class SecondaryImage extends \XLite\Model\Repo\Base\ImageWe also define that secondary image files will be stored in /images/product_secondary/ directory:public function getStorageName(){ return 'product_secondary';}We are done with creating SecondaryImage entity.Tweaking design of admin and customer interfacesFirst, we need to allow merchant to upload secondary images for a product on product details page in admin area. ThereComments
Is a guide explaining how to add new property to product.Basic plan to this task is:change DTO class \XLite\Model\DTO\Product\Info;change \XLite\View\FormModel\Product\Info class that renders product details form.We decorate \XLite\Model\DTO\Product\Info class, so we create the classes/XLite/Module/XCExample/ImageWidgetDemo/Model/DTO/Product/Info.php file with the following content: // vim: set ts=4 sw=4 sts=4 et:namespace XLite\Module\XCExample\ImageWidgetDemo\Model\DTO\Product;/** * Abstract widget */abstract class Info extends \XLite\Model\DTO\Product\Info implements \XLite\Base\IDecorator{ protected function init($object) { parent::init($object); $secondaryImages = $object->getSecondaryImages(); $dtoImages = [ 0 => [ 'delete' => false, 'position' => '', 'alt' => '', 'temp_id' => '', ] ]; foreach ($secondaryImages as $image) { $dtoImages[$image->getId()] = [ 'delete' => false, 'position' => '', 'alt' => '', 'temp_id' => '', ]; } $this->default->secondary_images = $dtoImages; } public function populateTo($object, $rawData = null) { parent::populateTo($object, $rawData); $object->processFiles('secondaryImages', $this->default->secondary_images); }}We implement two methods in this class:init() is used to populate data-transfer object (DTO) with secondary images' data;populateTo() is used to apply changes to product object based on submitted data. In this case, all needed routines for handling images are defined in processFiles() method, so we just call it with first parameter as name of our product's property (secondaryImages) and with second parameter as data submitted in the form ($this->default->secondary_images).Now we should apply changes to our product details' form. We decorate \XLite\View\FormModel\Product\Info class and create the classes/XLite/Module/XCExample/ImageWidgetDemo/View/FormModel/Product/Info.php file with the following content:// vim: set ts=4 sw=4 sts=4 et:namespace XLite\Module\XCExample\ImageWidgetDemo\View\FormModel\Product;/** * Product form model */abstract class Info extends \XLite\View\FormModel\Product\Info implements \XLite\Base\IDecorator{ protected function defineFields() { $schema = parent::defineFields(); $product = \XLite\Core\Database::getRepo('XLite\Model\Product')->find($this->getDataObject()->default->identity); $secondaryImages = []; if ($product) { $secondaryImages = $product->getSecondaryImages(); } $schema[self::SECTION_DEFAULT]['secondary_images'] = [ 'label' => static::t('Secondary Images'), 'type' => 'XLite\View\FormModel\Type\UploaderType', 'imageClass' => 'XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage', 'files' => $secondaryImages, 'multiple' => true, 'position' => 350, ]; return $schema; }}Essentially, we only have one defineFields() method here and inside it we define our 'secondary_images' field as follows:$schema[self::SECTION_DEFAULT]['secondary_images'] = [ 'label' => static::t('Secondary Images'), 'type' => 'XLite\View\FormModel\Type\UploaderType', 'imageClass' => 'XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage', 'files' => $secondaryImages, 'multiple' => true, 'position' => 350,];label of this field is 'Secondary Images';widget used for rendering this field is \XLite\View\FormModel\Type\UploaderType;this widget will work with images of \XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage class;existing secondary images are passed into 'files' parameter;this widget allows to specify multiple images for a product, not a single one ('multiple' => true).Besides that, we need to display secondary images in store-front. For that we create a template that will be shown on product details page. We createskins/customer/modules/XCExample/ImageWidgetsDemo/product/details/secondary-images.twig template with the following content: {## # @ListChild (list="product.details.page", weight="80") #} Secondary images {% for
2025-04-13GetSecondaryImages(){ return $this->secondaryImages;}public function addSecondaryImages($image){ $this->secondaryImages[] = $image; return $this;} Creating SecondaryImage classWe create the classes/XLite/Module/XCExample/ImageWidgetDemo/Model/Image/Product/SecondaryImage.php file with the following content: // vim: set ts=4 sw=4 sts=4 et:namespace XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product;/** * @Entity * @Table (name="product_secondary_images") */class SecondaryImage extends \XLite\Model\Base\Image{ /** * @Column (type="integer") */ protected $orderby = 0; /** * @ManyToOne (targetEntity="\XLite\Model\Product", inversedBy="secondary_images") * @JoinColumn (name="product_id", referencedColumnName="product_id") */ protected $product; /** * @Column (type="string", length=255) */ protected $alt = '';}Let us have a look at each important moment of this SecondaryImage class:The directive: means that this class defines a new entity.We define the name of the table where info about these objects will be stored: @Table (name="product_secondary_images")In our case, this table will be 'xc_product_secondary_images', assuming you have not changed table prefix in config.We create our SecondaryImage class based on standard \XLite\Model\Base\Image image class: class SecondaryImage extends \XLite\Model\Base\ImageOur image class will have three additional properties: $orderby field for sorting, $product property as a link to parent product's object and $alt field that will define a text for HTML's 'alt' property.Implementation of $orderby and $alt properties is quite straight-forwart, while $product is more complex: /** * @ManyToOne (targetEntity="\XLite\Model\Product", inversedBy="secondaryImages") * @JoinColumn (name="product_id", referencedColumnName="product_id") */We create a backward relation to \XLite\Model\Product class similar to $secondaryImages property in \XLite\Module\XCExample\ImageWidgetDemo\Model\Product class.We define $product property as @ManyToOne, because one secondary image can be assigned to one and only one product, while a product can have multiple secondary images assigned. Then we link $product property to $secondaryImages property of the \XLite\Model\Product class:@ManyToOne (targetEntity="\XLite\Model\Product", inversedBy="secondaryImages") We also specify that MySQL table, where secondary images are stored must contain the product_id column with value of parent image's ID in order to create this relation: @JoinColumn (name="product_id", referencedColumnName="product_id")Now it is time to create the repository class that will handled requests to database about SecondaryImage objects. We create the classes/XLite/Module/XCExample/ImageWidgetDemo/Model/Repo/Image/Product/SecondaryImage.php file with the following content: // vim: set ts=4 sw=4 sts=4 et:namespace XLite\Module\XCExample\ImageWidgetDemo\Model\Repo\Image\Product;class SecondaryImage extends \XLite\Model\Repo\Base\Image{ /** * Returns the name of the directory within '/images' where images are stored */ public function getStorageName() { return 'product_secondary'; }}We extend the standard \XLite\Model\Repo\Base\Image repository class and use it as a template: class SecondaryImage extends \XLite\Model\Repo\Base\ImageWe also define that secondary image files will be stored in /images/product_secondary/ directory:public function getStorageName(){ return 'product_secondary';}We are done with creating SecondaryImage entity.Tweaking design of admin and customer interfacesFirst, we need to allow merchant to upload secondary images for a product on product details page in admin area. There
2025-04-09IntroductionThis article describes how developers can create a new page in X-Cart. For instance, we want to create a page in admin area (admin.php?target=tony_custom) that will show some specific information. This guide explains how to achieve this task.Before get startedFirst thing to do is to create an empty module. We are creating a module with developer ID Tony and module ID PageDemo.Creating page in admin areaFor the sake of example, our task is to create the page which will be available at admin.php?target=tony_custom address and will display Hello world! text.Create new controller class. Since we want our page to be opened at admin.php?target=tony_custom, the controller class must be named TonyCustom. If you need more info about how controllers work in X-Cart, look at Controllers article.We create the classes/XLite/Module/Tony/PageDemo/Controller/Admin/TonyCustom.php file with the following content: namespace XLite\Module\Tony\PageDemo\Controller\Admin;class TonyCustom extends \XLite\Controller\Admin\AAdmin{}As you can see, it is pretty empty, but since no data should be processed from the request, we do not need any extra methods here.Create new viewer class that will manage the data output. This viewer class should sit in the classes/XLite/Module/Tony/PageDemo/View/Page/Admin/ directory and have the same as controller class. This is just an agreement and all page viewer classes follow the same principle. We are creating the classes/XLite/Module/Tony/PageDemo/View/Page/Admin/TonyCustom.php file with the following content: 5.2.x and earlier5.3.xnamespace XLite\Module\Tony\PageDemo\View\Page\Admin;/** * @ListChild (list="admin.center", zone="admin") */class TonyCustom extends \XLite\View\AView{ public static function getAllowedTargets() { return array_merge(parent::getAllowedTargets(), array('tony_custom')); } protected function getDefaultTemplate() { return 'modules/Tony/PageDemo/page/tony_custom/body.tpl'; }}As you can see this implementation has only few differences:namespace XLite\Module\Tony\PageDemo\View\Page\Customer;namespace is a bit different;/** * @ListChild (list="center") */We use this @ListChild directive in order to insert this viewer class into central area of customer area, instead of admin one;5.2.x and earlier5.3.xprotected function getDefaultTemplate(){ return 'modules/Tony/PageDemo/page/tony_custom/body.tpl';}The template for this viewer sits in other location. Aside from that, the implementation is the
2025-04-20IntroductionThis article explains how to use image selection widget in X-Cart. And also, how to attach images to an entity. For the sake of example, we will create a mod that adds 'Secondary images' field to a product. Merchant will be able to assign any number of secondary images to a product and these images will be shown on product details page in customer area.ImplementationCreating an empty moduleFirst of all, we create an empty module with developer ID XCExample and module ID ImageWidgetDemo.Decorating Product classInside this module, we decorate the \XLite\Model\Product class as we want to add a new property secondaryImages to it: // vim: set ts=4 sw=4 sts=4 et:namespace XLite\Module\XCExample\ImageWidgetDemo\Model;abstract class Product extends \XLite\Model\Product implements \XLite\Base\IDecorator{ /** * @OneToMany (targetEntity="XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage", mappedBy="product", cascade={"all"}) * @OrderBy ({"orderby" = "ASC"}) */ protected $secondaryImages; public function __construct(array $data = array()) { parent::__construct($data); $this->secondaryImages = new \Doctrine\Common\Collections\ArrayCollection(); } public function getSecondaryImages() { return $this->secondaryImages; } public function addSecondaryImages($image) { $this->secondaryImages[] = $image; return $this; }}Let us have a closer look at this implementation.We add a new property to a product object: /** * @OneToMany (targetEntity="XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage", mappedBy="product", cascade={"all"}) * @OrderBy ({"orderby" = "ASC"}) */ protected $secondaryImages;We define it as OneToMany, which means that one product can have many secondary images, while a secondary image always belongs to a single product.The secondary image object is defined by the \XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage class:targetEntity="XLite\Module\XCExample\ImageWidgetDemo\Model\Image\Product\SecondaryImage"This class does not exist yet, so we will have to create it as a next step. Then, we specify that each record about SecondaryImage object must contain a reference to its product object: Learn more about mappedBy in Doctrine documentation. Also, using mappedBy directive in Product class means that we will have to use inversedBy directive in SecondaryImage class in order to create bidirectional relation. This way we will be able to access SecondaryImage object from Product object $product->getSecondaryImages() as well as access Product object from SecondaryImage object $secondaryImage->getProduct(). This cascade directive defines that SecondaryImage objects are associated with its Product object and if we remove or clone Product entity, the same will happen to SecondaryImage objects linked to it. Learn more about cascade in Doctrine documentation. The @OrderBy directive means that SecondaryImage objects will be ordered by SecondaryImage's orderby field. @OrderBy ({"orderby" = "ASC"})We also change constructor method a bit: public function __construct(array $data = array()){ parent::__construct($data); $this->secondaryImages = new \Doctrine\Common\Collections\ArrayCollection();}and tell Product class that secondaryImages property is an array.Finally, we add getter/setter methods:public function
2025-03-26Bria User Guide - iOS - for Bria Solo and Bria TeamsPublication date: 2025-02-13 Copyright ©2025 CounterPath an Alianza Company. All rights reserved. This document contains information proprietary to CounterPath, and shall not be used for engineering, design, procurement, or manufacture, in whole or in part, without the consent of CounterPath. The content of this publication is intended to demonstrate typical uses and capabilities of Bria for iOS from CounterPath. Users of this material must determine for themselves whether the information contained herein applies to a particular IP-based networking system. CounterPath makes no warranty regarding the content of this document, including—but not limited to—implied warranties of fitness for any particular purpose. In no case will CounterPath, its employees, officers or directors be liable for any incidental, indirect or otherwise consequential damage or loss that may result after the use of this publication. CounterPath®, Bria®, X-Lite®, and the ® logo are registered trademarks of CounterPath Corporation. Stretto™ and the Stretto Platform™ are trademarks of CounterPath Corporation. Android and Google Play are trademarks of Google Inc. Eclipse is a trademark of Eclipse Foundation, Inc. Intel, the Intel logo, Intel Core and Core Inside are trademarks of Intel Corporation in the U.S. and/or other countries. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. iPhone, iPad, iPod, Mac, mac OS, App Store, Objective–C, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries. Microsoft, Active Directory, Office, Excel, Outlook, and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. Oracle and Java are registered trademarks of Oracle and/or its affiliates. All other products and services are
2025-04-08Bria User Guide - Windows and Mac - for Bria Solo and Bria TeamsPublication date: 2025-03-06 Copyright ©2025 CounterPath an Alianza Company. All rights reserved. This document contains information proprietary to CounterPath, and shall not be used for engineering, design, procurement, or manufacture, in whole or in part, without the consent of CounterPath. The content of this publication is intended to demonstrate typical uses and capabilities of Bria for Windows and Mac from CounterPath. Users of this material must determine for themselves whether the information contained herein applies to a particular IP-based networking system. CounterPath makes no warranty regarding the content of this document, including—but not limited to—implied warranties of fitness for any particular purpose. In no case will CounterPath, its employees, officers or directors be liable for any incidental, indirect or otherwise consequential damage or loss that may result after the use of this publication. CounterPath®, Bria®, X-Lite®, and the ® logo are registered trademarks of CounterPath Corporation. Stretto™ and the Stretto Platform™ are trademarks of CounterPath Corporation. Android and Google Play are trademarks of Google Inc. Eclipse is a trademark of Eclipse Foundation, Inc. Intel, the Intel logo, Intel Core and Core Inside are trademarks of Intel Corporation in the U.S. and/or other countries. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. iPhone, iPad, iPod, Mac, mac OS, App Store, Objective–C, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries. Microsoft, Active Directory, Office, Excel, Outlook, and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. Oracle and Java are registered trademarks of Oracle and/or its affiliates. All other products and services are the registered trademarks of their respective holders.
2025-03-31