extractFormatAndParams()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 17
ccs 11
cts 11
cp 1
rs 9.2
cc 4
eloc 10
nc 3
nop 2
crap 4
1
<?php
2
3
namespace Benrowe\Formatter;
4
5
use InvalidArgumentException;
6
use ReflectionClass;
7
use ReflectionMethod;
8
9
/**
10
 * AbstractFormatterProvider
11
 *
12
 * Base level functionality for any FormatterProvider that wants to implement
13
 * the standard formatting convention of `public function asFormatType($value)`
14
 *
15
 * @package Benrowe\Formatter
16
 */
17
abstract class AbstractFormatterProvider implements FormatterProvider
18
{
19
    protected $defaultFormatter;
20
    /**
21
     * method prefix
22
     */
23
    const METHOD_PATTERN_MATCH = '/^as([A-Z]\w+)$/';
24
25
    public $nullValue = '<span>Not Set</span>';
26
27
    /**
28
     * Provide a list of formatters this that are available from this provider
29
     *
30
     * @return array
31
     */
32 7
    public function formats()
33
    {
34
        // get a list of all public non-static methods that start with
35
        // METHOD_PREFIX
36 7
        $reflect = new ReflectionClass($this);
37 7
        $formats = [];
38 7
        foreach ($reflect->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
39 7
            $name = $this->getFormatterName($method);
40 7
            if ($name) {
41 7
                $formats[] = $name;
42 7
            }
43 7
        }
44
45 7
        return $formats;
46
    }
47
48
    /**
49
     * Get the name of the formatter method
50
     *
51
     * @param ReflectionMethod $method
52
     * @return string
53
     */
54 7
    private function getFormatterName(ReflectionMethod $method)
55
    {
56 7
        preg_match(self::METHOD_PATTERN_MATCH, $method->getName(), $match);
57 7
        $isFormatter = !$method->isStatic() && !empty($match);
58
59 7
        return $isFormatter ? strtolower($match[1]) : '';
60
    }
61
62
    /**
63
     * Combine the value & params
64
     * @param  mixed $value  the value (first argument of the format method)
65
     * @param  string|array $format the name of the formatter, or an array of
66
     *                              the formatter and its addtional params
67
     * @return array of two elements, format and the params for the formatter
68
     *                  method
69
     * @throws InvalidArgumentException if the format is incorrect
70
     */
71 9
    protected function extractFormatAndParams($value, $format)
72
    {
73 9
        $params = [$value];
74
75 9
        if (is_array($format)) {
76 4
            if (!isset($format[0]) || trim($format[0]) == '') {
77 1
                throw new InvalidArgumentException(
78
                    'The $format must contain at least one element'
79 1
                );
80
            }
81 3
            $params = $format;
82 3
            $format = array_shift($params);
83 3
            array_unshift($params, $value);
84 3
        }
85
86 8
        return [$format, $params];
87
    }
88
89
    /**
90
     * Format the supplied value, based on the desired format + configuration
91
     *
92
     * @param  mixed $value The value to format
93
     * @param  string|array|null $format either the formatter name, or the formatter
94
     *                              config as an array. If it's an array, the
95
     *                              first item must be the same of the formatter
96
     * @return mixed
97
     * @throws InvalidArgumentException if the format is incorrect
98
     */
99 4
    public function format($value, $format = null)
100
    {
101 4
        $format = $format ?: $this->defaultFormatter;
102
103 4
        list($format, $params) = $this->extractFormatAndParams($value, $format);
104
105 3
        if (!$this->hasFormat($format)) {
106 1
            throw new InvalidArgumentException(
107 1
                'Unknown format: "' . $format . '"'
108 1
            );
109
        }
110
111
        // is the formatter in a custom defined
112
113 2
        $func = [$this, 'as'.$format];
114
115 2
        return call_user_func_array($func, $params);
116
    }
117
118
    /**
119
     * Check if the requested format exists in this provider
120
     *
121
     * @param  string  $format The formatter name you want to check for
122
     * @return boolean
123
     */
124 6
    public function hasFormat($format)
125
    {
126 6
        if (!preg_match("/^[A-Za-z_]+$/", $format)) {
127 2
            throw new InvalidArgumentException(
128 2
                'Format "' . $format . '" is not provided in correct format'
129 2
            );
130
        }
131 4
        $formats = $this->formats();
132
133 4
        return in_array($format, $formats);
134
    }
135
}
136