PHP Classes

File: c_xml.php

Recommend this page to a friend!
  Classes of Rabotyahoff Alexandr   c_xml   c_xml.php   Download  
File: c_xml.php
Role: Class source
Content type: text/plain
Description: main class
Class: c_xml
Convert between XML files and arrays or strings
Author: By
Last change:
Date: 13 years ago
Size: 27,536 bytes
 

Contents

Class file image Download
<?php /** * c_xml * Comfort work with XML-documents * version: 0.1 * * 1. Converts: * XML -> c_xml * array -> c_xml * c_xml -> XML * c_xml -> array * c_xml -> String * c_xml -> dump * * 2. Search by xPath * 3. XSL-processing */ class c_xml_node{ /** * =true when loaded * @var boolean */ public $isLoaded=false; public $is_normalize_upper=null; protected $name=''; protected $value=''; protected $attributes=array(); /** * @var $childNodes array of c_xml_node */ protected $childNodes=array(); protected $childNodesByName=array();// $childNodesByName['name'][] /** * * @var $parentNode c_xml_node */ protected $parentNode=null; function __construct($name='', $value='', $attributes=array()){ $this->emptyNode(); $this->parentNode=null; $this->setName($name); $this->setValue($value); $attributes=(array)$attributes; foreach ($attributes as $k=>$v) $this->setAttribute($k,$v); return $this; } protected function normalizeName($name){ if ($this->is_normalize_upper===true) return mb_strtoupper(trim($name)); if ($this->is_normalize_upper===false) return mb_strtolower(trim($name)); return trim($name); } protected function normalizeNameArray($array){ foreach ($array as $k=>$v) $array[$k]=$this->normalizeName($v); return $array; } /** * * @param String $name * @return c_xml_node */ function setName($name){ $name=str_replace(':','_',$name); $this->name=$this->normalizeName($name); return $this; } function getName(){ return $this->name; } /** * * @param String $value * @return c_xml_node */ function setValue($value){ $this->value=trim($value); return $this; } /** * * @param boolean $is_for_xml using <![CDATA[...]]> */ function getValue($is_for_xml=false){ $res=''; if (empty($this->childNodes)) { $res=$this->value; if ($is_for_xml){ $res=$this->valueToXML($res); } } return $res; } static function valueToXML($value){ if (mb_strpos($value,'<')!==false || mb_strpos($value,'&')!==false) { $value="<![CDATA[$value]]>"; } return $value; } /** * * @param String $attributeName * @param String $attributeValue * @return c_xml_node */ function setAttribute($attributeName,$attributeValue=''){ $this->attributes[$this->normalizeName($attributeName)]=$attributeValue; return $this; } /** * * @param String $attributeName * @return c_xml_node */ function removeAttribute($attributeName){ unset($this->attributes[$this->normalizeName($attributeName)]); return $this; } function getAttributeValue($attributeName){ return $this->attributes[$this->normalizeName($attributeName)]; } function getAttributes(){ return $this->attributes; } /** * @return c_xml_node */ function getParentNode(){ return $this->parentNode; } function getCountChildNodes(){ return count($this->childNodes); } /** * Get node with nember $num. Begining from 0 * False when unavaible * * @param Integer $num * @return c_xml_node */ function getNodeByNum($num){ if ($num<0 || $num>=$this->getCountChildNodes()) return false; return $this->childNodes[$num]; } /** * * @param String $name * @return array */ function getNodesByName($name){ return $this->childNodesByName[$name]; } /** * * @param String $name * @param integer $num Begining from 0 * @return c_xml_node */ function getNodeByNameNum($name,$num=0){ $tmp=$this->getNodesByName($name); if (is_array($tmp)) return $tmp[$num]; return false; } /** * Get number of node. (Begining from 0) * False when unavaible * * @param c_xml_node $node * @return integer */ function getNodeNum($node){ $n=0; $cnt=$this->getCountChildNodes(); while ($n<$cnt){ if ($this->getNodeByNum($n)==$node){ return $n; } $n++; } return false; } /** * @param c_xml_node $node * @return c_xml_node */ function getNodeNextByNode($node){ if ($node==null) return $this->getNodeByNum(0); return $this->getNodeByNum($this->getNodeNum($node)+1); } /** * Add node to begin * * @param c_xml_node $node * @return c_xml_node */ function insertNodeFirst($node){ $node->parentNode=$this; $this->childNodesByName[$node->name]=(array)$this->childNodesByName[$node->name]; array_unshift($this->childNodesByName[$node->name],$node); array_unshift($this->childNodes,$node); return $this; } /** * Add node to end * * @param c_xml_node $node * @return c_xml_node */ function insertNodeToEnd($node){ $node->parentNode=$this; $this->childNodesByName[$node->name]=(array)$this->childNodesByName[$node->name]; array_push($this->childNodesByName[$node->name],$node); array_push($this->childNodes,$node); return $this; } /** * Create and insert node to begin * When $is_return_new_node=true, then return this new node * * @param String $name * @param String $value * @param array $attributes * @param boolean $is_return_new_node * @return c_xml_node */ function insertChildFirst($name='', $value='', $attributes=array(), $is_return_new_node=false){ $new_xml_node=new c_xml_node($name, $value, $attributes); $this->insertNodeFirst($new_xml_node); if ($is_return_new_node) return $new_xml_node; return $this; } /** * Create and insert node to end * When $is_return_new_node=true, then return this new node * * @param String $name * @param String $value * @param array $attributes * @param boolean $is_return_new_node * @return c_xml_node */ function insertChildToEnd($name='', $value='', $attributes=array(), $is_return_new_node=false){ $new_xml_node=new c_xml_node($name, $value, $attributes); $this->insertNodeToEnd($new_xml_node); if ($is_return_new_node) return $new_xml_node; return $this; } /** * * @param c_xml_node $node * @param c_xml_node $beforeNode * @return c_xml_node */ function insertNodeBefore($node,$beforeNode){ if ($beforeNode==null) { $this->insertNodeToEnd($node); return $this; } $node->parentNode=$this; $this->childNodesByName[$node->name]=(array)$this->childNodesByName[$node->name]; $num=$this->getNodeNum($beforeNode); if ($num!==false){ array_insert($this->childNodes, $node, $num); $this->childNodesByName[$node->name][]=$node;//@TODO insert node to right place } return $this; } /** * * @param c_xml_node $node * @param c_xml_node $beforeNode * @return c_xml_node */ function insertNodeAfter($node,$afterNode){ if ($afterNode==null) { $this->insertNodeFirst($node); return $this; } $node->parentNode=$this; $this->childNodesByName[$node->name]=(array)$this->childNodesByName[$node->name]; $num=$this->getNodeNum($afterNode); if ($num!==false){ array_insert($this->childNodes, $node, $num+1); $this->childNodesByName[$node->name][]=$node;//@TODO insert node to right place } return $this; } /** * * @param Integer $num * @return c_xml_node */ function deleteNodeByNum($num){ $serach_node=$this->getNodeByNum($num); $serach_node_name=$serach_node->name; $n=0; $cnt=count($this->childNodesByName[$serach_node_name]); while ($n<$cnt){ if ($this->childNodesByName[$serach_node_name][$n]==$serach_node){ unset($this->childNodesByName[$serach_node_name][$n]); $this->childNodesByName[$serach_node_name]=array_values($this->childNodesByName[$serach_node_name]); break; } $n++; } unset($this->childNodes[$num]); $this->childNodes=array_values($this->childNodes); return $this; } function getAttributesStr(){ $res=array(); foreach ($this->attributes as $k=>$v){ $v=str_replace('&','&amp;',$v); $v=str_replace('"','&quot;',$v); $v=str_replace('<','&lt;',$v); $res[]=$k.'='.'"'.$v.'"'; } if (empty($res)) return ''; return ' '.implode(' ',$res); } function getXMLOpenTag(){ return '<'.$this->name.$this->getAttributesStr().'>'; } function getXMLOpenCloseTag(){ return '<'.$this->name.$this->getAttributesStr().'/>'; } function getXMLCloseTag(){ return '</'.$this->name.'>'; } /** * * @param DOMNode $domNode */ protected function fromDOMNode($domNode){ $this->setName($domNode->nodeName); if (is_object($domNode->attributes)){ foreach ($domNode->attributes as $attrName => $attrNode) { $this->setAttribute($attrName, $attrNode->value); } } if ($domNode->hasChildNodes()){ foreach ($domNode->childNodes as $childNode){ switch ($childNode->nodeType) { case XML_ELEMENT_NODE: $new_xml_node=new c_xml_node(); $new_xml_node->fromDOMNode($childNode); $this->insertNodeToEnd($new_xml_node); break; case XML_TEXT_NODE: $this->setValue($this->value.$childNode->textContent); break; case XML_COMMENT_NODE: //no comments break; case XML_CDATA_SECTION_NODE: $this->setValue($this->value.$childNode->textContent); break; } } } $this->isLoaded=true; } /** * @return c_xml_node */ function emptyNode(){ $this->isLoaded=false; $this->name=''; $this->value=''; $this->attributes=array(); $this->childNodes=array(); $this->childNodesByName=array(); return $this; } /** * * @param String $xml * @return c_xml_node */ protected function fromXML($xml){ $this->emptyNode(); $dom = new DomDocument(); $dom->substituteEntities = true; $res_load=@$dom->loadXML($xml); if (!$res_load) return false; foreach ($dom->childNodes as $mayBeRootNode){ if ($mayBeRootNode->nodeType==XML_ELEMENT_NODE){ $this->fromDOMNode($mayBeRootNode); break; } } $this->isLoaded=true; return $this; } /** * Create tree from array * * @param string $nodeName * @param array $inArray */ function fromArray($nodeName,$inArray=array()){ $this->emptyNode(); if (!is_numeric($nodeName)) $this->setName($nodeName); else $this->setName('item'); if (is_array($inArray)){ foreach ($inArray as $childKey=>$childValue){ if (!is_array($childValue) && ($childKey[0]=='@' || strcmp($childKey, '.')==0 || strcmp($childKey, '*')==0)){ if ($childKey[0]==='@') $this->setAttribute(mb_substr($childKey,1,mb_strlen($childKey)-1), $childValue); if ($childKey==='.') $this->setValue($childValue); if ($childKey==='*' && $this->name=='item') $this->setName($childValue); } else { $new_xml_node=new c_xml_node(); $new_xml_node->is_upper_normalize=$this->is_upper_normalize; $new_xml_node->fromArray($childKey, $childValue); $this->insertNodeToEnd($new_xml_node); } } } else { $this->setValue($inArray); } $this->isLoaded=true; return $this; } /** * @param str $nodeName * @param array $inArray * @return str */ static function arrayToXML($nodeName,$inArray=array()){ $result=''; if (!is_numeric($nodeName)) $item_name=$nodeName; else $item_name='item'; $item_attributes=array(); $item_value=''; $item_inner=array(); if (is_array($inArray)){ foreach ($inArray as $childKey=>$childValue){ if (!is_array($childValue) && ($childKey[0]=='@' || strcmp($childKey, '.')==0 || strcmp($childKey, '*')==0)){ if ($childKey[0]==='@') $item_attributes[substr($childKey,1,strlen($childKey)-1)]=$childValue; if ($childKey==='.') $item_value=$childValue; if ($childKey==='*' && $item_name=='item') $item_name=$childValue; } else { $item_inner[]=c_xml_node::arrayToXML($childKey, $childValue); } } } else { $item_value=$inArray; } $result='<'.$item_name; foreach ($item_attributes as $k=>$v){ $result.=' '.$k.'="'.$v.'"'; } if (empty($item_inner) && $item_value===''){ $result.='/>'; } else { $result.='>'; if (!empty($item_inner)){ foreach ($item_inner as $v){ $result.=$v; } } else { $result.=c_xml_node::valueToXML(trim($item_value)); } $result.='</'.$item_name.'>'; } return $result; } function toXML(){ $value=$this->getValue(true); if ($value==='' && $this->getCountChildNodes()==0){ $res=$this->getXMLOpenCloseTag(); } else { $res=$this->getXMLOpenTag().$value; foreach ($this->childNodes as $node){ $res.=$node->toXML(); } $res.=$this->getXMLCloseTag(); } return $res; } function toStr(){ $res=$this->getValue(false); foreach ($this->childNodes as $node){ $res.=$node->toStr(); } return $res; } static function is_system_key($key){ return in_array(''.$key,array('.','*')); } static function is_item_key($key){ return is_numeric($key); } /** * Convert c_xml to array * atribute converts to array['@attr_name']='attr_val' * * to freach use is_system_key($key) * foreach ($res as $k=>$val){ * if (c_xml::is_system_key($k)) continue; * } */ function toArray($node_names_ass_int=array('item')){ $node_names_ass_int0=$node_names_ass_int; $res_value=$this->getValue(false); $is_value_in_array=true; if ($res_value==='' || $is_value_in_array){ if ($is_value_in_array) { $old_res_value=$res_value; if (!is_array($res_value)) $res_value=array(); $res_value['*']=$this->name; $res_value['.']=$old_res_value; } foreach ($this->attributes as $attr=>$attr_val){ if (!is_array($res_value)) $res_value=array(); $res_value['@'.$attr]=$attr_val; } } if ($this->getCountChildNodes()>0){ if (!is_array($res_value)) $res_value=array(); foreach ($this->childNodes as $node){ $child_name=$node->getName(); if (isset($res_value[$child_name])){ $tmp=$res_value[$child_name]; unset($res_value[$child_name]); $res_value[]=$tmp; $node_names_ass_int[]=strtolower($child_name); } if ($node_names_ass_int===true || in_array(strtolower($child_name), $node_names_ass_int)){ $res_value[]=$node->toArray($node_names_ass_int0, $is_value_in_array); } else { $res_value[$child_name]=$node->toArray($node_names_ass_int0, $is_value_in_array); } } } return $res_value; } /** * @param boolean $is_whitoutRootNode */ function getXPuthNode($is_whitoutRootNode=true){ if ($this->parentNode==null) return ($is_whitoutRootNode)?'':$this->getName(); $tmp=$this->getParentNode()->getPuthNode($is_whitoutRootNode); if (!empty($tmp)) $tmp.='/'; return $tmp.$this->getName(); } static function dump($xml, $nohead=false,$charset='UTF-8'){ return c_xml_node::transform('xmlDump.xsl',$xml,null,$charset,$nohead); } static function transform($xsl_file, $xml, $params=null,$charset='UTF-8',$nohead=false){ $ent = '<!DOCTYPE page [ <!ENTITY nbsp "&#160;"> <!ENTITY copy "&#169;"> <!ENTITY reg "&#174;"> <!ENTITY trade "&#8482;"> <!ENTITY mdash "&#8212;"> <!ENTITY ldquo "&#0171;"> <!ENTITY rdquo "&#0187;"> <!ENTITY pound "&#163;"> <!ENTITY sum "&#0216;"> <!ENTITY yen "&#165;"> <!ENTITY euro "&#8364;"> ]>'; if (!$nohead) $xml="<?xml version=\"1.0\" encoding=\"".$charset."\"?>\n".$ent.$xml; $browser=null; if(empty($xml)) $xml = '<empty_xml>Empty xml</empty_xml>'; if(!$nohead && $charset=='windows-1251') $xml=preg_replace("{[\x98]}i","",$xml); $xsl = new DomDocument(); //$xsl->resolveExternals = true; $xsl->substituteEntities = true; $xsl->load($xsl_file); //$inputdom = new DomDocument(); //$inputdom->loadXML($xml); /* create the processor and import the stylesheet */ $proc = new XsltProcessor(); $proc->registerPhpFunctions(); //$xsl = $proc->importStylesheet($xsl); if($params){ foreach ($params as $key=>$value){ $proc->setParameter(null, $key, $value); } } $inputdom = new DomDocument(); $inputdom->substituteEntities = true; $inputdom->loadXML($xml); $proc->importStyleSheet($xsl); $res = $proc->transformToXML($inputdom); return $res; } /** * * @param c_xml_node $node */ function isEmptyNode($node){ $value=$node->getValue(); $name=$node->getName(); return (empty($name) && empty($value) && $node->getCountChildNodes()==0); } /** * * @param c_xml_node $node * @param str $cond @attr1='val1' */ private function node_like_cond($node, $cond){ if (strpos('=',$cond)){ $conds=explode('=', $cond); $left=trim($conds[0]); $right=trim($conds[1]); if ($right[0]==='"' || $right[0]==="'") $right=substr($right,1,strlen($right)-2); if ($left[0]!='@') return false; $left=substr($left,1,strlen($left)-1); return $node->getAttributeValue($left)==$right; } elseif (strpos('!=',$cond)){ $conds=explode('!=', $cond); $left=trim($conds[0]); $right=trim($conds[1]); if ($right[0]==='"' || $right[0]==="'") $right=substr($right,1,strlen($right)-2); if ($left[0]!='@') return false; $left=substr($left,1,strlen($left)-1); return $node->getAttributeValue($left)!=$right; } } /** * * @param String $puth (String | Array) 'someNode/nextNode/item[5]/label' begining from 1, like xPath * @return c_xml_node */ function getNodeByXPath($puth){ if (empty($puth)) return $this; if (!is_array($puth)){ $puth=explode('/',$puth); $puth=$this->normalizeNameArray($puth); } $search_node_name=array_shift($puth);//item[n] $pos0=mb_strpos($search_node_name,'['); $pos1=mb_strpos($search_node_name,']'); $search_node_cond=0; if ($pos0!==false && $pos1!==false){ $search_node_cond=mb_substr($search_node_name,$pos0+1,$pos1-$pos0-1); $search_node_name=mb_substr($search_node_name,0,$pos0); } $child_nodes=$this->getNodesByName($search_node_name); if (is_array($child_nodes)) { $child_node=''; if (is_numeric($search_node_cond)){ $search_node_num=intval($search_node_cond)-1; $child_node=$child_nodes[$search_node_cond]; } else { foreach ($child_nodes as $tmp_node){ if ($this->node_like_cond($tmp_node, $search_node_cond)){ $child_node=$tmp_node; break; } } } if (!empty($child_node)) return $child_node->getNodeByPath($puth); } if (is_object($child_node)) { //проверим $child_node на соответствие условию $search_node_cond $is_ok=true; if (is_numeric($search_node_cond)){ //если задано число, то оно должно=1, т.к. нода только одна $is_ok=(intval($search_node_cond)==1); } else { $is_ok=$this->node_like_cond($child_node, $search_node_cond); } if ($is_ok) return $child_node->getNodeByPath($puth); } $empty_node=new c_xml_node(); $empty_node->is_upper_normalize=$this->is_upper_normalize; return $empty_node; } /** * * @param String $puth (String | Array) 'someNode/nextNode/item[5]/label' begining from 1, like xPath * @return c_xml_node */ function getCountNodesByPuth($puth){ if (empty($puth)) return 1; if (!is_array($puth)){ $puth=explode('/',$puth); $puth=$this->normalizeNameArray($puth); } $search_node_name=array_shift($puth);//item[n] $pos0=mb_strpos($search_node_name,'['); $pos1=mb_strpos($search_node_name,']'); $search_node_num=0; if ($pos0!==false && $pos1!==false){ $search_node_num=mb_substr($search_node_name,$pos0+1,$pos1-$pos0-1); $search_node_num=intval($search_node_num)-1; $search_node_name=mb_substr($search_node_name,0,$pos0); } $child_nodes=$this->getNodesByName($search_node_name); $child_node=''; if (is_array($child_nodes)) { if (empty($puth)) return count($child_nodes); $child_node=$child_nodes[$search_node_num]; } if (is_object($child_node)) return $child_node->getCountNodesByPuth($puth); else { return 0; } } /** * * @param c_xml_node $xml * @return c_xml_node */ function mergeWithXML($xml){ $this->merge2nodes($this,$xml); $this->unsetMark($this); return $this; } /** * * @param c_xml_node $node */ protected function unsetMark($node){ unset($node->mark); $cnt=$node->getCountChildNodes(); for ($n=0;$n<$cnt;$n++){ $tmp_node=$node->getNodeByNum($n); $this->unsetMark($tmp_node); } } /** * * @param c_xml_node $node1 * @param c_xml_node $node2 * @return c_xml_node */ protected function merge2nodes($node1,$node2){ $cnt=$node2->getCountChildNodes(); if ($cnt>0){ for ($n=0;$n<$cnt;$n++){ $tmp_node2=$node2->getNodeByNum($n); $tmp_node2_name=$tmp_node2->getName(); $tmp_node2_atribute_names=array_keys($tmp_node2->getAttributes()); $tmp_node2_atribute_values=array_values($tmp_node2->getAttributes()); $enable_node=false; $tmp_nodes1=$node1->getNodesByName($tmp_node2_name); if ($tmp_node2_name!='item' && is_array($tmp_nodes1)){ foreach ($tmp_nodes1 as $k=>$tmp_node1){ $tmp_node1_atribute_names=array_keys($tmp_node1->getAttributes()); $tmp_node1_atribute_values=array_values($tmp_node1->getAttributes()); $tmp_arr=array_diff($tmp_node2_atribute_names, $tmp_node1_atribute_names); $tmp_arr2=array_diff($tmp_node2_atribute_values, $tmp_node1_atribute_values); if (empty($tmp_arr) && empty($tmp_arr2) && $tmp_node1->mark!==true ){ $enable_node=$tmp_node1; break; } else { $tmp_node1->mark=true; } }//foreach } if ($enable_node!==false){ $enable_node->mark=true; $this->merge2nodes($enable_node, $tmp_node2); } else { $tmp_node2->mark=true; $node1->insertNodeToEnd($tmp_node2); } } } else { $node1->childNodes=array(); $node1->childNodesByName=array(); $node1->setValue($node2->getValue()); } return $node1; } /** * * @param c_xml_node $xml * @param bool $is_ignoreAttributes изнорировать атрибуты */ function addItemsFromXML($xml,$is_ignoreAttributes=true){ $this->addItemsFromNode($this,$xml,$is_ignoreAttributes); return $this; } /** * * @param c_xml_node $node1 * @param c_xml_node $node2 */ protected function addItemsFromNode($node1,$node2,$is_ignoreAttributes){ $cnt=$node2->getCountChildNodes(); if ($cnt>0){ for ($n=0;$n<$cnt;$n++){ $child_node2=$node2->getNodeByNum($n); if ($child_node2->getName()==$child_node2->normalizeName('item')){ $node1->insertNodeToEnd($child_node2); } else { $child_nodes1=$node1->getNodesByName($child_node2->getName()); if (!$is_ignoreAttributes){ //найдём ноду с такими же атрибутами $child_node2_attrNames=array_keys($child_node2->getAttributes()); $child_node2_attrValues=array_values($child_node2->getAttributes()); $finded_node1=false; if (is_array($child_nodes1)){ foreach ($child_nodes1 as $child_node1){ $child_node1_attrNames=array_keys($child_node1->getAttributes()); $child_node1_attrValues=array_values($child_node1->getAttributes()); $tmp1=array_diff($child_node1_attrValues,$child_node2_attrValues); $tmp2=array_diff($child_node1_attrNames,$child_node2_attrNames); if (empty($tmp1) && empty($tmp2)){ $finded_node1=$child_node1; break; } } }//if if ($finded_node1!==false){ $this->addItemsFromNode($finded_node1,$child_node2,$is_ignoreAttributes); } } else { foreach ($child_nodes1 as $child_node1){ $this->addItemsFromNode($child_node1,$child_node2,$is_ignoreAttributes); } } } } } } } class c_xml extends c_xml_node{ /** * * @param String $name * @param String $value * @return c_xml_node */ function __construct($xml=''){ parent::__construct(); if (!empty($xml)) $this->fromXML($xml); } /** * * @param String $xml * @return c_xml */ function fromXML($xml){ return parent::fromXML($xml); } } /** * * xml+xsl-processing * @param str $xsl_file * @param str $root_node_name * @param array,str,c_xml $dta * @param array $params * @param array $keys_as_params * @param bool $kill_doctype */ function xsl_out($xsl_file,$root_node_name,$dta=array(),$params=array(),$kill_doctype=true){ if (is_object($dta)) $xml=$dta->toXML(); elseif (is_array($dta)) $xml=c_xml::arrayToXML($root_node_name,$dta); else $xml=$dta; $res.=c_xml::transform($xsl_file, $xml, $params); if ($kill_doctype) $res=preg_replace("/^\<!DOCTYPE.*\.dtd\"\>/i",'',$res,1); return $res; } /** * Function array_insert(). * * Returns the new number of the elements in the array. * * @param array $array Array (by reference) * @param mixed $value New element * @param int $offset Position * @return int */ function array_insert(&$array, $value, $offset) { if (is_array($array)) { $array = array_values($array); $offset = intval($offset); if ($offset < 0 || $offset >= count($array)) { array_push($array, $value); } elseif ($offset == 0) { array_unshift($array, $value); } else { $temp = array_slice($array, 0, $offset); array_push($temp, $value); $array = array_slice($array, $offset); $array = array_merge($temp, $array); } } else { $array = array($value); } return count($array); }