First of all, here is what I would like to achieve. The module I am working on is for X-cart 5.3.6.0. We sell books, and we would like
to have a page of an author, where we have the name, photo, description of the author
(this part has been done), and all his books underneath. As I wrote in the thread,
https://forum.x-cart.com/showthread.php?t=77082 I made a model for entities "Author" in ManyToMany relationship with the model Product.
I have following files to output the page
Controller file Controller/Customer/Author.php with
Code:
class Author extends \XLite\Controller\Customer\ACustomer
{
protected $params = array('target', 'author_id');
public function getAuthorId()
{
return \XLite\Core\Request::getInstance()->author_id ?: 0;
}
}
so that the page can be called with author_id,
page viewer file View/Page/Customer/Author.php (basically a modification of
View/Page/Customer/Category.php )
Code:
<?php
namespace XLite\Module\EdB\Librairie\View\Page\Customer;
use \XLite\Core\Database;
use \Model\Catalog\Base;
/**
* Category widget
*
* @ListChild (list="center", zone="customer")
*/
class Author extends \XLite\View\AView
{
/**
* Return list of targets allowed for this widget
*
* @return array
*/
public static function getAllowedTargets()
{
$result = parent::getAllowedTargets();
$result[] = 'author';
return $result;
}
public function findAuthor()
{
$author_id = $this->getAuthorId();
$author = \XLite\Core\Database::getRepo('XLite\Module\EdB\Librairie\Model\Au
thor')->find($author_id);
return $author;
}
public function describeAuthor()
{
$author = $this->findAuthor();
$value = $author->getDescription();
$value = \XLite\Model\Base\Catalog::getPreprocessedValue($value);
echo $value;
}
protected function getDefaultTemplate()
{
return 'modules/EdB/Librairie/aut1.twig';
}
}
with the twig file skins/customer/modules/EdB/Librairie/aut1.twig
Code:
{{widget('\\XLite\\View\\Image', image=this.findAuthor().getImage(), className='
photo product-thumbnail', verticalAlign='top', id='product_image_' ~ this.findAu
thor().author_id, maxWidth=600, maxHeight=600, alt='') }}
{{this.findAuthor().name}}
<br>
<br>
{{this.describeAuthor()}}
This part is working. Now, to output the list of books by the author, I have another widget Librairie/View/ItemsList/Product/Customer/BooksBy.php with the following
content (below, I removed the part that "should" define which products to show, so
with this we get all products).
Code:
<?php
namespace XLite\Module\EdB\Librairie\View\ItemsList\Product\Customer;
/**
*
* @ListChild (list="center.bottom", zone="customer", weight="300")
*/
class BooksBy extends \XLite\View\ItemsList\Product\Customer\ACustomer
{
protected $BooksbyAuthor = null;
protected static function getWidgetTarget()
{
return 'author';
}
public static function getAllowedTargets()
{
$result = parent::getAllowedTargets();
$result[] = self::getWidgetTarget();
return $result;
}
protected function getData(\XLite\Core\CommonCell $cnd, $countOnly = false)
{
return \XLite\Core\Database::getRepo('\XLite\Model\Product')->search(
$cnd, $countOnly);
}
protected function getPagerClass()
{
return 'XLite\Module\EdB\Librairie\View\Pager\Customer\Product\Product';
}
}
Of course, I could join the xc_products table with xc_product_author_links table and create a query condition, write a function in Repo class, and this might take less time to finish writing up. However, as I already have pulled the author entity with all properties, including getProducts() which gives an array of products, I would rather use this array to "feed" the getData function.
Now, I encounter two problems.
- How to pass an array or even a function from viewer widget to the itemlists widget?
- How to transform an array to the return of the getData function?
For the first point, most of my trials ended up with " Using $this when not in object context" or "call to undefined function", so for now I have reproduced the function in ItemsList file, that is
Code:
public function findBooks()
{
$author_id = \XLite\Core\Request::getInstance()->author_id;
$author = \XLite\Core\Database::getRepo('XLite\Module\EdB\Librairie\Model\Au
thor')->find($author_id);
$products = $author->getProducts();
return $products;
}
This is already in Model class and Viewer class, so I really would like to remove these lines, but for now, it works. As to the second issue, the closest thing
I have seen is
https://forum.x-cart.com/showthread.php?t=70741
so I tried the following (among others)
Code:
protected $BooksbyAuthor = null;
protected function getData(\XLite\Core\CommonCell $cnd, $countOnly = false)
{
if(!isset($this->BooksbyAuthor)) {
$this->BooksbyAuthor = $this->findBooks();
}
return true == $countOnly
?count($this->BooksbyAuthor)
: $this->BooksbyAuthor;
}
but this leads to
Code:
ERROR: "0" (code N/A)
Argument 2 passed to XLite\Core\Model\EntityVersion\BulkEntityVersionFetcher::__construct() must be of the type array, null given, called in /srv/http/newbtq72/xcart-53/var/run/classes/XLite/View/ItemsList/Product/Customer/ACustomerAbstract.php on line 918
and in the log, I find,
Code:
XLite [warning] Warning: array_map(): Argument #2 should be an array in /srv/http/newbtq72/xcart-53/var/run/classes/XLite/View/ItemsList/Product/Customer/ACustomerAbstract.php on line 916
So, would anyone have any advice on this?