Related
I am working on a 2D string with \n new line at the end.
The maze is 1000 x 1000 but I downscales this to 10 x 5 for the sake of readability.
0 means empty space.
S means starting point.
T means target point.
I created a function called cal_path to calculate the path between S and T. However the
result is not correct. I've hard-coded an estimate answer. Any advice/help would be much appreciated.
<?php
$maze='S000000000
0000000000
0000000000
00000000T0
0000000000';
$maze_y=explode(PHP_EOL,$maze);//convert line to array
function show_maze($maze_y){
for ($y=0;$y<count($maze_y);$y++){
for ($x=0;$x<=strlen($maze_y[$y]);$x++){
echo $maze_y[$y][$x];
}
echo "\n";
}
}
function cal_path($maze_y){
// I hardcoded it right now, I am stuck here
return array(
array(1,1),
array(1,2),
array(1,3),
array(2,4),
array(2,5),
array(2,6),
array(3,7),
array(3,8),
);
}
show_maze($maze_y); //original maze
$path=cal_path($maze_y);
foreach ($path as $point){
$maze_y[$point[0]][$point[1]]='P';
}
show_maze($maze_y);
Output:
S000000000
0000000000
0000000000
00000000T0
0000000000
Estimate Output:
S000000000
0PPP000000
0000PPP000
0000000PP0
0000000000
Here's my attempt, but it fails to find a shortest path.
<?php
$maze = '0000000000
0000S00000
0000000000
00000000T0
0000000000';
$maze_y = explode(PHP_EOL, $maze); //convert line to array
function show_maze($maze_y)
{
for ($y = 0; $y < count($maze_y); $y++) {
for ($x = 0; $x < strlen($maze_y[$y]); $x++) {
echo $maze_y[$y][$x];
}
echo "\n";
}
}
function cal_path($maze_y)
{
$found_start = -1;
$found_end = -1;
$row = 0;
foreach ($maze_y as $current) {
for ($x = 0; $x <= strlen($current); $x++) {
if ($found_start == -1) {
$found_start = (strpos($current, 'S') === false) ? '-1' : strpos($current, 'S');
if ($found_start != -1) {
$found_start_y = $row;
}
}
if ($found_end == -1) {
$found_end = (strpos($current, 'T') === false) ? '-1' : strpos($current, 'T');
if ($found_end != -1) {
$found_end_y = $row;
}
}
}
$row++;
}
echo 'start' . $found_start . ' - ' . $found_start_y;
echo "\n";
echo 'end' . $found_end . ' - ' . $found_end_y;
echo "\n";
$step_size_y = $found_end_y - $found_start_y;
$step_size_x = $found_end - $found_start;
echo "step size X $step_size_x Y $step_size_y";
echo "\n";
$start_pointer = array($found_start, $found_start_y);
$maxtry = 100;
$cal_result = array();
while ($maxtry > 0 && ($start_pointer[0] != $found_end || $start_pointer[1] != $found_end_y)) {
$maxtry--;
if ($step_size_x > 1 && $start_pointer[0] != $found_end) {
$start_pointer[0]++;
} else if ($step_size_x < 1 && $start_pointer[0] != $found_end) {
$start_pointer[0]--;
}
if ($step_size_y > 1 && $start_pointer[1] != $found_end_y) {
$start_pointer[1]++;
} else if ($step_size_y < 1 && $start_pointer[1] != $found_end_y) {
$start_pointer[1]--;
}
array_push($cal_result, array($start_pointer[1] , $start_pointer[0] ));
echo 'Path: ' . $start_pointer[0] . ' - ' . $start_pointer[1] . "\n";
}
return $cal_result;
}
show_maze($maze_y); //original maze
$path = cal_path($maze_y);
foreach ($path as $point) {
$maze_y[$point[0]][$point[1]] = 'P';
}
show_maze($maze_y);
You can use the following as a starting point.
It's a simple implementation of the pseudocode at: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Using_a_priority_queue
<?php
require_once 'src/MinQueue.php';
require_once 'src/Dijkstra.php';
require_once 'src/Maze.php';
$maze = Maze::fromString(file_get_contents('maze.txt')); // < a simple text file
$start = $maze->find('S');
$goal = $maze->find('T');
$helper = new Dijkstra(
// return neighbors
function ($a) use ($maze) {
return $maze->getNeighbors($a, ['W']);
},
// calculate the distance
function ($a, $b) use ($maze) {
return $maze->getDistance($a, $b);
}
);
$tStart = microtime(true);
$path = $helper->findPath($start, $goal);
$tEnd = microtime(true);
// export the maze with the path marked with '.'
$mazeStrWithPath = $maze->toString(function ($tile) use ($path) {
return in_array($tile, $path, true) && !in_array($tile->value, ['S', 'T'])
? '.'
: $tile->value
;
});
printf("%s\nin: %.5fs\n\n", $mazeStrWithPath, $tEnd - $tStart);
example output:
_____________________________________________________W_________________
_____________________________________________________W_________________
_____________________________________________________W_________________
_________________W___________________________________W_________________
_________________W___________________________________W_____________T___
_________________W___________________________________W____________.____
_________________W___________________________________W___________._____
_________________W___________________________________W__________.______
_________________W___________________________________W_________._______
_________________W____________________.........______W________.________
_________________W___________________.WWWWWWWWW._____W_______._________
_________________W__________________._W_____...______W______.__________
_________________W_________________.__W____.WWWWWWWWWW_____.___________
_________________W________________.___W_____...............____________
_________________W_____________...____W________________________________
_________________W____________.WWWWWWWW________________________________
_________________W_____________.______W________________________________
_________W_______W______________._____W________________________________
_________W_______W______________._____W________________________________
_________W_______WWWWWWWWWWWWWWW._____W________________________________
_________W_____________________.______W________________________________
_________W____________________._______W________________________________
_________W___________________.________W________________________________
__S...___W__________________._________W________________________________
______.__W_________________.__________W________________________________
_______._W________________.___________W________________________________
________.W_______________.____________W________________________________
_________................_____________W________________________________
Using the following classes:
MinQueue
<?php
declare(strict_types=1);
class MinQueue implements \Countable
{
/**
* #var \SplPriorityQueue
*/
private $queue;
/**
* #var \SplObjectStorage
*/
private $register;
/**
* MinQueue constructor.
*/
public function __construct()
{
$this->queue = new class extends \SplPriorityQueue
{
/** #inheritdoc */
public function compare($p, $q)
{
return $q <=> $p;
}
};
$this->register = new \SplObjectStorage();
}
/**
* #param object $value
* #param mixed $priority
*/
public function insert($value, $priority)
{
$this->queue->insert($value, $priority);
$this->register->attach($value);
}
/**
* #return object
*/
public function extract()
{
$value = $this->queue->extract();
$this->register->detach($value);
return $value;
}
/**
* #inheritdoc
*/
public function contains($value)
{
return $this->register->contains($value);
}
/**
* #inheritdoc
*/
public function count()
{
return count($this->queue);
}
}
Dijkstra
<?php
declare(strict_types=1);
class Dijkstra
{
/**
* #var callable
*/
private $neighbors;
/**
* #var callable
*/
private $length;
/**
* Dijkstra constructor.
*
* #param callable $neighbors
* #param callable $length
*/
public function __construct(callable $neighbors, callable $length)
{
$this->neighbors = $neighbors;
$this->length = $length;
}
/**
* see: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Using_a_priority_queue
*
* #param object $src
* #param object $dst
*
* #return array
*/
public function findPath($src, $dst): array
{
// setup
$queue = new MinQueue();
$distance = new \SplObjectStorage();
$path = new \SplObjectStorage();
// init
$queue->insert($src, 0);
$distance[$src] = 0;
while (count($queue) > 0) {
$u = $queue->extract();
if ($u === $dst) {
return $this->buildPath($dst, $path);
}
foreach (call_user_func($this->neighbors, $u) as $v) {
$alt = $distance[$u] + call_user_func($this->length, $u, $v);
$best = isset($distance[$v]) ? $distance[$v] : INF;
if ($alt < $best) {
$distance[$v] = $alt;
$path[$v] = $u;
if (!$queue->contains($v)) {
$queue->insert($v, $alt);
}
}
}
}
throw new \LogicException('No path found.');
}
/**
* #param object $dst
* #param \SplObjectStorage $path
*
* #return array
*/
private function buildPath($dst, \SplObjectStorage $path): array
{
$result = [$dst];
while (isset($path[$dst]) && null !== $path[$dst]) {
$src = $path[$dst];
$result[] = $src;
$dst = $src;
}
return array_reverse($result);
}
}
Maze
<?php
declare(strict_types=1);
class Maze
{
/**
* #var array
*/
private $tiles = [];
/**
* Maze constructor.
*
* #param array $tiles
*/
private function __construct(array $tiles = [])
{
$this->tiles = $tiles;
}
/**
* #param string $maze
* #param string $rowDelimiter
*
* #return Maze
*/
public static function fromString(string $maze, string $rowDelimiter = "\n"): Maze
{
$tiles = [];
foreach (explode($rowDelimiter, $maze) as $r => $row) {
$rowTiles = [];
foreach (str_split(trim($row)) as $c => $value) {
$rowTiles[] = (object)[
'row' => $r,
'col' => $c,
'value' => $value
];
}
$tiles[] = $rowTiles;
}
return new self($tiles);
}
/**
* #param callable $renderer
* #param string $rowDelimiter
*
* #return string
*/
public function toString(callable $renderer = null, string $rowDelimiter = "\n"): string
{
$renderer = $renderer ?: function ($tile) { return $tile->value; };
$result = [];
foreach ($this->tiles as $r => $row) {
if (!isset($result[$r])) {
$result[$r] = [];
}
foreach ($row as $c => $tile) {
$result[$r][$c] = $renderer($tile);
}
}
return implode($rowDelimiter, array_map('implode', $result));
}
/**
* #param string $value
*
* #return object
*/
public function find(string $value)
{
foreach ($this->tiles as $row) {
foreach ($row as $tile) {
if ($tile->value === $value) {
return $tile;
}
}
}
return null;
}
/**
* #param object $tile
* #param array $filter
*
* #return array
*/
public function getNeighbors($tile, array $filter = []): array
{
$neighbors = [];
foreach ([
[-1, -1], [-1, 0], [-1, 1],
[ 0, -1], [ 0, 1],
[ 1, -1], [ 1, 0], [ 1, 1],
] as $transformation) {
$r = $tile->row + $transformation[0];
$c = $tile->col + $transformation[1];
if (isset($this->tiles[$r][$c]) && !in_array($this->tiles[$r][$c]->value, $filter, true)) {
$neighbors[] = $this->tiles[$r][$c];
}
}
return $neighbors;
}
/**
* #param object $a
* #param object $b
*
* #return float
*/
public function getDistance($a, $b): float
{
$p = $b->row - $a->row;
$q = $b->col - $a->col;
return sqrt($p * $p + $q * $q);
}
}
Download: https://github.com/Yoshix/so-49896590
I am trying to override the Topmenu block in Magento 2 so that I can change the HTML structure of my sub menus but I can't seem to get past this problem.
What I have done
I have created a module called Ecommerce\Topmenu.
Files
app/code/Ecommerce/Topmenu
-- etc/
--- di.xml
--- module.xml
-- Plugin/
--- Topmenu.php
-- registration.php
Topmenu.php
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Ecommerce\Topmenu\Plugin;
use \Magento\Framework\DataObject\IdentityInterface;
use \Magento\Framework\View\Element\Template;
use \Magento\Framework\Data\TreeFactory;
use \Magento\Framework\Data\Tree\Node;
use \Magento\Framework\Data\Tree\NodeFactory;
/**
* Html page top menu block
*/
class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{
/**
* Get top menu html
*
* #param string $outermostClass
* #param string $childrenWrapClass
* #param int $limit
* #return string
*/
public function getHtml($outermostClass = '', $childrenWrapClass = '', $limit = 0)
{
$this->_eventManager->dispatch(
'page_block_html_topmenu_gethtml_before',
['menu' => $this->_menu, 'block' => $this]
);
$this->_menu->setOutermostClass($outermostClass);
$this->_menu->setChildrenWrapClass($childrenWrapClass);
$html = $this->_getHtml($this->_menu, $childrenWrapClass, $limit);
$transportObject = new \Magento\Framework\DataObject(['html' => $html]);
$this->_eventManager->dispatch(
'page_block_html_topmenu_gethtml_after',
['menu' => $this->_menu, 'transportObject' => $transportObject]
);
$html = $transportObject->getHtml();
return $html;
}
/**
* Count All Subnavigation Items
*
* #param \Magento\Backend\Model\Menu $items
* #return int
*/
protected function _countItems($items)
{
$total = $items->count();
foreach ($items as $item) {
/** #var $item \Magento\Backend\Model\Menu\Item */
if ($item->hasChildren()) {
$total += $this->_countItems($item->getChildren());
}
}
return $total;
}
/**
* Building Array with Column Brake Stops
*
* #param \Magento\Backend\Model\Menu $items
* #param int $limit
* #return array|void
*
* #todo: Add Depth Level limit, and better logic for columns
*/
protected function _columnBrake($items, $limit)
{
$total = $this->_countItems($items);
if ($total <= $limit) {
return;
}
$result[] = ['total' => $total, 'max' => (int)ceil($total / ceil($total / $limit))];
$count = 0;
$firstCol = true;
foreach ($items as $item) {
$place = $this->_countItems($item->getChildren()) + 1;
$count += $place;
if ($place >= $limit) {
$colbrake = !$firstCol;
$count = 0;
} elseif ($count >= $limit) {
$colbrake = !$firstCol;
$count = $place;
} else {
$colbrake = false;
}
$result[] = ['place' => $place, 'colbrake' => $colbrake];
$firstCol = false;
}
return $result;
}
/**
* Add sub menu HTML code for current menu item
*
* #param \Magento\Framework\Data\Tree\Node $child
* #param string $childLevel
* #param string $childrenWrapClass
* #param int $limit
* #return string HTML code
*/
protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
{
$html = '';
if (!$child->hasChildren()) {
return $html;
}
$colStops = null;
if ($childLevel == 0 && $limit) {
$colStops = $this->_columnBrake($child->getChildren(), $limit);
}
$html .= '<ul class="level' . $childLevel . ' megaSub">';
$html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops);
$html .= '</ul>';
return $html;
}
/**
* Recursively generates top menu html from data that is specified in $menuTree
*
* #param \Magento\Framework\Data\Tree\Node $menuTree
* #param string $childrenWrapClass
* #param int $limit
* #param array $colBrakes
* #return string
*
* #SuppressWarnings(PHPMD.CyclomaticComplexity)
* #SuppressWarnings(PHPMD.NPathComplexity)
*/
protected function _getHtml(
\Magento\Framework\Data\Tree\Node $menuTree,
$childrenWrapClass,
$limit,
$colBrakes = []
) {
$html = '';
$children = $menuTree->getChildren();
$parentLevel = $menuTree->getLevel();
$childLevel = $parentLevel === null ? 0 : $parentLevel + 1;
$counter = 1;
$itemPosition = 1;
$childrenCount = $children->count();
$parentPositionClass = $menuTree->getPositionClass();
$itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';
foreach ($children as $child) {
$child->setLevel($childLevel);
$child->setIsFirst($counter == 1);
$child->setIsLast($counter == $childrenCount);
$child->setPositionClass($itemPositionClassPrefix . $counter);
$outermostClassCode = '';
$outermostClass = $menuTree->getOutermostClass();
if ($childLevel == 0 && $outermostClass) {
$outermostClassCode = ' class="' . $outermostClass . '" ';
$child->setClass($outermostClass);
}
if (count($colBrakes) && $colBrakes[$counter]['colbrake']) {
// $html .= '</ul></li><li class="column"><ul>';
}
if($counter > 1 && $childLevel == 1){
continue;
}
$html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
$html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml(
$child->getName()
) . '</span></a>' . $this->_addSubMenu(
$child,
$childLevel,
$childrenWrapClass,
$limit
) . '</li>';
$itemPosition++;
$counter++;
}
if (count($colBrakes) && $limit) {
$html = '<li class="column"><ul>' . $html . '</ul></li>';
}
return $html;
}
/**
* Generates string with all attributes that should be present in menu item element
*
* #param \Magento\Framework\Data\Tree\Node $item
* #return string
*/
protected function _getRenderedMenuItemAttributes(\Magento\Framework\Data\Tree\Node $item)
{
$html = '';
$attributes = $this->_getMenuItemAttributes($item);
foreach ($attributes as $attributeName => $attributeValue) {
$html .= ' ' . $attributeName . '="' . str_replace('"', '\"', $attributeValue) . '"';
}
return $html;
}
/**
* Returns array of menu item's attributes
*
* #param \Magento\Framework\Data\Tree\Node $item
* #return array
*/
protected function _getMenuItemAttributes(\Magento\Framework\Data\Tree\Node $item)
{
$menuItemClasses = $this->_getMenuItemClasses($item);
return ['class' => implode(' ', $menuItemClasses)];
}
/**
* Returns array of menu item's classes
*
* #param \Magento\Framework\Data\Tree\Node $item
* #return array
*/
protected function _getMenuItemClasses(\Magento\Framework\Data\Tree\Node $item)
{
$classes = [];
$classes[] = 'level' . $item->getLevel();
$classes[] = $item->getPositionClass();
if ($item->getIsFirst()) {
$classes[] = 'first';
}
if ($item->getIsActive()) {
$classes[] = 'active';
} elseif ($item->getHasActive()) {
$classes[] = 'has-active';
}
if ($item->getIsLast()) {
$classes[] = 'last';
}
if ($item->getClass()) {
$classes[] = $item->getClass();
}
if ($item->hasChildren()) {
$classes[] = 'parent';
}
return $classes;
}
/**
* Add identity
*
* #param array $identity
* #return void
*/
public function addIdentity($identity)
{
if (!in_array($identity, $this->identities)) {
$this->identities[] = $identity;
}
}
/**
* Get identities
*
* #return array
*/
public function getIdentities()
{
return $this->identities;
}
/**
* Get cache key informative items
*
* #return array
*/
public function getCacheKeyInfo()
{
$keyInfo = parent::getCacheKeyInfo();
$keyInfo[] = $this->getUrl('*/*/*', ['_current' => true, '_query' => '']);
return $keyInfo;
}
/**
* Get tags array for saving cache
*
* #return array
*/
protected function getCacheTags()
{
return array_merge(parent::getCacheTags(), $this->getIdentities());
}
/**
* Get menu object.
*
* #return Node
*/
public function getMenu()
{
return $this->_menu;
}
}
** Expected behavour **
My module should override the Magento Topmenu module whilst inheriting it allowing me to change the output markup
The problem
After running setup:upgrade and recompiling, I am just presented with the following error:
Fatal error: Call to a member function setOutermostClass() on null in /var/www/myecom.co.uk/app/code/Ecommerce/Topmenu/Plugin/Topmenu.php on line 36
It's like my code is not correctly extending the Topmenu block.
Any ideas?
For fix this my solution is insert construct as below:
public function __construct(Template\Context $context, NodeFactory $nodeFactory, TreeFactory $treeFactory, array $data = [])
{
parent::__construct($context, $nodeFactory, $treeFactory, $data);
$this->nodeFactory = $nodeFactory;
$this->treeFactory = $treeFactory;
}
This problem is a result of a recent Magento update which explains why I was having this problem using code that had previously worked for me on earlier Magento versions.
Final Solution
The final solution to fix this after Magento's update is to replace $this->_menu with $this->getMenu()
Now the working version of my custom module extends the Magento top menu class and just overrides the _getHtml function to change the markup as required.
I am using codeigniter 2.0 version. In datatables query not working using datatable method. But when i run this in mysql means it is perfectly working. I dont know how to solve this issue. Below i have given my query,
$this->load->library('datatables');
$this->datatables->query("select sales.id as id, sales.date as date, sales.customer_name, sale_items.product_name as pname, sales.depositcard_amt as debit, 0 as credit from sales join sale_items on sale_items.sale_id=sales.id where sales.customer_id = $user and sales.branch_id=$branchid and sales.depositcard_amt != 0.00 group by sales.id UNION ALL select deposit.id as id, deposit.credit_on as date, deposit_details.customer_name, deposit_details.package_name as pname, 0 as debit, deposit.total_amount as credit from deposit join deposit_details on deposit_details.deposit_id=deposit.id where deposit.customers=$user");
$this->datatables->add_column("Actions",
"<center></center>", "id")
->unset_column('id');
echo $this->datatables->generate();
Please give any ideas to solve this. Thanks in advance.
Library Datatables.php
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Ignited Datatables
*
* This is a wrapper class/library based on the native Datatables server-side implementation by Allan Jardine
* found at http://datatables.net/examples/data_sources/server_side.html for CodeIgniter
*
* #package CodeIgniter
* #subpackage libraries
* #category library
* #version 1.15
* #author Vincent Bambico <metal.conspiracy#gmail.com>
* Yusuf Ozdemir <yusuf#ozdemir.be>
* #link http://ellislab.com/forums/viewthread/160896/
*/
class Datatables
{
/**
* Global container variables for chained argument results
*
*/
private $ci;
private $table;
private $distinct;
private $query ;
private $fadu = "" ;
private $group_by = array();
private $order_by = array();
private $select = array();
private $joins = array();
private $left_joins = array();
private $outer_joins = array();
private $columns = array();
private $where = array();
private $or_where = array();
private $like = array();
private $filter = array();
private $add_columns = array();
private $edit_columns = array();
private $unset_columns = array();
/**
* Copies an instance of CI
*/
public function __construct()
{
$this->ci =& get_instance();
}
/**
* If you establish multiple databases in config/database.php this will allow you to
* set the database (other than $active_group) - more info: http://ellislab.com/forums/viewthread/145901/#712942
*/
public function set_database($db_name)
{
$db_data = $this->ci->load->database($db_name, TRUE);
$this->ci->db = $db_data;
}
/**
* Generates the SELECT portion of the query
*
* #param string $columns
* #param bool $backtick_protect
* #return mixed
*/
public function select($columns, $backtick_protect = TRUE)
{
foreach ($this->explode(',', $columns) as $val) {
$column = trim(preg_replace('/(.*)\s+as\s+(\w*)/i', '$2', $val));
$this->columns[] = $column;
$this->select[$column] = trim(preg_replace('/(.*)\s+as\s+(\w*)/i', '$1', $val));
}
$this->ci->db->select($columns, $backtick_protect);
return $this;
}
/**
* Generates the DISTINCT portion of the query
*
* #param string $column
* #return mixed
*/
public function distinct($column)
{
$this->distinct = $column;
$this->ci->db->distinct($column);
return $this;
}
/**
* Generates a custom GROUP BY portion of the query
*
* #param string $val
* #return mixed
*/
public function group_by($val)
{
$this->group_by[] = $val;
$this->ci->db->group_by($val);
return $this;
}
public function order_by($val, $direction = '')
{
$this->order_by[] = array($val, $direction );
$this->ci->db->order_by($val, $direction );
return $this;
}
public function query($val)
{
$this->query = $val;
$this->table = "";
return $this;
}
/**
* Generates the FROM portion of the query
*
* #param string $table
* #return mixed
*/
public function from($table , $fadu = "")
{
$this->table = $table;
$this->fadu = $fadu;
return $this;
}
/**
* Generates the JOIN portion of the query
*
* #param string $table
* #param string $fk
* #param string $type
* #return mixed
*/
public function join($table, $fk, $type = NULL)
{
$this->joins[] = array($table, $fk, $type);
$this->ci->db->join($table, $fk, $type);
return $this;
}
public function left_join($table, $fk, $type = NULL)
{
$this->left_joins[] = array($table, $fk, $type);
$this->ci->db->left_join($table, $fk, $type);
return $this;
}
public function outer_join($table, $fk, $type = NULL)
{
$this->outer_joins[] = array($table, $fk, $type);
$this->ci->db->outer_join($table, $fk, $type);
return $this;
}
/**
* Generates the WHERE portion of the query
*
* #param mixed $key_condition
* #param string $val
* #param bool $backtick_protect
* #return mixed
*/
public function where($key_condition, $val = NULL, $backtick_protect = TRUE)
{
$this->where[] = array($key_condition, $val, $backtick_protect);
$this->ci->db->where($key_condition, $val, $backtick_protect);
return $this;
}
/**
* Generates the WHERE portion of the query
*
* #param mixed $key_condition
* #param string $val
* #param bool $backtick_protect
* #return mixed
*/
public function or_where($key_condition, $val = NULL, $backtick_protect = TRUE)
{
$this->or_where[] = array($key_condition, $val, $backtick_protect);
$this->ci->db->or_where($key_condition, $val, $backtick_protect);
return $this;
}
/**
* Generates the WHERE portion of the query
*
* #param mixed $key_condition
* #param string $val
* #param bool $backtick_protect
* #return mixed
*/
public function filter($key_condition, $val = NULL, $backtick_protect = TRUE)
{
$this->filter[] = array($key_condition, $val, $backtick_protect);
return $this;
}
/**
* Generates a %LIKE% portion of the query
*
* #param mixed $key_condition
* #param string $val
* #param bool $backtick_protect
* #return mixed
*/
public function like($key_condition, $val = NULL, $backtick_protect = TRUE)
{
$this->like[] = array($key_condition, $val, $backtick_protect);
$this->ci->db->like($key_condition, $val, $backtick_protect);
return $this;
}
/**
* Sets additional column variables for adding custom columns
*
* #param string $column
* #param string $content
* #param string $match_replacement
* #return mixed
*/
public function add_column($column, $content, $match_replacement = NULL)
{
$this->add_columns[$column] = array('content' => $content, 'replacement' => $this->explode(',', $match_replacement));
return $this;
}
/**
* Sets additional column variables for editing columns
*
* #param string $column
* #param string $content
* #param string $match_replacement
* #return mixed
*/
public function edit_column($column, $content, $match_replacement)
{
$this->edit_columns[$column][] = array('content' => $content, 'replacement' => $this->explode(',', $match_replacement));
return $this;
}
/**
* Unset column
*
* #param string $column
* #return mixed
*/
public function unset_column($column)
{
$column = explode(',', $column);
$this->unset_columns = array_merge($this->unset_columns, $column);
return $this;
}
/**
* Builds all the necessary query segments and performs the main query based on results set from chained statements
*
* #param string $output
* #param string $charset
* #return string
*/
public function generate($output = 'json', $charset = 'UTF-8')
{
if (strtolower($output) == 'json')
$this->get_paging();
$this->get_ordering();
$this->get_filtering();
return $this->produce_output(strtolower($output), strtolower($charset));
}
/**
* Generates the LIMIT portion of the query
*
* #return mixed
*/
private function get_paging()
{
$iStart = $this->ci->input->post('iDisplayStart');
$iLength = $this->ci->input->post('iDisplayLength');
if ($iLength != '' && $iLength != '-1')
$this->ci->db->limit($iLength, ($iStart) ? $iStart : 0);
}
/**
* Generates the ORDER BY portion of the query
*
* #return mixed
*/
private function get_ordering()
{
if ($this->check_mDataprop())
$mColArray = $this->get_mDataprop();
elseif ($this->ci->input->post('sColumns'))
$mColArray = explode(',', $this->ci->input->post('sColumns'));
else
$mColArray = $this->columns;
$mColArray = array_values(array_diff($mColArray, $this->unset_columns));
$columns = array_values(array_diff($this->columns, $this->unset_columns));
for ($i = 0; $i < intval($this->ci->input->post('iSortingCols')); $i++)
if (isset($mColArray[intval($this->ci->input->post('iSortCol_' . $i))]) && in_array($mColArray[intval($this->ci->input->post('iSortCol_' . $i))], $columns) && $this->ci->input->post('bSortable_' . intval($this->ci->input->post('iSortCol_' . $i))) == 'true')
$this->ci->db->order_by($mColArray[intval($this->ci->input->post('iSortCol_' . $i))], $this->ci->input->post('sSortDir_' . $i));
}
/**
* Generates a %LIKE% portion of the query
*
* #return mixed
*/
private function get_filtering()
{
if ($this->check_mDataprop())
$mColArray = $this->get_mDataprop();
elseif ($this->ci->input->post('sColumns'))
$mColArray = explode(',', $this->ci->input->post('sColumns'));
else
$mColArray = $this->columns;
$sWhere = '';
$sSearch = $this->ci->db->escape_like_str($this->ci->input->post('sSearch'));
$mColArray = array_values(array_diff($mColArray, $this->unset_columns));
$columns = array_values(array_diff($this->columns, $this->unset_columns));
if ($sSearch != '')
for ($i = 0; $i < count($mColArray); $i++)
if ($this->ci->input->post('bSearchable_' . $i) == 'true' && in_array($mColArray[$i], $columns))
$sWhere .= $this->select[$mColArray[$i]] . " LIKE '%" . $sSearch . "%' OR ";
$sWhere = substr_replace($sWhere, '', -3);
if ($sWhere != '')
$this->ci->db->where('(' . $sWhere . ')');
$sRangeSeparator = $this->ci->input->post('sRangeSeparator');
for ($i = 0; $i < intval($this->ci->input->post('iColumns')); $i++) {
if (isset($_POST['sSearch_' . $i]) && $this->ci->input->post('sSearch_' . $i) != '' && in_array($mColArray[$i], $columns)) {
$miSearch = explode(',', $this->ci->input->post('sSearch_' . $i));
foreach ($miSearch as $val) {
if (preg_match("/(<=|>=|=|<|>)(\s*)(.+)/i", trim($val), $matches))
$this->ci->db->where($this->select[$mColArray[$i]] . ' ' . $matches[1], $matches[3]);
elseif (!empty($sRangeSeparator) && preg_match("/(.*)$sRangeSeparator(.*)/i", trim($val), $matches)) {
$rangeQuery = '';
if (!empty($matches[1]))
$rangeQuery = 'STR_TO_DATE(' . $this->select[$mColArray[$i]] . ",'%d/%m/%y %H:%i:%s') >= STR_TO_DATE('" . $matches[1] . " 00:00:00','%d/%m/%y %H:%i:%s')";
if (!empty($matches[2]))
$rangeQuery .= (!empty($rangeQuery) ? ' AND ' : '') . 'STR_TO_DATE(' . $this->select[$mColArray[$i]] . ",'%d/%m/%y %H:%i:%s') <= STR_TO_DATE('" . $matches[2] . " 23:59:59','%d/%m/%y %H:%i:%s')";
if (!empty($matches[1]) || !empty($matches[2]))
$this->ci->db->where($rangeQuery);
} else
$this->ci->db->where($this->select[$mColArray[$i]] . ' LIKE', '%' . $val . '%');
}
}
}
foreach ($this->filter as $val)
$this->ci->db->where($val[0], $val[1], $val[2]);
}
/**
* Compiles the select statement based on the other functions called and runs the query
*
* #return mixed
*/
private function get_display_result()
{
if($this->fadu != "")
{
return $this->ci->db->query($this->table);
}
else
{
return $this->ci->db->get($this->table);
}
}
/**
* Builds an encoded string data. Returns JSON by default, and an array of aaData and sColumns if output is set to raw.
*
* #param string $output
* #param string $charset
* #return mixed
*/
private function produce_output($output, $charset)
{
$aaData = array();
$rResult = $this->get_display_result();
if ($output == 'json') {
$iTotal = $this->get_total_results();
$iFilteredTotal = $this->get_total_results(TRUE);
}
foreach ($rResult->result_array() as $row_key => $row_val) {
$aaData[$row_key] = ($this->check_mDataprop()) ? $row_val : array_values($row_val);
foreach ($this->add_columns as $field => $val)
if ($this->check_mDataprop())
$aaData[$row_key][$field] = $this->exec_replace($val, $aaData[$row_key]);
else
$aaData[$row_key][] = $this->exec_replace($val, $aaData[$row_key]);
foreach ($this->edit_columns as $modkey => $modval)
foreach ($modval as $val)
$aaData[$row_key][($this->check_mDataprop()) ? $modkey : array_search($modkey, $this->columns)] = $this->exec_replace($val, $aaData[$row_key]);
$aaData[$row_key] = array_diff_key($aaData[$row_key], ($this->check_mDataprop()) ? $this->unset_columns : array_intersect($this->columns, $this->unset_columns));
if (!$this->check_mDataprop())
$aaData[$row_key] = array_values($aaData[$row_key]);
}
$sColumns = array_diff($this->columns, $this->unset_columns);
$sColumns = array_merge_recursive($sColumns, array_keys($this->add_columns));
if ($output == 'json') {
$sOutput = array
(
'sEcho' => intval($this->ci->input->post('sEcho')),
'iTotalRecords' => $iTotal,
'iTotalDisplayRecords' => $iFilteredTotal,
'aaData' => $aaData,
'sColumns' => implode(',', $sColumns)
);
if ($charset == 'utf-8')
return json_encode($sOutput);
else
return $this->jsonify($sOutput);
} else
return array('aaData' => $aaData, 'sColumns' => $sColumns);
}
/**
* Get result count
*
* #return integer
*/
private function get_total_results($filtering = FALSE)
{
if ($filtering)
$this->get_filtering();
foreach ($this->joins as $val)
$this->ci->db->join($val[0], $val[1], $val[2]);
foreach ($this->where as $val)
$this->ci->db->where($val[0], $val[1], $val[2]);
foreach ($this->or_where as $val)
$this->ci->db->or_where($val[0], $val[1], $val[2]);
foreach ($this->group_by as $val)
$this->ci->db->group_by($val);
foreach ($this->like as $val)
$this->ci->db->like($val[0], $val[1], $val[2]);
if (strlen($this->distinct) > 0) {
$this->ci->db->distinct($this->distinct);
$this->ci->db->select($this->columns);
}
if($this->fadu != "")
{
$query = $this->ci->db->query($this->table);
}
else
{
$query = $this->ci->db->get($this->table, NULL, NULL, FALSE);
}
return $query->num_rows();
}
/**
* Runs callback functions and makes replacements
*
* #param mixed $custom_val
* #param mixed $row_data
* #return string $custom_val['content']
*/
private function exec_replace($custom_val, $row_data)
{
$replace_string = '';
if (isset($custom_val['replacement']) && is_array($custom_val['replacement'])) {
foreach ($custom_val['replacement'] as $key => $val) {
$sval = preg_replace("/(?<!\w)([\'\"])(.*)\\1(?!\w)/i", '$2', trim($val));
if (preg_match('/(\w+::\w+|\w+)\((.*)\)/i', $val, $matches) && is_callable($matches[1])) {
$func = $matches[1];
$args = preg_split("/[\s,]*\\\"([^\\\"]+)\\\"[\s,]*|" . "[\s,]*'([^']+)'[\s,]*|" . "[,]+/", $matches[2], 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
foreach ($args as $args_key => $args_val) {
$args_val = preg_replace("/(?<!\w)([\'\"])(.*)\\1(?!\w)/i", '$2', trim($args_val));
$args[$args_key] = (in_array($args_val, $this->columns)) ? ($row_data[($this->check_mDataprop()) ? $args_val : array_search($args_val, $this->columns)]) : $args_val;
}
$replace_string = call_user_func_array($func, $args);
} elseif (in_array($sval, $this->columns))
$replace_string = $row_data[($this->check_mDataprop()) ? $sval : array_search($sval, $this->columns)];
else
$replace_string = $sval;
$custom_val['content'] = str_ireplace('$' . ($key + 1), $replace_string, $custom_val['content']);
}
}
return $custom_val['content'];
}
/**
* Check mDataprop
*
* #return bool
*/
private function check_mDataprop()
{
if (!$this->ci->input->post('mDataProp_0'))
return FALSE;
for ($i = 0; $i < intval($this->ci->input->post('iColumns')); $i++)
if (!is_numeric($this->ci->input->post('mDataProp_' . $i)))
return TRUE;
return FALSE;
}
/**
* Get mDataprop order
*
* #return mixed
*/
private function get_mDataprop()
{
$mDataProp = array();
for ($i = 0; $i < intval($this->ci->input->post('iColumns')); $i++)
$mDataProp[] = $this->ci->input->post('mDataProp_' . $i);
return $mDataProp;
}
/**
* Return the difference of open and close characters
*
* #param string $str
* #param string $open
* #param string $close
* #return string $retval
*/
private function balanceChars($str, $open, $close)
{
$openCount = substr_count($str, $open);
$closeCount = substr_count($str, $close);
$retval = $openCount - $closeCount;
return $retval;
}
/**
* Explode, but ignore delimiter until closing characters are found
*
* #param string $delimiter
* #param string $str
* #param string $open
* #param string $close
* #return mixed $retval
*/
private function explode($delimiter, $str, $open = '(', $close = ')')
{
$retval = array();
$hold = array();
$balance = 0;
$parts = explode($delimiter, $str);
foreach ($parts as $part) {
$hold[] = $part;
$balance += $this->balanceChars($part, $open, $close);
if ($balance < 1) {
$retval[] = implode($delimiter, $hold);
$hold = array();
$balance = 0;
}
}
if (count($hold) > 0)
$retval[] = implode($delimiter, $hold);
return $retval;
}
/**
* Workaround for json_encode's UTF-8 encoding if a different charset needs to be used
*
* #param mixed $result
* #return string
*/
private function jsonify($result = FALSE)
{
if (is_null($result))
return 'null';
if ($result === FALSE)
return 'false';
if ($result === TRUE)
return 'true';
if (is_scalar($result)) {
if (is_float($result))
return floatval(str_replace(',', '.', strval($result)));
if (is_string($result)) {
static $jsonReplaces = array(array('\\', '/', '\n', '\t', '\r', '\b', '\f', '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $result) . '"';
} else
return $result;
}
$isList = TRUE;
for ($i = 0, reset($result); $i < count($result); $i++, next($result)) {
if (key($result) !== $i) {
$isList = FALSE;
break;
}
}
$json = array();
if ($isList) {
foreach ($result as $value)
$json[] = $this->jsonify($value);
return '[' . join(',', $json) . ']';
} else {
foreach ($result as $key => $value)
$json[] = $this->jsonify($key) . ':' . $this->jsonify($value);
return '{' . join(',', $json) . '}';
}
}
}
/* End of file Datatables.php */
/* Location: ./application/libraries/Datatables.php */
Now
Your query something like
$this->load->library('datatables');
$this->datatables->from("select sales.id as id, sales.date as date,
sales.customer_name, sale_items.product_name as pname, sales.depositcard_amt as debit,
0 as credit from sales join sale_items on sale_items.sale_id=sales.id
where sales.customer_id = $user
and sales.branch_id=$branchid
and sales.depositcard_amt != 0.00
group by sales.id
UNION ALL
select deposit.id as id, deposit.credit_on as date,
deposit_details.customer_name, deposit_details.package_name as pname,
0 as debit, deposit.total_amount as credit from deposit
join deposit_details on deposit_details.deposit_id=deposit.id where deposit.customers=$user" ,"a");
$this->datatables->add_column("Actions", "<center></center>", "id");
$this->datatables->unset_column('id');
echo $this->datatables->generate();
In my-theme/template/catalog/navigation/left.phtml here is code for listing of all categories and its respective sub-categories and its working correctly. Here is code of left.phtml file
<?php $_menu = $this->renderCategoriesMenuHtml(0,'level-top') ?>
<?php if($_menu): ?>
<ul ><?php echo $_menu ?>
<ul>
<?php endif ?>
I found renderCategoriesMenuHtml() function in app / code / core / Mage / Catalog / Block/navigation.php here is code of navigation.php file
class Mage_Catalog_Block_Navigation extends Mage_Core_Block_Template
{
protected $_categoryInstance = null;
/**
* Current category key
*
* #var string
*/
protected $_currentCategoryKey;
/**
* Array of level position counters
*
* #var array
*/
protected $_itemLevelPositions = array();
protected function _construct()
{
$this->addData(array(
'cache_lifetime' => false,
'cache_tags' => array(Mage_Catalog_Model_Category::CACHE_TAG, Mage_Core_Model_Store_Group::CACHE_TAG),
));
}
/**
* Get Key pieces for caching block content
*
* #return array
*/
public function getCacheKeyInfo()
{
$shortCacheId = array(
'CATALOG_NAVIGATION',
Mage::app()->getStore()->getId(),
Mage::getDesign()->getPackageName(),
Mage::getDesign()->getTheme('template'),
Mage::getSingleton('customer/session')->getCustomerGroupId(),
'template' => $this->getTemplate(),
'name' => $this->getNameInLayout(),
$this->getCurrenCategoryKey()
);
$cacheId = $shortCacheId;
$shortCacheId = array_values($shortCacheId);
$shortCacheId = implode('|', $shortCacheId);
$shortCacheId = md5($shortCacheId);
$cacheId['category_path'] = $this->getCurrenCategoryKey();
$cacheId['short_cache_id'] = $shortCacheId;
return $cacheId;
}
/**
* Get current category key
*
* #return mixed
*/
public function getCurrenCategoryKey()
{
if (!$this->_currentCategoryKey) {
$category = Mage::registry('current_category');
if ($category) {
$this->_currentCategoryKey = $category->getPath();
} else {
$this->_currentCategoryKey = Mage::app()->getStore()->getRootCategoryId();
}
}
return $this->_currentCategoryKey;
}
/**
* Get catagories of current store
*
* #return Varien_Data_Tree_Node_Collection
*/
public function getStoreCategories()
{
$helper = Mage::helper('catalog/category');
return $helper->getStoreCategories();
}
/**
* Retrieve child categories of current category
*
* #return Varien_Data_Tree_Node_Collection
*/
public function getCurrentChildCategories()
{
$layer = Mage::getSingleton('catalog/layer');
$category = $layer->getCurrentCategory();
/* #var $category Mage_Catalog_Model_Category */
$categories = $category->getChildrenCategories();
$productCollection = Mage::getResourceModel('catalog/product_collection');
$layer->prepareProductCollection($productCollection);
$productCollection->addCountToCategories($categories);
return $categories;
}
/**
* Checkin activity of category
*
* #param Varien_Object $category
* #return bool
*/
public function isCategoryActive($category)
{
if ($this->getCurrentCategory()) {
return in_array($category->getId(), $this->getCurrentCategory()->getPathIds());
}
return false;
}
protected function _getCategoryInstance()
{
if (is_null($this->_categoryInstance)) {
$this->_categoryInstance = Mage::getModel('catalog/category');
}
return $this->_categoryInstance;
}
/**
* Get url for category data
*
* #param Mage_Catalog_Model_Category $category
* #return string
*/
public function getCategoryUrl($category)
{
if ($category instanceof Mage_Catalog_Model_Category) {
$url = $category->getUrl();
} else {
$url = $this->_getCategoryInstance()
->setData($category->getData())
->getUrl();
}
return $url;
}
/**
* Return item position representation in menu tree
*
* #param int $level
* #return string
*/
protected function _getItemPosition($level)
{
if ($level == 0) {
$zeroLevelPosition = isset($this->_itemLevelPositions[$level]) ? $this->_itemLevelPositions[$level] + 1 : 1;
$this->_itemLevelPositions = array();
$this->_itemLevelPositions[$level] = $zeroLevelPosition;
} elseif (isset($this->_itemLevelPositions[$level])) {
$this->_itemLevelPositions[$level]++;
} else {
$this->_itemLevelPositions[$level] = 1;
}
$position = array();
for($i = 0; $i <= $level; $i++) {
if (isset($this->_itemLevelPositions[$i])) {
$position[] = $this->_itemLevelPositions[$i];
}
}
return implode('-', $position);
}
/**
* Render category to html
*
* #param Mage_Catalog_Model_Category $category
* #param int Nesting level number
* #param boolean Whether ot not this item is last, affects list item class
* #param boolean Whether ot not this item is first, affects list item class
* #param boolean Whether ot not this item is outermost, affects list item class
* #param string Extra class of outermost list items
* #param string If specified wraps children list in div with this class
* #param boolean Whether ot not to add on* attributes to list item
* #return string
*/
protected function _renderCategoryMenuItemHtml($category, $level = 0, $isLast = false, $isFirst = false,
$isOutermost = false, $outermostItemClass = '', $childrenWrapClass = '', $noEventAttributes = false)
{
if (!$category->getIsActive()) {
return '';
}
$html = array();
// get all children
if (Mage::helper('catalog/category_flat')->isEnabled()) {
$children = (array)$category->getChildrenNodes();
$childrenCount = count($children);
} else {
$children = $category->getChildren();
$childrenCount = $children->count();
}
$hasChildren = ($children && $childrenCount);
// select active children
$activeChildren = array();
foreach ($children as $child) {
if ($child->getIsActive()) {
$activeChildren[] = $child;
}
}
$activeChildrenCount = count($activeChildren);
$hasActiveChildren = ($activeChildrenCount > 0);
// prepare list item html classes
$classes = array();
$classes[] = 'level' . $level;
$classes[] = 'nav-' . $this->_getItemPosition($level);
if ($this->isCategoryActive($category)) {
$classes[] = 'active';
}
$linkClass = '';
if ($isOutermost && $outermostItemClass) {
$classes[] = $outermostItemClass;
$linkClass = ' class="'.$outermostItemClass.'"';
}
if ($isFirst) {
$classes[] = 'first';
}
if ($isLast) {
$classes[] = 'last';
}
if ($hasActiveChildren) {
$classes[] = 'parent';
}
// prepare list item attributes
$attributes = array();
if (count($classes) > 0) {
$attributes['class'] = implode(' ', $classes);
}
if ($hasActiveChildren && !$noEventAttributes) {
$attributes['onmouseover'] = 'toggleMenu(this,1)';
$attributes['onmouseout'] = 'toggleMenu(this,0)';
}
// assemble list item with attributes
$htmlLi = '<li';
foreach ($attributes as $attrName => $attrValue) {
$htmlLi .= ' ' . $attrName . '="' . str_replace('"', '\"', $attrValue) . '"';
}
$htmlLi .= '>';
$html[] = $htmlLi;
$html[] = '<a href="'.$this->getCategoryUrl($category).'"'.$linkClass.'>';
$html[] = '<span>' . $this->escapeHtml($category->getName()) . '</span>';
$html[] = '</a>';
// render children
$htmlChildren = '';
$j = 0;
foreach ($activeChildren as $child) {
$htmlChildren .= $this->_renderCategoryMenuItemHtml(
$child,
($level + 1),
($j == $activeChildrenCount - 1),
($j == 0),
false,
$outermostItemClass,
$childrenWrapClass,
$noEventAttributes
);
$j++;
}
if (!empty($htmlChildren)) {
if ($childrenWrapClass) {
$html[] = '<div class="' . $childrenWrapClass . '">';
}
$html[] = '<ul class="level' . $level . '">';
$html[] = $htmlChildren;
$html[] = '</ul>';
if ($childrenWrapClass) {
$html[] = '</div>';
}
}
$html[] = '</li>';
$html = implode("\n", $html);
return $html;
}
/**
* Render category to html
*
* #deprecated deprecated after 1.4
* #param Mage_Catalog_Model_Category $category
* #param int Nesting level number
* #param boolean Whether ot not this item is last, affects list item class
* #return string
*/
public function drawItem($category, $level = 0, $last = false)
{
return $this->_renderCategoryMenuItemHtml($category, $level, $last);
}
/**
* Enter description here...
*
* #return Mage_Catalog_Model_Category
*/
public function getCurrentCategory()
{
if (Mage::getSingleton('catalog/layer')) {
return Mage::getSingleton('catalog/layer')->getCurrentCategory();
}
return false;
}
/**
* Enter description here...
*
* #return string
*/
public function getCurrentCategoryPath()
{
if ($this->getCurrentCategory()) {
return explode(',', $this->getCurrentCategory()->getPathInStore());
}
return array();
}
/**
* Enter description here...
*
* #param Mage_Catalog_Model_Category $category
* #return string
*/
public function drawOpenCategoryItem($category) {
$html = '';
if (!$category->getIsActive()) {
return $html;
}
$html.= '<li';
if ($this->isCategoryActive($category)) {
$html.= ' class="active"';
}
$html.= '>'."\n";
$html.= '<span>'.$this->htmlEscape($category->getName()).'</span>'."\n";
if (in_array($category->getId(), $this->getCurrentCategoryPath())){
$children = $category->getChildren();
$hasChildren = $children && $children->count();
if ($hasChildren) {
$htmlChildren = '';
foreach ($children as $child) {
$htmlChildren.= $this->drawOpenCategoryItem($child);
}
if (!empty($htmlChildren)) {
$html.= '<ul>'."\n"
.$htmlChildren
.'</ul>';
}
}
}
$html.= '</li>'."\n";
return $html;
}
/**
* Render categories menu in HTML
*
* #param int Level number for list item class to start from
* #param string Extra class of outermost list items
* #param string If specified wraps children list in div with this class
* #return string
*/
public function renderCategoriesMenuHtml($level = 0, $outermostItemClass = '', $childrenWrapClass = '')
{
$activeCategories = array();
foreach ($this->getStoreCategories() as $child) {
if ($child->getIsActive()) {
$activeCategories[] = $child;
}
}
$activeCategoriesCount = count($activeCategories);
$hasActiveCategoriesCount = ($activeCategoriesCount > 0);
if (!$hasActiveCategoriesCount) {
return '';
}
$html = '';
$j = 0;
foreach ($activeCategories as $category) {
$html .= $this->_renderCategoryMenuItemHtml(
$category,
$level,
($j == $activeCategoriesCount - 1),
($j == 0),
true,
$outermostItemClass,
$childrenWrapClass,
true
);
$j++;
}
return $html;
}
}
Now. I have created a new file template to list all categories and its subcategories at location my-theme/template/catalog/navigation/all_cat.phtml and I pasted the code of left.phtml file into all_cat.phtml file.
But when I'm executing this file on fronted I could not see any such categories and subcategories in all_cat.phtml file. I dont know what I'm missing and How to correct it. So please someone help me to find it out !
Please try this
{{block type="catalog/navigation" name="catalog.nav" template="catalog/navigation/all_cat.phtml"}}
I am getting this PHP fatal error message: "Fatal error: Class PT_Fieldtype contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (EE_Fieldtype::display_field) in /.../pt_fieldtype.php on line 148"
However, when I open the file and do a search, the word "abstract" is nowhere to be found at all. Thanks for the help!
Edit: Here's the code in question. My bad for not showing it before.
<?php if (! defined('BASEPATH')) exit('No direct script access allowed');
if (! defined('PT_FIELD_PACK_VER'))
{
// get the version from config.php
require PATH_THIRD.'pt_field_pack/config.php';
define('PT_FIELD_PACK_VER', $config['version']);
}
/**
* P&T Fieldtype Base Class
*
* #package P&T Field Pack
* #author Brandon Kelly <brandon#pixelandtonic.com>
* #copyright Copyright (c) 2010 Pixel & Tonic, LLC
*/
class PT_Fieldtype extends EE_Fieldtype {
/**
* PT_Fieldtype Constructor
*/
function PT_Fieldtype()
{
parent::EE_Fieldtype();
}
// --------------------------------------------------------------------
/**
* Options Setting
*/
function options_setting($options=array(), $indent = '')
{
$r = '';
foreach($options as $name => $label)
{
if ($r !== '') $r .= "\n";
// is this just a blank option?
if (! $name && ! $label) $name = $label = ' ';
$r .= $indent . htmlentities($name);
// is this an optgroup?
if (is_array($label)) $r .= "\n".$this->options_setting($label, $indent.' ');
else if ($name != $label) $r .= ' : '.$label;
}
return $r;
}
// --------------------------------------------------------------------
/**
* Save Options Setting
*/
function save_options_setting($options = '', $total_levels = 1)
{
// prepare options
$options = preg_split('/[\r\n]+/', $options);
foreach($options as &$option)
{
$option_parts = preg_split('/\s:\s/', $option, 2);
$option = array();
$option['indent'] = preg_match('/^\s+/', $option_parts[0], $matches) ? strlen(str_replace("\t", ' ', $matches[0])) : 0;
$option['name'] = trim($option_parts[0]);
$option['value'] = isset($option_parts[1]) ? trim($option_parts[1]) : $option['name'];
}
return $this->_structure_options($options, $total_levels);
}
/**
* Structure Options
*/
private function _structure_options(&$options, $total_levels, $level = 1, $indent = -1)
{
$r = array();
while ($options)
{
if ($indent == -1 || $options[0]['indent'] > $indent)
{
$option = array_shift($options);
$children = (! $total_levels OR $level < $total_levels)
? $this->_structure_options($options, $total_levels, $level+1, $option['indent']+1)
: FALSE;
$r[(string)$option['name']] = $children ? $children : (string)$option['value'];
}
else if ($options[0]['indent'] <= $indent)
{
break;
}
}
return $r;
}
// --------------------------------------------------------------------
/**
* Prep Iterators
*/
function prep_iterators(&$tagdata)
{
// find {switch} tags
$this->_switches = array();
$tagdata = preg_replace_callback('/'.LD.'switch\s*=\s*([\'\"])([^\1]+)\1'.RD.'/sU', array(&$this, '_get_switch_options'), $tagdata);
$this->_count_tag = 'count';
$this->_iterator_count = 0;
}
/**
* Get Switch Options
*/
function _get_switch_options($match)
{
global $FNS;
$marker = LD.'SWITCH['.$FNS->random('alpha', 8).']SWITCH'.RD;
$this->_switches[] = array('marker' => $marker, 'options' => explode('|', $match[2]));
return $marker;
}
/**
* Parse Iterators
*/
function parse_iterators(&$tagdata)
{
// {switch} tags
foreach($this->_switches as $i => $switch)
{
$option = $this->_iterator_count % count($switch['options']);
$tagdata = str_replace($switch['marker'], $switch['options'][$option], $tagdata);
}
// update the count
$this->_iterator_count++;
// {count} tags
$tagdata = $this->EE->TMPL->swap_var_single($this->_count_tag, $this->_iterator_count, $tagdata);
}
}
// ====================================================================
/**
* P&T Multi Fieldtype Base Class
*
* #package P&T Field Pack
* #author Brandon Kelly <brandon#pixelandtonic.com>
* #copyright Copyright (c) 2010 Pixel & Tonic, LLC
*/
class PT_Multi_Fieldtype extends PT_Fieldtype {
var $default_field_settings = array(
'options' => array(
'Option 1' => 'Option 1',
'Option 2' => 'Option 2',
'Option 3' => 'Option 3'
)
);
var $default_cell_settings = array(
'options' => array(
'Opt 1' => 'Opt 1',
'Opt 2' => 'Opt 2'
)
);
var $default_tag_params = array(
'sort' => '',
'backspace' => '0'
);
var $total_option_levels = 1;
// --------------------------------------------------------------------
/**
* Display Field Settings
*/
function display_settings($data)
{
// load the language file
$this->EE->lang->loadfile($this->class);
$options = isset($data['options']) ? $data['options'] : array();
$input_name = $this->class.'_options';
$this->EE->table->add_row(
lang($this->class.'_options', $input_name) . '<br />'
. lang('field_list_instructions') . '<br /><br />'
. lang('option_setting_examples'),
'<textarea id="'.$input_name.'" name="'.$input_name.'" rows="6">'.$this->options_setting($options).'</textarea>'
);
}
/**
* Display Cell Settings
*/
function display_cell_settings($data)
{
// load the language file
$this->EE->lang->loadfile($this->class);
$options = isset($data['options']) ? $data['options'] : array();
return array(
array(
lang($this->class.'_options'),
'<textarea class="matrix-textarea" name="options" rows="4">'.$this->options_setting($options).'</textarea>'
)
);
}
// --------------------------------------------------------------------
/**
* Save Field Settings
*/
function save_settings($data)
{
$post = $this->EE->input->post($this->class.'_options');
// replace quotes
$post = str_replace('"', '"', $post);
return array(
'options' => $this->save_options_setting($post, $this->total_option_levels)
);
}
/**
* Save Cell Settings
*/
function save_cell_settings($settings)
{
// replace quotes
$settings['options'] = str_replace('"', '"', $settings['options']);
$settings['options'] = $this->save_options_setting($settings['options'], $this->total_option_levels);
return $settings;
}
// --------------------------------------------------------------------
/**
* Prep Field Data
*
* Ensures $field_data is an array.
*/
function prep_field_data(&$data)
{
if (! is_array($data))
{
$data = array_filter(preg_split("/[\r\n]+/", $data));
}
}
// --------------------------------------------------------------------
/**
* Display Field
*/
function display_field($data)
{
if (is_string($data)) $data = html_entity_decode($data);
return $this->_display_field($data, $this->field_name);
}
/**
* Display Cell
*/
function display_cell($data)
{
return $this->_display_field($data, $this->cell_name);
}
// --------------------------------------------------------------------
/**
* Save
*/
function save($data)
{
// replace quotes
return str_replace('"', '"', $data);
}
/**
* Save Cell
*/
function save_cell($data)
{
// replace quotes
return $this->save($data);
}
// --------------------------------------------------------------------
/**
* Find Options
*/
private function _find_option($needle, $haystack)
{
foreach ($haystack as $key => $value)
{
$r = $value;
if ($needle == $key OR (is_array($value) AND (($r = $this->_find_option($needle, $value)) !== FALSE)))
{
return $r;
}
}
return FALSE;
}
// --------------------------------------------------------------------
/**
* Replace Tag
*/
function replace_tag($data, $params = array(), $tagdata = FALSE)
{
if (! isset($this->settings['options']) || ! $this->settings['options'])
{
return $data;
}
if (! $tagdata)
{
return $this->replace_ul($data, $params);
}
$this->prep_field_data($data);
$r = '';
if ($this->settings['options'] && $data)
{
// optional sorting
if (isset($params['sort']) && $params['sort'])
{
$sort = strtolower($params['sort']);
if ($sort == 'asc')
{
sort($data);
}
else if ($sort == 'desc')
{
rsort($data);
}
}
// offset and limit
if (isset($params['offset']) || isset($params['limit']))
{
$offset = isset($params['offset']) ? $params['offset'] : 0;
$limit = isset($params['limit']) ? $params['limit'] : count($data);
$data = array_splice($data, $offset, $limit);
}
// prepare for {switch} and {count} tags
$this->prep_iterators($tagdata);
foreach($data as $option_name)
{
if (($option = $this->_find_option($option_name, $this->settings['options'])) !== FALSE)
{
// copy $tagdata
$option_tagdata = $tagdata;
// simple var swaps
$option_tagdata = $this->EE->TMPL->swap_var_single('option', $option, $option_tagdata);
$option_tagdata = $this->EE->TMPL->swap_var_single('option_name', $option_name, $option_tagdata);
// parse {switch} and {count} tags
$this->parse_iterators($option_tagdata);
$r .= $option_tagdata;
}
}
if (isset($params['backspace']) && $params['backspace'])
{
$r = substr($r, 0, -$params['backspace']);
}
}
return $r;
}
// --------------------------------------------------------------------
/**
* Unordered List
*/
function replace_ul($data, $params = array())
{
return "<ul>\n"
. $this->replace_tag($data, $params, " <li>{option}</li>\n")
. '</ul>';
}
/**
* Ordered List
*/
function replace_ol($data, $params = array())
{
return "<ol>\n"
. $this->replace_tag($data, $params, " <li>{option}</li>\n")
. '</ol>';
}
// --------------------------------------------------------------------
/**
* All Options
*/
function replace_all_options($data, $params = array(), $tagdata = FALSE, $options = FALSE, $iterator_count = 0)
{
if (! $tagdata)
{
return "<ul>\n"
. $this->replace_all_options($data, $params, " <li>{option}</li>\n")
. "</ul>";
}
PT_Multi_Fieldtype::prep_field_data($data);
$r = '';
if ($options === FALSE)
{
$options = $this->settings['options'];
}
if ($options)
{
// optional sorting
if (isset($params['sort']) && $params['sort'])
{
$sort = strtolower($params['sort']);
if ($sort == 'asc')
{
asort($options);
}
else if ($sort == 'desc')
{
arsort($options);
}
}
// prepare for {switch} and {count} tags
$this->prep_iterators($tagdata);
$this->_iterator_count += $iterator_count;
foreach($options as $option_name => $option)
{
if (is_array($option))
{
$sub_params = array_merge($params, array('backspace' => '0'));
$r .= $this->replace_all_options($data, $sub_params, $tagdata, $option, $this->_iterator_count);
}
else
{
// copy $tagdata
$option_tagdata = $tagdata;
// simple var swaps
$option_tagdata = $this->EE->TMPL->swap_var_single('option', $option, $option_tagdata);
$option_tagdata = $this->EE->TMPL->swap_var_single('option_name', $option_name, $option_tagdata);
$option_tagdata = $this->EE->TMPL->swap_var_single('selected', (in_array($option_name, $data) ? 1 : 0), $option_tagdata);
// parse {switch} and {count} tags
$this->parse_iterators($option_tagdata);
$r .= $option_tagdata;
}
}
if (isset($params['backspace']) && $params['backspace'])
{
$r = substr($r, 0, -$params['backspace']);
}
}
return $r;
}
// --------------------------------------------------------------------
/**
* Is Selected?
*/
function replace_selected($data, $params = array())
{
$this->prep_field_data($data);
return (isset($params['option']) AND in_array($params['option'], $data)) ? 1 : 0;
}
/**
* Total Selections
*/
function replace_total_selections($data, $params = array())
{
$this->prep_field_data($data);
return $field_data ? (string) count($data) : '0';
}
}
The answer of your question is on line 148 of this file...
Maybe you are using a class with abstract methods without inheriting them that is rejected, make sure you implement all of them and after show us some code. ;-)