I use this code to make dropdown list like this, support selected parent when update mode
Current category dropdown (select category 1.1 a child of category 1)
public static function dropdown($parent, $child = null) {
static $level = 0;
static $return = '';
$search = self::all(array('parent' => $parent, 'status' => 1));
foreach ($search as $data) {
$level--;
$space = '';
for($i = 1; $i < ($level*-1); $i++) $space .= ' ';
if ($child == $data->id) $selected = 'selected';
else $selected = '';
$return .= '<option value="'.$data->id.'" '.$selected.'>'.$space.'- '.$data->name.'</option>';
self::dropdown($data->id, $child);
$level++;
}
return $return;
}
Problem : How to disable all child of category 1.1 and him self when i update category 1.1 ??
Goal screenshot :
try this :
public static function dropdown($parent, $child = null, $isSelected=false) {
static $level = 0;
static $return = '';
$search = self::all(array('parent' => $parent, 'status' => 1));
foreach ($search as $data) {
$level--;
$space = '';
for($i = 1; $i < ($level*-1); $i++) $space .= ' ';
if ($child == $data->id || $isSelected){
$selected = 'selected';
$isSelected = true;
}else{
$selected = '';
}
$return .= '<option value="'.$data->id.'" '.$selected.'>'.$space.'- '.$data->name.'</option>';
self::dropdown($data->id, $child, $isSelected);
$level++;
}
return $return;
}
Basically you have to transfer the status (selected or not) of the current node, and transfers it to his childs.
Related
Is it somehow possible to get the translated name of a category in Magento inside the php code? I.e. something like $category->getTranslatedName?
Background: I want to sort categories alphabetically, but having different names in different languages this only really works in the english shopview. My code:
foreach ($children as $child) {
$_children[$i]["child"] = $child;
$_children[$i]["name"] = $child->getName();
//gets english name, not the translated
$i++;
}
if (!function_exists('compare')) {
function compare($a,$b) {
return strcmp($a["name"],$b["name"]);
}
}
usort($_children, "compare");
for ($i=0; $i<count($_children); $i++) {
//code for main menu here
}
Edit: here is the part where it loads $children (it is taken from renderer.phtml):
$children = $menuTree->getChildren();
$parentLevel = $menuTree->getLevel();
$childLevel = is_null($parentLevel) ? 0 : $parentLevel + 1;
$counter = 1;
$childrenCount = $children->count();
$parentPositionClass = $menuTree->getPositionClass();
$itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';
$i = 0;
foreach ($children as $child) {
$_children[$i]["child"] = $child;
$_children[$i]["name"] = $child->getName();
$i++;
}
if (!function_exists('compare')) {
function compare($a,$b) {
return strcmp($a["name"],$b["name"]);
}
}
usort($_children, "compare");
for ($i=0; $i<count($_children); $i++) {
//Code for main menu
}
I have 2 function in a Class, one is a recursive function.
public static function _itemsByParent($categories, $parentId) {
$out = array();
foreach($categories as $category) {
if(empty($category['parent']) && $parentId == 0)
$out[] = $category;
elseif($category['parent'] == $parentId)
$out[] = $category;
}
return (empty($out) ? false : $out);
}
public static function loopOnLevels($input, $parent=0) {
$categories = self::_itemsByParent($input, $parent);
$out = null;
if($categories !== false) {
$i = 0;
$out = '<ul>';
foreach($categories as $category) {
$out .= '<li>'.$category['name_hu'];
$childs = self::loopOnLevels($input, $category['category_id']);
if($childs !== false) {
$out .= $childs;
}
$out .= '</li>';
$i++;
}
$out .= '</ul>';
}
return (empty($out) ? false : $out);
}
I pass a simple array and parent is null at start:
$o = self::loopOnLevels($categoriesTransformed, 0);
My array looks like: http://screencloud.net/v/10sq
....
Why I get 502 Bad Gateway.
Maybe infinite loop? But why?
I'm trying to build a tree with the exact specifications of..
This Question
Basically I need to create a tree from a parent - id table structure.
I'm using this function to try to achieve the above;
private static function fetch_recursive($src_arr, $currentid = 0, $parentfound = false, $cats = array())
{
foreach($src_arr as $row)
{
if((!$parentfound && $row['category_id'] == $currentid) || $row['parent_id'] == $currentid)
{
$rowdata = array();
foreach($row as $k => $v)
$rowdata[$k] = $v;
$cats[] = $rowdata;
if($row['parent_id'] == $currentid)
$cats = array_merge($cats, CategoryParentController::fetch_recursive($src_arr, $row['category_id'], true));
}
}
return $cats;
}
But I'm getting an error from PHP :
Maximum function nesting level of 100 reached, aborting!
I'm ordering the db results by parent_id and then by id to help out with the issue but it still persists.
As a side note by table contains ~250 records.
Finally found a solution that fits my needs! Thanks for all the help everyone and also for the constructive criticism :)
Laravel 4 - Eloquent. Infinite children into usable array?
Solution:
<?php
class ItemsHelper {
private $items;
public function __construct($items) {
$this->items = $items;
}
public function htmlList() {
return $this->htmlFromArray($this->itemArray());
}
private function itemArray() {
$result = array();
foreach($this->items as $item) {
if ($item->parent_id == 0) {
$result[$item->name] = $this->itemWithChildren($item);
}
}
return $result;
}
private function childrenOf($item) {
$result = array();
foreach($this->items as $i) {
if ($i->parent_id == $item->id) {
$result[] = $i;
}
}
return $result;
}
private function itemWithChildren($item) {
$result = array();
$children = $this->childrenOf($item);
foreach ($children as $child) {
$result[$child->name] = $this->itemWithChildren($child);
}
return $result;
}
private function htmlFromArray($array) {
$html = '';
foreach($array as $k=>$v) {
$html .= "<ul>";
$html .= "<li>".$k."</li>";
if(count($v) > 0) {
$html .= $this->htmlFromArray($v);
}
$html .= "</ul>";
}
return $html;
}
}
I have a problem with shuffling and slicing array.
I have this code:
$maxDisplayItem = $this->_getFlexformConfig('max_item_to_display', 'product_setting');
$selectedProducts = array_slice($selectedProducts, 0, $maxDisplayItem);
foreach ($selectedProducts as $_id) {
shuffle($products);
foreach ($products as $_product) {
....
}
}
My code limiting the number of displayed item but didn't shuffle it at all.
When I change the order of actions:
shuffle($selectedProducts);
foreach ($selectedProducts as $_id) {
$maxDisplayItem = $this->_getFlexformConfig('max_item_to_display', 'product_setting');
$products = array_slice($products, 0, $maxDisplayItem);
foreach ($products as $_product) {
....
}
}
the code shuffling and slicing results but only first (e.g. 3 results) from whole array who has 50 items.
Could anyone help me with this?
here is the whole function:
function displayProductList()
{
// Store View
$store = $this->getStoreViewCode();
$selectedProducts = $this->getSelectedProducts();
$products = $this->_products->getProductsFromDb($selectedProducts, $store, $this->getProductsStoragePid());
// Load Template File
$templateHtml = $this->cObj->fileResource( $this->_getConfig('templateProductList') );
$productListHtml = $this->cObj->getSubpart($templateHtml, '###PRODUCT_LIST###');
$productHtml = $this->cObj->getSubpart($productListHtml, '###PRODUCT_ITEM###');
$subPartContent = ''; $item = 0; $items = count($products); $even = true; $line = '';
shuffle($selectedProducts);
foreach ($selectedProducts as $_id) {
$maxDisplayItem = $this->_getFlexformConfig('max_item_to_display', 'product_setting');
$products = array_slice($products, 0, $maxDisplayItem);
foreach ($products as $_product) {
if ($_id === $_product['product_id']) {
$markers = $this->_products->getProductMarkers($_product);
// Even/Odd CSS Class Determination
if ($even === true) {
$line = 'even';
$even = false;
} else {
$line = 'odd';
$even = true;
}
// Class Determination First/Last
if ($item == 0) {
$markers['###EVENODD###'] = $line . ' ' . 'first';
} else if ($item == $items-1) {
$markers['###EVENODD###'] = $line . ' ' . 'last';
} else {
$markers['###EVENODD###'] = $line;
}
// Check if the product has an image
$imageHtml = '<p>'.$this->pi_getLL('template_label_no_image_available').'</p>';
if ($markers['###DETAIL_IMAGE###'] != 'no_selection') {
$imageHtml = $this->cObj->getSubpart($productHtml, '###PRODUCT_IMAGE###');
}
$p = $this->cObj->substituteSubpart($productHtml, '###PRODUCT_IMAGE###', $imageHtml);
$subPartContent .= $this->cObj->substituteMarkerArray($p, $markers);
$item++;
}
}
}
return $this->cObj->substituteSubpart($productListHtml, '###PRODUCT_ITEM###', $subPartContent);
}
function displayProductList(){
// Store View
$store = $this->getStoreViewCode();
$selectedProducts = $this->getSelectedProducts();
$products = $this->_products->getProductsFromDb($selectedProducts, $store, $this->getProductsStoragePid());
// Load Template File
$templateHtml = $this->cObj->fileResource( $this->_getConfig('templateProductList') );
$productListHtml = $this->cObj->getSubpart($templateHtml, '###PRODUCT_LIST###');
$productHtml = $this->cObj->getSubpart($productListHtml, '###PRODUCT_ITEM###');
$subPartContent = ''; $item = 0; $items = count($products); $even = true; $line = '';
$maxDisplayItem = $this->_getFlexformConfig('max_item_to_display', 'product_setting');
$products = array_slice($products, 0, $maxDisplayItem);
shuffle($products);
foreach ($products as $_product) {
$markers = $this->_products->getProductMarkers($_product);
// Even/Odd CSS Class Determination
if ($even === true) {
$line = 'even';
$even = false;
} else {
$line = 'odd';
$even = true;
}
// Class Determination First/Last
if ($item == 0) {
$markers['###EVENODD###'] = $line . ' ' . 'first';
} else if ($item == $items-1) {
$markers['###EVENODD###'] = $line . ' ' . 'last';
} else {
$markers['###EVENODD###'] = $line;
}
// Check if the product has an image
$imageHtml = '<p>'.$this->pi_getLL('template_label_no_image_available').'</p>';
if ($markers['###DETAIL_IMAGE###'] != 'no_selection') {
$imageHtml = $this->cObj->getSubpart($productHtml, '###PRODUCT_IMAGE###');
}
$p = $this->cObj->substituteSubpart($productHtml, '###PRODUCT_IMAGE###', $imageHtml);
$subPartContent .= $this->cObj->substituteMarkerArray($p, $markers);
$item++;
}
return $this->cObj->substituteSubpart($productListHtml, '###PRODUCT_ITEM###', $subPartContent);
}
Just got this code working for 2 levels of my menu. But I want it to work with unlimited levels.
Do any of you guys have an idea where to start?
Right now if I type in more levels in the database it says "Undefined index Linnk & Label Line 29", and the new parent that has been entered does not show up.
$sql = "SELECT id, label, link_url, parent_id FROM dyn_menu ORDER BY parent_id, id ASC";
$items = mysql_query($sql);
while ($obj = mysql_fetch_object($items)) {
if ($obj->parent_id == 0) {
$parent_menu[$obj->id]['label'] = $obj->label;
$parent_menu[$obj->id]['link'] = $obj->link_url;
} else {
$sub_menu[$obj->id]['parent'] = $obj->parent_id;
$sub_menu[$obj->id]['label'] = $obj->label;
$sub_menu[$obj->id]['link'] = $obj->link_url;
if (!isset($parent_menu[$obj->parent_id]['count'])) {
$parent_menu[$obj->parent_id]['count'] = 0;
}
$parent_menu[$obj->parent_id]['count']++;
}
}
mysql_free_result($items);
function dyn_menu($parent_array, $sub_array, $qs_val = "menu", $main_id = "nav", $sub_id = "subnav", $extra_style = "foldout") {
$menu = "<ul id=\"".$main_id."\">\n";
foreach ($parent_array as $pkey => $pval) {
if (!empty($pval['count'])) {
$menu .= " <li><a class=\"".$extra_style."\" href=\"".$pval['link']."?".$qs_val."=".$pkey."\">".$pval['label']."</a></li>\n";
} else {
$menu .= " <li>".$pval['label']."</li>\n";
}
if (!empty($_REQUEST[$qs_val])) {
$menu .= "<ul id=\"".$sub_id."\">\n";
foreach ($sub_array as $sval) {
if ($pkey == $_REQUEST[$qs_val] && $pkey == $sval['parent']) {
$menu .= "<li>".$sval['label']."</li>\n";
}
}
$menu .= "</ul>\n";
}
}
$menu .= "</ul>\n";
return $menu;
}
function rebuild_link($link, $parent_var, $parent_val) {
$link_parts = explode("?", $link);
$base_var = "?".$parent_var."=".$parent_val;
if (!empty($link_parts[1])) {
$link_parts[1] = str_replace("&", "##", $link_parts[1]);
$parts = explode("##", $link_parts[1]);
$newParts = array();
foreach ($parts as $val) {
$val_parts = explode("=", $val);
if ($val_parts[0] != $parent_var) {
array_push($newParts, $val);
}
}
if (count($newParts) != 0) {
$qs = "&".implode("&", $newParts);
}
return $link_parts[0].$base_var.$qs;
} else {
return $link_parts[0].$base_var;
}
}
echo dyn_menu($parent_menu, $sub_menu, "menu", "nav", "subnav");
In order to do this, you'll want to use a recursive function to handle your array -> list transformation.
Here's an example:
<?php
function arrToUl($arr) {
$out = '<ul>';
foreach($arr as $key=>$val) {
$out .= '<li>';
$out .= is_array($val) ? arrToUl($val) : $val;
$out .= '</li>';
}
return $out . '</ul>';
}
$arr = array('firstval','secondval',array('firstval2','secondval2',array('firstval3','secondval3',array('firstval4','secondval4',array('firstval5','secondval5')))));
echo arrToUl($arr);
Output in a jsfiddle.