00001 <?php
00007 namespace Habari;
00008
00032 class Stack
00033 {
00034 private static $stacks = array();
00035 private static $stack_sort = array();
00036 private static $sorting;
00037 private static $depends = array();
00038
00049 private function __construct( $input )
00050 {
00051 parent::__construct( $input );
00052 }
00053
00059 public static function get_named_stack( $stack_name )
00060 {
00061 if ( isset( self::$stacks[$stack_name] ) ) {
00062 return self::$stacks[$stack_name];
00063 }
00064 else {
00065 return self::create_stack( $stack_name );
00066 }
00067 }
00068
00076 public static function has ( $stack_name, $value_name )
00077 {
00078
00079
00080 $stack = self::get_named_stack( $stack_name );
00081
00082 if ( isset( $stack[ $value_name ] ) ) {
00083 return true;
00084 }
00085 else {
00086 return false;
00087 }
00088
00089 }
00090
00099 public static function get_item ( $stack_name, $value_name, $default_value = null )
00100 {
00101
00102
00103 $stack = self::get_named_stack( $stack_name );
00104
00105 if ( isset( $stack[ $value_name ] ) ) {
00106 return $stack[ $value_name ];
00107 }
00108 else {
00109 return $default_value;
00110 }
00111
00112 }
00113
00119 public static function create_stack( $stack_name )
00120 {
00121 if ( empty( self::$stacks[$stack_name] ) ) {
00122 $stack = array();
00123 self::$stacks[$stack_name] = $stack;
00124 self::$stack_sort[$stack_name] = array();
00125 }
00126 return self::$stacks[$stack_name];
00127 }
00128
00137 public static function add( $stack_name, $value, $value_name = null, $after = null )
00138 {
00139 $stack = self::get_named_stack( $stack_name );
00140 if($value_name == null && is_string($value)) {
00141 if($test = StackItem::get($value)) {
00142 $value = $test;
00143 }
00144 }
00145 if(!$value instanceof StackItem) {
00146 $value_name = $value_name ? $value_name : md5( serialize( $value ) );
00147 $value = StackItem::register($value_name, $value);
00148 foreach((array)$after as $a) {
00149 $value->add_dependency($a);
00150 }
00151 }
00152 $stack[$value->name] = $value;
00153 self::$stacks[$stack_name] = $stack;
00154 return $stack;
00155 }
00156
00163 public static function remove( $stack_name, $value_name = null )
00164 {
00165
00166 if ( $value_name == null ) {
00167 unset( self::$stacks[ $stack_name ] );
00168 return array();
00169 }
00170
00171 $stack = self::get_named_stack( $stack_name );
00172 if ( isset( $stack[$value_name] ) ) {
00173 unset( $stack[$value_name] );
00174 }
00175 self::$stacks[$stack_name] = $stack;
00176 return $stack;
00177 }
00178
00184 public static function get_sorted_stack( $stack_name )
00185 {
00186 $raw_stack = self::get_named_stack( $stack_name );
00187 $sorted = array();
00188
00189 $dependency_items = array();
00190 if(isset(self::$depends[$stack_name])) {
00191 foreach(self::$depends[$stack_name] as $stack) {
00192 $items = self::get_named_stack( $stack );
00193 foreach($items as $item) {
00194 $dependency_items[$item->name] = $item->name;
00195 }
00196 }
00197 }
00198
00199 $sort = function(&$stackitem, $sort) use (&$sorted, $dependency_items) {
00200 static $sortindex = array();
00201 if(isset($sortindex[$stackitem->name])) {
00202 return;
00203 }
00204 $sortindex[$stackitem->name] = true;
00206 $dependencies = $stackitem->get_dependencies();
00208 foreach($dependencies as &$dependency) {
00209 if(!in_array($dependency->name, $dependency_items)) {
00210 $sort($dependency, $sort);
00211 if(!$dependency->in_stack_index($sorted)) {
00212 $sorted[$dependency->name] = $dependency;
00213 $have_everything = false;
00214 }
00215 }
00216 }
00217 $sorted[$stackitem->name] = $stackitem;
00218 };
00219
00220 foreach($raw_stack as &$stackitem) {
00221 $sort($stackitem, $sort);
00222 }
00223
00224 return $sorted;
00225 }
00226
00232 public static function get( $stack_name, $format = null )
00233 {
00234 $out = '';
00235 $stack = self::get_sorted_stack( $stack_name );
00236 $stack = Plugins::filter( 'stack_out', $stack, $stack_name, $format );
00237 foreach ( $stack as $element ) {
00239 if ( is_callable( $format ) ) {
00240 $out.= call_user_func_array( $format, (array) $element->resource );
00241 }
00242 elseif ( is_string( $format ) ) {
00243 $out .= vsprintf( $format, (array) $element->resource );
00244 }
00245 else {
00246 $out.= $element;
00247 }
00248 }
00249 return $out;
00250 }
00251
00257 public static function out( $stack_name, $format = null )
00258 {
00259 echo self::get( $stack_name, $format );
00260 }
00261
00270 public static function scripts( $element, $attrib = null, $wrapper = '%s' )
00271 {
00272 if(is_array($attrib)) {
00273 $attrib = Utils::html_attr($attrib);
00274 }
00275 if ( self::is_url( $element ) ) {
00276 $output = sprintf( "<script %s src=\"%s\"></script>\r\n", $attrib, $element );
00277 }
00278 else {
00279 $output = sprintf( "<script %s>%s</script>\r\n", $attrib, $element );
00280 }
00281 $output = sprintf($wrapper, $output);
00282 return $output;
00283 }
00284
00293 public static function styles( $element, $typename = null, $props = array() )
00294 {
00295 $props = $props + array('type' => 'text/css');
00296 if ( !empty( $typename ) ) {
00297 $props['media'] = $typename;
00298 }
00299 $wrapper = '%s';
00300 if(isset($props['_wrapper'])) {
00301 $wrapper = $props['_wrapper'];
00302 unset($props['_wrapper']);
00303 }
00304
00305 if ( self::is_url( $element ) ) {
00306 $props = $props + array('rel' => 'stylesheet', 'href' => $element);
00307 $output = sprintf( "<link %s>\r\n", Utils::html_attr($props) );
00308 }
00309 else {
00310 $output = sprintf( "<style %2\$s>%1\$s</style>\r\n", $element, Utils::html_attr($props) );
00311 }
00312 $output = sprintf($wrapper, $output);
00313 return $output;
00314 }
00315
00324 private static function is_url( $url )
00325 {
00326 return ( ( strpos( $url, 'http://' ) === 0 || strpos( $url, 'https://' ) === 0 || strpos( $url, '//' ) === 0 || strpos( $url, '/' ) === 0 ) && strpos( $url, "\n" ) === false );
00327 }
00328
00334 public static function dependent($dependent, $dependson)
00335 {
00336 if(!isset(self::$depends[$dependent])) {
00337 self::$depends[$dependent] = array();
00338 }
00339 self::$depends[$dependent][$dependson] = $dependson;
00340 }
00341
00346 public static function load_stackitems()
00347 {
00348 Pluggable::load_hooks(__CLASS__);
00349 Plugins::act( 'register_stackitems' );
00350 }
00351
00355 public static function action_register_stackitems()
00356 {
00357
00358 StackItem::register( 'jquery', Site::get_url( 'vendor', '/jquery.js' ), '1.8.2' );
00359 StackItem::register( 'jquery.ui', Site::get_url( 'vendor', '/jquery-ui.min.js', '1.9.0' ) )->add_dependency( 'jquery' );
00360 StackItem::register( 'jquery.color', Site::get_url( 'vendor', '/jquery.color.js' ) )->add_dependency('jquery.ui' );
00361 StackItem::register( 'jquery-nested-sortable', Site::get_url( 'vendor', '/jquery.ui.nestedSortable.js'), '1.2.1' ) ->add_dependency('jquery.ui' );
00362 StackItem::register( 'humanmsg', Site::get_url( 'vendor', '/humanmsg/humanmsg.js' ), '2' )->add_dependency( 'jquery' )->add_dependency( 'locale-js' );
00363 StackItem::register( 'jquery.hotkeys', Site::get_url( 'vendor', '/jquery.hotkeys.js' ), '2.00.A' )->add_dependency( 'jquery' );
00364 StackItem::register( 'locale-js', URL::get( 'ajax', 'context=locale' ) );
00365 StackItem::register( 'media', Site::get_url( 'admin_theme', '/js/media.js' ) )->add_dependency( 'jquery' )->add_dependency( 'locale-js' );
00366 StackItem::register( 'admin-js', Site::get_url( 'admin_theme', '/js/admin.js' ) )->add_dependency( 'jquery' )->add_dependency( 'locale-js' );
00367 StackItem::register( 'crc32', Site::get_url( 'vendor', '/crc32.js' ), '1.2' );
00368 StackItem::register( 'select2', Site::get_url( 'vendor', '/select2/select2.min.js' ), '3.3.2' )->add_dependency( 'jquery' );
00369 StackItem::register( 'select2-debug', Site::get_url( 'vendor', '/select2/select2.js' ), '3.3.2' )->add_dependency( 'jquery' );
00370 StackItem::register( 'underscore', Site::get_url( 'vendor', '/underscore-1.4.3.js' ), '1.3.2' );
00371 StackItem::register( 'backbone', Site::get_url( 'vendor', '/backbone-0.9.10.js' ), '0.9.10' );
00372 StackItem::register( 'visualsearch', Site::get_url( 'vendor', '/visualsearch/visualsearch.js' ), '0.4.0' )
00373 ->add_dependency( 'underscore' )
00374 ->add_dependency( 'jquery.ui' )
00375 ->add_dependency( 'backbone' );
00376
00377 StackItem::register( 'admin-css', array( Site::get_url( 'admin_theme', '/css/admin.css'), 'screen' ) );
00378 StackItem::register( 'less', array( Site::get_url( 'vendor', '/less.min.js') ) );
00379 StackItem::register( 'admin-less', array( Site::get_url( 'admin_theme', '/less/admin.less'), null, array('rel' => 'stylesheet/less') ) );
00380 StackItem::register( 'jquery.ui-css', array( Site::get_url( 'admin_theme', '/css/jqueryui.css'), 'screen' ), '1.8.14' );
00381 StackItem::register( 'humanmsg-css', array( Site::get_url( 'vendor', '/humanmsg/humanmsg.css'), 'screen' ), '1.0.habari' );
00382 StackItem::register( 'select2-css', Site::get_url( 'vendor', '/select2/select2.css' ), '3.3.2' );
00383 StackItem::register( 'visualsearch-css', array(Site::get_url( 'vendor', '/visualsearch/visualsearch.css' ), null, array('_wrapper' => '<!--[if lt IE 7]><!-->%s<!--<![endif]-->')), '0.4.0' );
00384 StackItem::register( 'visualsearch-datauri-css', array(Site::get_url( 'vendor', '/visualsearch/visualsearch-datauri.css' ), null, array('_wrapper' => '<!--[if (!IE)|(gte IE 8)]><!-->%s<!--<![endif]-->')), '0.4.0' );
00385 }
00386
00387 }
00388
00389
00390 ?>