Completed
Pull Request — master (#6927)
by Damian
11:37 queued 03:26
created

FormTransformation::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Forms;
4
5
use BadMethodCallException;
6
use SilverStripe\Core\ClassInfo;
7
use SilverStripe\Core\Config\Configurable;
8
use SilverStripe\Core\Extensible;
9
use SilverStripe\Core\Injector\Injectable;
10
11
/**
12
 * This class represents "transformations" of a form - such as making it printable or making it readonly.
13
 * The idea is that sometimes you will want to make your own such transformations, and you shouldn't have
14
 * to edit the underlying code to support this.
15
 *
16
 * The first step in creating a transformation is subclassing FormTransformation.  After that, you have two
17
 * ways of defining specific functionality:
18
 *   - Define performMyTransformation() methods on each applicable FormField() object.
19
 *   - Define transformFieldType($field) methods on your subclass of FormTransformation.
20
 *
21
 * To actually perform the transformation, call $form->transform(new MyTransformation());
22
 */
23
class FormTransformation
24
{
25
    use Configurable;
26
    use Injectable;
27
    use Extensible;
28
29
    public function __construct()
30
    {
31
        $this->constructExtensions();
32
    }
33
34
    public function transform(FormField $field)
35
    {
36
        // Look for a performXXTransformation() method on the field itself.
37
        // performReadonlyTransformation() is a pretty commonly applied method.
38
        // Otherwise, look for a transformXXXField() method on this object.
39
        // This is more commonly done in custom transformations
40
41
        // We iterate through each array simultaneously, looking at [0] of both, then [1] of both.
42
        // This provides a more natural failover scheme.
43
44
        $transNames = array_reverse(array_map(
45
            function ($name) {
46
                return ClassInfo::shortName($name);
47
            },
48
            array_values(ClassInfo::ancestry($this))
49
        ));
50
        $fieldClasses = array_reverse(array_map(
51
            function ($name) {
52
                return ClassInfo::shortName($name);
53
            },
54
            array_values(ClassInfo::ancestry($field))
55
        ));
56
57
        $len = max(sizeof($transNames), sizeof($fieldClasses));
58
        for ($i=0; $i<$len; $i++) {
59
            // This is lets fieldClasses be longer than transNames
60
            if (!empty($transNames[$i])) {
61
                $funcName = 'perform' . $transNames[$i];
62
                if ($field->hasMethod($funcName)) {
63
                    //echo "<li>$field->class used $funcName";
64
                    return $field->$funcName($this);
65
                }
66
            }
67
68
            // And this one does the reverse.
69
            if (!empty($fieldClasses[$i])) {
70
                $funcName = 'transform' . $fieldClasses[$i];
71
                if ($this->hasMethod($funcName)) {
72
                    //echo "<li>$field->class used $funcName";
73
                    return $this->$funcName($field);
74
                }
75
            }
76
        }
77
78
        $class = static::class;
79
        $fieldClass = get_class($field);
80
        throw new BadMethodCallException("FormTransformation:: Can't perform '{$class}' on '{$fieldClass}'");
81
    }
82
}
83