1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Benrowe\Formatter; |
4
|
|
|
|
5
|
|
|
use ReflectionClass; |
6
|
|
|
use ReflectionMethod; |
7
|
|
|
use InvalidArgumentException; |
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
|
|
|
public function formats() |
33
|
|
|
{ |
34
|
|
|
// get a list of all public non-static methods that start with |
35
|
|
|
// METHOD_PREFIX |
36
|
|
|
$reflect = new ReflectionClass($this); |
37
|
|
|
$formats = []; |
38
|
|
|
foreach ($reflect->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { |
39
|
|
|
$name = $this->getFormatterName($method); |
40
|
|
|
if ($name) { |
41
|
|
|
$formats[] = $name; |
42
|
|
|
} |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
return $formats; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Get the name of the formatter method |
50
|
|
|
* |
51
|
|
|
* @param ReflectionMethod $method |
52
|
|
|
* @return string |
53
|
|
|
*/ |
54
|
|
|
private function getFormatterName(ReflectionMethod $method) |
55
|
|
|
{ |
56
|
|
|
preg_match(self::METHOD_PATTERN_MATCH, $method->getName(), $match); |
57
|
|
|
$isFormatter = !$method->isStatic() && $match; |
|
|
|
|
58
|
|
|
|
59
|
|
|
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
|
|
|
protected function extractFormatAndParams($value, $format) |
72
|
|
|
{ |
73
|
|
|
$params = [$value]; |
74
|
|
|
|
75
|
|
|
if (is_array($format)) { |
76
|
|
|
if (!isset($format[0])) { |
77
|
|
|
throw new InvalidArgumentException( |
78
|
|
|
'The $format must contain at least one element' |
79
|
|
|
); |
80
|
|
|
} |
81
|
|
|
$params = $format; |
82
|
|
|
$format = array_shift($params); |
83
|
|
|
array_unshift($params, $value); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
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
|
|
|
public function format($value, $format = null) |
100
|
|
|
{ |
101
|
|
|
$format = $format ?: $this->defaultFormatter; |
102
|
|
|
|
103
|
|
|
list($format, $params) = $this->extractFormatAndParams($value, $format); |
104
|
|
|
|
105
|
|
|
if (!$this->hasFormat($format)) { |
106
|
|
|
throw new InvalidArgumentException( |
107
|
|
|
'Unknown format: "' . $format . '"' |
108
|
|
|
); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
// is the formatter in a custom defined |
112
|
|
|
|
113
|
|
|
$func = [$this, 'as'.$format]; |
114
|
|
|
|
115
|
|
|
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
|
|
|
public function hasFormat($format) |
125
|
|
|
{ |
126
|
|
|
if (!preg_match("/^[A-Za-z]+$/", $format)) { |
127
|
|
|
throw new InvalidArgumentException( |
128
|
|
|
'Format "' . $format . '" is not provided in correct format' |
129
|
|
|
); |
130
|
|
|
} |
131
|
|
|
$formats = $this->formats(); |
132
|
|
|
|
133
|
|
|
return in_array($format, $formats); |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.