浏览代码

Handle 增加注解功能

xaboy 6 年之前
父节点
当前提交
e9dfd8a46f

+ 2 - 1
composer.json

@@ -29,7 +29,8 @@
   "require": {
   "require": {
     "php": ">=5.4.0",
     "php": ">=5.4.0",
     "ext-json": "*",
     "ext-json": "*",
-    "symfony/http-foundation": "~2.6|~2.7|~2.8|~3.0|~4.0"
+    "symfony/http-foundation": "~2.6|~2.7|~2.8|~3.0|~4.0",
+    "doctrine/annotations": "1.2.7"
   },
   },
   "minimum-stability": "stable"
   "minimum-stability": "stable"
 }
 }

+ 62 - 20
demo/elm.php

@@ -5,6 +5,12 @@ namespace App;
 
 
 require '../vendor/autoload.php';
 require '../vendor/autoload.php';
 
 
+use FormBuilder\Annotation\Col;
+use FormBuilder\Annotation\Emit;
+use FormBuilder\Annotation\Group;
+use FormBuilder\Annotation\Validate\Required;
+use FormBuilder\Annotation\Validate\Min;
+use FormBuilder\Annotation\Validate\Range;
 use FormBuilder\Factory\Elm;
 use FormBuilder\Factory\Elm;
 use FormBuilder\Handle\ElmFormHandle;
 use FormBuilder\Handle\ElmFormHandle;
 use FormBuilder\UI\Elm\Components\Rate;
 use FormBuilder\UI\Elm\Components\Rate;
@@ -24,57 +30,93 @@ class GoodsForm extends ElmFormHandle
 
 
     protected function getScene()
     protected function getScene()
     {
     {
-        $this->except = ['goods_name'];
+//        $this->except = ['goods_name'];
     }
     }
 
 
+    /**
+     * @Col(6)
+     * @return \FormBuilder\UI\Elm\Components\Input
+     */
     public function goods_name_field()
     public function goods_name_field()
     {
     {
         return Elm::input('goods_name', '商品名称')->required();
         return Elm::input('goods_name', '商品名称')->required();
     }
     }
 
 
+    /**
+     * @Required()
+     * @Group()
+     * @Col(8)
+     * @Range({10,1000},message = "最少输入10个字")
+     * @return \FormBuilder\UI\Elm\Components\Input
+     */
     public function goods_info_field()
     public function goods_info_field()
     {
     {
         return Elm::textarea('goods_info', '商品简介');
         return Elm::textarea('goods_info', '商品简介');
     }
     }
 
 
+    /**
+     * @Group()
+     * @Col(8)
+     * @Emit({"change","click"})
+     * @return \FormBuilder\UI\Elm\Components\Switches
+     */
     public function is_open_field()
     public function is_open_field()
     {
     {
         return Elm::switches('is_open', '是否开启');
         return Elm::switches('is_open', '是否开启');
     }
     }
 
 
-    public function id_field()
-    {
-        return Elm::hidden('1', '1');
-    }
-
+    /**
+     * @Group(2)
+     * @Col(12)
+     * @return \FormBuilder\UI\Elm\Components\Frame
+     */
     public function frame_field()
     public function frame_field()
     {
     {
         return Elm::frameFile('as', 'asd', 'afsdfasdf');
         return Elm::frameFile('as', 'asd', 'afsdfasdf');
     }
     }
 
 
+    /**
+     * @Group(2)
+     * @Col(12)
+     * @return \FormBuilder\UI\Elm\Components\Upload
+     */
     public function test_field()
     public function test_field()
     {
     {
         return Elm::uploadFiles('aaa', 'aaa', 'bbb', [1])->required();
         return Elm::uploadFiles('aaa', 'aaa', 'bbb', [1])->required();
     }
     }
 
 
