PageRenderTime 52ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/system/classes/stack.php

https://github.com/HabariMag/habarimag-old
PHP | 282 lines | 155 code | 25 blank | 102 comment | 30 complexity | 67c419241a51800be8db891b0c33b01d MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php
  2. /**
  3. * @package Habari
  4. *
  5. */
  6. /**
  7. * Habari Stack Class
  8. *
  9. * This class allows Habari to accumulate a group of unique values that
  10. * can be output using a specific formatting string.
  11. * This is useful for collecting a set of unique javascript references to output
  12. * and then insert them at a specific point on the page.
  13. *
  14. * <code>
  15. * // Add jquery to the javascript stack:
  16. * Stack::add( 'template_header_javascript', Site::get_url('scripts') . '/jquery.js', 'jquery' );
  17. *
  18. * // Add stylesheet to theme_stylesheet stack with media type
  19. * Stack::add( 'template_stylesheet', array( Site::get_url('theme') . '/style.css', 'screen' ), 'style' );
  20. *
  21. * // Output the javascript stack:
  22. * Stack::out( 'template_header_javascript', '<script src="%s" type="text/javascript"></script>' );
  23. *
  24. * // Output the theme_stylesheet stack:
  25. * Stack::out( 'template_stylesheet', '<link rel="stylesheet" type="text/css" href="%s" media="%s">' );
  26. * </code>
  27. *
  28. */
  29. class Stack
  30. {
  31. private static $stacks = array();
  32. private static $stack_sort = array();
  33. private static $sorting;
  34. /**
  35. * Private constructor for Stack.
  36. * Stack objects should only be created using the static
  37. * method Static::create_stack(), or one of the methods that
  38. * adds a value directly to a stack. This prevents multiple Stack
  39. * objects from being created with the same name.
  40. *
  41. * @param mixed $input An array or ArrayObject to create the stack from.
  42. * @return array The created stack
  43. */
  44. private function __construct( $input )
  45. {
  46. parent::__construct( $input );
  47. }
  48. /**
  49. * Retreive a named stack instance
  50. * @param string $stack_name The name of the stack to return
  51. * @return Stack The requested stack
  52. **/
  53. public static function get_named_stack( $stack_name )
  54. {
  55. if ( isset( self::$stacks[$stack_name] ) ) {
  56. return self::$stacks[$stack_name];
  57. }
  58. else {
  59. return self::create_stack( $stack_name );
  60. }
  61. }
  62. /**
  63. * Check for the existence of a given stack item.
  64. *
  65. * @param string $stack_name The name of the stack in which to check.
  66. * @param string $value The value to check for.
  67. * @return boolean true if the item exists, false otherwise.
  68. */
  69. public static function has ( $stack_name, $value_name )
  70. {
  71. // get the stack
  72. $stack = self::get_named_stack( $stack_name );
  73. if ( isset( $stack[ $value_name ] ) ) {
  74. return true;
  75. }
  76. else {
  77. return false;
  78. }
  79. }
  80. /**
  81. * Get a single item from a given stack.
  82. *
  83. * @param string $stack_name The name of the stack to fetch an item from.
  84. * @param string $value The item to fetch.
  85. * @param mixed $default_value The default value to return if the item does not exist in the stack.
  86. * @return mixed The item, or $default_value if it does not exist.
  87. */
  88. public static function get_item ( $stack_name, $value_name, $default_value = null )
  89. {
  90. // get the stack
  91. $stack = self::get_named_stack( $stack_name );
  92. if ( isset( $stack[ $value_name ] ) ) {
  93. return $stack[ $value_name ];
  94. }
  95. else {
  96. return $default_value;
  97. }
  98. }
  99. /**
  100. * Creates and retreives a named stack instance
  101. * @param string $stack_name The name of the stack to create and return
  102. * @return array The created stack
  103. **/
  104. public static function create_stack( $stack_name )
  105. {
  106. if ( empty( self::$stacks[$stack_name] ) ) {
  107. $stack = array();
  108. self::$stacks[$stack_name] = $stack;
  109. self::$stack_sort[$stack_name] = array();
  110. }
  111. return self::$stacks[$stack_name];
  112. }
  113. /**
  114. * Add a value to a stack
  115. * @param string $stack_name The name of the stack
  116. * @param mixed $value The value to add
  117. * @param string $value_name The name of the value to add
  118. * @param string $after The name of the stack element to insert this new element after
  119. * @return array The stack that was added to
  120. **/
  121. public static function add( $stack_name, $value, $value_name = null, $after = null )
  122. {
  123. $stack = self::get_named_stack( $stack_name );
  124. $value_name = $value_name ? $value_name : md5( serialize( $value ) );
  125. if ( !is_null( $after ) ) {
  126. if ( !is_array( $after ) ) {
  127. $after = array( $after );
  128. }
  129. foreach ( $after as $a ) {
  130. if ( !isset( self::$stack_sort[$stack_name] ) ) {
  131. self::$stack_sort[$stack_name] = array();
  132. }
  133. if ( !isset( self::$stack_sort[$stack_name][$a] ) ) {
  134. self::$stack_sort[$stack_name][$a] = array();
  135. }
  136. self::$stack_sort[$stack_name][$a][$value_name] = $value_name;
  137. }
  138. }
  139. $stack[$value_name] = $value;
  140. self::$stacks[$stack_name] = $stack;
  141. return $stack;
  142. }
  143. /**
  144. * Remove a value to a stack
  145. * @param string $stack_name The name of the stack
  146. * @param string $value_name The name of the value to remove
  147. * @return array The rest of the stack, post-remove
  148. **/
  149. public static function remove( $stack_name, $value_name = null )
  150. {
  151. if ( $value_name == null ) {
  152. unset( self::$stacks[ $stack_name ] );
  153. return array();
  154. }
  155. $stack = self::get_named_stack( $stack_name );
  156. if ( isset( $stack[$value_name] ) ) {
  157. unset( $stack[$value_name] );
  158. }
  159. self::$stacks[$stack_name] = $stack;
  160. return $stack;
  161. }
  162. public static function get_sorted_stack( $stack_name )
  163. {
  164. self::$sorting = $stack_name;
  165. $stack = self::get_named_stack( $stack_name );
  166. uksort( $stack, array( 'Stack', 'sort_stack_cmp' ) );
  167. return $stack;
  168. }
  169. public static function sort_stack_cmp( $a, $b )
  170. {
  171. $aa = isset( self::$stack_sort[self::$sorting][$a] ) ? self::$stack_sort[self::$sorting][$a] : array();
  172. $ba = isset( self::$stack_sort[self::$sorting][$b] ) ? self::$stack_sort[self::$sorting][$b] : array();
  173. $acb = isset( $aa[$b] );
  174. $bca = isset( $ba[$a] );
  175. $ac = count( $aa );
  176. $bc = count( $ba );
  177. if ( ( $acb && $bca ) || !( $acb || $bca ) ) {
  178. if ( $ac == $bc ) {
  179. // they are equal in 'bias', so go with the order in which they were added.
  180. return 1;
  181. }
  182. return $ac > $bc ? -1 : 1;
  183. }
  184. elseif ( $acb ) {
  185. return -1;
  186. }
  187. elseif ( $bca ) {
  188. return 1;
  189. }
  190. }
  191. /**
  192. * Returns all of the values of the stack
  193. * @param string $stack_name The name of the stack to output
  194. * @param mixed $format A printf-style formatting string or callback used to output each stack element
  195. **/
  196. public static function get( $stack_name, $format = null )
  197. {
  198. $out = '';
  199. $stack = self::get_sorted_stack( $stack_name );
  200. $stack = Plugins::filter( 'stack_out', $stack, $stack_name, $format );
  201. foreach ( $stack as $element ) {
  202. if ( is_callable( $format ) ) {
  203. $out.= call_user_func_array( $format, (array) $element );
  204. }
  205. elseif ( is_string( $format ) ) {
  206. $out .= vsprintf( $format, (array) $element );
  207. }
  208. else {
  209. $out.= $element;
  210. }
  211. }
  212. return $out;
  213. }
  214. /**
  215. * Outputs all of the values of the stack
  216. * @param string $stack_name The name of the stack to output
  217. * @param mixed $format A printf-style formatting string or callback used to output each stack element
  218. **/
  219. public static function out( $stack_name, $format = null )
  220. {
  221. echo self::get( $stack_name, $format );
  222. }
  223. /**
  224. * A callback for Stack::get() that outputs scripts as reference or inline depending on their content
  225. *
  226. * @param string $element The script element in the stack
  227. * @return string The resulting script tag
  228. */
  229. public static function scripts( $element )
  230. {
  231. if ( ( strpos( $element, 'http://' ) === 0 || strpos( $element, 'https://' ) === 0 ) && strpos( $element, "\n" ) === false ) {
  232. $output = sprintf( '<script src="%s" type="text/javascript"></script>'."\r\n", $element );
  233. }
  234. else {
  235. $output = sprintf( '<script type="text/javascript">%s</script>'."\r\n", $element );
  236. }
  237. return $output;
  238. }
  239. /**
  240. * A callback for Stack::get() that outputs styles as link or inline style tags depending on their content
  241. *
  242. * @param string $element The style element in the stack
  243. * @param string $typename The media disposition of the content
  244. * @return string The resulting style or link tag
  245. */
  246. public static function styles( $element, $typename )
  247. {
  248. if ( ( strpos( $element, 'http://' ) === 0 || strpos( $element, 'https://' ) === 0 ) && strpos( $element, "\n" ) === false ) {
  249. $output = sprintf( '<link rel="stylesheet" type="text/css" href="%s" media="%s">'."\r\n", $element, $typename );
  250. }
  251. else {
  252. $output = sprintf( '<style type="text/css" media="%s">%s</style>'."\r\n", $typename, $element );
  253. }
  254. return $output;
  255. }
  256. }
  257. ?>