**/ class twIf_Generic_Multi extends twIf_Generic_Basic { /* Allow this widget to be embeded/assimilated by other widgets */ const ALLOW_EMBED = true; const SHOW_CAPTION = true; /* Internal URL-Multiplexer */ private $urlMap = array (); protected $Navigation = array (); private $defaultURL = 'index'; private $multiInstance = 0; /* Internal Handle of current subclass */ protected $Subclass = null; protected $isSubclass = false; protected $subclassUrlMode = null; // {{{ __construct /** * Create a new Interface for interface-class-multiplexing (by URL) * * @param array $URL * @param string $Base * * @access friendly * @return void */ function __construct ($URL, $Base, $urlMode = self::MODE_URL) { // Set our base first $this->urlMode = $urlMode; $this->setBase ($Base); if ($this->subclassUrlMode === null) $this->subclassUrlMode = $urlMode; // Look if there is a directly assigned URL $lookupURL = $this->getLookupURL ($URL); if (isset ($this->urlMap [$lookupURL])) $this->loadSubclass ($this->urlMap [$lookupURL], $URL, $Base, true); // Have a look for the default URL-Mapping elseif (isset ($this->urlMap [$this->defaultURL])) { array_unshift ($URL, $this->defaultURL); $this->loadSubclass ($this->urlMap [$this->defaultURL], $URL, $Base, true); } } // }}} // {{{ getLookupURL /** * Retrive the Subclass-Name to lookup in our map * * @param array $URL * * @access protected * @return string **/ protected function getLookupURL ($URL) { if ($this->urlMode == self::MODE_PARAMETER) return $_GET ['twIfMulti' . $this->getInstanceID ()]; if (is_array ($URL)) $URL = $URL [0]; return basename ($URL, '.html'); } // }}} // {{{ getInstanceID /** * Try to determine how many Mutlis where created befor our own * * @access protected * @return int **/ protected function getInstanceID () { global $twIf_Generic_Multi_Instances; if ($this->multiInstance > 0) return $this->multiInstance; if (!isset ($twIf_Generic_Multi_Instances) || ($twIf_Generic_Multi_Instances < 1)) $this->multiInstance = $twIf_Generic_Multi_Instances = 1; else $this->multiInstance = ++$twIf_Generic_Multi_Instances; return $this->multiInstance; } // }}} // {{{ assignURLClass /** * Assign an URL to a given class * * @param string $URL URL of subclass * @param string $Class Which class to use * @param string $onNavigation (optional) Link this class with this caption on navigation * @param bool $First (optional) Put the class in first place on navigation * * @access protected * @return bool **/ protected function assignURLClass ($URL, $Class, $onNavigation = null, $First = false) { $this->urlMap [$this->getLookupURL ($URL)] = $Class; if ($onNavigation !== null) { $navItem = array ('Caption' => $onNavigation, 'URL' => $URL); if ($First) array_unshift ($this->Navigation, $navItem); else $this->Navigation [] = $navItem; } return true; } // }}} // {{{ assignDefaultURL /** * Set default handler URL * * @param string $URL * * @access protected * @return void **/ protected function assignDefaultURL ($URL) { $this->defaultURL = $this->getLookupURL ($URL); } // }}} // {{{ haveDefaultURL /** * Check if we have a valid default URL assigned * * @access protected * @return bool **/ protected function haveDefaultURL () { return (($this->defaultURL != '') && isset ($this->urlMap [$this->defaultURL])); } // }}} // {{{ getDefaultURL /** * Retrive our default URL * * @access protected * @return string **/ protected function getDefaultURL () { return $this->defaultURL; } // }}} // {{{ getSubclassParams /** * Retrive a list of parameters that are passed to the constructor of any subclass * * @access protected * @return array **/ protected function getSubclassParams () { return array (); } // }}} // {{{ loadSubclass /** * Load a given subclass * * @param string $Class Name of subclass * @param array $URL * @param string $Base * @param bool $Strip (optional, default) Strip first chunk of URL and take it as base * * @access private * @return object */ protected function loadSubclass ($Class, $URL, $Base, $Strip = true) { // Check if the requested subclass exists if (!class_exists ($Class)) { trigger_error (twIf_i18n::getText ('Class %s does not exist', $Class), E_USER_WARNING); return false; } // Check wheter to strip the URL if ($Strip) { if ($this->urlMode == self::MODE_PARAMETER) $Base = $this->insertURLParameter ('twIfMulti' . $this->getInstanceID (), null, $Base); elseif (count ($URL) > 0) { $cBase = array_shift ($URL); if (($Base [strlen ($Base) - 1] != '/')) $Base .= '/'; $Base .= $cBase . (substr ($cBase, -5) != '.html' ? '/' : ''); } } if ($this->subclassUrlMode === null) $this->subclassUrlMode = $this->urlMode; // Load the subclass if (!is_array ($Params = $this->getSubclassParams ()) || (count ($Params) == 0)) $this->Subclass = new $Class ($URL, $Base, $this->subclassUrlMode); elseif (!class_exists ('ReflectionClass')) { trigger_error (twIf_i18n::getText ('Missing Reflection-Support, dismissing %s user-defined parameters', count ($Params))); $this->Subclass = new $Class ($URL, $Base, $this->subclassUrlMode); } else { array_unshift ($Params, $URL, $Base, $this->subclassUrlMode); $this->Subclass = call_user_func_array (array (new ReflectionClass ($Class), 'newInstance'), $Params); } // Activate in navigation $this->getNavigation (); foreach ($this->Navigation as $ID=>$Item) if ($Item ['URL'] == $Base) $this->Navigation [$ID]['Selected'] = true; // Do some special stuff if ($this->Subclass instanceof twIf_Generic_Multi) $this->Subclass->setSubclass (); if (is_callable (array ($this->Subclass, 'setMulti'))) $this->Subclass->setMulti ($this); return $this->Subclass; } // }}} // {{{ getDefinition /** * Generate a definition for our output * * @access public * @return array */ public function getDefinition () { $Embeded = ($this->isSubclass && $this->allowEmbed ()); $BasicItems = array (); if (!$Embeded && self::findConstant ('SHOW_CAPTION', true)) $BasicItems [] = array ('Type' => 'Caption', 'Text' => $this->getCaption (), 'Main' => !$this->isSubclass); $BasicItems [] = array ('Type' => 'Block', 'Text' => $this->getIntroduction ()); if (!$Embeded) $BasicItems [] = array ('Type' => 'Navigation', 'Items' => array ($this, 'getNavigation')); $BasicItems [] = array ('Type' => 'Interface', 'Class' => $this->Subclass); return $BasicItems; } // }}} // {{{ setSubclass /** * Tell this widget that it is a subclass of another Generic_Multi * * @access private * @return void **/ private function setSubclass () { $this->isSubclass = true; } // }}} // {{{ allowEmbed /** * Check wheter this widget might be embeded by other Generic_Multi-Widgets * * @access public * @return bool **/ public function allowEmbed () { return self::findConstant ('ALLOW_EMBED', true); } // }}} // {{{ getNaviation /** * Retrive Navigation-definition for this interface * * @param bool $Force (optional) Force a navigation even if there is only one or less subclass * * @access protected * @return array **/ protected function getNavigation ($Force = false) { // Handle internal navigation foreach ($this->Navigation as $ID=>$Nav) if (!isset ($Nav ['Parsed'])) { $this->Navigation [$ID]['Parsed'] = true; if ($this->urlMode == self::MODE_URL) $this->Navigation [$ID]['URL'] = $this->getBase () . $this->Navigation [$ID]['URL'] . (substr ($this->Navigation [$ID]['URL'], -5) != '.html' ? '/' : ''); else $this->Navigation [$ID]['URL'] = $this->insertURLParameter ('twIfMulti' . $this->getInstanceID (), $this->Navigation [$ID]['URL'], $this->getBase ()); } // Copy to output-buffer $out = $this->Navigation; // Append navigation of subitem $isMulti = ($this->Subclass instanceof twIf_Generic_Multi); if (is_object ($this->Subclass) && (($isMulti && $this->Subclass->allowEmbed ()) || !$isMulti) && is_callable (array ($this->Subclass, 'getNavigation')) && (count ($Subitems = $this->Subclass->getNavigation ()) > 0)) { $out [] = array ('Caption' => '-', 'URL' => '-'); foreach ($Subitems as $Subitem) $out [] = $Subitem; } if (!$Force && (count ($out) < 2)) return array (); return $out; } // }}} // {{{ generateSubclassLink /** * Generate the link to a given subclass * * @access protected * @return string **/ public function generateSubclassLink ($Subclass, $ignoreEncoding = false) { if ($this->urlMode == self::MODE_URL) return $this->getBase () . $Subclass . (substr ($Subclass, -5) == '.html' ? '' : '/'); return $this->insertURLParameter ('twIfMulti' . $this->getInstanceID (), $Subclass, $this->getBase (), $ignoreEncoding); } // }}} // {{{ getCompleteBase /** * Do a deep search and retrive our complete base (including subclasses) * * @access public * @return string **/ public function getCompleteBase () { // Check if we have a subclass assigned if (!is_object ($this->Subclass)) return $this->getBase (); // Check if we can do a recursive thing if (is_callable (array ($this->Subclass, __FUNCTION__))) return call_user_func (array ($this->Subclass, __FUNCTION__)); // Reach to an end return $this->Subclass->getBase (); } // }}} } ?>