Completed
Branch BUG/double-ampersand-in-regist... (7dce02)
by
unknown
131:59 queued 62:17
created

CalculatedModelFields::generateNewMapping()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\libraries\rest_api;
4
5
use EEM_Base;
6
use EventEspresso\core\exceptions\UnexpectedEntityException;
7
use EventEspresso\core\libraries\rest_api\calculations\CalculatedModelFieldsFactory;
8
use EventEspresso\core\libraries\rest_api\controllers\Base;
9
use EEH_Inflector;
10
use EventEspresso\core\libraries\rest_api\controllers\Base as BaseController;
11
12
/**
13
 * Class CalculatedModelFields
14
 * Class for defining which model fields can be calculated, and performing those calculations
15
 * as requested
16
 *
17
 * @package               Event Espresso
18
 * @subpackage
19
 * @author                Mike Nelson
20
 * @since                 4.8.35.rc.001
21
 */
22
class CalculatedModelFields
23
{
24
25
    /**
26
     * @var array
27
     */
28
    protected $mapping;
29
30
    /**
31
     * @var array
32
     */
33
    protected $mapping_schema;
34
35
    /**
36
     * @var CalculatedModelFieldsFactory
37
     */
38
    private $factory;
39
40
    /**
41
     * CalculatedModelFields constructor.
42
     * @param CalculatedModelFieldsFactory $factory
43
     */
44
    public function __construct(CalculatedModelFieldsFactory $factory)
45
    {
46
        $this->factory = $factory;
47
    }
48
    /**
49
     * @param bool $refresh
50
     * @return array top-level-keys are model names (eg "Event")
51
     * next-level are the calculated field names AND method names on classes
52
     * which perform calculations, values are the fully qualified classnames which do the calculations
53
     * These callbacks should accept as arguments:
54
     * the wpdb row results,
55
     * the WP_Request object,
56
     * the controller object
57
     */
58
    public function mapping($refresh = false)
59
    {
60
        if (! $this->mapping || $refresh) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->mapping of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
61
            $this->mapping = $this->generateNewMapping();
62
        }
63
        return $this->mapping;
64
    }
65
66
67
    /**
68
     * Generates a new mapping between model calculated fields and their callbacks
69
     *
70
     * @return array
71
     */
72
    protected function generateNewMapping()
73
    {
74
        $mapping = array();
75
        $models_with_calculated_fields = array(
76
            'Attendee',
77
            'Datetime',
78
            'Event',
79
            'Registration'
80
        );
81
        foreach ($models_with_calculated_fields as $model_name) {
82
            $calculator = $this->factory->createFromModel($model_name);
83
            foreach (array_keys(call_user_func(array($calculator, 'schemaForCalculations'))) as $field_name) {
84
                $mapping[ $model_name ][ $field_name ] = get_class($calculator);
85
            }
86
        }
87
        return apply_filters(
88
            'FHEE__EventEspresso\core\libraries\rest_api\Calculated_Model_Fields__mapping',
89
            $mapping
90
        );
91
    }
92
93
94
    /**
95
     * Generates the schema for each calculation index in the calculation map.
96
     *
97
     * @return array
98
     * @throws UnexpectedEntityException
99
     */
100
    protected function generateNewMappingSchema()
101
    {
102
        $schema_map = array();
103
        foreach ($this->mapping() as $map_model => $map_for_model) {
104
            /**
105
             * @var string $calculation_index
106
             * @var string $calculations_class
107
             */
108
            foreach ($map_for_model as $calculation_index => $calculations_class) {
109
                $calculator = $this->factory->createFromClassname($calculations_class);
110
                $schema = call_user_func(array($calculator, 'schemaForCalculation'), $calculation_index);
111
                if (! empty($schema)) {
112
                    $schema_map[ $map_model ][ $calculation_index ] = $schema;
113
                }
114
            }
115
        }
116
        return $schema_map;
117
    }
118
119
120
    /**
121
     * Gets the known calculated fields for model
122
     *
123
     * @param EEM_Base $model
124
     * @return array allowable values for this field
125
     */
126
    public function retrieveCalculatedFieldsForModel(EEM_Base $model)
127
    {
128
        $mapping = $this->mapping();
129
        if (isset($mapping[ $model->get_this_model_name() ])) {
130
            return array_keys($mapping[ $model->get_this_model_name() ]);
131
        }
132
        return array();
133
    }
134
135
136
    /**
137
     * Returns the JsonSchema for the calculated fields on the given model.
138
     * @param EEM_Base $model
139
     * @return array
140
     */
141
    public function getJsonSchemaForModel(EEM_Base $model)
142
    {
143
        if (! $this->mapping_schema) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->mapping_schema of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
144
            $this->mapping_schema = $this->generateNewMappingSchema();
145
        }
146
        return array(
147
            'description' => esc_html__(
148
                'Available calculated fields for this model.  Fields are only present in the response if explicitly requested',
149
                'event_espresso'
150
            ),
151
            'type' => 'object',
152
            'properties' => isset($this->mapping_schema[ $model->get_this_model_name() ])
153
                ? $this->mapping_schema[ $model->get_this_model_name() ]
154
                : array(),
155
            'additionalProperties' => false,
156
            'readonly' => true,
157
        );
158
    }
159
160
161
    /**
162
     * Retrieves the value for this calculation
163
     *
164
     * @param EEM_Base $model
165
     * @param string $field_name
166
     * @param array $wpdb_row
167
     * @param $rest_request
168
     * @param BaseController $controller
169
     * @return mixed|null
170
     * @throws RestException
171
     * @throws UnexpectedEntityException
172
     */
173
    public function retrieveCalculatedFieldValue(
174
        EEM_Base $model,
175
        $field_name,
176
        $wpdb_row,
177
        $rest_request,
178
        Base $controller
179
    ) {
180
        $mapping = $this->mapping();
181
        if (isset($mapping[ $model->get_this_model_name() ])
182
            && isset($mapping[ $model->get_this_model_name() ][ $field_name ])
183
        ) {
184
            $classname = $mapping[ $model->get_this_model_name() ][ $field_name ];
185
            $calculator = $this->factory->createFromClassname($classname);
186
            $class_method_name = EEH_Inflector::camelize_all_but_first($field_name);
187
            return call_user_func(array($calculator, $class_method_name), $wpdb_row, $rest_request, $controller);
188
        }
189
        throw new RestException(
190
            'calculated_field_does_not_exist',
191
            sprintf(
192
                __('There is no calculated field %1$s on resource %2$s', 'event_espresso'),
193
                $field_name,
194
                $model->get_this_model_name()
195
            )
196
        );
197
    }
198
}
199