diff --git a/api/src/Etemplate/Widget.php b/api/src/Etemplate/Widget.php index 4ee8df8486..51e546a53f 100644 --- a/api/src/Etemplate/Widget.php +++ b/api/src/Etemplate/Widget.php @@ -308,13 +308,13 @@ class Widget if (!$widget_registry) // not in instance cache --> rescan from filesystem { - foreach(scandir($dir=__DIR__ . '/Widget') as $filename) + foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(__DIR__)) as $path) { - if(substr($filename, -4) == '.php') + if(substr($path, -4) == '.php') { try { - include_once($dir.'/'.$filename); + include_once($path); } catch(Exception $e) { @@ -390,6 +390,24 @@ class Widget } } } + else if (!class_exists($class_name)) + { + // Class in widget registry, but not loaded + // Try for a base class + $subtypes = explode('-',$type); + $basetype = $subtypes[0]; + $class_name = __CLASS__.'\\'.implode('\\',array_map('ucfirst',$subtypes)); + if(!class_exists($class_name) && self::$widget_registry[$basetype] && self::$widget_registry[$basetype] != $class_name) + { + // Try for base type, it's probably better than the root + $class_name = self::$widget_registry[$basetype]; + } + if(!class_exists($class_name)) + { + // Fall back to widget class, we can not ignore it, as the widget may contain other widgets + $class_name = __CLASS__; + } + } if(!$xml) { diff --git a/api/src/Etemplate/Widget/Nextmatch.php b/api/src/Etemplate/Widget/Nextmatch.php index f60b0e0267..7776114e0c 100644 --- a/api/src/Etemplate/Widget/Nextmatch.php +++ b/api/src/Etemplate/Widget/Nextmatch.php @@ -1157,79 +1157,4 @@ class Nextmatch extends Etemplate\Widget } // Registration needs to go here, otherwise customfields won't be loaded until some other cf shows up -Etemplate\Widget::registerWidget(__NAMESPACE__.'\\Customfields', array('nextmatch-customfields')); - -/** - * Extend selectbox so select options get parsed properly before being sent to client - */ -class NextmatchFilterHeader extends Select -{ -} -Etemplate\Widget::registerWidget(__NAMESPACE__.'\\NextmatchFilterHeader', array('nextmatch-filterheader')); - -/** - * Extend selectbox and change type so proper users / groups get loaded, according to preferences - */ -class NextmatchAccountFilter extends Select -{ - /** - * Parse and set extra attributes from xml in template object - * - * @param string|XMLReader $xml - * @param boolean $cloned =true true: object does NOT need to be cloned, false: to set attribute, set them in cloned object - */ - public function set_attrs($xml, $cloned=true) - { - parent::set_attrs($xml, $cloned); - - $this->attrs['type'] = 'select-account'; - } -} -Etemplate\Widget::registerWidget(__NAMESPACE__.'\\NextmatchAccountFilter', array('nextmatch-accountfilter')); - -/** - * A filter widget that fakes another (select) widget and turns it into a nextmatch filter widget. - */ -class NextmatchCustomFilter extends Transformer -{ - - protected $legacy_options = 'type,widget_options'; - - /** - * Fill type options in self::$request->sel_options to be used on the client - * - * @param string $cname - * @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont' - */ - public function beforeSendToClient($cname, array $expand=null) - { - switch($this->attrs['type']) - { - case "link-entry": - self::$transformation['type'] = $this->attrs['type'] = 'nextmatch-entryheader'; - break; - default: - list($type) = explode('-',$this->attrs['type']); - if($type == 'select') - { - if(in_array($this->attrs['type'], Select::$cached_types)) - { - $widget_type = $this->attrs['type']; - } - $this->attrs['type'] = 'nextmatch-filterheader'; - } - self::$transformation['type'] = $this->attrs['type']; - } - $form_name = self::form_name($cname, $this->id, $expand); - - $this->setElementAttribute($form_name, 'options', trim($this->attrs['widget_options']) != '' ? $this->attrs['widget_options'] : ''); - - $this->setElementAttribute($form_name, 'type', $this->attrs['type']); - if($widget_type) - { - $this->setElementAttribute($form_name, 'widget_type', $widget_type); - } - parent::beforeSendToClient($cname, $expand); - } -} -Etemplate\Widget::registerWidget(__NAMESPACE__.'\\NextmatchCustomFilter', array('nextmatch-customfilter')); +Etemplate\Widget::registerWidget(__NAMESPACE__.'\\Customfields', array('nextmatch-customfields')); \ No newline at end of file diff --git a/api/src/Etemplate/Widget/Nextmatch/Accountfilter.php b/api/src/Etemplate/Widget/Nextmatch/Accountfilter.php new file mode 100644 index 0000000000..ba3ec352d4 --- /dev/null +++ b/api/src/Etemplate/Widget/Nextmatch/Accountfilter.php @@ -0,0 +1,35 @@ + + * @copyright 2002-16 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +namespace EGroupware\Api\Etemplate\Widget\Nextmatch; + +use EGroupware\Api\Etemplate\Widget; + +/** + * Extend selectbox and change type so proper users / groups get loaded, according to preferences + */ +class AccountFilter extends Widget\Select +{ + /** + * Parse and set extra attributes from xml in template object + * + * @param string|XMLReader $xml + * @param boolean $cloned =true true: object does NOT need to be cloned, false: to set attribute, set them in cloned object + */ + public function set_attrs($xml, $cloned=true) + { + parent::set_attrs($xml, $cloned); + + $this->attrs['type'] = 'select-account'; + } +} \ No newline at end of file diff --git a/api/src/Etemplate/Widget/Nextmatch/Customfilter.php b/api/src/Etemplate/Widget/Nextmatch/Customfilter.php new file mode 100644 index 0000000000..1a5c32c5f7 --- /dev/null +++ b/api/src/Etemplate/Widget/Nextmatch/Customfilter.php @@ -0,0 +1,62 @@ + + * @copyright 2002-16 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +namespace EGroupware\Api\Etemplate\Widget\Nextmatch; + +use EGroupware\Api\Etemplate\Widget; + +/** + * A filter widget that fakes another (select) widget and turns it into a nextmatch filter widget. + */ +class NextmatchCustomFilter extends Widget\Transformer +{ + + protected $legacy_options = 'type,widget_options'; + + /** + * Fill type options in self::$request->sel_options to be used on the client + * + * @param string $cname + * @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont' + */ + public function beforeSendToClient($cname, array $expand=null) + { + switch($this->attrs['type']) + { + case "link-entry": + self::$transformation['type'] = $this->attrs['type'] = 'nextmatch-entryheader'; + break; + default: + list($type) = explode('-',$this->attrs['type']); + if($type == 'select') + { + if(in_array($this->attrs['type'], Select::$cached_types)) + { + $widget_type = $this->attrs['type']; + } + $this->attrs['type'] = 'nextmatch-filterheader'; + } + self::$transformation['type'] = $this->attrs['type']; + } + $form_name = self::form_name($cname, $this->id, $expand); + + $this->setElementAttribute($form_name, 'options', trim($this->attrs['widget_options']) != '' ? $this->attrs['widget_options'] : ''); + + $this->setElementAttribute($form_name, 'type', $this->attrs['type']); + if($widget_type) + { + $this->setElementAttribute($form_name, 'widget_type', $widget_type); + } + parent::beforeSendToClient($cname, $expand); + } +} diff --git a/api/src/Etemplate/Widget/Nextmatch/Filterheader.php b/api/src/Etemplate/Widget/Nextmatch/Filterheader.php new file mode 100644 index 0000000000..0d9c5a8b3b --- /dev/null +++ b/api/src/Etemplate/Widget/Nextmatch/Filterheader.php @@ -0,0 +1,23 @@ + + * @copyright 2002-16 by RalfBecker@outdoor-training.de + * @version $Id$ + */ + +namespace EGroupware\Api\Etemplate\Widget\Nextmatch; + +use EGroupware\Api\Etemplate\Widget; + +/** + * Extend selectbox so select options get parsed properly before being sent to client + */ +class Filterheader extends Widget\Select +{ +} \ No newline at end of file