+    /**
+     * @return \FormBuilder\UI\Elm\Components\Hidden
+     */
+    public function id_field()
+    {
+        return Elm::hidden('1', '1');
+    }
+
+    /**
+     * @Required("请输入 testRow")
+     * @return array
+     */
     public function row_field()
     public function row_field()
     {
     {
+//        return [
+//            'type' => 'row',
+//            'children' =>
+//                [
         return [
         return [
-            'type' => 'row',
-            'children' => [
-                [
-                    'type' => 'input',
-                    'field' => 'row',
-                    'title' => 'test Row',
-                    'value' => '123',
-                    'col' => [
-                        'span' => 12
-                    ]
-                ],
-                Elm::input('row2', 'row2', 'asdf')->col(12)
-            ],
-            'native' => true
+            'type' => 'input',
+            'field' => 'row',
+            'title' => 'test Row',
+            'value' => '123',
+            'col' => [
+                'span' => 12
+            ]
         ];
         ];
+//        ,
+//                Elm::input('row2', 'row2', 'asdf')->col(12)
+//            ],
+//            'native' => true
+//        ];
     }
     }
 
 
     /**
     /**

+ 17 - 1
demo/iview.php

@@ -5,6 +5,8 @@ namespace App;
 
 
 require '../vendor/autoload.php';
 require '../vendor/autoload.php';
 
 
+use FormBuilder\Annotation\Col;
+use FormBuilder\Annotation\Group;
 use  FormBuilder\Factory\Iview;
 use  FormBuilder\Factory\Iview;
 use FormBuilder\Handle\ElmFormHandle;
 use FormBuilder\Handle\ElmFormHandle;
 use FormBuilder\Handle\IviewFormHandle;
 use FormBuilder\Handle\IviewFormHandle;
@@ -27,19 +29,33 @@ class GoodsForm extends IviewFormHandle
 
 
     protected function getScene()
     protected function getScene()
     {
     {
-        $this->except = ['goods_name'];
+//        $this->except = ['goods_name'];
     }
     }
 
 
+    /**
+     * @Col(12)
+     * @return \FormBuilder\UI\Iview\Components\Input
+     */
     public function goods_name_field()
     public function goods_name_field()
     {
     {
         return Iview::input('goods_name', '商品名称')->required();
         return Iview::input('goods_name', '商品名称')->required();
     }
     }
 
 
+    /**
+     * @Group(className="test")
+     * @Col(12)
+     * @return \FormBuilder\UI\Iview\Components\Input
+     */
     public function goods_info_field()
     public function goods_info_field()
     {
     {
         return Iview::textarea('goods_info', '商品简介');
         return Iview::textarea('goods_info', '商品简介');
     }
     }
 
 
