<?php /* * Copyright (c) 2011 mlunzena@uos.de, aklassen@uos.de * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. */ namespace Studip; /** * Represents an abstract interactable element. */ abstract class Interactable { public $label, $attributes; /** * Constructs a new element to interact e.g. button or link * * @param string $label the label of the button * @param array $attributes the attributes of the button element */ final public function __construct($label, $attributes) { $this->label = $label; $this->attributes = $attributes; } /** * Magic method (triggered when invoking inaccessible methods in a static * context) used to dynamically create an interactable element with an * additional CSSclass. This works for every static method call matching: * /^create(.+)/ The matched group is used as CSS class for the * interactable element. * * @code * echo Button::createSubmit(); * * # => <button ... class="submit">... * @endcode * * @param string $name name of the method being called * @param array $args enumerated array containing the parameters * passed to the $name'ed method * * @return Interactable returns a Button, if $name =~ /^create/ * @throws throws a BadMethodCallException if $name does not * match */ public static function __callStatic($name, $args) { # only trigger, if $name =~ /^create/ and at least using $label if (0 === strncasecmp($name, 'create', 6)) { # instantiate button from arguments $interactable = call_user_func_array([get_called_class(), 'create'], $args); # but customize with class from $name: $class = self::hyphenate(mb_substr($name, 6)); # a.) set name unless set if (empty($args[1]) || !is_string($args[1])) { $interactable->attributes['name'] = $class; } # b.) set/append CSS class if (array_key_exists('class', $interactable->attributes)) { $interactable->attributes['class'] .= " $class"; } else { $interactable->attributes['class'] = $class; } return $interactable; } # otherwise bail out throw new \BadMethodCallException(); } /** * Easy factory method to create an Interactable instance. * All parameters are optional. * * @code * // example using subclass Button * * echo Button::create(); * # => <button type="submit" name="ok">ok</button> * * echo Button::create('Yes') * # => <button type="submit" name="yes">yes</button> * * echo Button::create('Yes', 'aName') * # => <button type="submit" name="aName">yes</button> * * echo Button::create('Yes', array('a' => 1, 'b' => 2)) * # => <button type="submit" a="1" b="2" name="yes">yes</button> * * echo Button::create('Yes', 'aName', array('a' => 1, 'b' => 2)), * # => <button type="submit" a="1" b="2" name="aName">yes</button> * @endcode * * @param string $label the label of the current element * @param string $trait the specific trait of the current element * @param array $attributes the attributes of the button element * * @return Interactable element */ public static function create($label = NULL, $trait = NULL, $attributes = []) { $argc = func_num_args(); // if label is empty, use default $label = $label ?: _('ok'); // if there are two parameters, there are two cases: // 1.) label and trait OR // 2.) label and attributes // // in the latter case, use parameter $trait as attributes // and use the default for name if ($argc === 2 && is_array($trait)) { list($attributes, $trait) = [$trait, NULL]; } $interactable = new static($label, $attributes); $interactable->initialize($label, $trait, $attributes); return $interactable; } /** * Initialize an interactable element. * The parameters to create are handed over to enable subclass * specific customization. * * @param string $label the label of the current element * @param string $trait the specific trait of the current element * @param array $attributes the attributes of the button element */ abstract protected function initialize($label, $trait, $attributes); /** * Convenience method used for autocompletion hints by your * editor. * * Without this method #__callStatic would do the same. * * @param string $label the label of the current element * @param string $trait the specific trait of the current element * @param array $attributes the attributes of the button element */ public static function createAccept($label = NULL, $trait = NULL, $attributes = []) { $args = func_num_args() ? func_get_args() : [_('Übernehmen')]; return self::__callStatic(__FUNCTION__, $args); } /** * Convenience method used for autocompletion hints by your * editor. * * Without this method #__callStatic would do the same. * * @param string $label the label of the current element * @param string $trait the specific trait of the current element * @param array $attributes the attributes of the button element */ public static function createEdit($label = NULL, $trait = NULL, $attributes = []) { $args = func_num_args() ? func_get_args() : [_('Bearbeiten')]; return self::__callStatic(__FUNCTION__, $args); } /** * Convenience method used for autocompletion hints by your * editor. * * Without this method #__callStatic would do the same. * * @param string $label the label of the current element * @param string $trait the specific trait of the current element * @param array $attributes the attributes of the button element */ public static function createCancel($label = NULL, $trait = NULL, $attributes = []) { $args = func_num_args() ? func_get_args() : [_('Abbrechen')]; return self::__callStatic(__FUNCTION__, $args); } /** * Hyphenates the passed word. * * @param string $word word to be hyphenated * * @return string hyphenated word */ private static function hyphenate($word) { return mb_strtolower(preg_replace('/(?<=\w)([A-Z])/', '-\\1', $word)); } }