/CRM/Utils/Array.php

https://github.com/ksecor/civicrm · PHP · 347 lines · 179 code · 35 blank · 133 comment · 38 complexity · 12fe5952045265621b68838bdbe81e5e MD5 · raw file

  1. <?php
  2. /*
  3. +--------------------------------------------------------------------+
  4. | CiviCRM version 3.1 |
  5. +--------------------------------------------------------------------+
  6. | Copyright CiviCRM LLC (c) 2004-2009 |
  7. +--------------------------------------------------------------------+
  8. | This file is a part of CiviCRM. |
  9. | |
  10. | CiviCRM is free software; you can copy, modify, and distribute it |
  11. | under the terms of the GNU Affero General Public License |
  12. | Version 3, 19 November 2007. |
  13. | |
  14. | CiviCRM is distributed in the hope that it will be useful, but |
  15. | WITHOUT ANY WARRANTY; without even the implied warranty of |
  16. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
  17. | See the GNU Affero General Public License for more details. |
  18. | |
  19. | You should have received a copy of the GNU Affero General Public |
  20. | License along with this program; if not, contact CiviCRM LLC |
  21. | at info[AT]civicrm[DOT]org. If you have questions about the |
  22. | GNU Affero General Public License or the licensing of CiviCRM, |
  23. | see the CiviCRM license FAQ at http://civicrm.org/licensing |
  24. +--------------------------------------------------------------------+
  25. */
  26. /**
  27. *
  28. * @package CRM
  29. * @copyright CiviCRM LLC (c) 2004-2009
  30. * $Id$
  31. *
  32. */
  33. class CRM_Utils_Array {
  34. /**
  35. * if the key exists in the list returns the associated value
  36. *
  37. * @access public
  38. *
  39. * @param array $list the array to be searched
  40. * @param string $key the key value
  41. *
  42. * @return value if exists else null
  43. * @static
  44. * @access public
  45. *
  46. */
  47. static function value( $key, &$list, $default = null ) {
  48. if ( is_array( $list ) ) {
  49. return array_key_exists( $key, $list ) ? $list[$key] : $default;
  50. }
  51. return $default;
  52. }
  53. /**
  54. * Given a parameter array and a key to search for,
  55. * search recursively for that key's value.
  56. *
  57. * @param array $values The parameter array
  58. * @param string $key The key to search for
  59. * @return mixed The value of the key, or null.
  60. * @access public
  61. * @static
  62. */
  63. static function retrieveValueRecursive(&$params, $key)
  64. {
  65. if (! is_array($params)) {
  66. return null;
  67. } else if ($value = CRM_Utils_Array::value($key, $params)) {
  68. return $value;
  69. } else {
  70. foreach ($params as $subParam) {
  71. if ( is_array( $subParam ) &&
  72. $value = self::retrieveValueRecursive( $subParam, $key ) ) {
  73. return $value;
  74. }
  75. }
  76. }
  77. return null;
  78. }
  79. /**
  80. * if the value exists in the list returns the associated key
  81. *
  82. * @access public
  83. *
  84. * @param list the array to be searched
  85. * @param value the search value
  86. *
  87. * @return key if exists else null
  88. * @static
  89. * @access public
  90. *
  91. */
  92. static function key( $value, &$list ) {
  93. if ( is_array( $list ) ) {
  94. $key = array_search( $value, $list );
  95. // array_search returns key if found, false otherwise
  96. // it may return values like 0 or empty string which
  97. // evaluates to false
  98. // hence we must use identical comparison operator
  99. return ($key === false) ? null : $key;
  100. }
  101. return null;
  102. }
  103. static function &xml( &$list, $depth = 1, $seperator = "\n" ) {
  104. $xml = '';
  105. foreach( $list as $name => $value ) {
  106. $xml .= str_repeat( ' ', $depth * 4 );
  107. if ( is_array( $value ) ) {
  108. $xml .= "<{$name}>{$seperator}";
  109. $xml .= self::xml( $value, $depth + 1, $seperator );
  110. $xml .= str_repeat( ' ', $depth * 4 );
  111. $xml .= "</{$name}>{$seperator}";
  112. } else {
  113. // make sure we escape value
  114. $value = self::escapeXML( $value );
  115. $xml .= "<{$name}>$value</{$name}>{$seperator}";
  116. }
  117. }
  118. return $xml;
  119. }
  120. static function escapeXML( $value ) {
  121. static $src = null;
  122. static $dst = null;
  123. if ( ! $src ) {
  124. $src = array( '&' , '<' , '>' , '' );
  125. $dst = array( '&amp;', '&lt;', '&gt;', ',' );
  126. }
  127. return str_replace( $src, $dst, $value );
  128. }
  129. static function flatten( &$list, &$flat, $prefix = '', $seperator = "." ) {
  130. foreach( $list as $name => $value ) {
  131. $newPrefix = ( $prefix ) ? $prefix . $seperator . $name : $name;
  132. if ( is_array( $value ) ) {
  133. self::flatten( $value, $flat, $newPrefix, $seperator );
  134. } else {
  135. if ( ! empty( $value ) ) {
  136. $flat[$newPrefix] = $value;
  137. }
  138. }
  139. }
  140. }
  141. /**
  142. * Funtion to merge to two arrays recursively
  143. *
  144. * @param array $a1
  145. * @param array $a2
  146. *
  147. * @return $a3
  148. * @static
  149. */
  150. static function crmArrayMerge( $a1, $a2 )
  151. {
  152. if ( empty($a1) ) {
  153. return $a2;
  154. }
  155. if ( empty( $a2 ) ) {
  156. return $a1;
  157. }
  158. $a3 = array( );
  159. foreach ( $a1 as $key => $value) {
  160. if ( array_key_exists($key, $a2) &&
  161. is_array($a2[$key]) && is_array($a1[$key]) ) {
  162. $a3[$key] = array_merge($a1[$key], $a2[$key]);
  163. } else {
  164. $a3[$key] = $a1[$key];
  165. }
  166. }
  167. foreach ( $a2 as $key => $value) {
  168. if ( array_key_exists($key, $a1) ) {
  169. // already handled in above loop
  170. continue;
  171. }
  172. $a3[$key] = $a2[$key];
  173. }
  174. return $a3;
  175. }
  176. static function isHierarchical( &$list ) {
  177. foreach ( $list as $n => $v ) {
  178. if ( is_array( $v ) ) {
  179. return true;
  180. }
  181. }
  182. return false;
  183. }
  184. /**
  185. * Array deep copy
  186. *
  187. * @params array $array
  188. * @params int $maxdepth
  189. * @params int $depth
  190. *
  191. * @return array copy of the array
  192. *
  193. * @static
  194. * @access public
  195. */
  196. static function array_deep_copy( &$array, $maxdepth=50, $depth=0 )
  197. {
  198. if( $depth > $maxdepth ) {
  199. return $array;
  200. }
  201. $copy = array();
  202. foreach( $array as $key => $value ) {
  203. if( is_array( $value ) ) {
  204. array_deep_copy( $value, $copy[$key], $maxdepth, ++$depth);
  205. } else {
  206. $copy[$key] = $value;
  207. }
  208. }
  209. return $copy;
  210. }
  211. /**
  212. * Array splice function that preserves associative keys
  213. * defauly php array_splice function doesnot preserve keys
  214. * So specify start and end of the array that you want to remove
  215. *
  216. * @param array $params array to slice
  217. * @param Integer $start
  218. * @param Integer $end
  219. *
  220. * @return void
  221. * @static
  222. */
  223. static function crmArraySplice( &$params, $start, $end )
  224. {
  225. // verify start and end date
  226. if ( $start < 0 ) $start = 0;
  227. if ( $end > count( $params ) ) $end = count( $params );
  228. $i = 0;
  229. // procees unset operation
  230. foreach ( $params as $key => $value ) {
  231. if ( $i >= $start && $i < $end ) {
  232. unset( $params[$key] );
  233. }
  234. $i++;
  235. }
  236. }
  237. /**
  238. * Function for case insensitive in_array search
  239. *
  240. * @param $value value or search string
  241. * @param $params array that need to be searched
  242. * @param $caseInsensitive boolean true or false
  243. *
  244. * @static
  245. */
  246. static function crmInArray( $value, $params, $caseInsensitive = true )
  247. {
  248. foreach ( $params as $item) {
  249. if ( is_array($item) ) {
  250. $ret = crmInArray( $value, $item, $caseInsensitive );
  251. } else {
  252. $ret = ($caseInsensitive) ? strtolower($item) == strtolower($value) : $item == $value;
  253. if ( $ret ) {
  254. return $ret;
  255. }
  256. }
  257. }
  258. return false;
  259. }
  260. /**
  261. * This function is used to convert associative array names to values
  262. * and vice-versa.
  263. *
  264. * This function is used by both the web form layer and the api. Note that
  265. * the api needs the name => value conversion, also the view layer typically
  266. * requires value => name conversion
  267. */
  268. static function lookupValue( &$defaults, $property, $lookup, $reverse )
  269. {
  270. $id = $property . '_id';
  271. $src = $reverse ? $property : $id;
  272. $dst = $reverse ? $id : $property;
  273. if ( ! array_key_exists( strtolower($src), array_change_key_case( $defaults, CASE_LOWER )) ) {
  274. return false;
  275. }
  276. $look = $reverse ? array_flip( $lookup ) : $lookup;
  277. //trim lookup array, ignore . ( fix for CRM-1514 ), eg for prefix/suffix make sure Dr. and Dr both are valid
  278. $newLook = array( );
  279. foreach( $look as $k => $v) {
  280. $newLook[trim($k, ".")] = $v;
  281. }
  282. $look = $newLook;
  283. if(is_array($look)) {
  284. if ( ! array_key_exists( trim(strtolower( $defaults[strtolower($src)] ),'.'), array_change_key_case( $look, CASE_LOWER )) ) {
  285. return false;
  286. }
  287. }
  288. $tempLook = array_change_key_case( $look ,CASE_LOWER);
  289. $defaults[$dst] = $tempLook[trim(strtolower( $defaults[strtolower($src)] ),'.')];
  290. return true;
  291. }
  292. /**
  293. * Function to check if give array is empty
  294. * @param array $array array that needs to be check for empty condition
  295. *
  296. * @return boolean true is array is empty else false
  297. * @static
  298. */
  299. static function crmIsEmptyArray( $array = array( ) ) {
  300. if ( !is_array( $array ) ) return true;
  301. foreach ( $array as $element ) {
  302. if ( is_array( $element ) ) {
  303. if ( !self::crmIsEmptyArray($element) ) {
  304. return false;
  305. }
  306. } elseif ( isset( $element ) ) {
  307. return false;
  308. }
  309. }
  310. return true;
  311. }
  312. }