+    /**
+     * @Group()
+     * @Col(12)
+     * @return \FormBuilder\UI\Iview\Components\Switches
+     */
     public function is_open_field()
     public function is_open_field()
     {
     {
         return Iview::switches('is_open', '是否开启');
         return Iview::switches('is_open', '是否开启');

+ 76 - 0
src/Annotation/AnnotationReader.php

@@ -0,0 +1,76 @@
+<?php
+
+
+namespace FormBuilder\Annotation;
+
+
+use Doctrine\Common\Annotations\AnnotationRegistry;
+use Doctrine\Common\Annotations\AnnotationReader as Render;
+use FormBuilder\Contract\AnnotationInterface;
+use FormBuilder\FormHandle;
+
+class AnnotationReader
+{
+    protected static $isInit = false;
+
+    protected $annotationReader;
+
+    protected $handle;
+
+    public function __construct(FormHandle $handle)
+    {
+        if (!self::$isInit) {
+            AnnotationRegistry::registerLoader('class_exists');
+            self::$isInit = true;
+        }
+
+        $this->annotationReader = new Render();
+        $this->handle = $handle;
+    }
+
+    public function getRender()
+    {
+        return $this->annotationReader;
+    }
+
+    /**
+     * @param $rules
+     * @return array
+     */
+    public function parse($rules)
+    {
+        $formRule = [];
+        $groupList = [];
+        foreach ($rules as $rule) {
+            $annotations = $this->annotationReader->getMethodAnnotations($rule['method']);
+            $value = $rule['value'];
+            $group = null;
+            foreach ($annotations as $annotation) {
+                if (!$annotation instanceof AnnotationInterface) continue;
+                if ($annotation instanceof Group) {
+                    $group = $annotation;
+                } else {
+                    $value = $rule['isArray'] ? $annotation->parseRule($value) : $annotation->parseComponent($value);
+                }
+            }
+
+            if (!is_null($group)) {
+                if (!isset($groupList[$group->id])) {
+                    $groupList[$group->id] = $group;
+                    $formRule[] = $group;
+                }
+                $groupList[$group->id]->appendChildren($value);
+            } else {
+                $formRule[] = $value;
+            }
+        }
+
+        foreach ($formRule as $k => $v) {
+            if ($v instanceof Group) {
+                $formRule[$k] = $v->parse($this->handle->ui());
+            }
+        }
+
+        return $formRule;
+    }
+}

+ 32 - 0
src/Annotation/ClassName.php

@@ -0,0 +1,32 @@
+<?php
+
+
+namespace FormBuilder\Annotation;
+
+use FormBuilder\Contract\AnnotationInterface;
+
+/**
+ * @Annotation
+ * Class RuleAnnotation
+ * @package FormBuilder
+ */
+final class ClassName implements AnnotationInterface
+{
+
+    /**
+     * @var string
+     */
+    public $className = '';
+
+    public function parseRule($rule)
+    {
+        $rule['className'] = $this->className;
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->className($this->className);
+        return $component;
+    }
+}

+ 38 - 0
src/Annotation/Col.php

@@ -0,0 +1,38 @@
+<?php
+
+
+namespace FormBuilder\Annotation;
+
+use FormBuilder\Contract\AnnotationInterface;
+
+/**
+ * @Annotation
+ * Class RuleAnnotation
+ * @package FormBuilder
+ */
+final class Col implements AnnotationInterface
+{
+    public $props = 24;
+
+    protected function getCol()
+    {
+        if (is_integer($this->props))
+            return ['span' => $this->props];
+        else
+            return $this->props;
+    }
+
+    public function parseRule($rule)
+    {
+        $rule['col'] = $this->getCol();
+
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->col($this->getCol());
+
+        return $component;
+    }
+}

+ 40 - 0
src/Annotation/Emit.php

@@ -0,0 +1,40 @@
+<?php
+
+
+namespace FormBuilder\Annotation;
+
+use FormBuilder\Contract\AnnotationInterface;
+
+/**
+ * @Annotation
+ * Class RuleAnnotation
+ * @package FormBuilder
+ */
+final class Emit implements AnnotationInterface
+{
+    /**
+     * @var array
+     */
+    public $emit = [];
+
+    /**
+     * @var string
+     */
+    public $prefix = '';
+
+
+    public function parseRule($rule)
+    {
+        $rule['emit'] = $this->emit;
+        if ($this->prefix)
+            $rule['emitPrefix'] = $this->prefix;
+
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->emit($this->emit)->emitPrefix($this->prefix);
+        return $component;
+    }
+}

+ 79 - 0
src/Annotation/Group.php

@@ -0,0 +1,79 @@
+<?php
+
+
+namespace FormBuilder\Annotation;
+
+use FormBuilder\Contract\AnnotationInterface;
+
+/**
+ * @Annotation
+ * Class Group
+ * @package FormBuilder\Annotation
+ */
+final class Group implements AnnotationInterface
+{
+    /**
+     * @var int
+     */
+    public $id = 1;
+
+    /**
+     * @var string
+     */
+    public $tag;
+
+    /**
+     * @var string
+     */
+    public $className = '';
+
+    public $span = 24;
+
+    protected $children = [];
+
+    public function parseRule($rule)
+    {
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        return $component;
+    }
+
+    public function appendChildren($rule)
+    {
+        $this->children[] = $rule;
+    }
+
+    /**
+     * @param string $UI
+     * @return array
+     */
+    public function parse($UI)
+    {
+        $col = 'i-col';
+        $row = 'row';
+        if ($UI == 'elm') {
+            $row = 'el-row';
+            $col = 'el-col';
+        }
+
+        return [
+            'type' => $col,
+            'props' => [
+                'span' => $this->span
+            ],
+            'children' => [
+                [
+                    'type' => is_null($this->tag) ? $row : $this->tag,
+                    'children' => $this->children,
+                    'attrs' => [
+                        'class' => $this->className
+                    ]
+                ]
+            ],
+            'native' => true
+        ];
+    }
+}

+ 31 - 0
src/Annotation/Validate/Enum.php

@@ -0,0 +1,31 @@
+<?php
+
+
+namespace FormBuilder\Annotation\Validate;
+
+
+/**
+ * @Annotation
+ */
+final class Enum extends ValidateAnnotation
+{
+    /**
+     * @Required
+     * @var array
+     */
+    public $value = [];
+
+
+    public function parseRule($rule)
+    {
+        $rule = $this->tidyValidate($rule);
+        $rule['validate'][] = ['enum' => $this->value, 'type' => $this->type, 'trigger' => $this->trigger, 'message' => $this->message];
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->appendValidate($component->createValidate()->enum($this->value)->message($this->message));
+        return $component;
+    }
+}

+ 30 - 0
src/Annotation/Validate/Len.php

@@ -0,0 +1,30 @@
+<?php
+
+
+namespace FormBuilder\Annotation\Validate;
+
+
+/**
+ * @Annotation
+ */
+final class Len extends ValidateAnnotation
+{
+    /**
+     * @Required
+     */
+    public $value;
+
+
+    public function parseRule($rule)
+    {
+        $rule = $this->tidyValidate($rule);
+        $rule['validate'][] = ['len' => $this->value, 'type' => $this->type, 'trigger' => $this->trigger, 'message' => $this->message];
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->appendValidate($component->createValidate()->len($this->value)->message($this->message));
+        return $component;
+    }
+}

+ 30 - 0
src/Annotation/Validate/Max.php

@@ -0,0 +1,30 @@
+<?php
+
+
+namespace FormBuilder\Annotation\Validate;
+
+
+/**
+ * @Annotation
+ */
+final class Max extends ValidateAnnotation
+{
+    /**
+     * @Required
+     */
+    public $value;
+
+
+    public function parseRule($rule)
+    {
+        $rule = $this->tidyValidate($rule);
+        $rule['validate'][] = ['max' => $this->value, 'type' => $this->type, 'trigger' => $this->trigger, 'message' => $this->message];
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->appendValidate($component->createValidate()->max($this->value)->message($this->message));
+        return $component;
+    }
+}

+ 30 - 0
src/Annotation/Validate/Min.php

@@ -0,0 +1,30 @@
+<?php
+
+
+namespace FormBuilder\Annotation\Validate;
+
+
+/**
+ * @Annotation
+ */
+final class Min extends ValidateAnnotation
+{
+    /**
+     * @Required
+     */
+    public $value;
+
+
+    public function parseRule($rule)
+    {
+        $rule = $this->tidyValidate($rule);
+        $rule['validate'][] = ['min' => $this->value, 'type' => $this->type, 'trigger' => $this->trigger, 'message' => $this->message];
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->appendValidate($component->createValidate()->min($this->value)->message($this->message));
+        return $component;
+    }
+}

+ 31 - 0
src/Annotation/Validate/Pattern.php

@@ -0,0 +1,31 @@
+<?php
+
+
+namespace FormBuilder\Annotation\Validate;
+
+
+/**
+ * @Annotation
+ */
+final class Pattern extends ValidateAnnotation
+{
+    /**
+     * @Required
+     * @var string
+     */
+    public $value = '';
+
+
+    public function parseRule($rule)
+    {
+        $rule = $this->tidyValidate($rule);
+        $rule['validate'][] = ['pattern' => $this->value, 'type' => $this->type, 'trigger' => $this->trigger, 'message' => $this->message];
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->appendValidate($component->createValidate()->pattern($this->value)->message($this->message));
+        return $component;
+    }
+}

+ 31 - 0
src/Annotation/Validate/Range.php

@@ -0,0 +1,31 @@
+<?php
+
+
+namespace FormBuilder\Annotation\Validate;
+
+
+/**
+ * @Annotation
+ */
+final class Range extends ValidateAnnotation
+{
+    /**
+     * @Required
+     * @var array
+     */
+    public $value = [];
+
+
+    public function parseRule($rule)
+    {
+        $rule = $this->tidyValidate($rule);
+        $rule['validate'][] = ['range' => $this->value, 'type' => $this->type, 'trigger' => $this->trigger, 'message' => $this->message];
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->appendValidate($component->createValidate()->range($this->value[0], $this->value[1])->message($this->message));
+        return $component;
+    }
+}

+ 29 - 0
src/Annotation/Validate/Required.php

@@ -0,0 +1,29 @@
+<?php
+
+
+namespace FormBuilder\Annotation\Validate;
+
+use FormBuilder\Contract\AnnotationInterface;
+
+/**
+ * @Annotation
+ * Class RuleAnnotation
+ * @package FormBuilder
+ */
+final class Required extends ValidateAnnotation
+{
+
+    public function parseRule($rule)
+    {
+        $rule = $this->tidyValidate($rule);
+        $rule['required'] = true;
+        $rule['validate'][] = ['required' => true, 'type' => $this->type, 'trigger' => $this->trigger, 'message' => $this->message];
+        return $rule;
+    }
+
+    public function parseComponent($component)
+    {
+        $component->required($this->message);
+        return $component;
+    }
+}

+ 35 - 0
src/Annotation/Validate/ValidateAnnotation.php

@@ -0,0 +1,35 @@
+<?php
+
+
+namespace FormBuilder\Annotation\Validate;
+
+
+use FormBuilder\Contract\AnnotationInterface;
+
+abstract class ValidateAnnotation implements AnnotationInterface
+{
+
+    /**
+     * @var string
+     */
+    public $message;
+
+    /**
+     * @var string
+     */
+    public $type = 'string';
+
+    /**
+     * @var string
+     */
+    public $trigger = 'change';
+
+
+    public function tidyValidate($rule)
+    {
+        if (!isset($rule['validate']) || !is_array($rule['validate'])) {
+            $rule['validate'] = [];
+        }
+        return $rule;
+    }
+}

+ 20 - 0
src/Contract/AnnotationInterface.php

@@ -0,0 +1,20 @@
+<?php
+
+
+namespace FormBuilder\Contract;
+
+
+interface AnnotationInterface
+{
+    /**
+     * @param array $rule
+     * @return array
+     */
+    public function parseRule($rule);
+
+    /**
+     * @param CustomComponentInterface $component
+     * @return CustomComponentInterface
+     */
+    public function parseComponent($component);
+}

+ 10 - 8
src/FormHandle.php

@@ -13,6 +13,7 @@
 namespace FormBuilder;
 namespace FormBuilder;
 
 
 
 
+use FormBuilder\Annotation\AnnotationReader;
 use FormBuilder\Contract\ConfigInterface;
 use FormBuilder\Contract\ConfigInterface;
 use FormBuilder\Contract\FormHandleInterface;
 use FormBuilder\Contract\FormHandleInterface;
 
 
@@ -45,7 +46,7 @@ abstract class FormHandle implements FormHandleInterface
      *
      *
      * @return mixed
      * @return mixed
      */
      */
-    abstract protected function ui();
+    abstract public function ui();
 
 
     /**
     /**
      * 获取表单数据
      * 获取表单数据
@@ -81,6 +82,7 @@ abstract class FormHandle implements FormHandleInterface
      * 获取表单组件
      * 获取表单组件
      *
      *
      * @return array
      * @return array
+     * @throws \ReflectionException
      */
      */
     protected function getFormRule()
     protected function getFormRule()
     {
     {
@@ -89,23 +91,23 @@ abstract class FormHandle implements FormHandleInterface
         $rule = [];
         $rule = [];
         foreach ($methods as $method) {
         foreach ($methods as $method) {
             $field = preg_replace('/^(.+)(Field|_field)$/', '$1', $method->name);
             $field = preg_replace('/^(.+)(Field|_field)$/', '$1', $method->name);
+            $value = null;
             if ($field != $method->name && !in_array($field, $this->except)) {
             if ($field != $method->name && !in_array($field, $this->except)) {
                 $params = $method->getParameters();
                 $params = $method->getParameters();
-                $flag = true;
                 if (isset($params[0]) && ($dep = $params[0]->getClass())) {
                 if (isset($params[0]) && ($dep = $params[0]->getClass())) {
                     if (in_array('FormBuilder\\Contract\\FormComponentInterface', $dep->getInterfaceNames())) {
                     if (in_array('FormBuilder\\Contract\\FormComponentInterface', $dep->getInterfaceNames())) {
                         $componentClass = $dep->getName();
                         $componentClass = $dep->getName();
                         $value = $method->invokeArgs($this, [new $componentClass($field, $this->getFieldTitle($field))]);
                         $value = $method->invokeArgs($this, [new $componentClass($field, $this->getFieldTitle($field))]);
-                        $flag = false;
                     }
                     }
                 }
                 }
-                if ($flag) $value = $method->invoke($this);
-                if (is_array($value) || Util::isComponent($value))
-                    $rule[] = $value;
+                if (is_null($value)) $value = $method->invoke($this);
+                if (!is_null($value) && (($isArray = is_array($value)) || Util::isComponent($value))) {
+                    $rule[] = compact('value', 'method', 'isArray');
+                }
             }
             }
         }
         }
-
-        return $rule;
+        $render = new AnnotationReader($this);
+        return $render->parse($rule);
     }
     }
 
 
     /**
     /**

+ 1 - 1
src/Handle/ElmFormHandle.php

@@ -23,7 +23,7 @@ use FormBuilder\FormHandle;
 abstract class ElmFormHandle extends FormHandle
 abstract class ElmFormHandle extends FormHandle
 {
 {
 
 
-    protected function ui()
+    public function ui()
     {
     {
         return 'elm';
         return 'elm';
     }
     }

+ 1 - 1
src/Handle/IviewFormHandle.php

@@ -26,7 +26,7 @@ abstract class IviewFormHandle extends FormHandle
 
 
     protected $version = 3;
     protected $version = 3;
 
 
-    protected function ui()
+    public function ui()
     {
     {
         return $this->version == 4 ? 'iview4' : 'iview';
         return $this->version == 4 ? 'iview4' : 'iview';
     }
     }