123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- <?php
- namespace mindplay\demo;
- use Composer\Autoload\ClassLoader;
- use mindplay\annotations\AnnotationCache;
- use mindplay\annotations\Annotations;
- use mindplay\demo\annotations\Package;
- $vendor_path = dirname(__DIR__) . '/vendor';
- if (!is_dir($vendor_path)) {
- echo 'Install dependencies first' . PHP_EOL;
- exit(1);
- }
- require_once($vendor_path . '/autoload.php');
- $auto_loader = new ClassLoader();
- $auto_loader->addPsr4("mindplay\\demo\\", __DIR__);
- $auto_loader->register();
- Annotations::$config['cache'] = new AnnotationCache(__DIR__ . '/runtime');
- Package::register(Annotations::getManager());
- class Person
- {
-
- public $name;
-
- public $address;
-
- public $age;
- }
- abstract class Widget
- {
- protected $object;
- protected $property;
- public $value;
-
- public $errors = array();
-
- public function __construct($object, $property)
- {
- $this->object = $object;
- $this->property = $property;
- $this->value = $object->$property;
- }
-
- public function addError($message)
- {
- $this->errors[] = $message;
- }
-
-
-
- protected function getMetadata($type, $name, $default = null)
- {
- $a = Annotations::ofProperty($this->object, $this->property, $type);
- if (!count($a)) {
- return $default;
- }
- return $a[0]->$name;
- }
-
-
- abstract public function update($input);
-
-
-
- public function validate()
- {
- if (empty($this->value)) {
- if ($this->isRequired()) {
- $this->addError("Please complete this field");
- } else {
- return;
- }
- }
- if (is_string($this->value)) {
- $min = $this->getMetadata('@length', 'min');
- $max = $this->getMetadata('@length', 'max');
- if ($min !== null && strlen($this->value) < $min) {
- $this->addError("Minimum length is {$min} characters");
- } else {
- if ($max !== null && strlen($this->value) > $max) {
- $this->addError("Maximum length is {$max} characters");
- }
- }
- }
- if (is_int($this->value)) {
- $min = $this->getMetadata('@range', 'min');
- $max = $this->getMetadata('@range', 'max');
- if (($min !== null && $this->value < $min) || ($max !== null && $this->value > $max)) {
- $this->addError("Please enter a value in the range {$min} to {$max}");
- }
- }
- }
-
-
- abstract public function display();
-
- public function getLabel()
- {
- return $this->getMetadata('@text', 'label', ucfirst($this->property));
- }
-
-
- public function isRequired()
- {
- return count(Annotations::ofProperty($this->object, $this->property, '@required')) > 0;
- }
- }
- class StringWidget extends Widget
- {
-
-
- public function update($input)
- {
- $this->value = $input;
- $this->validate();
- }
-
-
- public function display()
- {
- $length = $this->getMetadata('@length', 'max', 255);
- echo '<input type="text" name="' . get_class($this->object) . '[' . $this->property . ']"'
- . ' maxlength="' . $length . '" value="' . htmlspecialchars($this->value) . '"/>';
- }
- }
- class IntWidget extends StringWidget
- {
-
-
- public function update($input)
- {
- if (strval(intval($input)) === $input) {
- $this->value = intval($input);
- $this->validate();
- } else {
- $this->value = $input;
- if (!empty($input)) {
- $this->addError("Please enter a whole number value");
- }
- }
- }
- }
- class Form
- {
- private $object;
-
- private $widgets = array();
-
-
-
-
- public function __construct($object)
- {
- $this->object = $object;
- $class = new \ReflectionClass($this->object);
- foreach ($class->getProperties() as $property) {
- $type = $this->getMetadata($property->name, '@var', 'type', 'string');
- $wtype = 'mindplay\\demo\\' . ucfirst($type) . 'Widget';
- $this->widgets[$property->name] = new $wtype($this->object, $property->name);
- }
- }
-
-
- private function getMetadata($property, $type, $name, $default = null)
- {
- $a = Annotations::ofProperty(get_class($this->object), $property, $type);
- if (!count($a)) {
- return $default;
- }
- return $a[0]->$name;
- }
-
-
-
- public function update($post)
- {
- $data = $post[get_class($this->object)];
- foreach ($this->widgets as $property => $widget) {
- if (array_key_exists($property, $data)) {
- $this->widgets[$property]->update($data[$property]);
- }
- }
- $valid = true;
- foreach ($this->widgets as $widget) {
- $valid = $valid && (count($widget->errors) === 0);
- }
- if ($valid) {
- foreach ($this->widgets as $property => $widget) {
- $this->object->$property = $widget->value;
- }
- }
- return $valid;
- }
-
-
- public function display()
- {
- foreach ($this->widgets as $widget) {
- $star = $widget->isRequired() ? ' <span style="color:red">*</span>' : '';
- echo '<label>' . htmlspecialchars($widget->getLabel()) . $star . '<br/>';
- $widget->display();
- echo '</label><br/>';
- if (count($widget->errors)) {
- echo '<ul>';
- foreach ($widget->errors as $error) {
- echo '<li>' . htmlspecialchars($error) . '</li>';
- }
- echo '</ul>';
- }
- }
- }
- }
- echo <<<HTML
- <html>
- <head>
- <title>Metaprogramming With Annotations!</title>
- </head>
- <body>
- <h1>Edit a Person!</h1>
- <h4>Declarative Metaprogramming in action!</h4>
- <form method="post">
- HTML;
- $person = new Person;
- $form = new Form($person);
- if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- if ($form->update($_POST)) {
- echo '<h2 style="color:green">Person Accepted!</h2>';
- } else {
- echo '<h2 style="color:red">Oops! Try again.</h2>';
- }
- }
- $form->display();
- echo <<<HTML
- <br/>
- <input type="submit" value="Go!"/>
- </form>
- HTML;
- echo "<pre>\n\nHere's what your Person instance currently looks like:\n\n";
- var_dump($person);
- echo '</pre>';
- echo <<<HTML
- </body>
- </html>
- HTML;
|