@@ -50,7 +50,7 @@ discard block |
||
50 | 50 | */ |
51 | 51 | public function getModelVersionInfo() |
52 | 52 | { |
53 | - if (! $this->model_version_info) { |
|
53 | + if ( ! $this->model_version_info) { |
|
54 | 54 | throw new EE_Error( |
55 | 55 | sprintf( |
56 | 56 | esc_html__( |
@@ -95,7 +95,7 @@ discard block |
||
95 | 95 | */ |
96 | 96 | protected function validateModel($model_name) |
97 | 97 | { |
98 | - if (! $this->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
98 | + if ( ! $this->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
99 | 99 | throw new RestException( |
100 | 100 | 'endpoint_parsing_error', |
101 | 101 | sprintf( |
@@ -18,95 +18,95 @@ |
||
18 | 18 | */ |
19 | 19 | class Base extends Controller_Base |
20 | 20 | { |
21 | - /** |
|
22 | - * Holds reference to the model version info, which knows the requested version |
|
23 | - * |
|
24 | - * @var ModelVersionInfo |
|
25 | - */ |
|
26 | - protected $model_version_info; |
|
21 | + /** |
|
22 | + * Holds reference to the model version info, which knows the requested version |
|
23 | + * |
|
24 | + * @var ModelVersionInfo |
|
25 | + */ |
|
26 | + protected $model_version_info; |
|
27 | 27 | |
28 | 28 | |
29 | 29 | |
30 | - /** |
|
31 | - * Sets the version the user requested |
|
32 | - * |
|
33 | - * @param string $version eg '4.8' |
|
34 | - */ |
|
35 | - public function setRequestedVersion($version) |
|
36 | - { |
|
37 | - parent::setRequestedVersion($version); |
|
38 | - $this->model_version_info = new ModelVersionInfo($version); |
|
39 | - } |
|
30 | + /** |
|
31 | + * Sets the version the user requested |
|
32 | + * |
|
33 | + * @param string $version eg '4.8' |
|
34 | + */ |
|
35 | + public function setRequestedVersion($version) |
|
36 | + { |
|
37 | + parent::setRequestedVersion($version); |
|
38 | + $this->model_version_info = new ModelVersionInfo($version); |
|
39 | + } |
|
40 | 40 | |
41 | 41 | |
42 | 42 | |
43 | - /** |
|
44 | - * Gets the object that should be used for getting any info from the models, |
|
45 | - * because it's takes the requested and current core version into account |
|
46 | - * |
|
47 | - * @return \EventEspresso\core\libraries\rest_api\ModelVersionInfo |
|
48 | - * @throws EE_Error |
|
49 | - */ |
|
50 | - public function getModelVersionInfo() |
|
51 | - { |
|
52 | - if (! $this->model_version_info) { |
|
53 | - throw new EE_Error( |
|
54 | - sprintf( |
|
55 | - esc_html__( |
|
56 | - 'Cannot use model version info before setting the requested version in the controller', |
|
57 | - 'event_espresso' |
|
58 | - ) |
|
59 | - ) |
|
60 | - ); |
|
61 | - } |
|
62 | - return $this->model_version_info; |
|
63 | - } |
|
43 | + /** |
|
44 | + * Gets the object that should be used for getting any info from the models, |
|
45 | + * because it's takes the requested and current core version into account |
|
46 | + * |
|
47 | + * @return \EventEspresso\core\libraries\rest_api\ModelVersionInfo |
|
48 | + * @throws EE_Error |
|
49 | + */ |
|
50 | + public function getModelVersionInfo() |
|
51 | + { |
|
52 | + if (! $this->model_version_info) { |
|
53 | + throw new EE_Error( |
|
54 | + sprintf( |
|
55 | + esc_html__( |
|
56 | + 'Cannot use model version info before setting the requested version in the controller', |
|
57 | + 'event_espresso' |
|
58 | + ) |
|
59 | + ) |
|
60 | + ); |
|
61 | + } |
|
62 | + return $this->model_version_info; |
|
63 | + } |
|
64 | 64 | |
65 | 65 | |
66 | 66 | |
67 | - /** |
|
68 | - * Determines if $object is of one of the classes of $classes. Similar to |
|
69 | - * in_array(), except this checks if $object is a subclass of the classnames provided |
|
70 | - * in $classnames |
|
71 | - * |
|
72 | - * @param object $object |
|
73 | - * @param array $classnames |
|
74 | - * @return boolean |
|
75 | - */ |
|
76 | - public function isSubclassOfOne($object, $classnames) |
|
77 | - { |
|
78 | - foreach ($classnames as $classname) { |
|
79 | - if (is_a($object, $classname)) { |
|
80 | - return true; |
|
81 | - } |
|
82 | - } |
|
83 | - return false; |
|
84 | - } |
|
67 | + /** |
|
68 | + * Determines if $object is of one of the classes of $classes. Similar to |
|
69 | + * in_array(), except this checks if $object is a subclass of the classnames provided |
|
70 | + * in $classnames |
|
71 | + * |
|
72 | + * @param object $object |
|
73 | + * @param array $classnames |
|
74 | + * @return boolean |
|
75 | + */ |
|
76 | + public function isSubclassOfOne($object, $classnames) |
|
77 | + { |
|
78 | + foreach ($classnames as $classname) { |
|
79 | + if (is_a($object, $classname)) { |
|
80 | + return true; |
|
81 | + } |
|
82 | + } |
|
83 | + return false; |
|
84 | + } |
|
85 | 85 | |
86 | - /** |
|
87 | - * Verifies the model name provided was valid. If so, returns the model (as an object). Otherwise, throws an |
|
88 | - * exception. Must be called after `setRequestedVersion()`. |
|
89 | - * @since 4.9.76.p |
|
90 | - * @param $model_name |
|
91 | - * @return EEM_Base |
|
92 | - * @throws EE_Error |
|
93 | - * @throws RestException |
|
94 | - */ |
|
95 | - protected function validateModel($model_name) |
|
96 | - { |
|
97 | - if (! $this->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
98 | - throw new RestException( |
|
99 | - 'endpoint_parsing_error', |
|
100 | - sprintf( |
|
101 | - esc_html__( |
|
102 | - 'There is no model for endpoint %s. Please contact event espresso support', |
|
103 | - 'event_espresso' |
|
104 | - ), |
|
105 | - $model_name |
|
106 | - ) |
|
107 | - ); |
|
108 | - } |
|
109 | - return $this->getModelVersionInfo()->loadModel($model_name); |
|
110 | - } |
|
86 | + /** |
|
87 | + * Verifies the model name provided was valid. If so, returns the model (as an object). Otherwise, throws an |
|
88 | + * exception. Must be called after `setRequestedVersion()`. |
|
89 | + * @since 4.9.76.p |
|
90 | + * @param $model_name |
|
91 | + * @return EEM_Base |
|
92 | + * @throws EE_Error |
|
93 | + * @throws RestException |
|
94 | + */ |
|
95 | + protected function validateModel($model_name) |
|
96 | + { |
|
97 | + if (! $this->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
98 | + throw new RestException( |
|
99 | + 'endpoint_parsing_error', |
|
100 | + sprintf( |
|
101 | + esc_html__( |
|
102 | + 'There is no model for endpoint %s. Please contact event espresso support', |
|
103 | + 'event_espresso' |
|
104 | + ), |
|
105 | + $model_name |
|
106 | + ) |
|
107 | + ); |
|
108 | + } |
|
109 | + return $this->getModelVersionInfo()->loadModel($model_name); |
|
110 | + } |
|
111 | 111 | } |
112 | 112 | // End of file Base.php |
@@ -86,7 +86,7 @@ discard block |
||
86 | 86 | LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
87 | 87 | try { |
88 | 88 | $controller->setRequestedVersion($version); |
89 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
89 | + if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
90 | 90 | return $controller->sendResponse( |
91 | 91 | new WP_Error( |
92 | 92 | 'endpoint_parsing_error', |
@@ -128,7 +128,7 @@ discard block |
||
128 | 128 | LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
129 | 129 | try { |
130 | 130 | $controller->setRequestedVersion($version); |
131 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
131 | + if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
132 | 132 | return []; |
133 | 133 | } |
134 | 134 | // get the model for this version |
@@ -192,11 +192,11 @@ discard block |
||
192 | 192 | */ |
193 | 193 | protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema) |
194 | 194 | { |
195 | - if (isset($schema['properties'][ $field_name ]['default'])) { |
|
196 | - if (is_array($schema['properties'][ $field_name ]['default'])) { |
|
197 | - foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) { |
|
195 | + if (isset($schema['properties'][$field_name]['default'])) { |
|
196 | + if (is_array($schema['properties'][$field_name]['default'])) { |
|
197 | + foreach ($schema['properties'][$field_name]['default'] as $default_key => $default_value) { |
|
198 | 198 | if ($default_key === 'raw') { |
199 | - $schema['properties'][ $field_name ]['default'][ $default_key ] = |
|
199 | + $schema['properties'][$field_name]['default'][$default_key] = |
|
200 | 200 | ModelDataTranslator::prepareFieldValueForJson( |
201 | 201 | $field, |
202 | 202 | $default_value, |
@@ -205,9 +205,9 @@ discard block |
||
205 | 205 | } |
206 | 206 | } |
207 | 207 | } else { |
208 | - $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson( |
|
208 | + $schema['properties'][$field_name]['default'] = ModelDataTranslator::prepareFieldValueForJson( |
|
209 | 209 | $field, |
210 | - $schema['properties'][ $field_name ]['default'], |
|
210 | + $schema['properties'][$field_name]['default'], |
|
211 | 211 | $this->getModelVersionInfo()->requestedVersion() |
212 | 212 | ); |
213 | 213 | } |
@@ -229,9 +229,9 @@ discard block |
||
229 | 229 | protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema) |
230 | 230 | { |
231 | 231 | if ($field instanceof EE_Datetime_Field) { |
232 | - $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema(); |
|
232 | + $schema['properties'][$field_name.'_gmt'] = $field->getSchema(); |
|
233 | 233 | // modify the description |
234 | - $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf( |
|
234 | + $schema['properties'][$field_name.'_gmt']['description'] = sprintf( |
|
235 | 235 | esc_html__('%s - the value for this field is in GMT.', 'event_espresso'), |
236 | 236 | wp_specialchars_decode($field->get_nicename(), ENT_QUOTES) |
237 | 237 | ); |
@@ -280,7 +280,7 @@ discard block |
||
280 | 280 | LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
281 | 281 | try { |
282 | 282 | $controller->setRequestedVersion($version); |
283 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
283 | + if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
284 | 284 | return $controller->sendResponse( |
285 | 285 | new WP_Error( |
286 | 286 | 'endpoint_parsing_error', |
@@ -360,7 +360,7 @@ discard block |
||
360 | 360 | public function getEntitiesFromModel($model, $request) |
361 | 361 | { |
362 | 362 | $query_params = $this->createModelQueryParams($model, $request->get_params()); |
363 | - if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) { |
|
363 | + if ( ! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) { |
|
364 | 364 | $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name()); |
365 | 365 | throw new RestException( |
366 | 366 | sprintf('rest_%s_cannot_list', $model_name_plural), |
@@ -372,7 +372,7 @@ discard block |
||
372 | 372 | ['status' => 403] |
373 | 373 | ); |
374 | 374 | } |
375 | - if (! $request->get_header('no_rest_headers')) { |
|
375 | + if ( ! $request->get_header('no_rest_headers')) { |
|
376 | 376 | $this->setHeadersFromQueryParams($model, $query_params); |
377 | 377 | } |
378 | 378 | /** @type array $results */ |
@@ -413,7 +413,7 @@ discard block |
||
413 | 413 | $context = $this->validateContext($request->get_param('caps')); |
414 | 414 | $model = $relation->get_this_model(); |
415 | 415 | $related_model = $relation->get_other_model(); |
416 | - if (! isset($primary_model_query_params[0])) { |
|
416 | + if ( ! isset($primary_model_query_params[0])) { |
|
417 | 417 | $primary_model_query_params[0] = []; |
418 | 418 | } |
419 | 419 | // check if they can access the 1st model object |
@@ -477,13 +477,13 @@ discard block |
||
477 | 477 | ); |
478 | 478 | $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params()); |
479 | 479 | foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) { |
480 | - $query_params[0][ $relation->get_this_model()->get_this_model_name() |
|
480 | + $query_params[0][$relation->get_this_model()->get_this_model_name() |
|
481 | 481 | . '.' |
482 | - . $where_condition_key ] = $where_condition_value; |
|
482 | + . $where_condition_key] = $where_condition_value; |
|
483 | 483 | } |
484 | 484 | $query_params['default_where_conditions'] = 'none'; |
485 | 485 | $query_params['caps'] = $context; |
486 | - if (! $request->get_header('no_rest_headers')) { |
|
486 | + if ( ! $request->get_header('no_rest_headers')) { |
|
487 | 487 | $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params); |
488 | 488 | } |
489 | 489 | /** @type array $results */ |
@@ -503,7 +503,7 @@ discard block |
||
503 | 503 | $result, |
504 | 504 | $request |
505 | 505 | ); |
506 | - $joined_result = array_merge($join_model_result, $nice_result); |
|
506 | + $joined_result = array_merge($join_model_result, $nice_result); |
|
507 | 507 | // but keep the meta stuff from the main model |
508 | 508 | if (isset($nice_result['meta'])) { |
509 | 509 | $joined_result['meta'] = $nice_result['meta']; |
@@ -535,7 +535,7 @@ discard block |
||
535 | 535 | */ |
536 | 536 | public function getEntitiesFromRelation($id, $relation, $request) |
537 | 537 | { |
538 | - if (! $relation->get_this_model()->has_primary_key_field()) { |
|
538 | + if ( ! $relation->get_this_model()->has_primary_key_field()) { |
|
539 | 539 | throw new EE_Error( |
540 | 540 | sprintf( |
541 | 541 | esc_html__( |
@@ -582,7 +582,7 @@ discard block |
||
582 | 582 | Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
583 | 583 | ); |
584 | 584 | // normally the limit to a 2-part array, where the 2nd item is the limit |
585 | - if (! isset($query_params['limit'])) { |
|
585 | + if ( ! isset($query_params['limit'])) { |
|
586 | 586 | $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
587 | 587 | } |
588 | 588 | if (is_array($query_params['limit'])) { |
@@ -621,7 +621,7 @@ discard block |
||
621 | 621 | */ |
622 | 622 | public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null) |
623 | 623 | { |
624 | - if (! $rest_request instanceof WP_REST_Request) { |
|
624 | + if ( ! $rest_request instanceof WP_REST_Request) { |
|
625 | 625 | // ok so this was called in the old style, where the 3rd arg was |
626 | 626 | // $include, and the 4th arg was $context |
627 | 627 | // now setup the request just to avoid fatal errors, although we won't be able |
@@ -698,7 +698,7 @@ discard block |
||
698 | 698 | $rest_request, |
699 | 699 | $this |
700 | 700 | ); |
701 | - if (! $current_user_full_access_to_entity) { |
|
701 | + if ( ! $current_user_full_access_to_entity) { |
|
702 | 702 | $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields( |
703 | 703 | $entity_array, |
704 | 704 | $model, |
@@ -733,7 +733,7 @@ discard block |
||
733 | 733 | */ |
734 | 734 | protected function addProtectedProperty(EEM_Base $model, $results_so_far, $protected) |
735 | 735 | { |
736 | - if (! $model->hasPassword() || ! $protected) { |
|
736 | + if ( ! $model->hasPassword() || ! $protected) { |
|
737 | 737 | return $results_so_far; |
738 | 738 | } |
739 | 739 | $password_field = $model->getPasswordField(); |
@@ -782,8 +782,8 @@ discard block |
||
782 | 782 | if ($do_chevy_shuffle) { |
783 | 783 | global $post; |
784 | 784 | $old_post = $post; |
785 | - $post = get_post($result[ $model->primary_key_name() ]); |
|
786 | - if (! $post instanceof WP_Post) { |
|
785 | + $post = get_post($result[$model->primary_key_name()]); |
|
786 | + if ( ! $post instanceof WP_Post) { |
|
787 | 787 | // well that's weird, because $result is what we JUST fetched from the database |
788 | 788 | throw new RestException( |
789 | 789 | 'error_fetching_post_from_database_results', |
@@ -793,7 +793,7 @@ discard block |
||
793 | 793 | ) |
794 | 794 | ); |
795 | 795 | } |
796 | - $model_object_classname = 'EE_' . $model->get_this_model_name(); |
|
796 | + $model_object_classname = 'EE_'.$model->get_this_model_name(); |
|
797 | 797 | $post->{$model_object_classname} = EE_Registry::instance()->load_class( |
798 | 798 | $model_object_classname, |
799 | 799 | $result, |
@@ -804,14 +804,14 @@ discard block |
||
804 | 804 | foreach ($result as $field_name => $field_value) { |
805 | 805 | $field_obj = $model->field_settings_for($field_name); |
806 | 806 | if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) { |
807 | - unset($result[ $field_name ]); |
|
807 | + unset($result[$field_name]); |
|
808 | 808 | } elseif ( |
809 | 809 | $this->isSubclassOfOne( |
810 | 810 | $field_obj, |
811 | 811 | $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat() |
812 | 812 | ) |
813 | 813 | ) { |
814 | - $result[ $field_name ] = [ |
|
814 | + $result[$field_name] = [ |
|
815 | 815 | 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
816 | 816 | 'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
817 | 817 | ]; |
@@ -821,7 +821,7 @@ discard block |
||
821 | 821 | $this->getModelVersionInfo()->fieldsThatHavePrettyFormat() |
822 | 822 | ) |
823 | 823 | ) { |
824 | - $result[ $field_name ] = [ |
|
824 | + $result[$field_name] = [ |
|
825 | 825 | 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
826 | 826 | 'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
827 | 827 | ]; |
@@ -852,10 +852,10 @@ discard block |
||
852 | 852 | $this->getModelVersionInfo()->requestedVersion() |
853 | 853 | ); |
854 | 854 | } |
855 | - $result[ $field_name . '_gmt' ] = $gmt_date; |
|
856 | - $result[ $field_name ] = $local_date; |
|
855 | + $result[$field_name.'_gmt'] = $gmt_date; |
|
856 | + $result[$field_name] = $local_date; |
|
857 | 857 | } else { |
858 | - $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value); |
|
858 | + $result[$field_name] = $this->prepareFieldObjValueForJson($field_obj, $field_value); |
|
859 | 859 | } |
860 | 860 | } |
861 | 861 | if ($do_chevy_shuffle) { |
@@ -910,7 +910,7 @@ discard block |
||
910 | 910 | protected function addExtraFields(EEM_Base $model, $db_row, $entity_array) |
911 | 911 | { |
912 | 912 | if ($model instanceof EEM_CPT_Base) { |
913 | - $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]); |
|
913 | + $entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]); |
|
914 | 914 | } |
915 | 915 | return $entity_array; |
916 | 916 | } |
@@ -937,7 +937,7 @@ discard block |
||
937 | 937 | 'href' => $this->getVersionedLinkTo( |
938 | 938 | EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
939 | 939 | . '/' |
940 | - . $entity_array[ $model->primary_key_name() ] |
|
940 | + . $entity_array[$model->primary_key_name()] |
|
941 | 941 | ), |
942 | 942 | ], |
943 | 943 | ]; |
@@ -954,12 +954,12 @@ discard block |
||
954 | 954 | foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) { |
955 | 955 | $related_model_part = |
956 | 956 | Read::getRelatedEntityName($relation_name, $relation_obj); |
957 | - $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = [ |
|
957 | + $links[EED_Core_Rest_Api::ee_api_link_namespace.$related_model_part] = [ |
|
958 | 958 | [ |
959 | 959 | 'href' => $this->getVersionedLinkTo( |
960 | 960 | EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
961 | 961 | . '/' |
962 | - . $entity_array[ $model->primary_key_name() ] |
|
962 | + . $entity_array[$model->primary_key_name()] |
|
963 | 963 | . '/' |
964 | 964 | . $related_model_part |
965 | 965 | ), |
@@ -993,12 +993,12 @@ discard block |
||
993 | 993 | $included_items_protected = false |
994 | 994 | ) { |
995 | 995 | // if $db_row not included, hope the entity array has what we need |
996 | - if (! $db_row) { |
|
996 | + if ( ! $db_row) { |
|
997 | 997 | $db_row = $entity_array; |
998 | 998 | } |
999 | 999 | $relation_settings = $this->getModelVersionInfo()->relationSettings($model); |
1000 | 1000 | foreach ($relation_settings as $relation_name => $relation_obj) { |
1001 | - $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith( |
|
1001 | + $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith( |
|
1002 | 1002 | $rest_request->get_param('include'), |
1003 | 1003 | $relation_name |
1004 | 1004 | ); |
@@ -1026,7 +1026,7 @@ discard block |
||
1026 | 1026 | $model->deduce_fields_n_values_from_cols_n_values($db_row) |
1027 | 1027 | ) |
1028 | 1028 | ); |
1029 | - if (! $included_items_protected) { |
|
1029 | + if ( ! $included_items_protected) { |
|
1030 | 1030 | try { |
1031 | 1031 | $related_results = $this->getEntitiesFromRelationUsingModelQueryParams( |
1032 | 1032 | $primary_model_query_params, |
@@ -1047,7 +1047,7 @@ discard block |
||
1047 | 1047 | ? null |
1048 | 1048 | : []; |
1049 | 1049 | } |
1050 | - $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results; |
|
1050 | + $entity_array[Read::getRelatedEntityName($relation_name, $relation_obj)] = $related_results; |
|
1051 | 1051 | } |
1052 | 1052 | } |
1053 | 1053 | return $entity_array; |
@@ -1131,13 +1131,13 @@ discard block |
||
1131 | 1131 | $schema = $this->fields_calculator->getJsonSchemaForModel($model); |
1132 | 1132 | if ( |
1133 | 1133 | $row_is_protected |
1134 | - && isset($schema['properties'][ $field_to_calculate ]['protected']) |
|
1135 | - && $schema['properties'][ $field_to_calculate ]['protected'] |
|
1134 | + && isset($schema['properties'][$field_to_calculate]['protected']) |
|
1135 | + && $schema['properties'][$field_to_calculate]['protected'] |
|
1136 | 1136 | ) { |
1137 | 1137 | $calculated_value = null; |
1138 | 1138 | $protected_fields[] = $field_to_calculate; |
1139 | - if ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1140 | - switch ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1139 | + if ($schema['properties'][$field_to_calculate]['type']) { |
|
1140 | + switch ($schema['properties'][$field_to_calculate]['type']) { |
|
1141 | 1141 | case 'boolean': |
1142 | 1142 | $calculated_value = false; |
1143 | 1143 | break; |
@@ -1252,7 +1252,7 @@ discard block |
||
1252 | 1252 | */ |
1253 | 1253 | public function validateContext($context) |
1254 | 1254 | { |
1255 | - if (! $context) { |
|
1255 | + if ( ! $context) { |
|
1256 | 1256 | $context = EEM_Base::caps_read; |
1257 | 1257 | } |
1258 | 1258 | $valid_contexts = EEM_Base::valid_cap_contexts(); |
@@ -1277,7 +1277,7 @@ discard block |
||
1277 | 1277 | EEM_Base::default_where_conditions_minimum_all, |
1278 | 1278 | EEM_Base::default_where_conditions_minimum_others, |
1279 | 1279 | ]; |
1280 | - if (! $default_query_params) { |
|
1280 | + if ( ! $default_query_params) { |
|
1281 | 1281 | $default_query_params = EEM_Base::default_where_conditions_all; |
1282 | 1282 | } |
1283 | 1283 | if ( |
@@ -1363,14 +1363,14 @@ discard block |
||
1363 | 1363 | } |
1364 | 1364 | if (isset($query_params['limit'])) { |
1365 | 1365 | // limit should be either a string like '23' or '23,43', or an array with two items in it |
1366 | - if (! is_array($query_params['limit'])) { |
|
1366 | + if ( ! is_array($query_params['limit'])) { |
|
1367 | 1367 | $limit_array = explode(',', (string) $query_params['limit']); |
1368 | 1368 | } else { |
1369 | 1369 | $limit_array = $query_params['limit']; |
1370 | 1370 | } |
1371 | 1371 | $sanitized_limit = []; |
1372 | 1372 | foreach ($limit_array as $limit_part) { |
1373 | - if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) { |
|
1373 | + if ($this->debug_mode && ( ! is_numeric($limit_part) || count($sanitized_limit) > 2)) { |
|
1374 | 1374 | throw new EE_Error( |
1375 | 1375 | sprintf( |
1376 | 1376 | esc_html__( |
@@ -1428,7 +1428,7 @@ discard block |
||
1428 | 1428 | { |
1429 | 1429 | $model_ready_query_params = []; |
1430 | 1430 | foreach ($query_params as $key => $value) { |
1431 | - $model_ready_query_params[ $key ] = is_array($value) |
|
1431 | + $model_ready_query_params[$key] = is_array($value) |
|
1432 | 1432 | ? $this->prepareRestQueryParamsKeyForModels($model, $value) |
1433 | 1433 | : $value; |
1434 | 1434 | } |
@@ -1447,9 +1447,9 @@ discard block |
||
1447 | 1447 | $model_ready_query_params = []; |
1448 | 1448 | foreach ($query_params as $key => $value) { |
1449 | 1449 | if (is_array($value)) { |
1450 | - $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value); |
|
1450 | + $model_ready_query_params[$key] = $this->prepareRestQueryParamsValuesForModels($model, $value); |
|
1451 | 1451 | } else { |
1452 | - $model_ready_query_params[ $key ] = $value; |
|
1452 | + $model_ready_query_params[$key] = $value; |
|
1453 | 1453 | } |
1454 | 1454 | } |
1455 | 1455 | return $model_ready_query_params; |
@@ -1481,17 +1481,17 @@ discard block |
||
1481 | 1481 | foreach ($exploded_contents as $item) { |
1482 | 1482 | $item = trim($item); |
1483 | 1483 | // if no prefix was provided, so we look for items with no "." in them |
1484 | - if (! $prefix) { |
|
1484 | + if ( ! $prefix) { |
|
1485 | 1485 | // does this item have a period? |
1486 | 1486 | if (strpos($item, '.') === false) { |
1487 | 1487 | // if not, then its what we're looking for |
1488 | 1488 | $contents_with_prefix[] = $item; |
1489 | 1489 | } |
1490 | - } elseif (strpos($item, $prefix . '.') === 0) { |
|
1490 | + } elseif (strpos($item, $prefix.'.') === 0) { |
|
1491 | 1491 | // this item has the prefix and a period, grab it |
1492 | 1492 | $contents_with_prefix[] = substr( |
1493 | 1493 | $item, |
1494 | - strpos($item, $prefix . '.') + strlen($prefix . '.') |
|
1494 | + strpos($item, $prefix.'.') + strlen($prefix.'.') |
|
1495 | 1495 | ); |
1496 | 1496 | } elseif ($item === $prefix) { |
1497 | 1497 | // this item is JUST the prefix |
@@ -1533,9 +1533,9 @@ discard block |
||
1533 | 1533 | if ($model_name) { |
1534 | 1534 | foreach ($includes as $field_to_include) { |
1535 | 1535 | $field_to_include = trim($field_to_include); |
1536 | - if (strpos($field_to_include, $model_name . '.') === 0) { |
|
1536 | + if (strpos($field_to_include, $model_name.'.') === 0) { |
|
1537 | 1537 | // found the model name at the exact start |
1538 | - $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include); |
|
1538 | + $field_sans_model_name = str_replace($model_name.'.', '', $field_to_include); |
|
1539 | 1539 | $extracted_fields_to_include[] = $field_sans_model_name; |
1540 | 1540 | } elseif ($field_to_include == $model_name) { |
1541 | 1541 | $extracted_fields_to_include[] = '*'; |
@@ -1578,7 +1578,7 @@ discard block |
||
1578 | 1578 | $restricted_query_params['caps'] = $context; |
1579 | 1579 | $this->setDebugInfo('model query params', $restricted_query_params); |
1580 | 1580 | $model_rows = $model->get_all_wpdb_results($restricted_query_params); |
1581 | - if (! empty($model_rows)) { |
|
1581 | + if ( ! empty($model_rows)) { |
|
1582 | 1582 | return $this->createEntityFromWpdbResult( |
1583 | 1583 | $model, |
1584 | 1584 | reset($model_rows), |
@@ -1590,7 +1590,7 @@ discard block |
||
1590 | 1590 | if ($model->exists($query_params)) { |
1591 | 1591 | // you got shafted- it existed but we didn't want to tell you! |
1592 | 1592 | throw new RestException( |
1593 | - 'rest_user_cannot_' . $context, |
|
1593 | + 'rest_user_cannot_'.$context, |
|
1594 | 1594 | sprintf( |
1595 | 1595 | esc_html__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'), |
1596 | 1596 | $context, |
@@ -1644,14 +1644,14 @@ discard block |
||
1644 | 1644 | // if this entity requires a password, they better give it and it better be right! |
1645 | 1645 | if ( |
1646 | 1646 | $model->hasPassword() |
1647 | - && $model_row[ $model->getPasswordField()->get_qualified_column() ] !== '' |
|
1647 | + && $model_row[$model->getPasswordField()->get_qualified_column()] !== '' |
|
1648 | 1648 | ) { |
1649 | 1649 | if (empty($request['password'])) { |
1650 | 1650 | throw new RestPasswordRequiredException(); |
1651 | 1651 | } |
1652 | 1652 | if ( |
1653 | 1653 | ! hash_equals( |
1654 | - $model_row[ $model->getPasswordField()->get_qualified_column() ], |
|
1654 | + $model_row[$model->getPasswordField()->get_qualified_column()], |
|
1655 | 1655 | $request['password'] |
1656 | 1656 | ) |
1657 | 1657 | ) { |
@@ -1665,12 +1665,12 @@ discard block |
||
1665 | 1665 | $password_supplied = $request->get_param('password'); |
1666 | 1666 | if (empty($password_supplied)) { |
1667 | 1667 | $query_params['exclude_protected'] = true; |
1668 | - if (! $model->exists($query_params)) { |
|
1668 | + if ( ! $model->exists($query_params)) { |
|
1669 | 1669 | throw new RestPasswordRequiredException(); |
1670 | 1670 | } |
1671 | 1671 | } else { |
1672 | - $query_params[0][ $model->modelChainAndPassword() ] = $password_supplied; |
|
1673 | - if (! $model->exists($query_params)) { |
|
1672 | + $query_params[0][$model->modelChainAndPassword()] = $password_supplied; |
|
1673 | + if ( ! $model->exists($query_params)) { |
|
1674 | 1674 | throw new RestPasswordIncorrectException(); |
1675 | 1675 | } |
1676 | 1676 | } |
@@ -49,1629 +49,1629 @@ |
||
49 | 49 | */ |
50 | 50 | class Read extends Base |
51 | 51 | { |
52 | - /** |
|
53 | - * @var CalculatedModelFields |
|
54 | - */ |
|
55 | - protected $fields_calculator; |
|
56 | - |
|
57 | - |
|
58 | - /** |
|
59 | - * Read constructor. |
|
60 | - * |
|
61 | - * @param CalculatedModelFields $fields_calculator |
|
62 | - */ |
|
63 | - public function __construct(CalculatedModelFields $fields_calculator) |
|
64 | - { |
|
65 | - parent::__construct(); |
|
66 | - $this->fields_calculator = $fields_calculator; |
|
67 | - } |
|
68 | - |
|
69 | - |
|
70 | - /** |
|
71 | - * Handles requests to get all (or a filtered subset) of entities for a particular model |
|
72 | - * |
|
73 | - * @param WP_REST_Request $request |
|
74 | - * @param string $version |
|
75 | - * @param string $model_name |
|
76 | - * @return WP_REST_Response|WP_Error |
|
77 | - * @throws InvalidArgumentException |
|
78 | - * @throws InvalidDataTypeException |
|
79 | - * @throws InvalidInterfaceException |
|
80 | - */ |
|
81 | - public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name) |
|
82 | - { |
|
83 | - $controller = |
|
84 | - LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
85 | - try { |
|
86 | - $controller->setRequestedVersion($version); |
|
87 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
88 | - return $controller->sendResponse( |
|
89 | - new WP_Error( |
|
90 | - 'endpoint_parsing_error', |
|
91 | - sprintf( |
|
92 | - esc_html__( |
|
93 | - 'There is no model for endpoint %s. Please contact event espresso support', |
|
94 | - 'event_espresso' |
|
95 | - ), |
|
96 | - $model_name |
|
97 | - ) |
|
98 | - ) |
|
99 | - ); |
|
100 | - } |
|
101 | - return $controller->sendResponse( |
|
102 | - $controller->getEntitiesFromModel( |
|
103 | - $controller->getModelVersionInfo()->loadModel($model_name), |
|
104 | - $request |
|
105 | - ) |
|
106 | - ); |
|
107 | - } catch (Exception $e) { |
|
108 | - return $controller->sendResponse($e); |
|
109 | - } |
|
110 | - } |
|
111 | - |
|
112 | - |
|
113 | - /** |
|
114 | - * Prepares and returns schema for any OPTIONS request. |
|
115 | - * |
|
116 | - * @param string $version The API endpoint version being used. |
|
117 | - * @param string $model_name Something like `Event` or `Registration` |
|
118 | - * @return array |
|
119 | - * @throws InvalidArgumentException |
|
120 | - * @throws InvalidDataTypeException |
|
121 | - * @throws InvalidInterfaceException |
|
122 | - */ |
|
123 | - public static function handleSchemaRequest($version, $model_name) |
|
124 | - { |
|
125 | - $controller = |
|
126 | - LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
127 | - try { |
|
128 | - $controller->setRequestedVersion($version); |
|
129 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
130 | - return []; |
|
131 | - } |
|
132 | - // get the model for this version |
|
133 | - $model = $controller->getModelVersionInfo()->loadModel($model_name); |
|
134 | - $model_schema = new JsonModelSchema( |
|
135 | - $model, |
|
136 | - LoaderFactory::getLoader()->getShared('EventEspresso\core\libraries\rest_api\CalculatedModelFields') |
|
137 | - ); |
|
138 | - return $model_schema->getModelSchemaForRelations( |
|
139 | - $controller->getModelVersionInfo()->relationSettings($model), |
|
140 | - $controller->customizeSchemaForRestResponse( |
|
141 | - $model, |
|
142 | - $model_schema->getModelSchemaForFields( |
|
143 | - $controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model), |
|
144 | - $model_schema->getInitialSchemaStructure() |
|
145 | - ) |
|
146 | - ) |
|
147 | - ); |
|
148 | - } catch (Exception $e) { |
|
149 | - return []; |
|
150 | - } |
|
151 | - } |
|
152 | - |
|
153 | - |
|
154 | - /** |
|
155 | - * This loops through each field in the given schema for the model and does the following: |
|
156 | - * - add any extra fields that are REST API specific and related to existing fields. |
|
157 | - * - transform default values into the correct format for a REST API response. |
|
158 | - * |
|
159 | - * @param EEM_Base $model |
|
160 | - * @param array $schema |
|
161 | - * @return array The final schema. |
|
162 | - * @throws EE_Error |
|
163 | - * @throws EE_Error |
|
164 | - */ |
|
165 | - protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema) |
|
166 | - { |
|
167 | - foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) { |
|
168 | - $schema = $this->translateDefaultsForRestResponse( |
|
169 | - $field_name, |
|
170 | - $field, |
|
171 | - $this->maybeAddExtraFieldsToSchema($field_name, $field, $schema) |
|
172 | - ); |
|
173 | - } |
|
174 | - return $schema; |
|
175 | - } |
|
176 | - |
|
177 | - |
|
178 | - /** |
|
179 | - * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST |
|
180 | - * response. |
|
181 | - * |
|
182 | - * @param $field_name |
|
183 | - * @param EE_Model_Field_Base $field |
|
184 | - * @param array $schema |
|
185 | - * @return array |
|
186 | - * @throws RestException if a default value has a PHP object, which we should never do |
|
187 | - * (but if we did, let's know about it ASAP, so let the exception bubble up) |
|
188 | - * @throws EE_Error |
|
189 | - * |
|
190 | - */ |
|
191 | - protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema) |
|
192 | - { |
|
193 | - if (isset($schema['properties'][ $field_name ]['default'])) { |
|
194 | - if (is_array($schema['properties'][ $field_name ]['default'])) { |
|
195 | - foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) { |
|
196 | - if ($default_key === 'raw') { |
|
197 | - $schema['properties'][ $field_name ]['default'][ $default_key ] = |
|
198 | - ModelDataTranslator::prepareFieldValueForJson( |
|
199 | - $field, |
|
200 | - $default_value, |
|
201 | - $this->getModelVersionInfo()->requestedVersion() |
|
202 | - ); |
|
203 | - } |
|
204 | - } |
|
205 | - } else { |
|
206 | - $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson( |
|
207 | - $field, |
|
208 | - $schema['properties'][ $field_name ]['default'], |
|
209 | - $this->getModelVersionInfo()->requestedVersion() |
|
210 | - ); |
|
211 | - } |
|
212 | - } |
|
213 | - return $schema; |
|
214 | - } |
|
215 | - |
|
216 | - |
|
217 | - /** |
|
218 | - * Adds additional fields to the schema |
|
219 | - * The REST API returns a GMT value field for each datetime field in the resource. Thus the description about this |
|
220 | - * needs to be added to the schema. |
|
221 | - * |
|
222 | - * @param $field_name |
|
223 | - * @param EE_Model_Field_Base $field |
|
224 | - * @param array $schema |
|
225 | - * @return array |
|
226 | - */ |
|
227 | - protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema) |
|
228 | - { |
|
229 | - if ($field instanceof EE_Datetime_Field) { |
|
230 | - $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema(); |
|
231 | - // modify the description |
|
232 | - $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf( |
|
233 | - esc_html__('%s - the value for this field is in GMT.', 'event_espresso'), |
|
234 | - wp_specialchars_decode($field->get_nicename(), ENT_QUOTES) |
|
235 | - ); |
|
236 | - } |
|
237 | - return $schema; |
|
238 | - } |
|
239 | - |
|
240 | - |
|
241 | - /** |
|
242 | - * Used to figure out the route from the request when a `WP_REST_Request` object is not available |
|
243 | - * |
|
244 | - * @return string |
|
245 | - */ |
|
246 | - protected function getRouteFromRequest() |
|
247 | - { |
|
248 | - if ( |
|
249 | - isset($GLOBALS['wp']) |
|
250 | - && $GLOBALS['wp'] instanceof WP |
|
251 | - && isset($GLOBALS['wp']->query_vars['rest_route']) |
|
252 | - ) { |
|
253 | - return $GLOBALS['wp']->query_vars['rest_route']; |
|
254 | - } else { |
|
255 | - /** @var RequestInterface $request */ |
|
256 | - $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
257 | - return $request->serverParamIsSet('PATH_INFO') |
|
258 | - ? $request->getServerParam('PATH_INFO') |
|
259 | - : '/'; |
|
260 | - } |
|
261 | - } |
|
262 | - |
|
263 | - |
|
264 | - /** |
|
265 | - * Gets a single entity related to the model indicated in the path and its id |
|
266 | - * |
|
267 | - * @param WP_REST_Request $request |
|
268 | - * @param string $version |
|
269 | - * @param string $model_name |
|
270 | - * @return WP_REST_Response|WP_Error |
|
271 | - * @throws InvalidDataTypeException |
|
272 | - * @throws InvalidInterfaceException |
|
273 | - * @throws InvalidArgumentException |
|
274 | - */ |
|
275 | - public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name) |
|
276 | - { |
|
277 | - $controller = |
|
278 | - LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
279 | - try { |
|
280 | - $controller->setRequestedVersion($version); |
|
281 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
282 | - return $controller->sendResponse( |
|
283 | - new WP_Error( |
|
284 | - 'endpoint_parsing_error', |
|
285 | - sprintf( |
|
286 | - esc_html__( |
|
287 | - 'There is no model for endpoint %s. Please contact event espresso support', |
|
288 | - 'event_espresso' |
|
289 | - ), |
|
290 | - $model_name |
|
291 | - ) |
|
292 | - ) |
|
293 | - ); |
|
294 | - } |
|
295 | - return $controller->sendResponse( |
|
296 | - $controller->getEntityFromModel( |
|
297 | - $controller->getModelVersionInfo()->loadModel($model_name), |
|
298 | - $request |
|
299 | - ) |
|
300 | - ); |
|
301 | - } catch (Exception $e) { |
|
302 | - return $controller->sendResponse($e); |
|
303 | - } |
|
304 | - } |
|
305 | - |
|
306 | - |
|
307 | - /** |
|
308 | - * Gets all the related entities (or if its a belongs-to relation just the one) |
|
309 | - * to the item with the given id |
|
310 | - * |
|
311 | - * @param WP_REST_Request $request |
|
312 | - * @param string $version |
|
313 | - * @param string $model_name |
|
314 | - * @param string $related_model_name |
|
315 | - * @return WP_REST_Response|WP_Error |
|
316 | - * @throws InvalidDataTypeException |
|
317 | - * @throws InvalidInterfaceException |
|
318 | - * @throws InvalidArgumentException |
|
319 | - */ |
|
320 | - public static function handleRequestGetRelated( |
|
321 | - WP_REST_Request $request, |
|
322 | - $version, |
|
323 | - $model_name, |
|
324 | - $related_model_name |
|
325 | - ) { |
|
326 | - $controller = |
|
327 | - LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
328 | - try { |
|
329 | - $controller->setRequestedVersion($version); |
|
330 | - $main_model = $controller->validateModel($model_name); |
|
331 | - $controller->validateModel($related_model_name); |
|
332 | - return $controller->sendResponse( |
|
333 | - $controller->getEntitiesFromRelation( |
|
334 | - $request->get_param('id'), |
|
335 | - $main_model->related_settings_for($related_model_name), |
|
336 | - $request |
|
337 | - ) |
|
338 | - ); |
|
339 | - } catch (Exception $e) { |
|
340 | - return $controller->sendResponse($e); |
|
341 | - } |
|
342 | - } |
|
343 | - |
|
344 | - |
|
345 | - /** |
|
346 | - * Gets a collection for the given model and filters |
|
347 | - * |
|
348 | - * @param EEM_Base $model |
|
349 | - * @param WP_REST_Request $request |
|
350 | - * @return array |
|
351 | - * @throws EE_Error |
|
352 | - * @throws InvalidArgumentException |
|
353 | - * @throws InvalidDataTypeException |
|
354 | - * @throws InvalidInterfaceException |
|
355 | - * @throws ReflectionException |
|
356 | - * @throws RestException |
|
357 | - */ |
|
358 | - public function getEntitiesFromModel($model, $request) |
|
359 | - { |
|
360 | - $query_params = $this->createModelQueryParams($model, $request->get_params()); |
|
361 | - if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) { |
|
362 | - $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name()); |
|
363 | - throw new RestException( |
|
364 | - sprintf('rest_%s_cannot_list', $model_name_plural), |
|
365 | - sprintf( |
|
366 | - esc_html__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'), |
|
367 | - $model_name_plural, |
|
368 | - Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
|
369 | - ), |
|
370 | - ['status' => 403] |
|
371 | - ); |
|
372 | - } |
|
373 | - if (! $request->get_header('no_rest_headers')) { |
|
374 | - $this->setHeadersFromQueryParams($model, $query_params); |
|
375 | - } |
|
376 | - /** @type array $results */ |
|
377 | - $results = $model->get_all_wpdb_results($query_params); |
|
378 | - $nice_results = []; |
|
379 | - foreach ($results as $result) { |
|
380 | - $nice_results[] = $this->createEntityFromWpdbResult( |
|
381 | - $model, |
|
382 | - $result, |
|
383 | - $request |
|
384 | - ); |
|
385 | - } |
|
386 | - return $nice_results; |
|
387 | - } |
|
388 | - |
|
389 | - |
|
390 | - /** |
|
391 | - * Gets the collection for given relation object |
|
392 | - * The same as Read::get_entities_from_model(), except if the relation |
|
393 | - * is a HABTM relation, in which case it merges any non-foreign-key fields from |
|
394 | - * the join-model-object into the results |
|
395 | - * |
|
396 | - * @param array $primary_model_query_params query params for finding the item from which |
|
397 | - * relations will be based |
|
398 | - * @param EE_Model_Relation_Base $relation |
|
399 | - * @param WP_REST_Request $request |
|
400 | - * @return array |
|
401 | - * @throws EE_Error |
|
402 | - * @throws InvalidArgumentException |
|
403 | - * @throws InvalidDataTypeException |
|
404 | - * @throws InvalidInterfaceException |
|
405 | - * @throws ReflectionException |
|
406 | - * @throws RestException |
|
407 | - * @throws ModelConfigurationException |
|
408 | - */ |
|
409 | - protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request) |
|
410 | - { |
|
411 | - $context = $this->validateContext($request->get_param('caps')); |
|
412 | - $model = $relation->get_this_model(); |
|
413 | - $related_model = $relation->get_other_model(); |
|
414 | - if (! isset($primary_model_query_params[0])) { |
|
415 | - $primary_model_query_params[0] = []; |
|
416 | - } |
|
417 | - // check if they can access the 1st model object |
|
418 | - $primary_model_query_params = [ |
|
419 | - 0 => $primary_model_query_params[0], |
|
420 | - 'limit' => 1, |
|
421 | - ]; |
|
422 | - if ($model instanceof EEM_Soft_Delete_Base) { |
|
423 | - $primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included( |
|
424 | - $primary_model_query_params |
|
425 | - ); |
|
426 | - } |
|
427 | - $restricted_query_params = $primary_model_query_params; |
|
428 | - $restricted_query_params['caps'] = $context; |
|
429 | - $restricted_query_params['limit'] = 1; |
|
430 | - $this->setDebugInfo('main model query params', $restricted_query_params); |
|
431 | - $this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context)); |
|
432 | - $primary_model_rows = $model->get_all_wpdb_results($restricted_query_params); |
|
433 | - $primary_model_row = null; |
|
434 | - if (is_array($primary_model_rows)) { |
|
435 | - $primary_model_row = reset($primary_model_rows); |
|
436 | - } |
|
437 | - if ( |
|
438 | - ! ( |
|
439 | - $primary_model_row |
|
440 | - && Capabilities::currentUserHasPartialAccessTo($related_model, $context) |
|
441 | - ) |
|
442 | - ) { |
|
443 | - if ($relation instanceof EE_Belongs_To_Relation) { |
|
444 | - $related_model_name_maybe_plural = strtolower($related_model->get_this_model_name()); |
|
445 | - } else { |
|
446 | - $related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower( |
|
447 | - $related_model->get_this_model_name() |
|
448 | - ); |
|
449 | - } |
|
450 | - throw new RestException( |
|
451 | - sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural), |
|
452 | - sprintf( |
|
453 | - esc_html__( |
|
454 | - 'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s', |
|
455 | - 'event_espresso' |
|
456 | - ), |
|
457 | - $related_model_name_maybe_plural, |
|
458 | - $relation->get_this_model()->get_this_model_name(), |
|
459 | - implode( |
|
460 | - ',', |
|
461 | - array_keys( |
|
462 | - Capabilities::getMissingPermissions($related_model, $context) |
|
463 | - ) |
|
464 | - ) |
|
465 | - ), |
|
466 | - ['status' => 403] |
|
467 | - ); |
|
468 | - } |
|
469 | - |
|
470 | - $this->checkPassword( |
|
471 | - $model, |
|
472 | - $primary_model_row, |
|
473 | - $restricted_query_params, |
|
474 | - $request |
|
475 | - ); |
|
476 | - $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params()); |
|
477 | - foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) { |
|
478 | - $query_params[0][ $relation->get_this_model()->get_this_model_name() |
|
479 | - . '.' |
|
480 | - . $where_condition_key ] = $where_condition_value; |
|
481 | - } |
|
482 | - $query_params['default_where_conditions'] = 'none'; |
|
483 | - $query_params['caps'] = $context; |
|
484 | - if (! $request->get_header('no_rest_headers')) { |
|
485 | - $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params); |
|
486 | - } |
|
487 | - /** @type array $results */ |
|
488 | - $results = $relation->get_other_model()->get_all_wpdb_results($query_params); |
|
489 | - $nice_results = []; |
|
490 | - foreach ($results as $result) { |
|
491 | - $nice_result = $this->createEntityFromWpdbResult( |
|
492 | - $relation->get_other_model(), |
|
493 | - $result, |
|
494 | - $request |
|
495 | - ); |
|
496 | - if ($relation instanceof EE_HABTM_Relation) { |
|
497 | - // put the unusual stuff (properties from the HABTM relation) first, and make sure |
|
498 | - // if there are conflicts we prefer the properties from the main model |
|
499 | - $join_model_result = $this->createEntityFromWpdbResult( |
|
500 | - $relation->get_join_model(), |
|
501 | - $result, |
|
502 | - $request |
|
503 | - ); |
|
504 | - $joined_result = array_merge($join_model_result, $nice_result); |
|
505 | - // but keep the meta stuff from the main model |
|
506 | - if (isset($nice_result['meta'])) { |
|
507 | - $joined_result['meta'] = $nice_result['meta']; |
|
508 | - } |
|
509 | - $nice_result = $joined_result; |
|
510 | - } |
|
511 | - $nice_results[] = $nice_result; |
|
512 | - } |
|
513 | - if ($relation instanceof EE_Belongs_To_Relation) { |
|
514 | - return array_shift($nice_results); |
|
515 | - } else { |
|
516 | - return $nice_results; |
|
517 | - } |
|
518 | - } |
|
519 | - |
|
520 | - |
|
521 | - /** |
|
522 | - * Gets the collection for given relation object |
|
523 | - * The same as Read::get_entities_from_model(), except if the relation |
|
524 | - * is a HABTM relation, in which case it merges any non-foreign-key fields from |
|
525 | - * the join-model-object into the results |
|
526 | - * |
|
527 | - * @param string $id the ID of the thing we are fetching related stuff from |
|
528 | - * @param EE_Model_Relation_Base $relation |
|
529 | - * @param WP_REST_Request $request |
|
530 | - * @return array |
|
531 | - * @throws EE_Error |
|
532 | - * @throws ReflectionException |
|
533 | - */ |
|
534 | - public function getEntitiesFromRelation($id, $relation, $request) |
|
535 | - { |
|
536 | - if (! $relation->get_this_model()->has_primary_key_field()) { |
|
537 | - throw new EE_Error( |
|
538 | - sprintf( |
|
539 | - esc_html__( |
|
540 | - // @codingStandardsIgnoreStart |
|
541 | - 'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s', |
|
542 | - // @codingStandardsIgnoreEnd |
|
543 | - 'event_espresso' |
|
544 | - ), |
|
545 | - $relation->get_this_model()->get_this_model_name() |
|
546 | - ) |
|
547 | - ); |
|
548 | - } |
|
549 | - // can we edit that main item? |
|
550 | - // if not, show nothing but an error |
|
551 | - // otherwise, please proceed |
|
552 | - return $this->getEntitiesFromRelationUsingModelQueryParams( |
|
553 | - [ |
|
554 | - [ |
|
555 | - $relation->get_this_model()->primary_key_name() => $id, |
|
556 | - ], |
|
557 | - ], |
|
558 | - $relation, |
|
559 | - $request |
|
560 | - ); |
|
561 | - } |
|
562 | - |
|
563 | - |
|
564 | - /** |
|
565 | - * Sets the headers that are based on the model and query params, |
|
566 | - * like the total records. This should only be called on the original request |
|
567 | - * from the client, not on subsequent internal |
|
568 | - * |
|
569 | - * @param EEM_Base $model |
|
570 | - * @param array $query_params |
|
571 | - * @return void |
|
572 | - * @throws EE_Error |
|
573 | - * @throws EE_Error |
|
574 | - */ |
|
575 | - protected function setHeadersFromQueryParams($model, $query_params) |
|
576 | - { |
|
577 | - $this->setDebugInfo('model query params', $query_params); |
|
578 | - $this->setDebugInfo( |
|
579 | - 'missing caps', |
|
580 | - Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
|
581 | - ); |
|
582 | - // normally the limit to a 2-part array, where the 2nd item is the limit |
|
583 | - if (! isset($query_params['limit'])) { |
|
584 | - $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
|
585 | - } |
|
586 | - if (is_array($query_params['limit'])) { |
|
587 | - $limit_parts = $query_params['limit']; |
|
588 | - } else { |
|
589 | - $limit_parts = explode(',', $query_params['limit']); |
|
590 | - if (count($limit_parts) == 1) { |
|
591 | - $limit_parts = [0, $limit_parts[0]]; |
|
592 | - } |
|
593 | - } |
|
594 | - // remove the group by and having parts of the query, as those will |
|
595 | - // make the sql query return an array of values, instead of just a single value |
|
596 | - unset($query_params['group_by'], $query_params['having'], $query_params['limit']); |
|
597 | - $count = $model->count($query_params, null, true); |
|
598 | - $pages = $count / $limit_parts[1]; |
|
599 | - $this->setResponseHeader('Total', $count, false); |
|
600 | - $this->setResponseHeader('PageSize', $limit_parts[1], false); |
|
601 | - $this->setResponseHeader('TotalPages', ceil($pages), false); |
|
602 | - } |
|
603 | - |
|
604 | - |
|
605 | - /** |
|
606 | - * Changes database results into REST API entities |
|
607 | - * |
|
608 | - * @param EEM_Base $model |
|
609 | - * @param array $db_row like results from $wpdb->get_results() |
|
610 | - * @param WP_REST_Request $rest_request |
|
611 | - * @param string $deprecated no longer used |
|
612 | - * @return array ready for being converted into json for sending to client |
|
613 | - * @throws EE_Error |
|
614 | - * @throws RestException |
|
615 | - * @throws InvalidDataTypeException |
|
616 | - * @throws InvalidInterfaceException |
|
617 | - * @throws InvalidArgumentException |
|
618 | - * @throws ReflectionException |
|
619 | - */ |
|
620 | - public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null) |
|
621 | - { |
|
622 | - if (! $rest_request instanceof WP_REST_Request) { |
|
623 | - // ok so this was called in the old style, where the 3rd arg was |
|
624 | - // $include, and the 4th arg was $context |
|
625 | - // now setup the request just to avoid fatal errors, although we won't be able |
|
626 | - // to truly make use of it because it's kinda devoid of info |
|
627 | - $rest_request = new WP_REST_Request(); |
|
628 | - $rest_request->set_param('include', $rest_request); |
|
629 | - $rest_request->set_param('caps', $deprecated); |
|
630 | - } |
|
631 | - if ($rest_request->get_param('caps') == null) { |
|
632 | - $rest_request->set_param('caps', EEM_Base::caps_read); |
|
633 | - } |
|
634 | - $current_user_full_access_to_entity = $model->currentUserCan( |
|
635 | - EEM_Base::caps_read_admin, |
|
636 | - $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
637 | - ); |
|
638 | - $entity_array = $this->createBareEntityFromWpdbResults($model, $db_row); |
|
639 | - $entity_array = $this->addExtraFields($model, $db_row, $entity_array); |
|
640 | - $entity_array['_links'] = $this->getEntityLinks($model, $db_row, $entity_array); |
|
641 | - // when it's a regular read request for a model with a password and the password wasn't provided |
|
642 | - // remove the password protected fields |
|
643 | - $has_protected_fields = false; |
|
644 | - try { |
|
645 | - $this->checkPassword( |
|
646 | - $model, |
|
647 | - $db_row, |
|
648 | - $model->alter_query_params_to_restrict_by_ID( |
|
649 | - $model->get_index_primary_key_string( |
|
650 | - $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
651 | - ) |
|
652 | - ), |
|
653 | - $rest_request |
|
654 | - ); |
|
655 | - } catch (RestPasswordRequiredException $e) { |
|
656 | - if ($model->hasPassword()) { |
|
657 | - // just remove protected fields |
|
658 | - $has_protected_fields = true; |
|
659 | - $entity_array = Capabilities::filterOutPasswordProtectedFields( |
|
660 | - $entity_array, |
|
661 | - $model, |
|
662 | - $this->getModelVersionInfo() |
|
663 | - ); |
|
664 | - } else { |
|
665 | - // that's a problem. None of this should be accessible if no password was provided |
|
666 | - throw $e; |
|
667 | - } |
|
668 | - } |
|
669 | - |
|
670 | - $entity_array['_calculated_fields'] = |
|
671 | - $this->getEntityCalculations($model, $db_row, $rest_request, $has_protected_fields); |
|
672 | - $entity_array = apply_filters( |
|
673 | - 'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models', |
|
674 | - $entity_array, |
|
675 | - $model, |
|
676 | - $rest_request->get_param('caps'), |
|
677 | - $rest_request, |
|
678 | - $this |
|
679 | - ); |
|
680 | - // add an empty protected property for now. If it's still around after we remove everything the request didn't |
|
681 | - // want, we'll populate it then. k? |
|
682 | - $entity_array['_protected'] = []; |
|
683 | - // remove any properties the request didn't want. This way _protected won't bother mentioning them |
|
684 | - $entity_array = $this->includeOnlyRequestedProperties($model, $rest_request, $entity_array); |
|
685 | - $entity_array = |
|
686 | - $this->includeRequestedModels($model, $rest_request, $entity_array, $db_row, $has_protected_fields); |
|
687 | - // if they still wanted the _protected property, add it. |
|
688 | - if (isset($entity_array['_protected'])) { |
|
689 | - $entity_array = $this->addProtectedProperty($model, $entity_array, $has_protected_fields); |
|
690 | - } |
|
691 | - $entity_array = apply_filters( |
|
692 | - 'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal', |
|
693 | - $entity_array, |
|
694 | - $model, |
|
695 | - $rest_request->get_param('caps'), |
|
696 | - $rest_request, |
|
697 | - $this |
|
698 | - ); |
|
699 | - if (! $current_user_full_access_to_entity) { |
|
700 | - $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields( |
|
701 | - $entity_array, |
|
702 | - $model, |
|
703 | - $rest_request->get_param('caps'), |
|
704 | - $this->getModelVersionInfo() |
|
705 | - ); |
|
706 | - } else { |
|
707 | - $result_without_inaccessible_fields = $entity_array; |
|
708 | - } |
|
709 | - $this->setDebugInfo( |
|
710 | - 'inaccessible fields', |
|
711 | - array_keys(array_diff_key((array) $entity_array, (array) $result_without_inaccessible_fields)) |
|
712 | - ); |
|
713 | - return apply_filters( |
|
714 | - 'FHEE__Read__create_entity_from_wpdb_results__entity_return', |
|
715 | - $result_without_inaccessible_fields, |
|
716 | - $model, |
|
717 | - $rest_request->get_param('caps') |
|
718 | - ); |
|
719 | - } |
|
720 | - |
|
721 | - |
|
722 | - /** |
|
723 | - * Returns an array describing which fields can be protected, and which actually were removed this request |
|
724 | - * |
|
725 | - * @param EEM_Base $model |
|
726 | - * @param array $results_so_far |
|
727 | - * @param bool $protected |
|
728 | - * @return array results |
|
729 | - * @throws EE_Error |
|
730 | - * @since 4.9.74.p |
|
731 | - */ |
|
732 | - protected function addProtectedProperty(EEM_Base $model, $results_so_far, $protected) |
|
733 | - { |
|
734 | - if (! $model->hasPassword() || ! $protected) { |
|
735 | - return $results_so_far; |
|
736 | - } |
|
737 | - $password_field = $model->getPasswordField(); |
|
738 | - $all_protected = array_merge( |
|
739 | - [$password_field->get_name()], |
|
740 | - $password_field->protectedFields() |
|
741 | - ); |
|
742 | - $fields_included = array_keys($results_so_far); |
|
743 | - $fields_included = array_intersect( |
|
744 | - $all_protected, |
|
745 | - $fields_included |
|
746 | - ); |
|
747 | - foreach ($fields_included as $field_name) { |
|
748 | - $results_so_far['_protected'][] = $field_name; |
|
749 | - } |
|
750 | - return $results_so_far; |
|
751 | - } |
|
752 | - |
|
753 | - |
|
754 | - /** |
|
755 | - * Creates a REST entity array (JSON object we're going to return in the response, but |
|
756 | - * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry), |
|
757 | - * from $wpdb->get_row( $sql, ARRAY_A) |
|
758 | - * |
|
759 | - * @param EEM_Base $model |
|
760 | - * @param array $db_row |
|
761 | - * @return array entity mostly ready for converting to JSON and sending in the response |
|
762 | - * @throws EE_Error |
|
763 | - * @throws ReflectionException |
|
764 | - * @throws RestException |
|
765 | - */ |
|
766 | - protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row) |
|
767 | - { |
|
768 | - $result = $model->deduce_fields_n_values_from_cols_n_values($db_row); |
|
769 | - $result = array_intersect_key( |
|
770 | - $result, |
|
771 | - $this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) |
|
772 | - ); |
|
773 | - // if this is a CPT, we need to set the global $post to it, |
|
774 | - // otherwise shortcodes etc won't work properly while rendering it |
|
775 | - if ($model instanceof EEM_CPT_Base) { |
|
776 | - $do_chevy_shuffle = true; |
|
777 | - } else { |
|
778 | - $do_chevy_shuffle = false; |
|
779 | - } |
|
780 | - if ($do_chevy_shuffle) { |
|
781 | - global $post; |
|
782 | - $old_post = $post; |
|
783 | - $post = get_post($result[ $model->primary_key_name() ]); |
|
784 | - if (! $post instanceof WP_Post) { |
|
785 | - // well that's weird, because $result is what we JUST fetched from the database |
|
786 | - throw new RestException( |
|
787 | - 'error_fetching_post_from_database_results', |
|
788 | - esc_html__( |
|
789 | - 'An item was retrieved from the database but it\'s not a WP_Post like it should be.', |
|
790 | - 'event_espresso' |
|
791 | - ) |
|
792 | - ); |
|
793 | - } |
|
794 | - $model_object_classname = 'EE_' . $model->get_this_model_name(); |
|
795 | - $post->{$model_object_classname} = EE_Registry::instance()->load_class( |
|
796 | - $model_object_classname, |
|
797 | - $result, |
|
798 | - false, |
|
799 | - false |
|
800 | - ); |
|
801 | - } |
|
802 | - foreach ($result as $field_name => $field_value) { |
|
803 | - $field_obj = $model->field_settings_for($field_name); |
|
804 | - if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) { |
|
805 | - unset($result[ $field_name ]); |
|
806 | - } elseif ( |
|
807 | - $this->isSubclassOfOne( |
|
808 | - $field_obj, |
|
809 | - $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat() |
|
810 | - ) |
|
811 | - ) { |
|
812 | - $result[ $field_name ] = [ |
|
813 | - 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
|
814 | - 'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
|
815 | - ]; |
|
816 | - } elseif ( |
|
817 | - $this->isSubclassOfOne( |
|
818 | - $field_obj, |
|
819 | - $this->getModelVersionInfo()->fieldsThatHavePrettyFormat() |
|
820 | - ) |
|
821 | - ) { |
|
822 | - $result[ $field_name ] = [ |
|
823 | - 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
|
824 | - 'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
|
825 | - ]; |
|
826 | - } elseif ($field_obj instanceof EE_Datetime_Field) { |
|
827 | - $field_value = $field_obj->prepare_for_set_from_db($field_value); |
|
828 | - // if the value is null, but we're not supposed to permit null, then set to the field's default |
|
829 | - if (is_null($field_value)) { |
|
830 | - $field_value = $field_obj->getDefaultDateTimeObj(); |
|
831 | - } |
|
832 | - if (is_null($field_value)) { |
|
833 | - $gmt_date = $local_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
834 | - $field_obj, |
|
835 | - $field_value, |
|
836 | - $this->getModelVersionInfo()->requestedVersion() |
|
837 | - ); |
|
838 | - } else { |
|
839 | - $timezone = $field_value->getTimezone(); |
|
840 | - EEH_DTT_Helper::setTimezone($field_value, new DateTimeZone('UTC')); |
|
841 | - $gmt_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
842 | - $field_obj, |
|
843 | - $field_value, |
|
844 | - $this->getModelVersionInfo()->requestedVersion() |
|
845 | - ); |
|
846 | - EEH_DTT_Helper::setTimezone($field_value, $timezone); |
|
847 | - $local_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
848 | - $field_obj, |
|
849 | - $field_value, |
|
850 | - $this->getModelVersionInfo()->requestedVersion() |
|
851 | - ); |
|
852 | - } |
|
853 | - $result[ $field_name . '_gmt' ] = $gmt_date; |
|
854 | - $result[ $field_name ] = $local_date; |
|
855 | - } else { |
|
856 | - $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value); |
|
857 | - } |
|
858 | - } |
|
859 | - if ($do_chevy_shuffle) { |
|
860 | - $post = $old_post; |
|
861 | - } |
|
862 | - return $result; |
|
863 | - } |
|
864 | - |
|
865 | - |
|
866 | - /** |
|
867 | - * Takes a value all the way from the DB representation, to the model object's representation, to the |
|
868 | - * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB |
|
869 | - * representation using $field_obj->prepare_for_set_from_db()) |
|
870 | - * |
|
871 | - * @param EE_Model_Field_Base $field_obj |
|
872 | - * @param mixed $value as it's stored on a model object |
|
873 | - * @param string $format valid values are 'normal' (default), 'pretty', 'datetime_obj' |
|
874 | - * @return array |
|
875 | - * @throws RestException if $value contains a PHP object |
|
876 | - * @throws EE_Error |
|
877 | - */ |
|
878 | - protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal') |
|
879 | - { |
|
880 | - $value = $field_obj->prepare_for_set_from_db($value); |
|
881 | - switch ($format) { |
|
882 | - case 'pretty': |
|
883 | - $value = $field_obj->prepare_for_pretty_echoing($value); |
|
884 | - break; |
|
885 | - case 'normal': |
|
886 | - default: |
|
887 | - $value = $field_obj->prepare_for_get($value); |
|
888 | - break; |
|
889 | - } |
|
890 | - return ModelDataTranslator::prepareFieldValuesForJson( |
|
891 | - $field_obj, |
|
892 | - $value, |
|
893 | - $this->getModelVersionInfo()->requestedVersion() |
|
894 | - ); |
|
895 | - } |
|
896 | - |
|
897 | - |
|
898 | - /** |
|
899 | - * Adds a few extra fields to the entity response |
|
900 | - * |
|
901 | - * @param EEM_Base $model |
|
902 | - * @param array $db_row |
|
903 | - * @param array $entity_array |
|
904 | - * @return array modified entity |
|
905 | - * @throws EE_Error |
|
906 | - * @throws EE_Error |
|
907 | - */ |
|
908 | - protected function addExtraFields(EEM_Base $model, $db_row, $entity_array) |
|
909 | - { |
|
910 | - if ($model instanceof EEM_CPT_Base) { |
|
911 | - $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]); |
|
912 | - } |
|
913 | - return $entity_array; |
|
914 | - } |
|
915 | - |
|
916 | - |
|
917 | - /** |
|
918 | - * Gets links we want to add to the response |
|
919 | - * |
|
920 | - * @param EEM_Base $model |
|
921 | - * @param array $db_row |
|
922 | - * @param array $entity_array |
|
923 | - * @return array the _links item in the entity |
|
924 | - * @throws EE_Error |
|
925 | - * @throws EE_Error |
|
926 | - * @global WP_REST_Server $wp_rest_server |
|
927 | - */ |
|
928 | - protected function getEntityLinks($model, $db_row, $entity_array) |
|
929 | - { |
|
930 | - // add basic links |
|
931 | - $links = []; |
|
932 | - if ($model->has_primary_key_field()) { |
|
933 | - $links['self'] = [ |
|
934 | - [ |
|
935 | - 'href' => $this->getVersionedLinkTo( |
|
936 | - EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
937 | - . '/' |
|
938 | - . $entity_array[ $model->primary_key_name() ] |
|
939 | - ), |
|
940 | - ], |
|
941 | - ]; |
|
942 | - } |
|
943 | - $links['collection'] = [ |
|
944 | - [ |
|
945 | - 'href' => $this->getVersionedLinkTo( |
|
946 | - EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
947 | - ), |
|
948 | - ], |
|
949 | - ]; |
|
950 | - // add links to related models |
|
951 | - if ($model->has_primary_key_field()) { |
|
952 | - foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) { |
|
953 | - $related_model_part = |
|
954 | - Read::getRelatedEntityName($relation_name, $relation_obj); |
|
955 | - $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = [ |
|
956 | - [ |
|
957 | - 'href' => $this->getVersionedLinkTo( |
|
958 | - EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
959 | - . '/' |
|
960 | - . $entity_array[ $model->primary_key_name() ] |
|
961 | - . '/' |
|
962 | - . $related_model_part |
|
963 | - ), |
|
964 | - 'single' => $relation_obj instanceof EE_Belongs_To_Relation, |
|
965 | - ], |
|
966 | - ]; |
|
967 | - } |
|
968 | - } |
|
969 | - return $links; |
|
970 | - } |
|
971 | - |
|
972 | - |
|
973 | - /** |
|
974 | - * Adds the included models indicated in the request to the entity provided |
|
975 | - * |
|
976 | - * @param EEM_Base $model |
|
977 | - * @param WP_REST_Request $rest_request |
|
978 | - * @param array $entity_array |
|
979 | - * @param array $db_row |
|
980 | - * @param boolean $included_items_protected if the original item is password protected, don't include any |
|
981 | - * related models. |
|
982 | - * @return array the modified entity |
|
983 | - * @throws EE_Error |
|
984 | - * @throws ReflectionException |
|
985 | - */ |
|
986 | - protected function includeRequestedModels( |
|
987 | - EEM_Base $model, |
|
988 | - WP_REST_Request $rest_request, |
|
989 | - $entity_array, |
|
990 | - $db_row = [], |
|
991 | - $included_items_protected = false |
|
992 | - ) { |
|
993 | - // if $db_row not included, hope the entity array has what we need |
|
994 | - if (! $db_row) { |
|
995 | - $db_row = $entity_array; |
|
996 | - } |
|
997 | - $relation_settings = $this->getModelVersionInfo()->relationSettings($model); |
|
998 | - foreach ($relation_settings as $relation_name => $relation_obj) { |
|
999 | - $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith( |
|
1000 | - $rest_request->get_param('include'), |
|
1001 | - $relation_name |
|
1002 | - ); |
|
1003 | - $related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith( |
|
1004 | - $rest_request->get_param('calculate'), |
|
1005 | - $relation_name |
|
1006 | - ); |
|
1007 | - // did they specify they wanted to include a related model, or |
|
1008 | - // specific fields from a related model? |
|
1009 | - // or did they specify to calculate a field from a related model? |
|
1010 | - if ($related_fields_to_include || $related_fields_to_calculate) { |
|
1011 | - // if so, we should include at least some part of the related model |
|
1012 | - $pretend_related_request = new WP_REST_Request(); |
|
1013 | - $pretend_related_request->set_query_params( |
|
1014 | - [ |
|
1015 | - 'caps' => $rest_request->get_param('caps'), |
|
1016 | - 'include' => $related_fields_to_include, |
|
1017 | - 'calculate' => $related_fields_to_calculate, |
|
1018 | - 'password' => $rest_request->get_param('password'), |
|
1019 | - ] |
|
1020 | - ); |
|
1021 | - $pretend_related_request->add_header('no_rest_headers', true); |
|
1022 | - $primary_model_query_params = $model->alter_query_params_to_restrict_by_ID( |
|
1023 | - $model->get_index_primary_key_string( |
|
1024 | - $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
1025 | - ) |
|
1026 | - ); |
|
1027 | - if (! $included_items_protected) { |
|
1028 | - try { |
|
1029 | - $related_results = $this->getEntitiesFromRelationUsingModelQueryParams( |
|
1030 | - $primary_model_query_params, |
|
1031 | - $relation_obj, |
|
1032 | - $pretend_related_request |
|
1033 | - ); |
|
1034 | - } catch (RestException $e) { |
|
1035 | - $related_results = null; |
|
1036 | - } |
|
1037 | - } else { |
|
1038 | - // they're protected, hide them. |
|
1039 | - $related_results = null; |
|
1040 | - $entity_array['_protected'][] = Read::getRelatedEntityName($relation_name, $relation_obj); |
|
1041 | - } |
|
1042 | - if ($related_results instanceof WP_Error || $related_results === null) { |
|
1043 | - $related_results = |
|
1044 | - $relation_obj instanceof EE_Belongs_To_Relation |
|
1045 | - ? null |
|
1046 | - : []; |
|
1047 | - } |
|
1048 | - $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results; |
|
1049 | - } |
|
1050 | - } |
|
1051 | - return $entity_array; |
|
1052 | - } |
|
1053 | - |
|
1054 | - |
|
1055 | - /** |
|
1056 | - * If the user has requested only specific properties (including meta properties like _links or _protected) |
|
1057 | - * remove everything else. |
|
1058 | - * |
|
1059 | - * @param EEM_Base $model |
|
1060 | - * @param WP_REST_Request $rest_request |
|
1061 | - * @param $entity_array |
|
1062 | - * @return array |
|
1063 | - * @throws EE_Error |
|
1064 | - * @since 4.9.74.p |
|
1065 | - */ |
|
1066 | - protected function includeOnlyRequestedProperties( |
|
1067 | - EEM_Base $model, |
|
1068 | - WP_REST_Request $rest_request, |
|
1069 | - $entity_array |
|
1070 | - ) { |
|
1071 | - |
|
1072 | - $includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), ''); |
|
1073 | - $includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model); |
|
1074 | - // if they passed in * or didn't specify any includes, return everything |
|
1075 | - if ( |
|
1076 | - ! in_array('*', $includes_for_this_model) |
|
1077 | - && ! empty($includes_for_this_model) |
|
1078 | - ) { |
|
1079 | - if ($model->has_primary_key_field()) { |
|
1080 | - // always include the primary key. ya just gotta know that at least |
|
1081 | - $includes_for_this_model[] = $model->primary_key_name(); |
|
1082 | - } |
|
1083 | - if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) { |
|
1084 | - $includes_for_this_model[] = '_calculated_fields'; |
|
1085 | - } |
|
1086 | - $entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model)); |
|
1087 | - } |
|
1088 | - return $entity_array; |
|
1089 | - } |
|
1090 | - |
|
1091 | - |
|
1092 | - /** |
|
1093 | - * Returns a new array with all the names of models removed. Eg |
|
1094 | - * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' ) |
|
1095 | - * |
|
1096 | - * @param array $arr |
|
1097 | - * @return array |
|
1098 | - */ |
|
1099 | - private function removeModelNamesFromArray($arr) |
|
1100 | - { |
|
1101 | - return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models)); |
|
1102 | - } |
|
1103 | - |
|
1104 | - |
|
1105 | - /** |
|
1106 | - * Gets the calculated fields for the response |
|
1107 | - * |
|
1108 | - * @param EEM_Base $model |
|
1109 | - * @param array $wpdb_row |
|
1110 | - * @param WP_REST_Request $rest_request |
|
1111 | - * @param boolean $row_is_protected whether this row is password protected or not |
|
1112 | - * @return stdClass the _calculations item in the entity |
|
1113 | - * @throws RestException if a default value has a PHP object, which should never do (and if we |
|
1114 | - * @throws EE_Error |
|
1115 | - * did, let's know about it ASAP, so let the exception bubble up) |
|
1116 | - */ |
|
1117 | - protected function getEntityCalculations($model, $wpdb_row, $rest_request, $row_is_protected = false) |
|
1118 | - { |
|
1119 | - $calculated_fields = $this->explodeAndGetItemsPrefixedWith( |
|
1120 | - $rest_request->get_param('calculate'), |
|
1121 | - '' |
|
1122 | - ); |
|
1123 | - // note: setting calculate=* doesn't do anything |
|
1124 | - $calculated_fields_to_return = new stdClass(); |
|
1125 | - $protected_fields = []; |
|
1126 | - foreach ($calculated_fields as $field_to_calculate) { |
|
1127 | - try { |
|
1128 | - // it's password protected, so they shouldn't be able to read this. Remove the value |
|
1129 | - $schema = $this->fields_calculator->getJsonSchemaForModel($model); |
|
1130 | - if ( |
|
1131 | - $row_is_protected |
|
1132 | - && isset($schema['properties'][ $field_to_calculate ]['protected']) |
|
1133 | - && $schema['properties'][ $field_to_calculate ]['protected'] |
|
1134 | - ) { |
|
1135 | - $calculated_value = null; |
|
1136 | - $protected_fields[] = $field_to_calculate; |
|
1137 | - if ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1138 | - switch ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1139 | - case 'boolean': |
|
1140 | - $calculated_value = false; |
|
1141 | - break; |
|
1142 | - case 'integer': |
|
1143 | - $calculated_value = 0; |
|
1144 | - break; |
|
1145 | - case 'string': |
|
1146 | - $calculated_value = ''; |
|
1147 | - break; |
|
1148 | - case 'array': |
|
1149 | - $calculated_value = []; |
|
1150 | - break; |
|
1151 | - case 'object': |
|
1152 | - $calculated_value = new stdClass(); |
|
1153 | - break; |
|
1154 | - } |
|
1155 | - } |
|
1156 | - } else { |
|
1157 | - $calculated_value = ModelDataTranslator::prepareFieldValueForJson( |
|
1158 | - null, |
|
1159 | - $this->fields_calculator->retrieveCalculatedFieldValue( |
|
1160 | - $model, |
|
1161 | - $field_to_calculate, |
|
1162 | - $wpdb_row, |
|
1163 | - $rest_request, |
|
1164 | - $this |
|
1165 | - ), |
|
1166 | - $this->getModelVersionInfo()->requestedVersion() |
|
1167 | - ); |
|
1168 | - } |
|
1169 | - $calculated_fields_to_return->{$field_to_calculate} = $calculated_value; |
|
1170 | - } catch (RestException $e) { |
|
1171 | - // if we don't have permission to read it, just leave it out. but let devs know about the problem |
|
1172 | - $this->setResponseHeader( |
|
1173 | - 'Notices-Field-Calculation-Errors[' |
|
1174 | - . $e->getStringCode() |
|
1175 | - . '][' |
|
1176 | - . $model->get_this_model_name() |
|
1177 | - . '][' |
|
1178 | - . $field_to_calculate |
|
1179 | - . ']', |
|
1180 | - $e->getMessage(), |
|
1181 | - true |
|
1182 | - ); |
|
1183 | - } |
|
1184 | - } |
|
1185 | - $calculated_fields_to_return->_protected = $protected_fields; |
|
1186 | - return $calculated_fields_to_return; |
|
1187 | - } |
|
1188 | - |
|
1189 | - |
|
1190 | - /** |
|
1191 | - * Gets the full URL to the resource, taking the requested version into account |
|
1192 | - * |
|
1193 | - * @param string $link_part_after_version_and_slash eg "events/10/datetimes" |
|
1194 | - * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes" |
|
1195 | - * @throws EE_Error |
|
1196 | - * @throws EE_Error |
|
1197 | - */ |
|
1198 | - public function getVersionedLinkTo($link_part_after_version_and_slash) |
|
1199 | - { |
|
1200 | - return rest_url( |
|
1201 | - EED_Core_Rest_Api::get_versioned_route_to( |
|
1202 | - $link_part_after_version_and_slash, |
|
1203 | - $this->getModelVersionInfo()->requestedVersion() |
|
1204 | - ) |
|
1205 | - ); |
|
1206 | - } |
|
1207 | - |
|
1208 | - |
|
1209 | - /** |
|
1210 | - * Gets the correct lowercase name for the relation in the API according |
|
1211 | - * to the relation's type |
|
1212 | - * |
|
1213 | - * @param string $relation_name |
|
1214 | - * @param EE_Model_Relation_Base $relation_obj |
|
1215 | - * @return string |
|
1216 | - */ |
|
1217 | - public static function getRelatedEntityName($relation_name, $relation_obj) |
|
1218 | - { |
|
1219 | - if ($relation_obj instanceof EE_Belongs_To_Relation) { |
|
1220 | - return strtolower($relation_name); |
|
1221 | - } else { |
|
1222 | - return EEH_Inflector::pluralize_and_lower($relation_name); |
|
1223 | - } |
|
1224 | - } |
|
1225 | - |
|
1226 | - |
|
1227 | - /** |
|
1228 | - * Gets the one model object with the specified id for the specified model |
|
1229 | - * |
|
1230 | - * @param EEM_Base $model |
|
1231 | - * @param WP_REST_Request $request |
|
1232 | - * @return array |
|
1233 | - * @throws EE_Error |
|
1234 | - * @throws EE_Error |
|
1235 | - * @throws ReflectionException |
|
1236 | - */ |
|
1237 | - public function getEntityFromModel($model, $request) |
|
1238 | - { |
|
1239 | - $context = $this->validateContext($request->get_param('caps')); |
|
1240 | - return $this->getOneOrReportPermissionError($model, $request, $context); |
|
1241 | - } |
|
1242 | - |
|
1243 | - |
|
1244 | - /** |
|
1245 | - * If a context is provided which isn't valid, maybe it was added in a future |
|
1246 | - * version so just treat it as a default read |
|
1247 | - * |
|
1248 | - * @param string $context |
|
1249 | - * @return string array key of EEM_Base::cap_contexts_to_cap_action_map() |
|
1250 | - */ |
|
1251 | - public function validateContext($context) |
|
1252 | - { |
|
1253 | - if (! $context) { |
|
1254 | - $context = EEM_Base::caps_read; |
|
1255 | - } |
|
1256 | - $valid_contexts = EEM_Base::valid_cap_contexts(); |
|
1257 | - if (in_array($context, $valid_contexts)) { |
|
1258 | - return $context; |
|
1259 | - } else { |
|
1260 | - return EEM_Base::caps_read; |
|
1261 | - } |
|
1262 | - } |
|
1263 | - |
|
1264 | - |
|
1265 | - /** |
|
1266 | - * Verifies the passed in value is an allowable default where conditions value. |
|
1267 | - * |
|
1268 | - * @param $default_query_params |
|
1269 | - * @return string |
|
1270 | - */ |
|
1271 | - public function validateDefaultQueryParams($default_query_params) |
|
1272 | - { |
|
1273 | - $valid_default_where_conditions_for_api_calls = [ |
|
1274 | - EEM_Base::default_where_conditions_all, |
|
1275 | - EEM_Base::default_where_conditions_minimum_all, |
|
1276 | - EEM_Base::default_where_conditions_minimum_others, |
|
1277 | - ]; |
|
1278 | - if (! $default_query_params) { |
|
1279 | - $default_query_params = EEM_Base::default_where_conditions_all; |
|
1280 | - } |
|
1281 | - if ( |
|
1282 | - in_array( |
|
1283 | - $default_query_params, |
|
1284 | - $valid_default_where_conditions_for_api_calls, |
|
1285 | - true |
|
1286 | - ) |
|
1287 | - ) { |
|
1288 | - return $default_query_params; |
|
1289 | - } |
|
1290 | - return EEM_Base::default_where_conditions_all; |
|
1291 | - } |
|
1292 | - |
|
1293 | - |
|
1294 | - /** |
|
1295 | - * Translates API filter get parameter into model query params @see |
|
1296 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions. |
|
1297 | - * Note: right now the query parameter keys for fields (and related fields) can be left as-is, but it's quite |
|
1298 | - * possible this will change someday. Also, this method's contents might be candidate for moving to |
|
1299 | - * Model_Data_Translator |
|
1300 | - * |
|
1301 | - * @param EEM_Base $model |
|
1302 | - * @param array $query_params |
|
1303 | - * @return array model query params (@see |
|
1304 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions) |
|
1305 | - * or FALSE to indicate that absolutely no results should be returned |
|
1306 | - * @throws EE_Error |
|
1307 | - * @throws RestException |
|
1308 | - */ |
|
1309 | - public function createModelQueryParams($model, $query_params) |
|
1310 | - { |
|
1311 | - $model_query_params = []; |
|
1312 | - if (isset($query_params['where'])) { |
|
1313 | - $model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
1314 | - $query_params['where'], |
|
1315 | - $model, |
|
1316 | - $this->getModelVersionInfo()->requestedVersion() |
|
1317 | - ); |
|
1318 | - } |
|
1319 | - if (isset($query_params['order_by'])) { |
|
1320 | - $order_by = $query_params['order_by']; |
|
1321 | - } elseif (isset($query_params['orderby'])) { |
|
1322 | - $order_by = $query_params['orderby']; |
|
1323 | - } else { |
|
1324 | - $order_by = null; |
|
1325 | - } |
|
1326 | - if ($order_by !== null) { |
|
1327 | - if (is_array($order_by)) { |
|
1328 | - $order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by); |
|
1329 | - } else { |
|
1330 | - // it's a single item |
|
1331 | - $order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by); |
|
1332 | - } |
|
1333 | - $model_query_params['order_by'] = $order_by; |
|
1334 | - } |
|
1335 | - if (isset($query_params['group_by'])) { |
|
1336 | - $group_by = $query_params['group_by']; |
|
1337 | - } elseif (isset($query_params['groupby'])) { |
|
1338 | - $group_by = $query_params['groupby']; |
|
1339 | - } else { |
|
1340 | - $group_by = array_keys($model->get_combined_primary_key_fields()); |
|
1341 | - } |
|
1342 | - // make sure they're all real names |
|
1343 | - if (is_array($group_by)) { |
|
1344 | - $group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by); |
|
1345 | - } |
|
1346 | - if ($group_by !== null) { |
|
1347 | - $model_query_params['group_by'] = $group_by; |
|
1348 | - } |
|
1349 | - if (isset($query_params['having'])) { |
|
1350 | - $model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
1351 | - $query_params['having'], |
|
1352 | - $model, |
|
1353 | - $this->getModelVersionInfo()->requestedVersion() |
|
1354 | - ); |
|
1355 | - } |
|
1356 | - if (isset($query_params['order'])) { |
|
1357 | - $model_query_params['order'] = $query_params['order']; |
|
1358 | - } |
|
1359 | - if (isset($query_params['mine'])) { |
|
1360 | - $model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params); |
|
1361 | - } |
|
1362 | - if (isset($query_params['limit'])) { |
|
1363 | - // limit should be either a string like '23' or '23,43', or an array with two items in it |
|
1364 | - if (! is_array($query_params['limit'])) { |
|
1365 | - $limit_array = explode(',', (string) $query_params['limit']); |
|
1366 | - } else { |
|
1367 | - $limit_array = $query_params['limit']; |
|
1368 | - } |
|
1369 | - $sanitized_limit = []; |
|
1370 | - foreach ($limit_array as $limit_part) { |
|
1371 | - if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) { |
|
1372 | - throw new EE_Error( |
|
1373 | - sprintf( |
|
1374 | - esc_html__( |
|
1375 | - // @codingStandardsIgnoreStart |
|
1376 | - 'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.', |
|
1377 | - // @codingStandardsIgnoreEnd |
|
1378 | - 'event_espresso' |
|
1379 | - ), |
|
1380 | - wp_json_encode($query_params['limit']) |
|
1381 | - ) |
|
1382 | - ); |
|
1383 | - } |
|
1384 | - $sanitized_limit[] = (int) $limit_part; |
|
1385 | - } |
|
1386 | - $model_query_params['limit'] = implode(',', $sanitized_limit); |
|
1387 | - } else { |
|
1388 | - $model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
|
1389 | - } |
|
1390 | - if (isset($query_params['caps'])) { |
|
1391 | - $model_query_params['caps'] = $this->validateContext($query_params['caps']); |
|
1392 | - } else { |
|
1393 | - $model_query_params['caps'] = EEM_Base::caps_read; |
|
1394 | - } |
|
1395 | - if (isset($query_params['default_where_conditions'])) { |
|
1396 | - $model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams( |
|
1397 | - $query_params['default_where_conditions'] |
|
1398 | - ); |
|
1399 | - } |
|
1400 | - // if this is a model protected by a password on another model, exclude the password protected |
|
1401 | - // entities by default. But if they passed in a password, try to show them all. If the password is wrong, |
|
1402 | - // though, they'll get an error (see Read::createEntityFromWpdbResult() which calls Read::checkPassword) |
|
1403 | - if ( |
|
1404 | - ! $model->hasPassword() |
|
1405 | - && $model->restrictedByRelatedModelPassword() |
|
1406 | - && $model_query_params['caps'] === EEM_Base::caps_read |
|
1407 | - ) { |
|
1408 | - if (empty($query_params['password'])) { |
|
1409 | - $model_query_params['exclude_protected'] = true; |
|
1410 | - } |
|
1411 | - } |
|
1412 | - |
|
1413 | - return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_params, $model); |
|
1414 | - } |
|
1415 | - |
|
1416 | - |
|
1417 | - /** |
|
1418 | - * Changes the REST-style query params for use in the models |
|
1419 | - * |
|
1420 | - * @param EEM_Base $model |
|
1421 | - * @param array $query_params sub-array from @see EEM_Base::get_all() |
|
1422 | - * @return array |
|
1423 | - * @deprecated |
|
1424 | - */ |
|
1425 | - public function prepareRestQueryParamsKeyForModels($model, $query_params) |
|
1426 | - { |
|
1427 | - $model_ready_query_params = []; |
|
1428 | - foreach ($query_params as $key => $value) { |
|
1429 | - $model_ready_query_params[ $key ] = is_array($value) |
|
1430 | - ? $this->prepareRestQueryParamsKeyForModels($model, $value) |
|
1431 | - : $value; |
|
1432 | - } |
|
1433 | - return $model_ready_query_params; |
|
1434 | - } |
|
1435 | - |
|
1436 | - |
|
1437 | - /** |
|
1438 | - * @param $model |
|
1439 | - * @param $query_params |
|
1440 | - * @return array |
|
1441 | - * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson() |
|
1442 | - */ |
|
1443 | - public function prepareRestQueryParamsValuesForModels($model, $query_params) |
|
1444 | - { |
|
1445 | - $model_ready_query_params = []; |
|
1446 | - foreach ($query_params as $key => $value) { |
|
1447 | - if (is_array($value)) { |
|
1448 | - $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value); |
|
1449 | - } else { |
|
1450 | - $model_ready_query_params[ $key ] = $value; |
|
1451 | - } |
|
1452 | - } |
|
1453 | - return $model_ready_query_params; |
|
1454 | - } |
|
1455 | - |
|
1456 | - |
|
1457 | - /** |
|
1458 | - * Explodes the string on commas, and only returns items with $prefix followed by a period. |
|
1459 | - * If no prefix is specified, returns items with no period. |
|
1460 | - * |
|
1461 | - * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' ) |
|
1462 | - * @param string $prefix "Event" or "foobar" |
|
1463 | - * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified |
|
1464 | - * we only return strings starting with that and a period; if no prefix was |
|
1465 | - * specified we return all items containing NO periods |
|
1466 | - */ |
|
1467 | - public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix) |
|
1468 | - { |
|
1469 | - if (is_string($string_to_explode)) { |
|
1470 | - $exploded_contents = explode(',', $string_to_explode); |
|
1471 | - } elseif (is_array($string_to_explode)) { |
|
1472 | - $exploded_contents = $string_to_explode; |
|
1473 | - } else { |
|
1474 | - $exploded_contents = []; |
|
1475 | - } |
|
1476 | - // if the string was empty, we want an empty array |
|
1477 | - $exploded_contents = array_filter($exploded_contents); |
|
1478 | - $contents_with_prefix = []; |
|
1479 | - foreach ($exploded_contents as $item) { |
|
1480 | - $item = trim($item); |
|
1481 | - // if no prefix was provided, so we look for items with no "." in them |
|
1482 | - if (! $prefix) { |
|
1483 | - // does this item have a period? |
|
1484 | - if (strpos($item, '.') === false) { |
|
1485 | - // if not, then its what we're looking for |
|
1486 | - $contents_with_prefix[] = $item; |
|
1487 | - } |
|
1488 | - } elseif (strpos($item, $prefix . '.') === 0) { |
|
1489 | - // this item has the prefix and a period, grab it |
|
1490 | - $contents_with_prefix[] = substr( |
|
1491 | - $item, |
|
1492 | - strpos($item, $prefix . '.') + strlen($prefix . '.') |
|
1493 | - ); |
|
1494 | - } elseif ($item === $prefix) { |
|
1495 | - // this item is JUST the prefix |
|
1496 | - // so let's grab everything after, which is a blank string |
|
1497 | - $contents_with_prefix[] = ''; |
|
1498 | - } |
|
1499 | - } |
|
1500 | - return $contents_with_prefix; |
|
1501 | - } |
|
1502 | - |
|
1503 | - |
|
1504 | - /** |
|
1505 | - * @param string $include_string @see Read:handle_request_get_all |
|
1506 | - * @param string $model_name |
|
1507 | - * @return array of fields for this model. If $model_name is provided, then |
|
1508 | - * the fields for that model, with the model's name removed from each. |
|
1509 | - * If $include_string was blank or '*' returns an empty array |
|
1510 | - * @throws EE_Error |
|
1511 | - * @throws EE_Error |
|
1512 | - * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with. |
|
1513 | - * Deprecated because its return values were really quite confusing- sometimes it |
|
1514 | - * returned an empty array (when the include string was blank or '*') or sometimes it |
|
1515 | - * returned array('*') (when you provided a model and a model of that kind was |
|
1516 | - * found). Parses the $include_string so we fetch all the field names relating to |
|
1517 | - * THIS model |
|
1518 | - * (ie have NO period in them), or for the provided model (ie start with the model |
|
1519 | - * name and then a period). |
|
1520 | - */ |
|
1521 | - public function extractIncludesForThisModel($include_string, $model_name = null) |
|
1522 | - { |
|
1523 | - if (is_array($include_string)) { |
|
1524 | - $include_string = implode(',', $include_string); |
|
1525 | - } |
|
1526 | - if ($include_string === '*' || $include_string === '') { |
|
1527 | - return []; |
|
1528 | - } |
|
1529 | - $includes = explode(',', $include_string); |
|
1530 | - $extracted_fields_to_include = []; |
|
1531 | - if ($model_name) { |
|
1532 | - foreach ($includes as $field_to_include) { |
|
1533 | - $field_to_include = trim($field_to_include); |
|
1534 | - if (strpos($field_to_include, $model_name . '.') === 0) { |
|
1535 | - // found the model name at the exact start |
|
1536 | - $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include); |
|
1537 | - $extracted_fields_to_include[] = $field_sans_model_name; |
|
1538 | - } elseif ($field_to_include == $model_name) { |
|
1539 | - $extracted_fields_to_include[] = '*'; |
|
1540 | - } |
|
1541 | - } |
|
1542 | - } else { |
|
1543 | - // look for ones with no period |
|
1544 | - foreach ($includes as $field_to_include) { |
|
1545 | - $field_to_include = trim($field_to_include); |
|
1546 | - if ( |
|
1547 | - strpos($field_to_include, '.') === false |
|
1548 | - && ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include) |
|
1549 | - ) { |
|
1550 | - $extracted_fields_to_include[] = $field_to_include; |
|
1551 | - } |
|
1552 | - } |
|
1553 | - } |
|
1554 | - return $extracted_fields_to_include; |
|
1555 | - } |
|
1556 | - |
|
1557 | - |
|
1558 | - /** |
|
1559 | - * Gets the single item using the model according to the request in the context given, otherwise |
|
1560 | - * returns that it's inaccessible to the current user |
|
1561 | - * |
|
1562 | - * @param EEM_Base $model |
|
1563 | - * @param WP_REST_Request $request |
|
1564 | - * @param null $context |
|
1565 | - * @return array |
|
1566 | - * @throws EE_Error |
|
1567 | - * @throws ReflectionException |
|
1568 | - */ |
|
1569 | - public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null) |
|
1570 | - { |
|
1571 | - $query_params = [[$model->primary_key_name() => $request->get_param('id')], 'limit' => 1]; |
|
1572 | - if ($model instanceof EEM_Soft_Delete_Base) { |
|
1573 | - $query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params); |
|
1574 | - } |
|
1575 | - $restricted_query_params = $query_params; |
|
1576 | - $restricted_query_params['caps'] = $context; |
|
1577 | - $this->setDebugInfo('model query params', $restricted_query_params); |
|
1578 | - $model_rows = $model->get_all_wpdb_results($restricted_query_params); |
|
1579 | - if (! empty($model_rows)) { |
|
1580 | - return $this->createEntityFromWpdbResult( |
|
1581 | - $model, |
|
1582 | - reset($model_rows), |
|
1583 | - $request |
|
1584 | - ); |
|
1585 | - } else { |
|
1586 | - // ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities |
|
1587 | - $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
1588 | - if ($model->exists($query_params)) { |
|
1589 | - // you got shafted- it existed but we didn't want to tell you! |
|
1590 | - throw new RestException( |
|
1591 | - 'rest_user_cannot_' . $context, |
|
1592 | - sprintf( |
|
1593 | - esc_html__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'), |
|
1594 | - $context, |
|
1595 | - $lowercase_model_name, |
|
1596 | - Capabilities::getMissingPermissionsString( |
|
1597 | - $model, |
|
1598 | - $context |
|
1599 | - ) |
|
1600 | - ), |
|
1601 | - ['status' => 403] |
|
1602 | - ); |
|
1603 | - } else { |
|
1604 | - // it's not you. It just doesn't exist |
|
1605 | - throw new RestException( |
|
1606 | - sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
1607 | - sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
1608 | - ['status' => 404] |
|
1609 | - ); |
|
1610 | - } |
|
1611 | - } |
|
1612 | - } |
|
1613 | - |
|
1614 | - |
|
1615 | - /** |
|
1616 | - * Checks that if this content requires a password to be read, that it's been provided and is correct. |
|
1617 | - * |
|
1618 | - * @param EEM_Base $model |
|
1619 | - * @param array $model_row |
|
1620 | - * @param array $query_params Adds 'default_where_conditions' => 'minimum' |
|
1621 | - * to ensure we don't confuse trashed with password protected. |
|
1622 | - * @param WP_REST_Request $request |
|
1623 | - * @throws EE_Error |
|
1624 | - * @throws InvalidArgumentException |
|
1625 | - * @throws InvalidDataTypeException |
|
1626 | - * @throws InvalidInterfaceException |
|
1627 | - * @throws RestPasswordRequiredException |
|
1628 | - * @throws RestPasswordIncorrectException |
|
1629 | - * @throws ModelConfigurationException |
|
1630 | - * @throws ReflectionException |
|
1631 | - * @since 4.9.74.p |
|
1632 | - */ |
|
1633 | - protected function checkPassword(EEM_Base $model, $model_row, $query_params, WP_REST_Request $request) |
|
1634 | - { |
|
1635 | - $query_params['default_where_conditions'] = 'minimum'; |
|
1636 | - // stuff is only "protected" for front-end requests. Elsewhere, you either get full permission to access the object |
|
1637 | - // or you don't. |
|
1638 | - $request_caps = $request->get_param('caps'); |
|
1639 | - if (isset($request_caps) && $request_caps !== EEM_Base::caps_read) { |
|
1640 | - return; |
|
1641 | - } |
|
1642 | - // if this entity requires a password, they better give it and it better be right! |
|
1643 | - if ( |
|
1644 | - $model->hasPassword() |
|
1645 | - && $model_row[ $model->getPasswordField()->get_qualified_column() ] !== '' |
|
1646 | - ) { |
|
1647 | - if (empty($request['password'])) { |
|
1648 | - throw new RestPasswordRequiredException(); |
|
1649 | - } |
|
1650 | - if ( |
|
1651 | - ! hash_equals( |
|
1652 | - $model_row[ $model->getPasswordField()->get_qualified_column() ], |
|
1653 | - $request['password'] |
|
1654 | - ) |
|
1655 | - ) { |
|
1656 | - throw new RestPasswordIncorrectException(); |
|
1657 | - } |
|
1658 | - } elseif ( |
|
1659 | - // wait! maybe this content is password protected |
|
1660 | - $model->restrictedByRelatedModelPassword() |
|
1661 | - && $request->get_param('caps') === EEM_Base::caps_read |
|
1662 | - ) { |
|
1663 | - $password_supplied = $request->get_param('password'); |
|
1664 | - if (empty($password_supplied)) { |
|
1665 | - $query_params['exclude_protected'] = true; |
|
1666 | - if (! $model->exists($query_params)) { |
|
1667 | - throw new RestPasswordRequiredException(); |
|
1668 | - } |
|
1669 | - } else { |
|
1670 | - $query_params[0][ $model->modelChainAndPassword() ] = $password_supplied; |
|
1671 | - if (! $model->exists($query_params)) { |
|
1672 | - throw new RestPasswordIncorrectException(); |
|
1673 | - } |
|
1674 | - } |
|
1675 | - } |
|
1676 | - } |
|
52 | + /** |
|
53 | + * @var CalculatedModelFields |
|
54 | + */ |
|
55 | + protected $fields_calculator; |
|
56 | + |
|
57 | + |
|
58 | + /** |
|
59 | + * Read constructor. |
|
60 | + * |
|
61 | + * @param CalculatedModelFields $fields_calculator |
|
62 | + */ |
|
63 | + public function __construct(CalculatedModelFields $fields_calculator) |
|
64 | + { |
|
65 | + parent::__construct(); |
|
66 | + $this->fields_calculator = $fields_calculator; |
|
67 | + } |
|
68 | + |
|
69 | + |
|
70 | + /** |
|
71 | + * Handles requests to get all (or a filtered subset) of entities for a particular model |
|
72 | + * |
|
73 | + * @param WP_REST_Request $request |
|
74 | + * @param string $version |
|
75 | + * @param string $model_name |
|
76 | + * @return WP_REST_Response|WP_Error |
|
77 | + * @throws InvalidArgumentException |
|
78 | + * @throws InvalidDataTypeException |
|
79 | + * @throws InvalidInterfaceException |
|
80 | + */ |
|
81 | + public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name) |
|
82 | + { |
|
83 | + $controller = |
|
84 | + LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
85 | + try { |
|
86 | + $controller->setRequestedVersion($version); |
|
87 | + if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
88 | + return $controller->sendResponse( |
|
89 | + new WP_Error( |
|
90 | + 'endpoint_parsing_error', |
|
91 | + sprintf( |
|
92 | + esc_html__( |
|
93 | + 'There is no model for endpoint %s. Please contact event espresso support', |
|
94 | + 'event_espresso' |
|
95 | + ), |
|
96 | + $model_name |
|
97 | + ) |
|
98 | + ) |
|
99 | + ); |
|
100 | + } |
|
101 | + return $controller->sendResponse( |
|
102 | + $controller->getEntitiesFromModel( |
|
103 | + $controller->getModelVersionInfo()->loadModel($model_name), |
|
104 | + $request |
|
105 | + ) |
|
106 | + ); |
|
107 | + } catch (Exception $e) { |
|
108 | + return $controller->sendResponse($e); |
|
109 | + } |
|
110 | + } |
|
111 | + |
|
112 | + |
|
113 | + /** |
|
114 | + * Prepares and returns schema for any OPTIONS request. |
|
115 | + * |
|
116 | + * @param string $version The API endpoint version being used. |
|
117 | + * @param string $model_name Something like `Event` or `Registration` |
|
118 | + * @return array |
|
119 | + * @throws InvalidArgumentException |
|
120 | + * @throws InvalidDataTypeException |
|
121 | + * @throws InvalidInterfaceException |
|
122 | + */ |
|
123 | + public static function handleSchemaRequest($version, $model_name) |
|
124 | + { |
|
125 | + $controller = |
|
126 | + LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
127 | + try { |
|
128 | + $controller->setRequestedVersion($version); |
|
129 | + if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
130 | + return []; |
|
131 | + } |
|
132 | + // get the model for this version |
|
133 | + $model = $controller->getModelVersionInfo()->loadModel($model_name); |
|
134 | + $model_schema = new JsonModelSchema( |
|
135 | + $model, |
|
136 | + LoaderFactory::getLoader()->getShared('EventEspresso\core\libraries\rest_api\CalculatedModelFields') |
|
137 | + ); |
|
138 | + return $model_schema->getModelSchemaForRelations( |
|
139 | + $controller->getModelVersionInfo()->relationSettings($model), |
|
140 | + $controller->customizeSchemaForRestResponse( |
|
141 | + $model, |
|
142 | + $model_schema->getModelSchemaForFields( |
|
143 | + $controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model), |
|
144 | + $model_schema->getInitialSchemaStructure() |
|
145 | + ) |
|
146 | + ) |
|
147 | + ); |
|
148 | + } catch (Exception $e) { |
|
149 | + return []; |
|
150 | + } |
|
151 | + } |
|
152 | + |
|
153 | + |
|
154 | + /** |
|
155 | + * This loops through each field in the given schema for the model and does the following: |
|
156 | + * - add any extra fields that are REST API specific and related to existing fields. |
|
157 | + * - transform default values into the correct format for a REST API response. |
|
158 | + * |
|
159 | + * @param EEM_Base $model |
|
160 | + * @param array $schema |
|
161 | + * @return array The final schema. |
|
162 | + * @throws EE_Error |
|
163 | + * @throws EE_Error |
|
164 | + */ |
|
165 | + protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema) |
|
166 | + { |
|
167 | + foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) { |
|
168 | + $schema = $this->translateDefaultsForRestResponse( |
|
169 | + $field_name, |
|
170 | + $field, |
|
171 | + $this->maybeAddExtraFieldsToSchema($field_name, $field, $schema) |
|
172 | + ); |
|
173 | + } |
|
174 | + return $schema; |
|
175 | + } |
|
176 | + |
|
177 | + |
|
178 | + /** |
|
179 | + * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST |
|
180 | + * response. |
|
181 | + * |
|
182 | + * @param $field_name |
|
183 | + * @param EE_Model_Field_Base $field |
|
184 | + * @param array $schema |
|
185 | + * @return array |
|
186 | + * @throws RestException if a default value has a PHP object, which we should never do |
|
187 | + * (but if we did, let's know about it ASAP, so let the exception bubble up) |
|
188 | + * @throws EE_Error |
|
189 | + * |
|
190 | + */ |
|
191 | + protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema) |
|
192 | + { |
|
193 | + if (isset($schema['properties'][ $field_name ]['default'])) { |
|
194 | + if (is_array($schema['properties'][ $field_name ]['default'])) { |
|
195 | + foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) { |
|
196 | + if ($default_key === 'raw') { |
|
197 | + $schema['properties'][ $field_name ]['default'][ $default_key ] = |
|
198 | + ModelDataTranslator::prepareFieldValueForJson( |
|
199 | + $field, |
|
200 | + $default_value, |
|
201 | + $this->getModelVersionInfo()->requestedVersion() |
|
202 | + ); |
|
203 | + } |
|
204 | + } |
|
205 | + } else { |
|
206 | + $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson( |
|
207 | + $field, |
|
208 | + $schema['properties'][ $field_name ]['default'], |
|
209 | + $this->getModelVersionInfo()->requestedVersion() |
|
210 | + ); |
|
211 | + } |
|
212 | + } |
|
213 | + return $schema; |
|
214 | + } |
|
215 | + |
|
216 | + |
|
217 | + /** |
|
218 | + * Adds additional fields to the schema |
|
219 | + * The REST API returns a GMT value field for each datetime field in the resource. Thus the description about this |
|
220 | + * needs to be added to the schema. |
|
221 | + * |
|
222 | + * @param $field_name |
|
223 | + * @param EE_Model_Field_Base $field |
|
224 | + * @param array $schema |
|
225 | + * @return array |
|
226 | + */ |
|
227 | + protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema) |
|
228 | + { |
|
229 | + if ($field instanceof EE_Datetime_Field) { |
|
230 | + $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema(); |
|
231 | + // modify the description |
|
232 | + $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf( |
|
233 | + esc_html__('%s - the value for this field is in GMT.', 'event_espresso'), |
|
234 | + wp_specialchars_decode($field->get_nicename(), ENT_QUOTES) |
|
235 | + ); |
|
236 | + } |
|
237 | + return $schema; |
|
238 | + } |
|
239 | + |
|
240 | + |
|
241 | + /** |
|
242 | + * Used to figure out the route from the request when a `WP_REST_Request` object is not available |
|
243 | + * |
|
244 | + * @return string |
|
245 | + */ |
|
246 | + protected function getRouteFromRequest() |
|
247 | + { |
|
248 | + if ( |
|
249 | + isset($GLOBALS['wp']) |
|
250 | + && $GLOBALS['wp'] instanceof WP |
|
251 | + && isset($GLOBALS['wp']->query_vars['rest_route']) |
|
252 | + ) { |
|
253 | + return $GLOBALS['wp']->query_vars['rest_route']; |
|
254 | + } else { |
|
255 | + /** @var RequestInterface $request */ |
|
256 | + $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
257 | + return $request->serverParamIsSet('PATH_INFO') |
|
258 | + ? $request->getServerParam('PATH_INFO') |
|
259 | + : '/'; |
|
260 | + } |
|
261 | + } |
|
262 | + |
|
263 | + |
|
264 | + /** |
|
265 | + * Gets a single entity related to the model indicated in the path and its id |
|
266 | + * |
|
267 | + * @param WP_REST_Request $request |
|
268 | + * @param string $version |
|
269 | + * @param string $model_name |
|
270 | + * @return WP_REST_Response|WP_Error |
|
271 | + * @throws InvalidDataTypeException |
|
272 | + * @throws InvalidInterfaceException |
|
273 | + * @throws InvalidArgumentException |
|
274 | + */ |
|
275 | + public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name) |
|
276 | + { |
|
277 | + $controller = |
|
278 | + LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
279 | + try { |
|
280 | + $controller->setRequestedVersion($version); |
|
281 | + if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
282 | + return $controller->sendResponse( |
|
283 | + new WP_Error( |
|
284 | + 'endpoint_parsing_error', |
|
285 | + sprintf( |
|
286 | + esc_html__( |
|
287 | + 'There is no model for endpoint %s. Please contact event espresso support', |
|
288 | + 'event_espresso' |
|
289 | + ), |
|
290 | + $model_name |
|
291 | + ) |
|
292 | + ) |
|
293 | + ); |
|
294 | + } |
|
295 | + return $controller->sendResponse( |
|
296 | + $controller->getEntityFromModel( |
|
297 | + $controller->getModelVersionInfo()->loadModel($model_name), |
|
298 | + $request |
|
299 | + ) |
|
300 | + ); |
|
301 | + } catch (Exception $e) { |
|
302 | + return $controller->sendResponse($e); |
|
303 | + } |
|
304 | + } |
|
305 | + |
|
306 | + |
|
307 | + /** |
|
308 | + * Gets all the related entities (or if its a belongs-to relation just the one) |
|
309 | + * to the item with the given id |
|
310 | + * |
|
311 | + * @param WP_REST_Request $request |
|
312 | + * @param string $version |
|
313 | + * @param string $model_name |
|
314 | + * @param string $related_model_name |
|
315 | + * @return WP_REST_Response|WP_Error |
|
316 | + * @throws InvalidDataTypeException |
|
317 | + * @throws InvalidInterfaceException |
|
318 | + * @throws InvalidArgumentException |
|
319 | + */ |
|
320 | + public static function handleRequestGetRelated( |
|
321 | + WP_REST_Request $request, |
|
322 | + $version, |
|
323 | + $model_name, |
|
324 | + $related_model_name |
|
325 | + ) { |
|
326 | + $controller = |
|
327 | + LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
328 | + try { |
|
329 | + $controller->setRequestedVersion($version); |
|
330 | + $main_model = $controller->validateModel($model_name); |
|
331 | + $controller->validateModel($related_model_name); |
|
332 | + return $controller->sendResponse( |
|
333 | + $controller->getEntitiesFromRelation( |
|
334 | + $request->get_param('id'), |
|
335 | + $main_model->related_settings_for($related_model_name), |
|
336 | + $request |
|
337 | + ) |
|
338 | + ); |
|
339 | + } catch (Exception $e) { |
|
340 | + return $controller->sendResponse($e); |
|
341 | + } |
|
342 | + } |
|
343 | + |
|
344 | + |
|
345 | + /** |
|
346 | + * Gets a collection for the given model and filters |
|
347 | + * |
|
348 | + * @param EEM_Base $model |
|
349 | + * @param WP_REST_Request $request |
|
350 | + * @return array |
|
351 | + * @throws EE_Error |
|
352 | + * @throws InvalidArgumentException |
|
353 | + * @throws InvalidDataTypeException |
|
354 | + * @throws InvalidInterfaceException |
|
355 | + * @throws ReflectionException |
|
356 | + * @throws RestException |
|
357 | + */ |
|
358 | + public function getEntitiesFromModel($model, $request) |
|
359 | + { |
|
360 | + $query_params = $this->createModelQueryParams($model, $request->get_params()); |
|
361 | + if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) { |
|
362 | + $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name()); |
|
363 | + throw new RestException( |
|
364 | + sprintf('rest_%s_cannot_list', $model_name_plural), |
|
365 | + sprintf( |
|
366 | + esc_html__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'), |
|
367 | + $model_name_plural, |
|
368 | + Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
|
369 | + ), |
|
370 | + ['status' => 403] |
|
371 | + ); |
|
372 | + } |
|
373 | + if (! $request->get_header('no_rest_headers')) { |
|
374 | + $this->setHeadersFromQueryParams($model, $query_params); |
|
375 | + } |
|
376 | + /** @type array $results */ |
|
377 | + $results = $model->get_all_wpdb_results($query_params); |
|
378 | + $nice_results = []; |
|
379 | + foreach ($results as $result) { |
|
380 | + $nice_results[] = $this->createEntityFromWpdbResult( |
|
381 | + $model, |
|
382 | + $result, |
|
383 | + $request |
|
384 | + ); |
|
385 | + } |
|
386 | + return $nice_results; |
|
387 | + } |
|
388 | + |
|
389 | + |
|
390 | + /** |
|
391 | + * Gets the collection for given relation object |
|
392 | + * The same as Read::get_entities_from_model(), except if the relation |
|
393 | + * is a HABTM relation, in which case it merges any non-foreign-key fields from |
|
394 | + * the join-model-object into the results |
|
395 | + * |
|
396 | + * @param array $primary_model_query_params query params for finding the item from which |
|
397 | + * relations will be based |
|
398 | + * @param EE_Model_Relation_Base $relation |
|
399 | + * @param WP_REST_Request $request |
|
400 | + * @return array |
|
401 | + * @throws EE_Error |
|
402 | + * @throws InvalidArgumentException |
|
403 | + * @throws InvalidDataTypeException |
|
404 | + * @throws InvalidInterfaceException |
|
405 | + * @throws ReflectionException |
|
406 | + * @throws RestException |
|
407 | + * @throws ModelConfigurationException |
|
408 | + */ |
|
409 | + protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request) |
|
410 | + { |
|
411 | + $context = $this->validateContext($request->get_param('caps')); |
|
412 | + $model = $relation->get_this_model(); |
|
413 | + $related_model = $relation->get_other_model(); |
|
414 | + if (! isset($primary_model_query_params[0])) { |
|
415 | + $primary_model_query_params[0] = []; |
|
416 | + } |
|
417 | + // check if they can access the 1st model object |
|
418 | + $primary_model_query_params = [ |
|
419 | + 0 => $primary_model_query_params[0], |
|
420 | + 'limit' => 1, |
|
421 | + ]; |
|
422 | + if ($model instanceof EEM_Soft_Delete_Base) { |
|
423 | + $primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included( |
|
424 | + $primary_model_query_params |
|
425 | + ); |
|
426 | + } |
|
427 | + $restricted_query_params = $primary_model_query_params; |
|
428 | + $restricted_query_params['caps'] = $context; |
|
429 | + $restricted_query_params['limit'] = 1; |
|
430 | + $this->setDebugInfo('main model query params', $restricted_query_params); |
|
431 | + $this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context)); |
|
432 | + $primary_model_rows = $model->get_all_wpdb_results($restricted_query_params); |
|
433 | + $primary_model_row = null; |
|
434 | + if (is_array($primary_model_rows)) { |
|
435 | + $primary_model_row = reset($primary_model_rows); |
|
436 | + } |
|
437 | + if ( |
|
438 | + ! ( |
|
439 | + $primary_model_row |
|
440 | + && Capabilities::currentUserHasPartialAccessTo($related_model, $context) |
|
441 | + ) |
|
442 | + ) { |
|
443 | + if ($relation instanceof EE_Belongs_To_Relation) { |
|
444 | + $related_model_name_maybe_plural = strtolower($related_model->get_this_model_name()); |
|
445 | + } else { |
|
446 | + $related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower( |
|
447 | + $related_model->get_this_model_name() |
|
448 | + ); |
|
449 | + } |
|
450 | + throw new RestException( |
|
451 | + sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural), |
|
452 | + sprintf( |
|
453 | + esc_html__( |
|
454 | + 'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s', |
|
455 | + 'event_espresso' |
|
456 | + ), |
|
457 | + $related_model_name_maybe_plural, |
|
458 | + $relation->get_this_model()->get_this_model_name(), |
|
459 | + implode( |
|
460 | + ',', |
|
461 | + array_keys( |
|
462 | + Capabilities::getMissingPermissions($related_model, $context) |
|
463 | + ) |
|
464 | + ) |
|
465 | + ), |
|
466 | + ['status' => 403] |
|
467 | + ); |
|
468 | + } |
|
469 | + |
|
470 | + $this->checkPassword( |
|
471 | + $model, |
|
472 | + $primary_model_row, |
|
473 | + $restricted_query_params, |
|
474 | + $request |
|
475 | + ); |
|
476 | + $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params()); |
|
477 | + foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) { |
|
478 | + $query_params[0][ $relation->get_this_model()->get_this_model_name() |
|
479 | + . '.' |
|
480 | + . $where_condition_key ] = $where_condition_value; |
|
481 | + } |
|
482 | + $query_params['default_where_conditions'] = 'none'; |
|
483 | + $query_params['caps'] = $context; |
|
484 | + if (! $request->get_header('no_rest_headers')) { |
|
485 | + $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params); |
|
486 | + } |
|
487 | + /** @type array $results */ |
|
488 | + $results = $relation->get_other_model()->get_all_wpdb_results($query_params); |
|
489 | + $nice_results = []; |
|
490 | + foreach ($results as $result) { |
|
491 | + $nice_result = $this->createEntityFromWpdbResult( |
|
492 | + $relation->get_other_model(), |
|
493 | + $result, |
|
494 | + $request |
|
495 | + ); |
|
496 | + if ($relation instanceof EE_HABTM_Relation) { |
|
497 | + // put the unusual stuff (properties from the HABTM relation) first, and make sure |
|
498 | + // if there are conflicts we prefer the properties from the main model |
|
499 | + $join_model_result = $this->createEntityFromWpdbResult( |
|
500 | + $relation->get_join_model(), |
|
501 | + $result, |
|
502 | + $request |
|
503 | + ); |
|
504 | + $joined_result = array_merge($join_model_result, $nice_result); |
|
505 | + // but keep the meta stuff from the main model |
|
506 | + if (isset($nice_result['meta'])) { |
|
507 | + $joined_result['meta'] = $nice_result['meta']; |
|
508 | + } |
|
509 | + $nice_result = $joined_result; |
|
510 | + } |
|
511 | + $nice_results[] = $nice_result; |
|
512 | + } |
|
513 | + if ($relation instanceof EE_Belongs_To_Relation) { |
|
514 | + return array_shift($nice_results); |
|
515 | + } else { |
|
516 | + return $nice_results; |
|
517 | + } |
|
518 | + } |
|
519 | + |
|
520 | + |
|
521 | + /** |
|
522 | + * Gets the collection for given relation object |
|
523 | + * The same as Read::get_entities_from_model(), except if the relation |
|
524 | + * is a HABTM relation, in which case it merges any non-foreign-key fields from |
|
525 | + * the join-model-object into the results |
|
526 | + * |
|
527 | + * @param string $id the ID of the thing we are fetching related stuff from |
|
528 | + * @param EE_Model_Relation_Base $relation |
|
529 | + * @param WP_REST_Request $request |
|
530 | + * @return array |
|
531 | + * @throws EE_Error |
|
532 | + * @throws ReflectionException |
|
533 | + */ |
|
534 | + public function getEntitiesFromRelation($id, $relation, $request) |
|
535 | + { |
|
536 | + if (! $relation->get_this_model()->has_primary_key_field()) { |
|
537 | + throw new EE_Error( |
|
538 | + sprintf( |
|
539 | + esc_html__( |
|
540 | + // @codingStandardsIgnoreStart |
|
541 | + 'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s', |
|
542 | + // @codingStandardsIgnoreEnd |
|
543 | + 'event_espresso' |
|
544 | + ), |
|
545 | + $relation->get_this_model()->get_this_model_name() |
|
546 | + ) |
|
547 | + ); |
|
548 | + } |
|
549 | + // can we edit that main item? |
|
550 | + // if not, show nothing but an error |
|
551 | + // otherwise, please proceed |
|
552 | + return $this->getEntitiesFromRelationUsingModelQueryParams( |
|
553 | + [ |
|
554 | + [ |
|
555 | + $relation->get_this_model()->primary_key_name() => $id, |
|
556 | + ], |
|
557 | + ], |
|
558 | + $relation, |
|
559 | + $request |
|
560 | + ); |
|
561 | + } |
|
562 | + |
|
563 | + |
|
564 | + /** |
|
565 | + * Sets the headers that are based on the model and query params, |
|
566 | + * like the total records. This should only be called on the original request |
|
567 | + * from the client, not on subsequent internal |
|
568 | + * |
|
569 | + * @param EEM_Base $model |
|
570 | + * @param array $query_params |
|
571 | + * @return void |
|
572 | + * @throws EE_Error |
|
573 | + * @throws EE_Error |
|
574 | + */ |
|
575 | + protected function setHeadersFromQueryParams($model, $query_params) |
|
576 | + { |
|
577 | + $this->setDebugInfo('model query params', $query_params); |
|
578 | + $this->setDebugInfo( |
|
579 | + 'missing caps', |
|
580 | + Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
|
581 | + ); |
|
582 | + // normally the limit to a 2-part array, where the 2nd item is the limit |
|
583 | + if (! isset($query_params['limit'])) { |
|
584 | + $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
|
585 | + } |
|
586 | + if (is_array($query_params['limit'])) { |
|
587 | + $limit_parts = $query_params['limit']; |
|
588 | + } else { |
|
589 | + $limit_parts = explode(',', $query_params['limit']); |
|
590 | + if (count($limit_parts) == 1) { |
|
591 | + $limit_parts = [0, $limit_parts[0]]; |
|
592 | + } |
|
593 | + } |
|
594 | + // remove the group by and having parts of the query, as those will |
|
595 | + // make the sql query return an array of values, instead of just a single value |
|
596 | + unset($query_params['group_by'], $query_params['having'], $query_params['limit']); |
|
597 | + $count = $model->count($query_params, null, true); |
|
598 | + $pages = $count / $limit_parts[1]; |
|
599 | + $this->setResponseHeader('Total', $count, false); |
|
600 | + $this->setResponseHeader('PageSize', $limit_parts[1], false); |
|
601 | + $this->setResponseHeader('TotalPages', ceil($pages), false); |
|
602 | + } |
|
603 | + |
|
604 | + |
|
605 | + /** |
|
606 | + * Changes database results into REST API entities |
|
607 | + * |
|
608 | + * @param EEM_Base $model |
|
609 | + * @param array $db_row like results from $wpdb->get_results() |
|
610 | + * @param WP_REST_Request $rest_request |
|
611 | + * @param string $deprecated no longer used |
|
612 | + * @return array ready for being converted into json for sending to client |
|
613 | + * @throws EE_Error |
|
614 | + * @throws RestException |
|
615 | + * @throws InvalidDataTypeException |
|
616 | + * @throws InvalidInterfaceException |
|
617 | + * @throws InvalidArgumentException |
|
618 | + * @throws ReflectionException |
|
619 | + */ |
|
620 | + public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null) |
|
621 | + { |
|
622 | + if (! $rest_request instanceof WP_REST_Request) { |
|
623 | + // ok so this was called in the old style, where the 3rd arg was |
|
624 | + // $include, and the 4th arg was $context |
|
625 | + // now setup the request just to avoid fatal errors, although we won't be able |
|
626 | + // to truly make use of it because it's kinda devoid of info |
|
627 | + $rest_request = new WP_REST_Request(); |
|
628 | + $rest_request->set_param('include', $rest_request); |
|
629 | + $rest_request->set_param('caps', $deprecated); |
|
630 | + } |
|
631 | + if ($rest_request->get_param('caps') == null) { |
|
632 | + $rest_request->set_param('caps', EEM_Base::caps_read); |
|
633 | + } |
|
634 | + $current_user_full_access_to_entity = $model->currentUserCan( |
|
635 | + EEM_Base::caps_read_admin, |
|
636 | + $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
637 | + ); |
|
638 | + $entity_array = $this->createBareEntityFromWpdbResults($model, $db_row); |
|
639 | + $entity_array = $this->addExtraFields($model, $db_row, $entity_array); |
|
640 | + $entity_array['_links'] = $this->getEntityLinks($model, $db_row, $entity_array); |
|
641 | + // when it's a regular read request for a model with a password and the password wasn't provided |
|
642 | + // remove the password protected fields |
|
643 | + $has_protected_fields = false; |
|
644 | + try { |
|
645 | + $this->checkPassword( |
|
646 | + $model, |
|
647 | + $db_row, |
|
648 | + $model->alter_query_params_to_restrict_by_ID( |
|
649 | + $model->get_index_primary_key_string( |
|
650 | + $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
651 | + ) |
|
652 | + ), |
|
653 | + $rest_request |
|
654 | + ); |
|
655 | + } catch (RestPasswordRequiredException $e) { |
|
656 | + if ($model->hasPassword()) { |
|
657 | + // just remove protected fields |
|
658 | + $has_protected_fields = true; |
|
659 | + $entity_array = Capabilities::filterOutPasswordProtectedFields( |
|
660 | + $entity_array, |
|
661 | + $model, |
|
662 | + $this->getModelVersionInfo() |
|
663 | + ); |
|
664 | + } else { |
|
665 | + // that's a problem. None of this should be accessible if no password was provided |
|
666 | + throw $e; |
|
667 | + } |
|
668 | + } |
|
669 | + |
|
670 | + $entity_array['_calculated_fields'] = |
|
671 | + $this->getEntityCalculations($model, $db_row, $rest_request, $has_protected_fields); |
|
672 | + $entity_array = apply_filters( |
|
673 | + 'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models', |
|
674 | + $entity_array, |
|
675 | + $model, |
|
676 | + $rest_request->get_param('caps'), |
|
677 | + $rest_request, |
|
678 | + $this |
|
679 | + ); |
|
680 | + // add an empty protected property for now. If it's still around after we remove everything the request didn't |
|
681 | + // want, we'll populate it then. k? |
|
682 | + $entity_array['_protected'] = []; |
|
683 | + // remove any properties the request didn't want. This way _protected won't bother mentioning them |
|
684 | + $entity_array = $this->includeOnlyRequestedProperties($model, $rest_request, $entity_array); |
|
685 | + $entity_array = |
|
686 | + $this->includeRequestedModels($model, $rest_request, $entity_array, $db_row, $has_protected_fields); |
|
687 | + // if they still wanted the _protected property, add it. |
|
688 | + if (isset($entity_array['_protected'])) { |
|
689 | + $entity_array = $this->addProtectedProperty($model, $entity_array, $has_protected_fields); |
|
690 | + } |
|
691 | + $entity_array = apply_filters( |
|
692 | + 'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal', |
|
693 | + $entity_array, |
|
694 | + $model, |
|
695 | + $rest_request->get_param('caps'), |
|
696 | + $rest_request, |
|
697 | + $this |
|
698 | + ); |
|
699 | + if (! $current_user_full_access_to_entity) { |
|
700 | + $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields( |
|
701 | + $entity_array, |
|
702 | + $model, |
|
703 | + $rest_request->get_param('caps'), |
|
704 | + $this->getModelVersionInfo() |
|
705 | + ); |
|
706 | + } else { |
|
707 | + $result_without_inaccessible_fields = $entity_array; |
|
708 | + } |
|
709 | + $this->setDebugInfo( |
|
710 | + 'inaccessible fields', |
|
711 | + array_keys(array_diff_key((array) $entity_array, (array) $result_without_inaccessible_fields)) |
|
712 | + ); |
|
713 | + return apply_filters( |
|
714 | + 'FHEE__Read__create_entity_from_wpdb_results__entity_return', |
|
715 | + $result_without_inaccessible_fields, |
|
716 | + $model, |
|
717 | + $rest_request->get_param('caps') |
|
718 | + ); |
|
719 | + } |
|
720 | + |
|
721 | + |
|
722 | + /** |
|
723 | + * Returns an array describing which fields can be protected, and which actually were removed this request |
|
724 | + * |
|
725 | + * @param EEM_Base $model |
|
726 | + * @param array $results_so_far |
|
727 | + * @param bool $protected |
|
728 | + * @return array results |
|
729 | + * @throws EE_Error |
|
730 | + * @since 4.9.74.p |
|
731 | + */ |
|
732 | + protected function addProtectedProperty(EEM_Base $model, $results_so_far, $protected) |
|
733 | + { |
|
734 | + if (! $model->hasPassword() || ! $protected) { |
|
735 | + return $results_so_far; |
|
736 | + } |
|
737 | + $password_field = $model->getPasswordField(); |
|
738 | + $all_protected = array_merge( |
|
739 | + [$password_field->get_name()], |
|
740 | + $password_field->protectedFields() |
|
741 | + ); |
|
742 | + $fields_included = array_keys($results_so_far); |
|
743 | + $fields_included = array_intersect( |
|
744 | + $all_protected, |
|
745 | + $fields_included |
|
746 | + ); |
|
747 | + foreach ($fields_included as $field_name) { |
|
748 | + $results_so_far['_protected'][] = $field_name; |
|
749 | + } |
|
750 | + return $results_so_far; |
|
751 | + } |
|
752 | + |
|
753 | + |
|
754 | + /** |
|
755 | + * Creates a REST entity array (JSON object we're going to return in the response, but |
|
756 | + * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry), |
|
757 | + * from $wpdb->get_row( $sql, ARRAY_A) |
|
758 | + * |
|
759 | + * @param EEM_Base $model |
|
760 | + * @param array $db_row |
|
761 | + * @return array entity mostly ready for converting to JSON and sending in the response |
|
762 | + * @throws EE_Error |
|
763 | + * @throws ReflectionException |
|
764 | + * @throws RestException |
|
765 | + */ |
|
766 | + protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row) |
|
767 | + { |
|
768 | + $result = $model->deduce_fields_n_values_from_cols_n_values($db_row); |
|
769 | + $result = array_intersect_key( |
|
770 | + $result, |
|
771 | + $this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) |
|
772 | + ); |
|
773 | + // if this is a CPT, we need to set the global $post to it, |
|
774 | + // otherwise shortcodes etc won't work properly while rendering it |
|
775 | + if ($model instanceof EEM_CPT_Base) { |
|
776 | + $do_chevy_shuffle = true; |
|
777 | + } else { |
|
778 | + $do_chevy_shuffle = false; |
|
779 | + } |
|
780 | + if ($do_chevy_shuffle) { |
|
781 | + global $post; |
|
782 | + $old_post = $post; |
|
783 | + $post = get_post($result[ $model->primary_key_name() ]); |
|
784 | + if (! $post instanceof WP_Post) { |
|
785 | + // well that's weird, because $result is what we JUST fetched from the database |
|
786 | + throw new RestException( |
|
787 | + 'error_fetching_post_from_database_results', |
|
788 | + esc_html__( |
|
789 | + 'An item was retrieved from the database but it\'s not a WP_Post like it should be.', |
|
790 | + 'event_espresso' |
|
791 | + ) |
|
792 | + ); |
|
793 | + } |
|
794 | + $model_object_classname = 'EE_' . $model->get_this_model_name(); |
|
795 | + $post->{$model_object_classname} = EE_Registry::instance()->load_class( |
|
796 | + $model_object_classname, |
|
797 | + $result, |
|
798 | + false, |
|
799 | + false |
|
800 | + ); |
|
801 | + } |
|
802 | + foreach ($result as $field_name => $field_value) { |
|
803 | + $field_obj = $model->field_settings_for($field_name); |
|
804 | + if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) { |
|
805 | + unset($result[ $field_name ]); |
|
806 | + } elseif ( |
|
807 | + $this->isSubclassOfOne( |
|
808 | + $field_obj, |
|
809 | + $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat() |
|
810 | + ) |
|
811 | + ) { |
|
812 | + $result[ $field_name ] = [ |
|
813 | + 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
|
814 | + 'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
|
815 | + ]; |
|
816 | + } elseif ( |
|
817 | + $this->isSubclassOfOne( |
|
818 | + $field_obj, |
|
819 | + $this->getModelVersionInfo()->fieldsThatHavePrettyFormat() |
|
820 | + ) |
|
821 | + ) { |
|
822 | + $result[ $field_name ] = [ |
|
823 | + 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
|
824 | + 'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
|
825 | + ]; |
|
826 | + } elseif ($field_obj instanceof EE_Datetime_Field) { |
|
827 | + $field_value = $field_obj->prepare_for_set_from_db($field_value); |
|
828 | + // if the value is null, but we're not supposed to permit null, then set to the field's default |
|
829 | + if (is_null($field_value)) { |
|
830 | + $field_value = $field_obj->getDefaultDateTimeObj(); |
|
831 | + } |
|
832 | + if (is_null($field_value)) { |
|
833 | + $gmt_date = $local_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
834 | + $field_obj, |
|
835 | + $field_value, |
|
836 | + $this->getModelVersionInfo()->requestedVersion() |
|
837 | + ); |
|
838 | + } else { |
|
839 | + $timezone = $field_value->getTimezone(); |
|
840 | + EEH_DTT_Helper::setTimezone($field_value, new DateTimeZone('UTC')); |
|
841 | + $gmt_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
842 | + $field_obj, |
|
843 | + $field_value, |
|
844 | + $this->getModelVersionInfo()->requestedVersion() |
|
845 | + ); |
|
846 | + EEH_DTT_Helper::setTimezone($field_value, $timezone); |
|
847 | + $local_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
848 | + $field_obj, |
|
849 | + $field_value, |
|
850 | + $this->getModelVersionInfo()->requestedVersion() |
|
851 | + ); |
|
852 | + } |
|
853 | + $result[ $field_name . '_gmt' ] = $gmt_date; |
|
854 | + $result[ $field_name ] = $local_date; |
|
855 | + } else { |
|
856 | + $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value); |
|
857 | + } |
|
858 | + } |
|
859 | + if ($do_chevy_shuffle) { |
|
860 | + $post = $old_post; |
|
861 | + } |
|
862 | + return $result; |
|
863 | + } |
|
864 | + |
|
865 | + |
|
866 | + /** |
|
867 | + * Takes a value all the way from the DB representation, to the model object's representation, to the |
|
868 | + * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB |
|
869 | + * representation using $field_obj->prepare_for_set_from_db()) |
|
870 | + * |
|
871 | + * @param EE_Model_Field_Base $field_obj |
|
872 | + * @param mixed $value as it's stored on a model object |
|
873 | + * @param string $format valid values are 'normal' (default), 'pretty', 'datetime_obj' |
|
874 | + * @return array |
|
875 | + * @throws RestException if $value contains a PHP object |
|
876 | + * @throws EE_Error |
|
877 | + */ |
|
878 | + protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal') |
|
879 | + { |
|
880 | + $value = $field_obj->prepare_for_set_from_db($value); |
|
881 | + switch ($format) { |
|
882 | + case 'pretty': |
|
883 | + $value = $field_obj->prepare_for_pretty_echoing($value); |
|
884 | + break; |
|
885 | + case 'normal': |
|
886 | + default: |
|
887 | + $value = $field_obj->prepare_for_get($value); |
|
888 | + break; |
|
889 | + } |
|
890 | + return ModelDataTranslator::prepareFieldValuesForJson( |
|
891 | + $field_obj, |
|
892 | + $value, |
|
893 | + $this->getModelVersionInfo()->requestedVersion() |
|
894 | + ); |
|
895 | + } |
|
896 | + |
|
897 | + |
|
898 | + /** |
|
899 | + * Adds a few extra fields to the entity response |
|
900 | + * |
|
901 | + * @param EEM_Base $model |
|
902 | + * @param array $db_row |
|
903 | + * @param array $entity_array |
|
904 | + * @return array modified entity |
|
905 | + * @throws EE_Error |
|
906 | + * @throws EE_Error |
|
907 | + */ |
|
908 | + protected function addExtraFields(EEM_Base $model, $db_row, $entity_array) |
|
909 | + { |
|
910 | + if ($model instanceof EEM_CPT_Base) { |
|
911 | + $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]); |
|
912 | + } |
|
913 | + return $entity_array; |
|
914 | + } |
|
915 | + |
|
916 | + |
|
917 | + /** |
|
918 | + * Gets links we want to add to the response |
|
919 | + * |
|
920 | + * @param EEM_Base $model |
|
921 | + * @param array $db_row |
|
922 | + * @param array $entity_array |
|
923 | + * @return array the _links item in the entity |
|
924 | + * @throws EE_Error |
|
925 | + * @throws EE_Error |
|
926 | + * @global WP_REST_Server $wp_rest_server |
|
927 | + */ |
|
928 | + protected function getEntityLinks($model, $db_row, $entity_array) |
|
929 | + { |
|
930 | + // add basic links |
|
931 | + $links = []; |
|
932 | + if ($model->has_primary_key_field()) { |
|
933 | + $links['self'] = [ |
|
934 | + [ |
|
935 | + 'href' => $this->getVersionedLinkTo( |
|
936 | + EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
937 | + . '/' |
|
938 | + . $entity_array[ $model->primary_key_name() ] |
|
939 | + ), |
|
940 | + ], |
|
941 | + ]; |
|
942 | + } |
|
943 | + $links['collection'] = [ |
|
944 | + [ |
|
945 | + 'href' => $this->getVersionedLinkTo( |
|
946 | + EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
947 | + ), |
|
948 | + ], |
|
949 | + ]; |
|
950 | + // add links to related models |
|
951 | + if ($model->has_primary_key_field()) { |
|
952 | + foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) { |
|
953 | + $related_model_part = |
|
954 | + Read::getRelatedEntityName($relation_name, $relation_obj); |
|
955 | + $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = [ |
|
956 | + [ |
|
957 | + 'href' => $this->getVersionedLinkTo( |
|
958 | + EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
959 | + . '/' |
|
960 | + . $entity_array[ $model->primary_key_name() ] |
|
961 | + . '/' |
|
962 | + . $related_model_part |
|
963 | + ), |
|
964 | + 'single' => $relation_obj instanceof EE_Belongs_To_Relation, |
|
965 | + ], |
|
966 | + ]; |
|
967 | + } |
|
968 | + } |
|
969 | + return $links; |
|
970 | + } |
|
971 | + |
|
972 | + |
|
973 | + /** |
|
974 | + * Adds the included models indicated in the request to the entity provided |
|
975 | + * |
|
976 | + * @param EEM_Base $model |
|
977 | + * @param WP_REST_Request $rest_request |
|
978 | + * @param array $entity_array |
|
979 | + * @param array $db_row |
|
980 | + * @param boolean $included_items_protected if the original item is password protected, don't include any |
|
981 | + * related models. |
|
982 | + * @return array the modified entity |
|
983 | + * @throws EE_Error |
|
984 | + * @throws ReflectionException |
|
985 | + */ |
|
986 | + protected function includeRequestedModels( |
|
987 | + EEM_Base $model, |
|
988 | + WP_REST_Request $rest_request, |
|
989 | + $entity_array, |
|
990 | + $db_row = [], |
|
991 | + $included_items_protected = false |
|
992 | + ) { |
|
993 | + // if $db_row not included, hope the entity array has what we need |
|
994 | + if (! $db_row) { |
|
995 | + $db_row = $entity_array; |
|
996 | + } |
|
997 | + $relation_settings = $this->getModelVersionInfo()->relationSettings($model); |
|
998 | + foreach ($relation_settings as $relation_name => $relation_obj) { |
|
999 | + $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith( |
|
1000 | + $rest_request->get_param('include'), |
|
1001 | + $relation_name |
|
1002 | + ); |
|
1003 | + $related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith( |
|
1004 | + $rest_request->get_param('calculate'), |
|
1005 | + $relation_name |
|
1006 | + ); |
|
1007 | + // did they specify they wanted to include a related model, or |
|
1008 | + // specific fields from a related model? |
|
1009 | + // or did they specify to calculate a field from a related model? |
|
1010 | + if ($related_fields_to_include || $related_fields_to_calculate) { |
|
1011 | + // if so, we should include at least some part of the related model |
|
1012 | + $pretend_related_request = new WP_REST_Request(); |
|
1013 | + $pretend_related_request->set_query_params( |
|
1014 | + [ |
|
1015 | + 'caps' => $rest_request->get_param('caps'), |
|
1016 | + 'include' => $related_fields_to_include, |
|
1017 | + 'calculate' => $related_fields_to_calculate, |
|
1018 | + 'password' => $rest_request->get_param('password'), |
|
1019 | + ] |
|
1020 | + ); |
|
1021 | + $pretend_related_request->add_header('no_rest_headers', true); |
|
1022 | + $primary_model_query_params = $model->alter_query_params_to_restrict_by_ID( |
|
1023 | + $model->get_index_primary_key_string( |
|
1024 | + $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
1025 | + ) |
|
1026 | + ); |
|
1027 | + if (! $included_items_protected) { |
|
1028 | + try { |
|
1029 | + $related_results = $this->getEntitiesFromRelationUsingModelQueryParams( |
|
1030 | + $primary_model_query_params, |
|
1031 | + $relation_obj, |
|
1032 | + $pretend_related_request |
|
1033 | + ); |
|
1034 | + } catch (RestException $e) { |
|
1035 | + $related_results = null; |
|
1036 | + } |
|
1037 | + } else { |
|
1038 | + // they're protected, hide them. |
|
1039 | + $related_results = null; |
|
1040 | + $entity_array['_protected'][] = Read::getRelatedEntityName($relation_name, $relation_obj); |
|
1041 | + } |
|
1042 | + if ($related_results instanceof WP_Error || $related_results === null) { |
|
1043 | + $related_results = |
|
1044 | + $relation_obj instanceof EE_Belongs_To_Relation |
|
1045 | + ? null |
|
1046 | + : []; |
|
1047 | + } |
|
1048 | + $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results; |
|
1049 | + } |
|
1050 | + } |
|
1051 | + return $entity_array; |
|
1052 | + } |
|
1053 | + |
|
1054 | + |
|
1055 | + /** |
|
1056 | + * If the user has requested only specific properties (including meta properties like _links or _protected) |
|
1057 | + * remove everything else. |
|
1058 | + * |
|
1059 | + * @param EEM_Base $model |
|
1060 | + * @param WP_REST_Request $rest_request |
|
1061 | + * @param $entity_array |
|
1062 | + * @return array |
|
1063 | + * @throws EE_Error |
|
1064 | + * @since 4.9.74.p |
|
1065 | + */ |
|
1066 | + protected function includeOnlyRequestedProperties( |
|
1067 | + EEM_Base $model, |
|
1068 | + WP_REST_Request $rest_request, |
|
1069 | + $entity_array |
|
1070 | + ) { |
|
1071 | + |
|
1072 | + $includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), ''); |
|
1073 | + $includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model); |
|
1074 | + // if they passed in * or didn't specify any includes, return everything |
|
1075 | + if ( |
|
1076 | + ! in_array('*', $includes_for_this_model) |
|
1077 | + && ! empty($includes_for_this_model) |
|
1078 | + ) { |
|
1079 | + if ($model->has_primary_key_field()) { |
|
1080 | + // always include the primary key. ya just gotta know that at least |
|
1081 | + $includes_for_this_model[] = $model->primary_key_name(); |
|
1082 | + } |
|
1083 | + if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) { |
|
1084 | + $includes_for_this_model[] = '_calculated_fields'; |
|
1085 | + } |
|
1086 | + $entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model)); |
|
1087 | + } |
|
1088 | + return $entity_array; |
|
1089 | + } |
|
1090 | + |
|
1091 | + |
|
1092 | + /** |
|
1093 | + * Returns a new array with all the names of models removed. Eg |
|
1094 | + * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' ) |
|
1095 | + * |
|
1096 | + * @param array $arr |
|
1097 | + * @return array |
|
1098 | + */ |
|
1099 | + private function removeModelNamesFromArray($arr) |
|
1100 | + { |
|
1101 | + return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models)); |
|
1102 | + } |
|
1103 | + |
|
1104 | + |
|
1105 | + /** |
|
1106 | + * Gets the calculated fields for the response |
|
1107 | + * |
|
1108 | + * @param EEM_Base $model |
|
1109 | + * @param array $wpdb_row |
|
1110 | + * @param WP_REST_Request $rest_request |
|
1111 | + * @param boolean $row_is_protected whether this row is password protected or not |
|
1112 | + * @return stdClass the _calculations item in the entity |
|
1113 | + * @throws RestException if a default value has a PHP object, which should never do (and if we |
|
1114 | + * @throws EE_Error |
|
1115 | + * did, let's know about it ASAP, so let the exception bubble up) |
|
1116 | + */ |
|
1117 | + protected function getEntityCalculations($model, $wpdb_row, $rest_request, $row_is_protected = false) |
|
1118 | + { |
|
1119 | + $calculated_fields = $this->explodeAndGetItemsPrefixedWith( |
|
1120 | + $rest_request->get_param('calculate'), |
|
1121 | + '' |
|
1122 | + ); |
|
1123 | + // note: setting calculate=* doesn't do anything |
|
1124 | + $calculated_fields_to_return = new stdClass(); |
|
1125 | + $protected_fields = []; |
|
1126 | + foreach ($calculated_fields as $field_to_calculate) { |
|
1127 | + try { |
|
1128 | + // it's password protected, so they shouldn't be able to read this. Remove the value |
|
1129 | + $schema = $this->fields_calculator->getJsonSchemaForModel($model); |
|
1130 | + if ( |
|
1131 | + $row_is_protected |
|
1132 | + && isset($schema['properties'][ $field_to_calculate ]['protected']) |
|
1133 | + && $schema['properties'][ $field_to_calculate ]['protected'] |
|
1134 | + ) { |
|
1135 | + $calculated_value = null; |
|
1136 | + $protected_fields[] = $field_to_calculate; |
|
1137 | + if ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1138 | + switch ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1139 | + case 'boolean': |
|
1140 | + $calculated_value = false; |
|
1141 | + break; |
|
1142 | + case 'integer': |
|
1143 | + $calculated_value = 0; |
|
1144 | + break; |
|
1145 | + case 'string': |
|
1146 | + $calculated_value = ''; |
|
1147 | + break; |
|
1148 | + case 'array': |
|
1149 | + $calculated_value = []; |
|
1150 | + break; |
|
1151 | + case 'object': |
|
1152 | + $calculated_value = new stdClass(); |
|
1153 | + break; |
|
1154 | + } |
|
1155 | + } |
|
1156 | + } else { |
|
1157 | + $calculated_value = ModelDataTranslator::prepareFieldValueForJson( |
|
1158 | + null, |
|
1159 | + $this->fields_calculator->retrieveCalculatedFieldValue( |
|
1160 | + $model, |
|
1161 | + $field_to_calculate, |
|
1162 | + $wpdb_row, |
|
1163 | + $rest_request, |
|
1164 | + $this |
|
1165 | + ), |
|
1166 | + $this->getModelVersionInfo()->requestedVersion() |
|
1167 | + ); |
|
1168 | + } |
|
1169 | + $calculated_fields_to_return->{$field_to_calculate} = $calculated_value; |
|
1170 | + } catch (RestException $e) { |
|
1171 | + // if we don't have permission to read it, just leave it out. but let devs know about the problem |
|
1172 | + $this->setResponseHeader( |
|
1173 | + 'Notices-Field-Calculation-Errors[' |
|
1174 | + . $e->getStringCode() |
|
1175 | + . '][' |
|
1176 | + . $model->get_this_model_name() |
|
1177 | + . '][' |
|
1178 | + . $field_to_calculate |
|
1179 | + . ']', |
|
1180 | + $e->getMessage(), |
|
1181 | + true |
|
1182 | + ); |
|
1183 | + } |
|
1184 | + } |
|
1185 | + $calculated_fields_to_return->_protected = $protected_fields; |
|
1186 | + return $calculated_fields_to_return; |
|
1187 | + } |
|
1188 | + |
|
1189 | + |
|
1190 | + /** |
|
1191 | + * Gets the full URL to the resource, taking the requested version into account |
|
1192 | + * |
|
1193 | + * @param string $link_part_after_version_and_slash eg "events/10/datetimes" |
|
1194 | + * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes" |
|
1195 | + * @throws EE_Error |
|
1196 | + * @throws EE_Error |
|
1197 | + */ |
|
1198 | + public function getVersionedLinkTo($link_part_after_version_and_slash) |
|
1199 | + { |
|
1200 | + return rest_url( |
|
1201 | + EED_Core_Rest_Api::get_versioned_route_to( |
|
1202 | + $link_part_after_version_and_slash, |
|
1203 | + $this->getModelVersionInfo()->requestedVersion() |
|
1204 | + ) |
|
1205 | + ); |
|
1206 | + } |
|
1207 | + |
|
1208 | + |
|
1209 | + /** |
|
1210 | + * Gets the correct lowercase name for the relation in the API according |
|
1211 | + * to the relation's type |
|
1212 | + * |
|
1213 | + * @param string $relation_name |
|
1214 | + * @param EE_Model_Relation_Base $relation_obj |
|
1215 | + * @return string |
|
1216 | + */ |
|
1217 | + public static function getRelatedEntityName($relation_name, $relation_obj) |
|
1218 | + { |
|
1219 | + if ($relation_obj instanceof EE_Belongs_To_Relation) { |
|
1220 | + return strtolower($relation_name); |
|
1221 | + } else { |
|
1222 | + return EEH_Inflector::pluralize_and_lower($relation_name); |
|
1223 | + } |
|
1224 | + } |
|
1225 | + |
|
1226 | + |
|
1227 | + /** |
|
1228 | + * Gets the one model object with the specified id for the specified model |
|
1229 | + * |
|
1230 | + * @param EEM_Base $model |
|
1231 | + * @param WP_REST_Request $request |
|
1232 | + * @return array |
|
1233 | + * @throws EE_Error |
|
1234 | + * @throws EE_Error |
|
1235 | + * @throws ReflectionException |
|
1236 | + */ |
|
1237 | + public function getEntityFromModel($model, $request) |
|
1238 | + { |
|
1239 | + $context = $this->validateContext($request->get_param('caps')); |
|
1240 | + return $this->getOneOrReportPermissionError($model, $request, $context); |
|
1241 | + } |
|
1242 | + |
|
1243 | + |
|
1244 | + /** |
|
1245 | + * If a context is provided which isn't valid, maybe it was added in a future |
|
1246 | + * version so just treat it as a default read |
|
1247 | + * |
|
1248 | + * @param string $context |
|
1249 | + * @return string array key of EEM_Base::cap_contexts_to_cap_action_map() |
|
1250 | + */ |
|
1251 | + public function validateContext($context) |
|
1252 | + { |
|
1253 | + if (! $context) { |
|
1254 | + $context = EEM_Base::caps_read; |
|
1255 | + } |
|
1256 | + $valid_contexts = EEM_Base::valid_cap_contexts(); |
|
1257 | + if (in_array($context, $valid_contexts)) { |
|
1258 | + return $context; |
|
1259 | + } else { |
|
1260 | + return EEM_Base::caps_read; |
|
1261 | + } |
|
1262 | + } |
|
1263 | + |
|
1264 | + |
|
1265 | + /** |
|
1266 | + * Verifies the passed in value is an allowable default where conditions value. |
|
1267 | + * |
|
1268 | + * @param $default_query_params |
|
1269 | + * @return string |
|
1270 | + */ |
|
1271 | + public function validateDefaultQueryParams($default_query_params) |
|
1272 | + { |
|
1273 | + $valid_default_where_conditions_for_api_calls = [ |
|
1274 | + EEM_Base::default_where_conditions_all, |
|
1275 | + EEM_Base::default_where_conditions_minimum_all, |
|
1276 | + EEM_Base::default_where_conditions_minimum_others, |
|
1277 | + ]; |
|
1278 | + if (! $default_query_params) { |
|
1279 | + $default_query_params = EEM_Base::default_where_conditions_all; |
|
1280 | + } |
|
1281 | + if ( |
|
1282 | + in_array( |
|
1283 | + $default_query_params, |
|
1284 | + $valid_default_where_conditions_for_api_calls, |
|
1285 | + true |
|
1286 | + ) |
|
1287 | + ) { |
|
1288 | + return $default_query_params; |
|
1289 | + } |
|
1290 | + return EEM_Base::default_where_conditions_all; |
|
1291 | + } |
|
1292 | + |
|
1293 | + |
|
1294 | + /** |
|
1295 | + * Translates API filter get parameter into model query params @see |
|
1296 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions. |
|
1297 | + * Note: right now the query parameter keys for fields (and related fields) can be left as-is, but it's quite |
|
1298 | + * possible this will change someday. Also, this method's contents might be candidate for moving to |
|
1299 | + * Model_Data_Translator |
|
1300 | + * |
|
1301 | + * @param EEM_Base $model |
|
1302 | + * @param array $query_params |
|
1303 | + * @return array model query params (@see |
|
1304 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions) |
|
1305 | + * or FALSE to indicate that absolutely no results should be returned |
|
1306 | + * @throws EE_Error |
|
1307 | + * @throws RestException |
|
1308 | + */ |
|
1309 | + public function createModelQueryParams($model, $query_params) |
|
1310 | + { |
|
1311 | + $model_query_params = []; |
|
1312 | + if (isset($query_params['where'])) { |
|
1313 | + $model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
1314 | + $query_params['where'], |
|
1315 | + $model, |
|
1316 | + $this->getModelVersionInfo()->requestedVersion() |
|
1317 | + ); |
|
1318 | + } |
|
1319 | + if (isset($query_params['order_by'])) { |
|
1320 | + $order_by = $query_params['order_by']; |
|
1321 | + } elseif (isset($query_params['orderby'])) { |
|
1322 | + $order_by = $query_params['orderby']; |
|
1323 | + } else { |
|
1324 | + $order_by = null; |
|
1325 | + } |
|
1326 | + if ($order_by !== null) { |
|
1327 | + if (is_array($order_by)) { |
|
1328 | + $order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by); |
|
1329 | + } else { |
|
1330 | + // it's a single item |
|
1331 | + $order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by); |
|
1332 | + } |
|
1333 | + $model_query_params['order_by'] = $order_by; |
|
1334 | + } |
|
1335 | + if (isset($query_params['group_by'])) { |
|
1336 | + $group_by = $query_params['group_by']; |
|
1337 | + } elseif (isset($query_params['groupby'])) { |
|
1338 | + $group_by = $query_params['groupby']; |
|
1339 | + } else { |
|
1340 | + $group_by = array_keys($model->get_combined_primary_key_fields()); |
|
1341 | + } |
|
1342 | + // make sure they're all real names |
|
1343 | + if (is_array($group_by)) { |
|
1344 | + $group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by); |
|
1345 | + } |
|
1346 | + if ($group_by !== null) { |
|
1347 | + $model_query_params['group_by'] = $group_by; |
|
1348 | + } |
|
1349 | + if (isset($query_params['having'])) { |
|
1350 | + $model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
1351 | + $query_params['having'], |
|
1352 | + $model, |
|
1353 | + $this->getModelVersionInfo()->requestedVersion() |
|
1354 | + ); |
|
1355 | + } |
|
1356 | + if (isset($query_params['order'])) { |
|
1357 | + $model_query_params['order'] = $query_params['order']; |
|
1358 | + } |
|
1359 | + if (isset($query_params['mine'])) { |
|
1360 | + $model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params); |
|
1361 | + } |
|
1362 | + if (isset($query_params['limit'])) { |
|
1363 | + // limit should be either a string like '23' or '23,43', or an array with two items in it |
|
1364 | + if (! is_array($query_params['limit'])) { |
|
1365 | + $limit_array = explode(',', (string) $query_params['limit']); |
|
1366 | + } else { |
|
1367 | + $limit_array = $query_params['limit']; |
|
1368 | + } |
|
1369 | + $sanitized_limit = []; |
|
1370 | + foreach ($limit_array as $limit_part) { |
|
1371 | + if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) { |
|
1372 | + throw new EE_Error( |
|
1373 | + sprintf( |
|
1374 | + esc_html__( |
|
1375 | + // @codingStandardsIgnoreStart |
|
1376 | + 'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.', |
|
1377 | + // @codingStandardsIgnoreEnd |
|
1378 | + 'event_espresso' |
|
1379 | + ), |
|
1380 | + wp_json_encode($query_params['limit']) |
|
1381 | + ) |
|
1382 | + ); |
|
1383 | + } |
|
1384 | + $sanitized_limit[] = (int) $limit_part; |
|
1385 | + } |
|
1386 | + $model_query_params['limit'] = implode(',', $sanitized_limit); |
|
1387 | + } else { |
|
1388 | + $model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
|
1389 | + } |
|
1390 | + if (isset($query_params['caps'])) { |
|
1391 | + $model_query_params['caps'] = $this->validateContext($query_params['caps']); |
|
1392 | + } else { |
|
1393 | + $model_query_params['caps'] = EEM_Base::caps_read; |
|
1394 | + } |
|
1395 | + if (isset($query_params['default_where_conditions'])) { |
|
1396 | + $model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams( |
|
1397 | + $query_params['default_where_conditions'] |
|
1398 | + ); |
|
1399 | + } |
|
1400 | + // if this is a model protected by a password on another model, exclude the password protected |
|
1401 | + // entities by default. But if they passed in a password, try to show them all. If the password is wrong, |
|
1402 | + // though, they'll get an error (see Read::createEntityFromWpdbResult() which calls Read::checkPassword) |
|
1403 | + if ( |
|
1404 | + ! $model->hasPassword() |
|
1405 | + && $model->restrictedByRelatedModelPassword() |
|
1406 | + && $model_query_params['caps'] === EEM_Base::caps_read |
|
1407 | + ) { |
|
1408 | + if (empty($query_params['password'])) { |
|
1409 | + $model_query_params['exclude_protected'] = true; |
|
1410 | + } |
|
1411 | + } |
|
1412 | + |
|
1413 | + return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_params, $model); |
|
1414 | + } |
|
1415 | + |
|
1416 | + |
|
1417 | + /** |
|
1418 | + * Changes the REST-style query params for use in the models |
|
1419 | + * |
|
1420 | + * @param EEM_Base $model |
|
1421 | + * @param array $query_params sub-array from @see EEM_Base::get_all() |
|
1422 | + * @return array |
|
1423 | + * @deprecated |
|
1424 | + */ |
|
1425 | + public function prepareRestQueryParamsKeyForModels($model, $query_params) |
|
1426 | + { |
|
1427 | + $model_ready_query_params = []; |
|
1428 | + foreach ($query_params as $key => $value) { |
|
1429 | + $model_ready_query_params[ $key ] = is_array($value) |
|
1430 | + ? $this->prepareRestQueryParamsKeyForModels($model, $value) |
|
1431 | + : $value; |
|
1432 | + } |
|
1433 | + return $model_ready_query_params; |
|
1434 | + } |
|
1435 | + |
|
1436 | + |
|
1437 | + /** |
|
1438 | + * @param $model |
|
1439 | + * @param $query_params |
|
1440 | + * @return array |
|
1441 | + * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson() |
|
1442 | + */ |
|
1443 | + public function prepareRestQueryParamsValuesForModels($model, $query_params) |
|
1444 | + { |
|
1445 | + $model_ready_query_params = []; |
|
1446 | + foreach ($query_params as $key => $value) { |
|
1447 | + if (is_array($value)) { |
|
1448 | + $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value); |
|
1449 | + } else { |
|
1450 | + $model_ready_query_params[ $key ] = $value; |
|
1451 | + } |
|
1452 | + } |
|
1453 | + return $model_ready_query_params; |
|
1454 | + } |
|
1455 | + |
|
1456 | + |
|
1457 | + /** |
|
1458 | + * Explodes the string on commas, and only returns items with $prefix followed by a period. |
|
1459 | + * If no prefix is specified, returns items with no period. |
|
1460 | + * |
|
1461 | + * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' ) |
|
1462 | + * @param string $prefix "Event" or "foobar" |
|
1463 | + * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified |
|
1464 | + * we only return strings starting with that and a period; if no prefix was |
|
1465 | + * specified we return all items containing NO periods |
|
1466 | + */ |
|
1467 | + public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix) |
|
1468 | + { |
|
1469 | + if (is_string($string_to_explode)) { |
|
1470 | + $exploded_contents = explode(',', $string_to_explode); |
|
1471 | + } elseif (is_array($string_to_explode)) { |
|
1472 | + $exploded_contents = $string_to_explode; |
|
1473 | + } else { |
|
1474 | + $exploded_contents = []; |
|
1475 | + } |
|
1476 | + // if the string was empty, we want an empty array |
|
1477 | + $exploded_contents = array_filter($exploded_contents); |
|
1478 | + $contents_with_prefix = []; |
|
1479 | + foreach ($exploded_contents as $item) { |
|
1480 | + $item = trim($item); |
|
1481 | + // if no prefix was provided, so we look for items with no "." in them |
|
1482 | + if (! $prefix) { |
|
1483 | + // does this item have a period? |
|
1484 | + if (strpos($item, '.') === false) { |
|
1485 | + // if not, then its what we're looking for |
|
1486 | + $contents_with_prefix[] = $item; |
|
1487 | + } |
|
1488 | + } elseif (strpos($item, $prefix . '.') === 0) { |
|
1489 | + // this item has the prefix and a period, grab it |
|
1490 | + $contents_with_prefix[] = substr( |
|
1491 | + $item, |
|
1492 | + strpos($item, $prefix . '.') + strlen($prefix . '.') |
|
1493 | + ); |
|
1494 | + } elseif ($item === $prefix) { |
|
1495 | + // this item is JUST the prefix |
|
1496 | + // so let's grab everything after, which is a blank string |
|
1497 | + $contents_with_prefix[] = ''; |
|
1498 | + } |
|
1499 | + } |
|
1500 | + return $contents_with_prefix; |
|
1501 | + } |
|
1502 | + |
|
1503 | + |
|
1504 | + /** |
|
1505 | + * @param string $include_string @see Read:handle_request_get_all |
|
1506 | + * @param string $model_name |
|
1507 | + * @return array of fields for this model. If $model_name is provided, then |
|
1508 | + * the fields for that model, with the model's name removed from each. |
|
1509 | + * If $include_string was blank or '*' returns an empty array |
|
1510 | + * @throws EE_Error |
|
1511 | + * @throws EE_Error |
|
1512 | + * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with. |
|
1513 | + * Deprecated because its return values were really quite confusing- sometimes it |
|
1514 | + * returned an empty array (when the include string was blank or '*') or sometimes it |
|
1515 | + * returned array('*') (when you provided a model and a model of that kind was |
|
1516 | + * found). Parses the $include_string so we fetch all the field names relating to |
|
1517 | + * THIS model |
|
1518 | + * (ie have NO period in them), or for the provided model (ie start with the model |
|
1519 | + * name and then a period). |
|
1520 | + */ |
|
1521 | + public function extractIncludesForThisModel($include_string, $model_name = null) |
|
1522 | + { |
|
1523 | + if (is_array($include_string)) { |
|
1524 | + $include_string = implode(',', $include_string); |
|
1525 | + } |
|
1526 | + if ($include_string === '*' || $include_string === '') { |
|
1527 | + return []; |
|
1528 | + } |
|
1529 | + $includes = explode(',', $include_string); |
|
1530 | + $extracted_fields_to_include = []; |
|
1531 | + if ($model_name) { |
|
1532 | + foreach ($includes as $field_to_include) { |
|
1533 | + $field_to_include = trim($field_to_include); |
|
1534 | + if (strpos($field_to_include, $model_name . '.') === 0) { |
|
1535 | + // found the model name at the exact start |
|
1536 | + $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include); |
|
1537 | + $extracted_fields_to_include[] = $field_sans_model_name; |
|
1538 | + } elseif ($field_to_include == $model_name) { |
|
1539 | + $extracted_fields_to_include[] = '*'; |
|
1540 | + } |
|
1541 | + } |
|
1542 | + } else { |
|
1543 | + // look for ones with no period |
|
1544 | + foreach ($includes as $field_to_include) { |
|
1545 | + $field_to_include = trim($field_to_include); |
|
1546 | + if ( |
|
1547 | + strpos($field_to_include, '.') === false |
|
1548 | + && ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include) |
|
1549 | + ) { |
|
1550 | + $extracted_fields_to_include[] = $field_to_include; |
|
1551 | + } |
|
1552 | + } |
|
1553 | + } |
|
1554 | + return $extracted_fields_to_include; |
|
1555 | + } |
|
1556 | + |
|
1557 | + |
|
1558 | + /** |
|
1559 | + * Gets the single item using the model according to the request in the context given, otherwise |
|
1560 | + * returns that it's inaccessible to the current user |
|
1561 | + * |
|
1562 | + * @param EEM_Base $model |
|
1563 | + * @param WP_REST_Request $request |
|
1564 | + * @param null $context |
|
1565 | + * @return array |
|
1566 | + * @throws EE_Error |
|
1567 | + * @throws ReflectionException |
|
1568 | + */ |
|
1569 | + public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null) |
|
1570 | + { |
|
1571 | + $query_params = [[$model->primary_key_name() => $request->get_param('id')], 'limit' => 1]; |
|
1572 | + if ($model instanceof EEM_Soft_Delete_Base) { |
|
1573 | + $query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params); |
|
1574 | + } |
|
1575 | + $restricted_query_params = $query_params; |
|
1576 | + $restricted_query_params['caps'] = $context; |
|
1577 | + $this->setDebugInfo('model query params', $restricted_query_params); |
|
1578 | + $model_rows = $model->get_all_wpdb_results($restricted_query_params); |
|
1579 | + if (! empty($model_rows)) { |
|
1580 | + return $this->createEntityFromWpdbResult( |
|
1581 | + $model, |
|
1582 | + reset($model_rows), |
|
1583 | + $request |
|
1584 | + ); |
|
1585 | + } else { |
|
1586 | + // ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities |
|
1587 | + $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
1588 | + if ($model->exists($query_params)) { |
|
1589 | + // you got shafted- it existed but we didn't want to tell you! |
|
1590 | + throw new RestException( |
|
1591 | + 'rest_user_cannot_' . $context, |
|
1592 | + sprintf( |
|
1593 | + esc_html__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'), |
|
1594 | + $context, |
|
1595 | + $lowercase_model_name, |
|
1596 | + Capabilities::getMissingPermissionsString( |
|
1597 | + $model, |
|
1598 | + $context |
|
1599 | + ) |
|
1600 | + ), |
|
1601 | + ['status' => 403] |
|
1602 | + ); |
|
1603 | + } else { |
|
1604 | + // it's not you. It just doesn't exist |
|
1605 | + throw new RestException( |
|
1606 | + sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
1607 | + sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
1608 | + ['status' => 404] |
|
1609 | + ); |
|
1610 | + } |
|
1611 | + } |
|
1612 | + } |
|
1613 | + |
|
1614 | + |
|
1615 | + /** |
|
1616 | + * Checks that if this content requires a password to be read, that it's been provided and is correct. |
|
1617 | + * |
|
1618 | + * @param EEM_Base $model |
|
1619 | + * @param array $model_row |
|
1620 | + * @param array $query_params Adds 'default_where_conditions' => 'minimum' |
|
1621 | + * to ensure we don't confuse trashed with password protected. |
|
1622 | + * @param WP_REST_Request $request |
|
1623 | + * @throws EE_Error |
|
1624 | + * @throws InvalidArgumentException |
|
1625 | + * @throws InvalidDataTypeException |
|
1626 | + * @throws InvalidInterfaceException |
|
1627 | + * @throws RestPasswordRequiredException |
|
1628 | + * @throws RestPasswordIncorrectException |
|
1629 | + * @throws ModelConfigurationException |
|
1630 | + * @throws ReflectionException |
|
1631 | + * @since 4.9.74.p |
|
1632 | + */ |
|
1633 | + protected function checkPassword(EEM_Base $model, $model_row, $query_params, WP_REST_Request $request) |
|
1634 | + { |
|
1635 | + $query_params['default_where_conditions'] = 'minimum'; |
|
1636 | + // stuff is only "protected" for front-end requests. Elsewhere, you either get full permission to access the object |
|
1637 | + // or you don't. |
|
1638 | + $request_caps = $request->get_param('caps'); |
|
1639 | + if (isset($request_caps) && $request_caps !== EEM_Base::caps_read) { |
|
1640 | + return; |
|
1641 | + } |
|
1642 | + // if this entity requires a password, they better give it and it better be right! |
|
1643 | + if ( |
|
1644 | + $model->hasPassword() |
|
1645 | + && $model_row[ $model->getPasswordField()->get_qualified_column() ] !== '' |
|
1646 | + ) { |
|
1647 | + if (empty($request['password'])) { |
|
1648 | + throw new RestPasswordRequiredException(); |
|
1649 | + } |
|
1650 | + if ( |
|
1651 | + ! hash_equals( |
|
1652 | + $model_row[ $model->getPasswordField()->get_qualified_column() ], |
|
1653 | + $request['password'] |
|
1654 | + ) |
|
1655 | + ) { |
|
1656 | + throw new RestPasswordIncorrectException(); |
|
1657 | + } |
|
1658 | + } elseif ( |
|
1659 | + // wait! maybe this content is password protected |
|
1660 | + $model->restrictedByRelatedModelPassword() |
|
1661 | + && $request->get_param('caps') === EEM_Base::caps_read |
|
1662 | + ) { |
|
1663 | + $password_supplied = $request->get_param('password'); |
|
1664 | + if (empty($password_supplied)) { |
|
1665 | + $query_params['exclude_protected'] = true; |
|
1666 | + if (! $model->exists($query_params)) { |
|
1667 | + throw new RestPasswordRequiredException(); |
|
1668 | + } |
|
1669 | + } else { |
|
1670 | + $query_params[0][ $model->modelChainAndPassword() ] = $password_supplied; |
|
1671 | + if (! $model->exists($query_params)) { |
|
1672 | + throw new RestPasswordIncorrectException(); |
|
1673 | + } |
|
1674 | + } |
|
1675 | + } |
|
1676 | + } |
|
1677 | 1677 | } |
@@ -134,9 +134,9 @@ discard block |
||
134 | 134 | { |
135 | 135 | Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'create'); |
136 | 136 | $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
137 | - if (! current_user_can($default_cap_to_check_for)) { |
|
137 | + if ( ! current_user_can($default_cap_to_check_for)) { |
|
138 | 138 | throw new RestException( |
139 | - 'rest_cannot_create_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
139 | + 'rest_cannot_create_'.EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
140 | 140 | sprintf( |
141 | 141 | esc_html__( |
142 | 142 | // @codingStandardsIgnoreStart |
@@ -164,7 +164,7 @@ discard block |
||
164 | 164 | ); |
165 | 165 | $model_obj->save(); |
166 | 166 | $new_id = $model_obj->ID(); |
167 | - if (! $new_id) { |
|
167 | + if ( ! $new_id) { |
|
168 | 168 | throw new RestException( |
169 | 169 | 'rest_insertion_failed', |
170 | 170 | sprintf(esc_html__('Could not insert new %1$s', 'event_espresso'), $model->get_this_model_name()) |
@@ -186,9 +186,9 @@ discard block |
||
186 | 186 | { |
187 | 187 | Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit'); |
188 | 188 | $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
189 | - if (! current_user_can($default_cap_to_check_for)) { |
|
189 | + if ( ! current_user_can($default_cap_to_check_for)) { |
|
190 | 190 | throw new RestException( |
191 | - 'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
191 | + 'rest_cannot_edit_'.EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
192 | 192 | sprintf( |
193 | 193 | esc_html__( |
194 | 194 | // @codingStandardsIgnoreStart |
@@ -202,7 +202,7 @@ discard block |
||
202 | 202 | ); |
203 | 203 | } |
204 | 204 | $obj_id = $request->get_param('id'); |
205 | - if (! $obj_id) { |
|
205 | + if ( ! $obj_id) { |
|
206 | 206 | throw new RestException( |
207 | 207 | 'rest_edit_failed', |
208 | 208 | sprintf(esc_html__('Could not edit %1$s', 'event_espresso'), $model->get_this_model_name()) |
@@ -215,7 +215,7 @@ discard block |
||
215 | 215 | true |
216 | 216 | ); |
217 | 217 | $model_obj = $model->get_one_by_ID($obj_id); |
218 | - if (! $model_obj instanceof EE_Base_Class) { |
|
218 | + if ( ! $model_obj instanceof EE_Base_Class) { |
|
219 | 219 | $lowercase_model_name = strtolower($model->get_this_model_name()); |
220 | 220 | throw new RestException( |
221 | 221 | sprintf('rest_%s_invalid_id', $lowercase_model_name), |
@@ -240,9 +240,9 @@ discard block |
||
240 | 240 | { |
241 | 241 | Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_delete, 'delete'); |
242 | 242 | $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
243 | - if (! current_user_can($default_cap_to_check_for)) { |
|
243 | + if ( ! current_user_can($default_cap_to_check_for)) { |
|
244 | 244 | throw new RestException( |
245 | - 'rest_cannot_delete_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
245 | + 'rest_cannot_delete_'.EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
246 | 246 | sprintf( |
247 | 247 | esc_html__( |
248 | 248 | // @codingStandardsIgnoreStart |
@@ -258,7 +258,7 @@ discard block |
||
258 | 258 | $obj_id = $request->get_param('id'); |
259 | 259 | // this is where we would apply more fine-grained caps |
260 | 260 | $model_obj = $model->get_one_by_ID($obj_id); |
261 | - if (! $model_obj instanceof EE_Base_Class) { |
|
261 | + if ( ! $model_obj instanceof EE_Base_Class) { |
|
262 | 262 | $lowercase_model_name = strtolower($model->get_this_model_name()); |
263 | 263 | throw new RestException( |
264 | 264 | sprintf('rest_%s_invalid_id', $lowercase_model_name), |
@@ -316,7 +316,7 @@ discard block |
||
316 | 316 | } else { |
317 | 317 | $raw_value = $model_obj->get_raw($field_name); |
318 | 318 | } |
319 | - $simulated_db_row[ $field_obj->get_qualified_column() ] = $field_obj->prepare_for_use_in_db($raw_value); |
|
319 | + $simulated_db_row[$field_obj->get_qualified_column()] = $field_obj->prepare_for_use_in_db($raw_value); |
|
320 | 320 | } |
321 | 321 | $read_controller = LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
322 | 322 | $read_controller->setRequestedVersion($this->getRequestedVersion()); |
@@ -447,7 +447,7 @@ discard block |
||
447 | 447 | ) |
448 | 448 | ) |
449 | 449 | ); |
450 | - $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request); |
|
450 | + $response['join'][strtolower($relation->get_join_model()->get_this_model_name())] = $this->returnModelObjAsJsonResponse($join_model_obj, $request); |
|
451 | 451 | } |
452 | 452 | return $response; |
453 | 453 | } |
@@ -495,7 +495,7 @@ discard block |
||
495 | 495 | { |
496 | 496 | // This endpoint doesn't accept body parameters (it's understandable to think it might, so let developers know |
497 | 497 | // up-front that it doesn't.) |
498 | - if (!empty($request->get_body_params())) { |
|
498 | + if ( ! empty($request->get_body_params())) { |
|
499 | 499 | $body_params = $request->get_body_params(); |
500 | 500 | throw new RestException( |
501 | 501 | 'invalid_field', |
@@ -537,9 +537,9 @@ discard block |
||
537 | 537 | ) |
538 | 538 | ); |
539 | 539 | if ($join_model_obj instanceof EE_Base_Class) { |
540 | - $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request); |
|
540 | + $response['join'][strtolower($relation->get_join_model()->get_this_model_name())] = $this->returnModelObjAsJsonResponse($join_model_obj, $request); |
|
541 | 541 | } else { |
542 | - $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = null; |
|
542 | + $response['join'][strtolower($relation->get_join_model()->get_this_model_name())] = null; |
|
543 | 543 | } |
544 | 544 | } |
545 | 545 | return $response; |
@@ -564,9 +564,9 @@ discard block |
||
564 | 564 | // Check generic caps. For now, we're only allowing access to this endpoint to full admins. |
565 | 565 | Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit'); |
566 | 566 | $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
567 | - if (! current_user_can($default_cap_to_check_for)) { |
|
567 | + if ( ! current_user_can($default_cap_to_check_for)) { |
|
568 | 568 | throw new RestException( |
569 | - 'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
569 | + 'rest_cannot_edit_'.EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
570 | 570 | sprintf( |
571 | 571 | esc_html__( |
572 | 572 | // @codingStandardsIgnoreStart |
@@ -583,7 +583,7 @@ discard block |
||
583 | 583 | $model_obj = $this->getOneOrThrowException($model, $request->get_param('id')); |
584 | 584 | // For now, we require the other model object to exist too. This might be relaxed later. |
585 | 585 | $other_obj = $this->getOneOrThrowException($relation->get_other_model(), $request->get_param('related_id')); |
586 | - return array($model_obj,$other_obj); |
|
586 | + return array($model_obj, $other_obj); |
|
587 | 587 | } |
588 | 588 | |
589 | 589 | /** |
@@ -37,573 +37,573 @@ |
||
37 | 37 | */ |
38 | 38 | class Write extends Base |
39 | 39 | { |
40 | - public function __construct() |
|
41 | - { |
|
42 | - parent::__construct(); |
|
43 | - EE_Registry::instance()->load_helper('Inflector'); |
|
44 | - } |
|
40 | + public function __construct() |
|
41 | + { |
|
42 | + parent::__construct(); |
|
43 | + EE_Registry::instance()->load_helper('Inflector'); |
|
44 | + } |
|
45 | 45 | |
46 | 46 | |
47 | - /** |
|
48 | - * Handles requests to get all (or a filtered subset) of entities for a particular model |
|
49 | - * |
|
50 | - * @param WP_REST_Request $request |
|
51 | - * @param string $version |
|
52 | - * @param string $model_name |
|
53 | - * @return WP_REST_Response|\WP_Error |
|
54 | - */ |
|
55 | - public static function handleRequestInsert(WP_REST_Request $request, $version, $model_name) |
|
56 | - { |
|
57 | - $controller = new Write(); |
|
58 | - try { |
|
59 | - $controller->setRequestedVersion($version); |
|
60 | - return $controller->sendResponse( |
|
61 | - $controller->insert( |
|
62 | - $controller->getModelVersionInfo()->loadModel($model_name), |
|
63 | - $request |
|
64 | - ) |
|
65 | - ); |
|
66 | - } catch (Exception $e) { |
|
67 | - return $controller->sendResponse($e); |
|
68 | - } |
|
69 | - } |
|
47 | + /** |
|
48 | + * Handles requests to get all (or a filtered subset) of entities for a particular model |
|
49 | + * |
|
50 | + * @param WP_REST_Request $request |
|
51 | + * @param string $version |
|
52 | + * @param string $model_name |
|
53 | + * @return WP_REST_Response|\WP_Error |
|
54 | + */ |
|
55 | + public static function handleRequestInsert(WP_REST_Request $request, $version, $model_name) |
|
56 | + { |
|
57 | + $controller = new Write(); |
|
58 | + try { |
|
59 | + $controller->setRequestedVersion($version); |
|
60 | + return $controller->sendResponse( |
|
61 | + $controller->insert( |
|
62 | + $controller->getModelVersionInfo()->loadModel($model_name), |
|
63 | + $request |
|
64 | + ) |
|
65 | + ); |
|
66 | + } catch (Exception $e) { |
|
67 | + return $controller->sendResponse($e); |
|
68 | + } |
|
69 | + } |
|
70 | 70 | |
71 | 71 | |
72 | - /** |
|
73 | - * Handles a request from \WP_REST_Server to update an EE model |
|
74 | - * |
|
75 | - * @param WP_REST_Request $request |
|
76 | - * @param string $version |
|
77 | - * @param string $model_name |
|
78 | - * @return WP_REST_Response|\WP_Error |
|
79 | - */ |
|
80 | - public static function handleRequestUpdate(WP_REST_Request $request, $version, $model_name) |
|
81 | - { |
|
82 | - $controller = new Write(); |
|
83 | - try { |
|
84 | - $controller->setRequestedVersion($version); |
|
85 | - return $controller->sendResponse( |
|
86 | - $controller->update( |
|
87 | - $controller->getModelVersionInfo()->loadModel($model_name), |
|
88 | - $request |
|
89 | - ) |
|
90 | - ); |
|
91 | - } catch (Exception $e) { |
|
92 | - return $controller->sendResponse($e); |
|
93 | - } |
|
94 | - } |
|
72 | + /** |
|
73 | + * Handles a request from \WP_REST_Server to update an EE model |
|
74 | + * |
|
75 | + * @param WP_REST_Request $request |
|
76 | + * @param string $version |
|
77 | + * @param string $model_name |
|
78 | + * @return WP_REST_Response|\WP_Error |
|
79 | + */ |
|
80 | + public static function handleRequestUpdate(WP_REST_Request $request, $version, $model_name) |
|
81 | + { |
|
82 | + $controller = new Write(); |
|
83 | + try { |
|
84 | + $controller->setRequestedVersion($version); |
|
85 | + return $controller->sendResponse( |
|
86 | + $controller->update( |
|
87 | + $controller->getModelVersionInfo()->loadModel($model_name), |
|
88 | + $request |
|
89 | + ) |
|
90 | + ); |
|
91 | + } catch (Exception $e) { |
|
92 | + return $controller->sendResponse($e); |
|
93 | + } |
|
94 | + } |
|
95 | 95 | |
96 | 96 | |
97 | - /** |
|
98 | - * Deletes a single model object and returns it. Unless |
|
99 | - * |
|
100 | - * @param WP_REST_Request $request |
|
101 | - * @param string $version |
|
102 | - * @param string $model_name |
|
103 | - * @return WP_REST_Response|\WP_Error |
|
104 | - */ |
|
105 | - public static function handleRequestDelete(WP_REST_Request $request, $version, $model_name) |
|
106 | - { |
|
107 | - $controller = new Write(); |
|
108 | - try { |
|
109 | - $controller->setRequestedVersion($version); |
|
110 | - return $controller->sendResponse( |
|
111 | - $controller->delete( |
|
112 | - $controller->getModelVersionInfo()->loadModel($model_name), |
|
113 | - $request |
|
114 | - ) |
|
115 | - ); |
|
116 | - } catch (Exception $e) { |
|
117 | - return $controller->sendResponse($e); |
|
118 | - } |
|
119 | - } |
|
97 | + /** |
|
98 | + * Deletes a single model object and returns it. Unless |
|
99 | + * |
|
100 | + * @param WP_REST_Request $request |
|
101 | + * @param string $version |
|
102 | + * @param string $model_name |
|
103 | + * @return WP_REST_Response|\WP_Error |
|
104 | + */ |
|
105 | + public static function handleRequestDelete(WP_REST_Request $request, $version, $model_name) |
|
106 | + { |
|
107 | + $controller = new Write(); |
|
108 | + try { |
|
109 | + $controller->setRequestedVersion($version); |
|
110 | + return $controller->sendResponse( |
|
111 | + $controller->delete( |
|
112 | + $controller->getModelVersionInfo()->loadModel($model_name), |
|
113 | + $request |
|
114 | + ) |
|
115 | + ); |
|
116 | + } catch (Exception $e) { |
|
117 | + return $controller->sendResponse($e); |
|
118 | + } |
|
119 | + } |
|
120 | 120 | |
121 | 121 | |
122 | - /** |
|
123 | - * Inserts a new model object according to the $request |
|
124 | - * |
|
125 | - * @param EEM_Base $model |
|
126 | - * @param WP_REST_Request $request |
|
127 | - * @return array |
|
128 | - * @throws EE_Error |
|
129 | - * @throws RestException |
|
130 | - */ |
|
131 | - public function insert(EEM_Base $model, WP_REST_Request $request) |
|
132 | - { |
|
133 | - Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'create'); |
|
134 | - $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
|
135 | - if (! current_user_can($default_cap_to_check_for)) { |
|
136 | - throw new RestException( |
|
137 | - 'rest_cannot_create_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
138 | - sprintf( |
|
139 | - esc_html__( |
|
140 | - // @codingStandardsIgnoreStart |
|
141 | - 'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to insert data into Event Espresso.', |
|
142 | - // @codingStandardsIgnoreEnd |
|
143 | - 'event_espresso' |
|
144 | - ), |
|
145 | - $default_cap_to_check_for |
|
146 | - ), |
|
147 | - array('status' => 403) |
|
148 | - ); |
|
149 | - } |
|
150 | - $submitted_json_data = array_merge((array) $request->get_body_params(), (array) $request->get_json_params()); |
|
151 | - $model_data = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
152 | - $submitted_json_data, |
|
153 | - $model, |
|
154 | - $this->getModelVersionInfo()->requestedVersion(), |
|
155 | - true |
|
156 | - ); |
|
157 | - $model_obj = EE_Registry::instance()->load_class( |
|
158 | - $model->get_this_model_name(), |
|
159 | - array($model_data, $model->get_timezone()), |
|
160 | - false, |
|
161 | - false |
|
162 | - ); |
|
163 | - $model_obj->save(); |
|
164 | - $new_id = $model_obj->ID(); |
|
165 | - if (! $new_id) { |
|
166 | - throw new RestException( |
|
167 | - 'rest_insertion_failed', |
|
168 | - sprintf(esc_html__('Could not insert new %1$s', 'event_espresso'), $model->get_this_model_name()) |
|
169 | - ); |
|
170 | - } |
|
171 | - return $this->returnModelObjAsJsonResponse($model_obj, $request); |
|
172 | - } |
|
122 | + /** |
|
123 | + * Inserts a new model object according to the $request |
|
124 | + * |
|
125 | + * @param EEM_Base $model |
|
126 | + * @param WP_REST_Request $request |
|
127 | + * @return array |
|
128 | + * @throws EE_Error |
|
129 | + * @throws RestException |
|
130 | + */ |
|
131 | + public function insert(EEM_Base $model, WP_REST_Request $request) |
|
132 | + { |
|
133 | + Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'create'); |
|
134 | + $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
|
135 | + if (! current_user_can($default_cap_to_check_for)) { |
|
136 | + throw new RestException( |
|
137 | + 'rest_cannot_create_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
138 | + sprintf( |
|
139 | + esc_html__( |
|
140 | + // @codingStandardsIgnoreStart |
|
141 | + 'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to insert data into Event Espresso.', |
|
142 | + // @codingStandardsIgnoreEnd |
|
143 | + 'event_espresso' |
|
144 | + ), |
|
145 | + $default_cap_to_check_for |
|
146 | + ), |
|
147 | + array('status' => 403) |
|
148 | + ); |
|
149 | + } |
|
150 | + $submitted_json_data = array_merge((array) $request->get_body_params(), (array) $request->get_json_params()); |
|
151 | + $model_data = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
152 | + $submitted_json_data, |
|
153 | + $model, |
|
154 | + $this->getModelVersionInfo()->requestedVersion(), |
|
155 | + true |
|
156 | + ); |
|
157 | + $model_obj = EE_Registry::instance()->load_class( |
|
158 | + $model->get_this_model_name(), |
|
159 | + array($model_data, $model->get_timezone()), |
|
160 | + false, |
|
161 | + false |
|
162 | + ); |
|
163 | + $model_obj->save(); |
|
164 | + $new_id = $model_obj->ID(); |
|
165 | + if (! $new_id) { |
|
166 | + throw new RestException( |
|
167 | + 'rest_insertion_failed', |
|
168 | + sprintf(esc_html__('Could not insert new %1$s', 'event_espresso'), $model->get_this_model_name()) |
|
169 | + ); |
|
170 | + } |
|
171 | + return $this->returnModelObjAsJsonResponse($model_obj, $request); |
|
172 | + } |
|
173 | 173 | |
174 | 174 | |
175 | - /** |
|
176 | - * Updates an existing model object according to the $request |
|
177 | - * |
|
178 | - * @param EEM_Base $model |
|
179 | - * @param WP_REST_Request $request |
|
180 | - * @return array |
|
181 | - * @throws EE_Error |
|
182 | - */ |
|
183 | - public function update(EEM_Base $model, WP_REST_Request $request) |
|
184 | - { |
|
185 | - Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit'); |
|
186 | - $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
|
187 | - if (! current_user_can($default_cap_to_check_for)) { |
|
188 | - throw new RestException( |
|
189 | - 'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
190 | - sprintf( |
|
191 | - esc_html__( |
|
192 | - // @codingStandardsIgnoreStart |
|
193 | - 'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to update data into Event Espresso.', |
|
194 | - // @codingStandardsIgnoreEnd |
|
195 | - 'event_espresso' |
|
196 | - ), |
|
197 | - $default_cap_to_check_for |
|
198 | - ), |
|
199 | - array('status' => 403) |
|
200 | - ); |
|
201 | - } |
|
202 | - $obj_id = $request->get_param('id'); |
|
203 | - if (! $obj_id) { |
|
204 | - throw new RestException( |
|
205 | - 'rest_edit_failed', |
|
206 | - sprintf(esc_html__('Could not edit %1$s', 'event_espresso'), $model->get_this_model_name()) |
|
207 | - ); |
|
208 | - } |
|
209 | - $model_data = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
210 | - $this->getBodyParams($request), |
|
211 | - $model, |
|
212 | - $this->getModelVersionInfo()->requestedVersion(), |
|
213 | - true |
|
214 | - ); |
|
215 | - $model_obj = $model->get_one_by_ID($obj_id); |
|
216 | - if (! $model_obj instanceof EE_Base_Class) { |
|
217 | - $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
218 | - throw new RestException( |
|
219 | - sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
220 | - sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
221 | - array('status' => 404) |
|
222 | - ); |
|
223 | - } |
|
224 | - $model_obj->save($model_data); |
|
225 | - return $this->returnModelObjAsJsonResponse($model_obj, $request); |
|
226 | - } |
|
175 | + /** |
|
176 | + * Updates an existing model object according to the $request |
|
177 | + * |
|
178 | + * @param EEM_Base $model |
|
179 | + * @param WP_REST_Request $request |
|
180 | + * @return array |
|
181 | + * @throws EE_Error |
|
182 | + */ |
|
183 | + public function update(EEM_Base $model, WP_REST_Request $request) |
|
184 | + { |
|
185 | + Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit'); |
|
186 | + $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
|
187 | + if (! current_user_can($default_cap_to_check_for)) { |
|
188 | + throw new RestException( |
|
189 | + 'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
190 | + sprintf( |
|
191 | + esc_html__( |
|
192 | + // @codingStandardsIgnoreStart |
|
193 | + 'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to update data into Event Espresso.', |
|
194 | + // @codingStandardsIgnoreEnd |
|
195 | + 'event_espresso' |
|
196 | + ), |
|
197 | + $default_cap_to_check_for |
|
198 | + ), |
|
199 | + array('status' => 403) |
|
200 | + ); |
|
201 | + } |
|
202 | + $obj_id = $request->get_param('id'); |
|
203 | + if (! $obj_id) { |
|
204 | + throw new RestException( |
|
205 | + 'rest_edit_failed', |
|
206 | + sprintf(esc_html__('Could not edit %1$s', 'event_espresso'), $model->get_this_model_name()) |
|
207 | + ); |
|
208 | + } |
|
209 | + $model_data = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
210 | + $this->getBodyParams($request), |
|
211 | + $model, |
|
212 | + $this->getModelVersionInfo()->requestedVersion(), |
|
213 | + true |
|
214 | + ); |
|
215 | + $model_obj = $model->get_one_by_ID($obj_id); |
|
216 | + if (! $model_obj instanceof EE_Base_Class) { |
|
217 | + $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
218 | + throw new RestException( |
|
219 | + sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
220 | + sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
221 | + array('status' => 404) |
|
222 | + ); |
|
223 | + } |
|
224 | + $model_obj->save($model_data); |
|
225 | + return $this->returnModelObjAsJsonResponse($model_obj, $request); |
|
226 | + } |
|
227 | 227 | |
228 | 228 | |
229 | - /** |
|
230 | - * Updates an existing model object according to the $request |
|
231 | - * |
|
232 | - * @param EEM_Base $model |
|
233 | - * @param WP_REST_Request $request |
|
234 | - * @return array of either the soft-deleted item, or |
|
235 | - * @throws EE_Error |
|
236 | - */ |
|
237 | - public function delete(EEM_Base $model, WP_REST_Request $request) |
|
238 | - { |
|
239 | - Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_delete, 'delete'); |
|
240 | - $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
|
241 | - if (! current_user_can($default_cap_to_check_for)) { |
|
242 | - throw new RestException( |
|
243 | - 'rest_cannot_delete_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
244 | - sprintf( |
|
245 | - esc_html__( |
|
246 | - // @codingStandardsIgnoreStart |
|
247 | - 'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to delete data into Event Espresso.', |
|
248 | - // @codingStandardsIgnoreEnd |
|
249 | - 'event_espresso' |
|
250 | - ), |
|
251 | - $default_cap_to_check_for |
|
252 | - ), |
|
253 | - array('status' => 403) |
|
254 | - ); |
|
255 | - } |
|
256 | - $obj_id = $request->get_param('id'); |
|
257 | - // this is where we would apply more fine-grained caps |
|
258 | - $model_obj = $model->get_one_by_ID($obj_id); |
|
259 | - if (! $model_obj instanceof EE_Base_Class) { |
|
260 | - $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
261 | - throw new RestException( |
|
262 | - sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
263 | - sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
264 | - array('status' => 404) |
|
265 | - ); |
|
266 | - } |
|
267 | - $requested_permanent_delete = filter_var($request->get_param('force'), FILTER_VALIDATE_BOOLEAN); |
|
268 | - $requested_allow_blocking = filter_var($request->get_param('allow_blocking'), FILTER_VALIDATE_BOOLEAN); |
|
269 | - if ($requested_permanent_delete) { |
|
270 | - $previous = $this->returnModelObjAsJsonResponse($model_obj, $request); |
|
271 | - $deleted = (bool) $model->delete_permanently_by_ID($obj_id, $requested_allow_blocking); |
|
272 | - return array( |
|
273 | - 'deleted' => $deleted, |
|
274 | - 'previous' => $previous, |
|
275 | - ); |
|
276 | - } else { |
|
277 | - if ($model instanceof EEM_Soft_Delete_Base) { |
|
278 | - $model->delete_by_ID($obj_id, $requested_allow_blocking); |
|
279 | - return $this->returnModelObjAsJsonResponse($model_obj, $request); |
|
280 | - } else { |
|
281 | - throw new RestException( |
|
282 | - 'rest_trash_not_supported', |
|
283 | - 501, |
|
284 | - sprintf( |
|
285 | - esc_html__('%1$s do not support trashing. Set force=1 to delete.', 'event_espresso'), |
|
286 | - EEH_Inflector::pluralize($model->get_this_model_name()) |
|
287 | - ) |
|
288 | - ); |
|
289 | - } |
|
290 | - } |
|
291 | - } |
|
229 | + /** |
|
230 | + * Updates an existing model object according to the $request |
|
231 | + * |
|
232 | + * @param EEM_Base $model |
|
233 | + * @param WP_REST_Request $request |
|
234 | + * @return array of either the soft-deleted item, or |
|
235 | + * @throws EE_Error |
|
236 | + */ |
|
237 | + public function delete(EEM_Base $model, WP_REST_Request $request) |
|
238 | + { |
|
239 | + Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_delete, 'delete'); |
|
240 | + $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
|
241 | + if (! current_user_can($default_cap_to_check_for)) { |
|
242 | + throw new RestException( |
|
243 | + 'rest_cannot_delete_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
244 | + sprintf( |
|
245 | + esc_html__( |
|
246 | + // @codingStandardsIgnoreStart |
|
247 | + 'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to delete data into Event Espresso.', |
|
248 | + // @codingStandardsIgnoreEnd |
|
249 | + 'event_espresso' |
|
250 | + ), |
|
251 | + $default_cap_to_check_for |
|
252 | + ), |
|
253 | + array('status' => 403) |
|
254 | + ); |
|
255 | + } |
|
256 | + $obj_id = $request->get_param('id'); |
|
257 | + // this is where we would apply more fine-grained caps |
|
258 | + $model_obj = $model->get_one_by_ID($obj_id); |
|
259 | + if (! $model_obj instanceof EE_Base_Class) { |
|
260 | + $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
261 | + throw new RestException( |
|
262 | + sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
263 | + sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
264 | + array('status' => 404) |
|
265 | + ); |
|
266 | + } |
|
267 | + $requested_permanent_delete = filter_var($request->get_param('force'), FILTER_VALIDATE_BOOLEAN); |
|
268 | + $requested_allow_blocking = filter_var($request->get_param('allow_blocking'), FILTER_VALIDATE_BOOLEAN); |
|
269 | + if ($requested_permanent_delete) { |
|
270 | + $previous = $this->returnModelObjAsJsonResponse($model_obj, $request); |
|
271 | + $deleted = (bool) $model->delete_permanently_by_ID($obj_id, $requested_allow_blocking); |
|
272 | + return array( |
|
273 | + 'deleted' => $deleted, |
|
274 | + 'previous' => $previous, |
|
275 | + ); |
|
276 | + } else { |
|
277 | + if ($model instanceof EEM_Soft_Delete_Base) { |
|
278 | + $model->delete_by_ID($obj_id, $requested_allow_blocking); |
|
279 | + return $this->returnModelObjAsJsonResponse($model_obj, $request); |
|
280 | + } else { |
|
281 | + throw new RestException( |
|
282 | + 'rest_trash_not_supported', |
|
283 | + 501, |
|
284 | + sprintf( |
|
285 | + esc_html__('%1$s do not support trashing. Set force=1 to delete.', 'event_espresso'), |
|
286 | + EEH_Inflector::pluralize($model->get_this_model_name()) |
|
287 | + ) |
|
288 | + ); |
|
289 | + } |
|
290 | + } |
|
291 | + } |
|
292 | 292 | |
293 | 293 | |
294 | - /** |
|
295 | - * Returns an array ready to be converted into a JSON response, based solely on the model object |
|
296 | - * |
|
297 | - * @param EE_Base_Class $model_obj |
|
298 | - * @param WP_REST_Request $request |
|
299 | - * @return array ready for a response |
|
300 | - */ |
|
301 | - protected function returnModelObjAsJsonResponse(EE_Base_Class $model_obj, WP_REST_Request $request) |
|
302 | - { |
|
303 | - $model = $model_obj->get_model(); |
|
304 | - // create an array exactly like the wpdb results row, |
|
305 | - // so we can pass it to controllers/model/Read::create_entity_from_wpdb_result() |
|
306 | - $simulated_db_row = array(); |
|
307 | - foreach ($model->field_settings(true) as $field_name => $field_obj) { |
|
308 | - // we need to reconstruct the normal wpdb results, including the db-only fields |
|
309 | - // like a secondary table's primary key. The models expect those (but don't care what value they have) |
|
310 | - if ($field_obj instanceof EE_DB_Only_Field_Base) { |
|
311 | - $raw_value = true; |
|
312 | - } elseif ($field_obj instanceof EE_Datetime_Field) { |
|
313 | - $raw_value = $model_obj->get_DateTime_object($field_name); |
|
314 | - } else { |
|
315 | - $raw_value = $model_obj->get_raw($field_name); |
|
316 | - } |
|
317 | - $simulated_db_row[ $field_obj->get_qualified_column() ] = $field_obj->prepare_for_use_in_db($raw_value); |
|
318 | - } |
|
319 | - $read_controller = LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
320 | - $read_controller->setRequestedVersion($this->getRequestedVersion()); |
|
321 | - // the simulates request really doesn't need any info downstream |
|
322 | - $simulated_request = new WP_REST_Request('GET'); |
|
323 | - // set the caps context on the simulated according to the original request. |
|
324 | - switch ($request->get_method()) { |
|
325 | - case 'POST': |
|
326 | - case 'PUT': |
|
327 | - $caps_context = EEM_Base::caps_edit; |
|
328 | - break; |
|
329 | - case 'DELETE': |
|
330 | - $caps_context = EEM_Base::caps_delete; |
|
331 | - break; |
|
332 | - default: |
|
333 | - $caps_context = EEM_Base::caps_read_admin; |
|
334 | - } |
|
335 | - $simulated_request->set_param('caps', $caps_context); |
|
336 | - return $read_controller->createEntityFromWpdbResult( |
|
337 | - $model_obj->get_model(), |
|
338 | - $simulated_db_row, |
|
339 | - $simulated_request |
|
340 | - ); |
|
341 | - } |
|
294 | + /** |
|
295 | + * Returns an array ready to be converted into a JSON response, based solely on the model object |
|
296 | + * |
|
297 | + * @param EE_Base_Class $model_obj |
|
298 | + * @param WP_REST_Request $request |
|
299 | + * @return array ready for a response |
|
300 | + */ |
|
301 | + protected function returnModelObjAsJsonResponse(EE_Base_Class $model_obj, WP_REST_Request $request) |
|
302 | + { |
|
303 | + $model = $model_obj->get_model(); |
|
304 | + // create an array exactly like the wpdb results row, |
|
305 | + // so we can pass it to controllers/model/Read::create_entity_from_wpdb_result() |
|
306 | + $simulated_db_row = array(); |
|
307 | + foreach ($model->field_settings(true) as $field_name => $field_obj) { |
|
308 | + // we need to reconstruct the normal wpdb results, including the db-only fields |
|
309 | + // like a secondary table's primary key. The models expect those (but don't care what value they have) |
|
310 | + if ($field_obj instanceof EE_DB_Only_Field_Base) { |
|
311 | + $raw_value = true; |
|
312 | + } elseif ($field_obj instanceof EE_Datetime_Field) { |
|
313 | + $raw_value = $model_obj->get_DateTime_object($field_name); |
|
314 | + } else { |
|
315 | + $raw_value = $model_obj->get_raw($field_name); |
|
316 | + } |
|
317 | + $simulated_db_row[ $field_obj->get_qualified_column() ] = $field_obj->prepare_for_use_in_db($raw_value); |
|
318 | + } |
|
319 | + $read_controller = LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
320 | + $read_controller->setRequestedVersion($this->getRequestedVersion()); |
|
321 | + // the simulates request really doesn't need any info downstream |
|
322 | + $simulated_request = new WP_REST_Request('GET'); |
|
323 | + // set the caps context on the simulated according to the original request. |
|
324 | + switch ($request->get_method()) { |
|
325 | + case 'POST': |
|
326 | + case 'PUT': |
|
327 | + $caps_context = EEM_Base::caps_edit; |
|
328 | + break; |
|
329 | + case 'DELETE': |
|
330 | + $caps_context = EEM_Base::caps_delete; |
|
331 | + break; |
|
332 | + default: |
|
333 | + $caps_context = EEM_Base::caps_read_admin; |
|
334 | + } |
|
335 | + $simulated_request->set_param('caps', $caps_context); |
|
336 | + return $read_controller->createEntityFromWpdbResult( |
|
337 | + $model_obj->get_model(), |
|
338 | + $simulated_db_row, |
|
339 | + $simulated_request |
|
340 | + ); |
|
341 | + } |
|
342 | 342 | |
343 | 343 | |
344 | - /** |
|
345 | - * Gets the item affected by this request |
|
346 | - * |
|
347 | - * @param EEM_Base $model |
|
348 | - * @param WP_REST_Request $request |
|
349 | - * @param int|string $obj_id |
|
350 | - * @return \WP_Error|array |
|
351 | - */ |
|
352 | - protected function getOneBasedOnRequest(EEM_Base $model, WP_REST_Request $request, $obj_id) |
|
353 | - { |
|
354 | - $requested_version = $this->getRequestedVersion($request->get_route()); |
|
355 | - $get_request = new WP_REST_Request( |
|
356 | - 'GET', |
|
357 | - EED_Core_Rest_Api::ee_api_namespace |
|
358 | - . $requested_version |
|
359 | - . '/' |
|
360 | - . EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
361 | - . '/' |
|
362 | - . $obj_id |
|
363 | - ); |
|
364 | - $get_request->set_url_params( |
|
365 | - array( |
|
366 | - 'id' => $obj_id, |
|
367 | - 'include' => $request->get_param('include'), |
|
368 | - ) |
|
369 | - ); |
|
370 | - $read_controller = new Read(); |
|
371 | - $read_controller->setRequestedVersion($this->getRequestedVersion()); |
|
372 | - return $read_controller->getEntityFromModel($model, $get_request); |
|
373 | - } |
|
344 | + /** |
|
345 | + * Gets the item affected by this request |
|
346 | + * |
|
347 | + * @param EEM_Base $model |
|
348 | + * @param WP_REST_Request $request |
|
349 | + * @param int|string $obj_id |
|
350 | + * @return \WP_Error|array |
|
351 | + */ |
|
352 | + protected function getOneBasedOnRequest(EEM_Base $model, WP_REST_Request $request, $obj_id) |
|
353 | + { |
|
354 | + $requested_version = $this->getRequestedVersion($request->get_route()); |
|
355 | + $get_request = new WP_REST_Request( |
|
356 | + 'GET', |
|
357 | + EED_Core_Rest_Api::ee_api_namespace |
|
358 | + . $requested_version |
|
359 | + . '/' |
|
360 | + . EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
361 | + . '/' |
|
362 | + . $obj_id |
|
363 | + ); |
|
364 | + $get_request->set_url_params( |
|
365 | + array( |
|
366 | + 'id' => $obj_id, |
|
367 | + 'include' => $request->get_param('include'), |
|
368 | + ) |
|
369 | + ); |
|
370 | + $read_controller = new Read(); |
|
371 | + $read_controller->setRequestedVersion($this->getRequestedVersion()); |
|
372 | + return $read_controller->getEntityFromModel($model, $get_request); |
|
373 | + } |
|
374 | 374 | |
375 | - /** |
|
376 | - * Adds a relation between the specified models (if it doesn't already exist.) |
|
377 | - * @since 4.9.76.p |
|
378 | - * @param WP_REST_Request $request |
|
379 | - * @return WP_REST_Response |
|
380 | - */ |
|
381 | - public static function handleRequestAddRelation(WP_REST_Request $request, $version, $model_name, $related_model_name) |
|
382 | - { |
|
383 | - $controller = new Write(); |
|
384 | - try { |
|
385 | - $controller->setRequestedVersion($version); |
|
386 | - $main_model = $controller->validateModel($model_name); |
|
387 | - $controller->validateModel($related_model_name); |
|
388 | - return $controller->sendResponse( |
|
389 | - $controller->addRelation( |
|
390 | - $main_model, |
|
391 | - $main_model->related_settings_for($related_model_name), |
|
392 | - $request |
|
393 | - ) |
|
394 | - ); |
|
395 | - } catch (Exception $e) { |
|
396 | - return $controller->sendResponse($e); |
|
397 | - } |
|
398 | - } |
|
375 | + /** |
|
376 | + * Adds a relation between the specified models (if it doesn't already exist.) |
|
377 | + * @since 4.9.76.p |
|
378 | + * @param WP_REST_Request $request |
|
379 | + * @return WP_REST_Response |
|
380 | + */ |
|
381 | + public static function handleRequestAddRelation(WP_REST_Request $request, $version, $model_name, $related_model_name) |
|
382 | + { |
|
383 | + $controller = new Write(); |
|
384 | + try { |
|
385 | + $controller->setRequestedVersion($version); |
|
386 | + $main_model = $controller->validateModel($model_name); |
|
387 | + $controller->validateModel($related_model_name); |
|
388 | + return $controller->sendResponse( |
|
389 | + $controller->addRelation( |
|
390 | + $main_model, |
|
391 | + $main_model->related_settings_for($related_model_name), |
|
392 | + $request |
|
393 | + ) |
|
394 | + ); |
|
395 | + } catch (Exception $e) { |
|
396 | + return $controller->sendResponse($e); |
|
397 | + } |
|
398 | + } |
|
399 | 399 | |
400 | - /** |
|
401 | - * Adds a relation between the two model specified model objects. |
|
402 | - * @since 4.9.76.p |
|
403 | - * @param EEM_Base $model |
|
404 | - * @param EE_Model_Relation_Base $relation |
|
405 | - * @param WP_REST_Request $request |
|
406 | - * @return array |
|
407 | - * @throws EE_Error |
|
408 | - * @throws InvalidArgumentException |
|
409 | - * @throws InvalidDataTypeException |
|
410 | - * @throws InvalidInterfaceException |
|
411 | - * @throws RestException |
|
412 | - * @throws DomainException |
|
413 | - */ |
|
414 | - public function addRelation(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request) |
|
415 | - { |
|
416 | - list($model_obj, $other_obj) = $this->getBothModelObjects($model, $relation, $request); |
|
417 | - $extra_params = array(); |
|
418 | - if ($relation instanceof EE_HABTM_Relation) { |
|
419 | - $extra_params = array_intersect_key( |
|
420 | - ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
421 | - $request->get_body_params(), |
|
422 | - $relation->get_join_model(), |
|
423 | - $this->getModelVersionInfo()->requestedVersion(), |
|
424 | - true |
|
425 | - ), |
|
426 | - $relation->getNonKeyFields() |
|
427 | - ); |
|
428 | - } |
|
429 | - // Add a relation. |
|
430 | - $related_obj = $model_obj->_add_relation_to( |
|
431 | - $other_obj, |
|
432 | - $relation->get_other_model()->get_this_model_name(), |
|
433 | - $extra_params |
|
434 | - ); |
|
435 | - $response = array( |
|
436 | - strtolower($model->get_this_model_name()) => $this->returnModelObjAsJsonResponse($model_obj, $request), |
|
437 | - strtolower($relation->get_other_model()->get_this_model_name()) => $this->returnModelObjAsJsonResponse($related_obj, $request), |
|
438 | - ); |
|
439 | - if ($relation instanceof EE_HABTM_Relation) { |
|
440 | - $join_model_obj = $relation->get_join_model()->get_one( |
|
441 | - array( |
|
442 | - array( |
|
443 | - $relation->get_join_model()->get_foreign_key_to($model->get_this_model_name())->get_name() => $model_obj->ID(), |
|
444 | - $relation->get_join_model()->get_foreign_key_to($relation->get_other_model()->get_this_model_name())->get_name() => $related_obj->ID() |
|
445 | - ) |
|
446 | - ) |
|
447 | - ); |
|
448 | - $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request); |
|
449 | - } |
|
450 | - return $response; |
|
451 | - } |
|
400 | + /** |
|
401 | + * Adds a relation between the two model specified model objects. |
|
402 | + * @since 4.9.76.p |
|
403 | + * @param EEM_Base $model |
|
404 | + * @param EE_Model_Relation_Base $relation |
|
405 | + * @param WP_REST_Request $request |
|
406 | + * @return array |
|
407 | + * @throws EE_Error |
|
408 | + * @throws InvalidArgumentException |
|
409 | + * @throws InvalidDataTypeException |
|
410 | + * @throws InvalidInterfaceException |
|
411 | + * @throws RestException |
|
412 | + * @throws DomainException |
|
413 | + */ |
|
414 | + public function addRelation(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request) |
|
415 | + { |
|
416 | + list($model_obj, $other_obj) = $this->getBothModelObjects($model, $relation, $request); |
|
417 | + $extra_params = array(); |
|
418 | + if ($relation instanceof EE_HABTM_Relation) { |
|
419 | + $extra_params = array_intersect_key( |
|
420 | + ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
421 | + $request->get_body_params(), |
|
422 | + $relation->get_join_model(), |
|
423 | + $this->getModelVersionInfo()->requestedVersion(), |
|
424 | + true |
|
425 | + ), |
|
426 | + $relation->getNonKeyFields() |
|
427 | + ); |
|
428 | + } |
|
429 | + // Add a relation. |
|
430 | + $related_obj = $model_obj->_add_relation_to( |
|
431 | + $other_obj, |
|
432 | + $relation->get_other_model()->get_this_model_name(), |
|
433 | + $extra_params |
|
434 | + ); |
|
435 | + $response = array( |
|
436 | + strtolower($model->get_this_model_name()) => $this->returnModelObjAsJsonResponse($model_obj, $request), |
|
437 | + strtolower($relation->get_other_model()->get_this_model_name()) => $this->returnModelObjAsJsonResponse($related_obj, $request), |
|
438 | + ); |
|
439 | + if ($relation instanceof EE_HABTM_Relation) { |
|
440 | + $join_model_obj = $relation->get_join_model()->get_one( |
|
441 | + array( |
|
442 | + array( |
|
443 | + $relation->get_join_model()->get_foreign_key_to($model->get_this_model_name())->get_name() => $model_obj->ID(), |
|
444 | + $relation->get_join_model()->get_foreign_key_to($relation->get_other_model()->get_this_model_name())->get_name() => $related_obj->ID() |
|
445 | + ) |
|
446 | + ) |
|
447 | + ); |
|
448 | + $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request); |
|
449 | + } |
|
450 | + return $response; |
|
451 | + } |
|
452 | 452 | |
453 | 453 | |
454 | - /** |
|
455 | - * Removes the relation between the specified models (if it exists). |
|
456 | - * @since 4.9.76.p |
|
457 | - * @param WP_REST_Request $request |
|
458 | - * @return WP_REST_Response |
|
459 | - */ |
|
460 | - public static function handleRequestRemoveRelation(WP_REST_Request $request, $version, $model_name, $related_model_name) |
|
461 | - { |
|
462 | - $controller = new Write(); |
|
463 | - try { |
|
464 | - $controller->setRequestedVersion($version); |
|
465 | - $main_model = $controller->getModelVersionInfo()->loadModel($model_name); |
|
466 | - return $controller->sendResponse( |
|
467 | - $controller->removeRelation( |
|
468 | - $main_model, |
|
469 | - $main_model->related_settings_for($related_model_name), |
|
470 | - $request |
|
471 | - ) |
|
472 | - ); |
|
473 | - } catch (Exception $e) { |
|
474 | - return $controller->sendResponse($e); |
|
475 | - } |
|
476 | - } |
|
454 | + /** |
|
455 | + * Removes the relation between the specified models (if it exists). |
|
456 | + * @since 4.9.76.p |
|
457 | + * @param WP_REST_Request $request |
|
458 | + * @return WP_REST_Response |
|
459 | + */ |
|
460 | + public static function handleRequestRemoveRelation(WP_REST_Request $request, $version, $model_name, $related_model_name) |
|
461 | + { |
|
462 | + $controller = new Write(); |
|
463 | + try { |
|
464 | + $controller->setRequestedVersion($version); |
|
465 | + $main_model = $controller->getModelVersionInfo()->loadModel($model_name); |
|
466 | + return $controller->sendResponse( |
|
467 | + $controller->removeRelation( |
|
468 | + $main_model, |
|
469 | + $main_model->related_settings_for($related_model_name), |
|
470 | + $request |
|
471 | + ) |
|
472 | + ); |
|
473 | + } catch (Exception $e) { |
|
474 | + return $controller->sendResponse($e); |
|
475 | + } |
|
476 | + } |
|
477 | 477 | |
478 | - /** |
|
479 | - * Adds a relation between the two model specified model objects. |
|
480 | - * @since 4.9.76.p |
|
481 | - * @param EEM_Base $model |
|
482 | - * @param EE_Model_Relation_Base $relation |
|
483 | - * @param WP_REST_Request $request |
|
484 | - * @return array |
|
485 | - * @throws DomainException |
|
486 | - * @throws EE_Error |
|
487 | - * @throws InvalidArgumentException |
|
488 | - * @throws InvalidDataTypeException |
|
489 | - * @throws InvalidInterfaceException |
|
490 | - * @throws RestException |
|
491 | - */ |
|
492 | - public function removeRelation(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request) |
|
493 | - { |
|
494 | - // This endpoint doesn't accept body parameters (it's understandable to think it might, so let developers know |
|
495 | - // up-front that it doesn't.) |
|
496 | - if (!empty($request->get_body_params())) { |
|
497 | - $body_params = $request->get_body_params(); |
|
498 | - throw new RestException( |
|
499 | - 'invalid_field', |
|
500 | - sprintf( |
|
501 | - esc_html__('This endpoint doesn\'t accept post body arguments, you sent in %1$s', 'event_espresso'), |
|
502 | - implode(array_keys($body_params)) |
|
503 | - ) |
|
504 | - ); |
|
505 | - } |
|
506 | - list($model_obj, $other_obj) = $this->getBothModelObjects($model, $relation, $request); |
|
507 | - // Remember the old relation, if it used a join entry. |
|
508 | - $join_model_obj = null; |
|
509 | - if ($relation instanceof EE_HABTM_Relation) { |
|
510 | - $join_model_obj = $relation->get_join_model()->get_one( |
|
511 | - array( |
|
512 | - array( |
|
513 | - $model->primary_key_name() => $model_obj->ID(), |
|
514 | - $relation->get_other_model()->primary_key_name() => $other_obj->ID() |
|
515 | - ) |
|
516 | - ) |
|
517 | - ); |
|
518 | - } |
|
519 | - // Remove the relation. |
|
520 | - $related_obj = $model_obj->_remove_relation_to( |
|
521 | - $other_obj, |
|
522 | - $relation->get_other_model()->get_this_model_name() |
|
523 | - ); |
|
524 | - $response = array( |
|
525 | - strtolower($model->get_this_model_name()) => $this->returnModelObjAsJsonResponse($model_obj, $request), |
|
526 | - strtolower($relation->get_other_model()->get_this_model_name()) => $this->returnModelObjAsJsonResponse($related_obj, $request), |
|
527 | - ); |
|
528 | - if ($relation instanceof EE_HABTM_Relation) { |
|
529 | - $join_model_obj_after_removal = $relation->get_join_model()->get_one( |
|
530 | - array( |
|
531 | - array( |
|
532 | - $model->primary_key_name() => $model_obj->ID(), |
|
533 | - $relation->get_other_model()->primary_key_name() => $other_obj->ID() |
|
534 | - ) |
|
535 | - ) |
|
536 | - ); |
|
537 | - if ($join_model_obj instanceof EE_Base_Class) { |
|
538 | - $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request); |
|
539 | - } else { |
|
540 | - $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = null; |
|
541 | - } |
|
542 | - } |
|
543 | - return $response; |
|
544 | - } |
|
478 | + /** |
|
479 | + * Adds a relation between the two model specified model objects. |
|
480 | + * @since 4.9.76.p |
|
481 | + * @param EEM_Base $model |
|
482 | + * @param EE_Model_Relation_Base $relation |
|
483 | + * @param WP_REST_Request $request |
|
484 | + * @return array |
|
485 | + * @throws DomainException |
|
486 | + * @throws EE_Error |
|
487 | + * @throws InvalidArgumentException |
|
488 | + * @throws InvalidDataTypeException |
|
489 | + * @throws InvalidInterfaceException |
|
490 | + * @throws RestException |
|
491 | + */ |
|
492 | + public function removeRelation(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request) |
|
493 | + { |
|
494 | + // This endpoint doesn't accept body parameters (it's understandable to think it might, so let developers know |
|
495 | + // up-front that it doesn't.) |
|
496 | + if (!empty($request->get_body_params())) { |
|
497 | + $body_params = $request->get_body_params(); |
|
498 | + throw new RestException( |
|
499 | + 'invalid_field', |
|
500 | + sprintf( |
|
501 | + esc_html__('This endpoint doesn\'t accept post body arguments, you sent in %1$s', 'event_espresso'), |
|
502 | + implode(array_keys($body_params)) |
|
503 | + ) |
|
504 | + ); |
|
505 | + } |
|
506 | + list($model_obj, $other_obj) = $this->getBothModelObjects($model, $relation, $request); |
|
507 | + // Remember the old relation, if it used a join entry. |
|
508 | + $join_model_obj = null; |
|
509 | + if ($relation instanceof EE_HABTM_Relation) { |
|
510 | + $join_model_obj = $relation->get_join_model()->get_one( |
|
511 | + array( |
|
512 | + array( |
|
513 | + $model->primary_key_name() => $model_obj->ID(), |
|
514 | + $relation->get_other_model()->primary_key_name() => $other_obj->ID() |
|
515 | + ) |
|
516 | + ) |
|
517 | + ); |
|
518 | + } |
|
519 | + // Remove the relation. |
|
520 | + $related_obj = $model_obj->_remove_relation_to( |
|
521 | + $other_obj, |
|
522 | + $relation->get_other_model()->get_this_model_name() |
|
523 | + ); |
|
524 | + $response = array( |
|
525 | + strtolower($model->get_this_model_name()) => $this->returnModelObjAsJsonResponse($model_obj, $request), |
|
526 | + strtolower($relation->get_other_model()->get_this_model_name()) => $this->returnModelObjAsJsonResponse($related_obj, $request), |
|
527 | + ); |
|
528 | + if ($relation instanceof EE_HABTM_Relation) { |
|
529 | + $join_model_obj_after_removal = $relation->get_join_model()->get_one( |
|
530 | + array( |
|
531 | + array( |
|
532 | + $model->primary_key_name() => $model_obj->ID(), |
|
533 | + $relation->get_other_model()->primary_key_name() => $other_obj->ID() |
|
534 | + ) |
|
535 | + ) |
|
536 | + ); |
|
537 | + if ($join_model_obj instanceof EE_Base_Class) { |
|
538 | + $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = $this->returnModelObjAsJsonResponse($join_model_obj, $request); |
|
539 | + } else { |
|
540 | + $response['join'][ strtolower($relation->get_join_model()->get_this_model_name()) ] = null; |
|
541 | + } |
|
542 | + } |
|
543 | + return $response; |
|
544 | + } |
|
545 | 545 | |
546 | - /** |
|
547 | - * Gets the model objects indicated by the model, relation object, and request. |
|
548 | - * Throws an exception if the first object doesn't exist, and currently if the related object also doesn't exist. |
|
549 | - * However, this behaviour may change, as we may add support for simultaneously creating and relating data. |
|
550 | - * @since 4.9.76.p |
|
551 | - * @param EEM_Base $model |
|
552 | - * @param EE_Model_Relation_Base $relation |
|
553 | - * @param WP_REST_Request $request |
|
554 | - * @return array { |
|
555 | - * @type EE_Base_Class $model_obj |
|
556 | - * @type EE_Base_Class|null $other_model_obj |
|
557 | - * } |
|
558 | - * @throws RestException |
|
559 | - */ |
|
560 | - protected function getBothModelObjects(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request) |
|
561 | - { |
|
562 | - // Check generic caps. For now, we're only allowing access to this endpoint to full admins. |
|
563 | - Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit'); |
|
564 | - $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
|
565 | - if (! current_user_can($default_cap_to_check_for)) { |
|
566 | - throw new RestException( |
|
567 | - 'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
568 | - sprintf( |
|
569 | - esc_html__( |
|
570 | - // @codingStandardsIgnoreStart |
|
571 | - 'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to add relations in Event Espresso.', |
|
572 | - // @codingStandardsIgnoreEnd |
|
573 | - 'event_espresso' |
|
574 | - ), |
|
575 | - $default_cap_to_check_for |
|
576 | - ), |
|
577 | - array('status' => 403) |
|
578 | - ); |
|
579 | - } |
|
580 | - // Get the main model object. |
|
581 | - $model_obj = $this->getOneOrThrowException($model, $request->get_param('id')); |
|
582 | - // For now, we require the other model object to exist too. This might be relaxed later. |
|
583 | - $other_obj = $this->getOneOrThrowException($relation->get_other_model(), $request->get_param('related_id')); |
|
584 | - return array($model_obj,$other_obj); |
|
585 | - } |
|
546 | + /** |
|
547 | + * Gets the model objects indicated by the model, relation object, and request. |
|
548 | + * Throws an exception if the first object doesn't exist, and currently if the related object also doesn't exist. |
|
549 | + * However, this behaviour may change, as we may add support for simultaneously creating and relating data. |
|
550 | + * @since 4.9.76.p |
|
551 | + * @param EEM_Base $model |
|
552 | + * @param EE_Model_Relation_Base $relation |
|
553 | + * @param WP_REST_Request $request |
|
554 | + * @return array { |
|
555 | + * @type EE_Base_Class $model_obj |
|
556 | + * @type EE_Base_Class|null $other_model_obj |
|
557 | + * } |
|
558 | + * @throws RestException |
|
559 | + */ |
|
560 | + protected function getBothModelObjects(EEM_Base $model, EE_Model_Relation_Base $relation, WP_REST_Request $request) |
|
561 | + { |
|
562 | + // Check generic caps. For now, we're only allowing access to this endpoint to full admins. |
|
563 | + Capabilities::verifyAtLeastPartialAccessTo($model, EEM_Base::caps_edit, 'edit'); |
|
564 | + $default_cap_to_check_for = EE_Restriction_Generator_Base::get_default_restrictions_cap(); |
|
565 | + if (! current_user_can($default_cap_to_check_for)) { |
|
566 | + throw new RestException( |
|
567 | + 'rest_cannot_edit_' . EEH_Inflector::pluralize_and_lower(($model->get_this_model_name())), |
|
568 | + sprintf( |
|
569 | + esc_html__( |
|
570 | + // @codingStandardsIgnoreStart |
|
571 | + 'For now, only those with the admin capability to "%1$s" are allowed to use the REST API to add relations in Event Espresso.', |
|
572 | + // @codingStandardsIgnoreEnd |
|
573 | + 'event_espresso' |
|
574 | + ), |
|
575 | + $default_cap_to_check_for |
|
576 | + ), |
|
577 | + array('status' => 403) |
|
578 | + ); |
|
579 | + } |
|
580 | + // Get the main model object. |
|
581 | + $model_obj = $this->getOneOrThrowException($model, $request->get_param('id')); |
|
582 | + // For now, we require the other model object to exist too. This might be relaxed later. |
|
583 | + $other_obj = $this->getOneOrThrowException($relation->get_other_model(), $request->get_param('related_id')); |
|
584 | + return array($model_obj,$other_obj); |
|
585 | + } |
|
586 | 586 | |
587 | - /** |
|
588 | - * Gets the model with that ID or throws a REST exception. |
|
589 | - * @since 4.9.76.p |
|
590 | - * @param EEM_Base $model |
|
591 | - * @param $id |
|
592 | - * @return EE_Base_Class |
|
593 | - * @throws RestException |
|
594 | - */ |
|
595 | - protected function getOneOrThrowException(EEM_Base $model, $id) |
|
596 | - { |
|
597 | - $model_obj = $model->get_one_by_ID($id); |
|
598 | - // @todo: check they can permission for it. For now unnecessary because only full admins can use this endpoint. |
|
599 | - if ($model_obj instanceof EE_Base_Class) { |
|
600 | - return $model_obj; |
|
601 | - } |
|
602 | - $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
603 | - throw new RestException( |
|
604 | - sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
605 | - sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
606 | - array('status' => 404) |
|
607 | - ); |
|
608 | - } |
|
587 | + /** |
|
588 | + * Gets the model with that ID or throws a REST exception. |
|
589 | + * @since 4.9.76.p |
|
590 | + * @param EEM_Base $model |
|
591 | + * @param $id |
|
592 | + * @return EE_Base_Class |
|
593 | + * @throws RestException |
|
594 | + */ |
|
595 | + protected function getOneOrThrowException(EEM_Base $model, $id) |
|
596 | + { |
|
597 | + $model_obj = $model->get_one_by_ID($id); |
|
598 | + // @todo: check they can permission for it. For now unnecessary because only full admins can use this endpoint. |
|
599 | + if ($model_obj instanceof EE_Base_Class) { |
|
600 | + return $model_obj; |
|
601 | + } |
|
602 | + $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
603 | + throw new RestException( |
|
604 | + sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
605 | + sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
606 | + array('status' => 404) |
|
607 | + ); |
|
608 | + } |
|
609 | 609 | } |
@@ -37,74 +37,74 @@ |
||
37 | 37 | abstract class ChangesInBase |
38 | 38 | { |
39 | 39 | |
40 | - /** |
|
41 | - * The version that these changes happened |
|
42 | - * |
|
43 | - * @var string |
|
44 | - */ |
|
45 | - protected $version = null; |
|
40 | + /** |
|
41 | + * The version that these changes happened |
|
42 | + * |
|
43 | + * @var string |
|
44 | + */ |
|
45 | + protected $version = null; |
|
46 | 46 | |
47 | 47 | |
48 | - /** |
|
49 | - * Called when an EE4 REST API request is made to an earlier version than |
|
50 | - * what is indicated in this class' name. |
|
51 | - * Uses WordPress' add_filter and add_action to modify the EE4 REST API's response |
|
52 | - * so that regardless of what version of EE4 core is running, API clients |
|
53 | - * will have a consistent response |
|
54 | - * |
|
55 | - * @return void |
|
56 | - */ |
|
57 | - abstract public function setHooks(); |
|
48 | + /** |
|
49 | + * Called when an EE4 REST API request is made to an earlier version than |
|
50 | + * what is indicated in this class' name. |
|
51 | + * Uses WordPress' add_filter and add_action to modify the EE4 REST API's response |
|
52 | + * so that regardless of what version of EE4 core is running, API clients |
|
53 | + * will have a consistent response |
|
54 | + * |
|
55 | + * @return void |
|
56 | + */ |
|
57 | + abstract public function setHooks(); |
|
58 | 58 | |
59 | 59 | |
60 | - /** |
|
61 | - * Returns whether or not this class' name indicates its hooks should |
|
62 | - * apply when a request comes in for $requested_version. A class can use |
|
63 | - * other conditions when determining whether to perform their callbacks or not, |
|
64 | - * but this will typically be enough |
|
65 | - * |
|
66 | - * @param string $requested_version eg "4.8.33" |
|
67 | - * @return boolean true: this class' name indicates its filters and actions |
|
68 | - * should take effect. False: this class' name indicates it shouldn't do anything |
|
69 | - */ |
|
70 | - public function appliesToVersion($requested_version) |
|
71 | - { |
|
72 | - if ($this->version() > $requested_version) { |
|
73 | - return true; |
|
74 | - } |
|
75 | - return false; |
|
76 | - } |
|
60 | + /** |
|
61 | + * Returns whether or not this class' name indicates its hooks should |
|
62 | + * apply when a request comes in for $requested_version. A class can use |
|
63 | + * other conditions when determining whether to perform their callbacks or not, |
|
64 | + * but this will typically be enough |
|
65 | + * |
|
66 | + * @param string $requested_version eg "4.8.33" |
|
67 | + * @return boolean true: this class' name indicates its filters and actions |
|
68 | + * should take effect. False: this class' name indicates it shouldn't do anything |
|
69 | + */ |
|
70 | + public function appliesToVersion($requested_version) |
|
71 | + { |
|
72 | + if ($this->version() > $requested_version) { |
|
73 | + return true; |
|
74 | + } |
|
75 | + return false; |
|
76 | + } |
|
77 | 77 | |
78 | 78 | |
79 | - /** |
|
80 | - * Gets the EE core version when this changes were made to the rest api. |
|
81 | - * Any requests to earlier versions should have modifications made to them |
|
82 | - * by the callbacks of this class. |
|
83 | - * |
|
84 | - * @return string eg "4.8.33" |
|
85 | - * @throws EE_Error |
|
86 | - */ |
|
87 | - public function version() |
|
88 | - { |
|
89 | - if ($this->version === null) { |
|
90 | - $matches = array(); |
|
91 | - $regex = '~ChangesIn(\d)(\d\d)(\d\d)$~'; |
|
92 | - $success = preg_match( |
|
93 | - $regex, |
|
94 | - get_class($this), |
|
95 | - $matches |
|
96 | - ); |
|
97 | - if (! $success) { |
|
98 | - throw new EE_Error( |
|
99 | - sprintf( |
|
100 | - esc_html__('The class %1$s was misnamed. It name should match the regex "%2$s"', 'event_espresso'), |
|
101 | - get_class($this), |
|
102 | - $regex |
|
103 | - ) |
|
104 | - ); |
|
105 | - } |
|
106 | - $this->version = (int) $matches[1] . '.' . (int) $matches[2] . '.' . (int) $matches[3]; |
|
107 | - } |
|
108 | - return $this->version; |
|
109 | - } |
|
79 | + /** |
|
80 | + * Gets the EE core version when this changes were made to the rest api. |
|
81 | + * Any requests to earlier versions should have modifications made to them |
|
82 | + * by the callbacks of this class. |
|
83 | + * |
|
84 | + * @return string eg "4.8.33" |
|
85 | + * @throws EE_Error |
|
86 | + */ |
|
87 | + public function version() |
|
88 | + { |
|
89 | + if ($this->version === null) { |
|
90 | + $matches = array(); |
|
91 | + $regex = '~ChangesIn(\d)(\d\d)(\d\d)$~'; |
|
92 | + $success = preg_match( |
|
93 | + $regex, |
|
94 | + get_class($this), |
|
95 | + $matches |
|
96 | + ); |
|
97 | + if (! $success) { |
|
98 | + throw new EE_Error( |
|
99 | + sprintf( |
|
100 | + esc_html__('The class %1$s was misnamed. It name should match the regex "%2$s"', 'event_espresso'), |
|
101 | + get_class($this), |
|
102 | + $regex |
|
103 | + ) |
|
104 | + ); |
|
105 | + } |
|
106 | + $this->version = (int) $matches[1] . '.' . (int) $matches[2] . '.' . (int) $matches[3]; |
|
107 | + } |
|
108 | + return $this->version; |
|
109 | + } |
|
110 | 110 | } |
@@ -94,7 +94,7 @@ discard block |
||
94 | 94 | get_class($this), |
95 | 95 | $matches |
96 | 96 | ); |
97 | - if (! $success) { |
|
97 | + if ( ! $success) { |
|
98 | 98 | throw new EE_Error( |
99 | 99 | sprintf( |
100 | 100 | esc_html__('The class %1$s was misnamed. It name should match the regex "%2$s"', 'event_espresso'), |
@@ -103,7 +103,7 @@ discard block |
||
103 | 103 | ) |
104 | 104 | ); |
105 | 105 | } |
106 | - $this->version = (int) $matches[1] . '.' . (int) $matches[2] . '.' . (int) $matches[3]; |
|
106 | + $this->version = (int) $matches[1].'.'.(int) $matches[2].'.'.(int) $matches[3]; |
|
107 | 107 | } |
108 | 108 | return $this->version; |
109 | 109 | } |
@@ -17,214 +17,214 @@ |
||
17 | 17 | |
18 | 18 | class Datetime extends DatetimeCalculationBase |
19 | 19 | { |
20 | - /** |
|
21 | - * @var EEM_Datetime |
|
22 | - */ |
|
23 | - protected $datetime_model; |
|
20 | + /** |
|
21 | + * @var EEM_Datetime |
|
22 | + */ |
|
23 | + protected $datetime_model; |
|
24 | 24 | |
25 | - /** |
|
26 | - * @var EEM_Registration |
|
27 | - */ |
|
28 | - protected $registration_model; |
|
29 | - public function __construct(EEM_Datetime $datetime_model, EEM_Registration $registration_model) |
|
30 | - { |
|
31 | - $this->datetime_model = $datetime_model; |
|
32 | - $this->registration_model = $registration_model; |
|
33 | - } |
|
25 | + /** |
|
26 | + * @var EEM_Registration |
|
27 | + */ |
|
28 | + protected $registration_model; |
|
29 | + public function __construct(EEM_Datetime $datetime_model, EEM_Registration $registration_model) |
|
30 | + { |
|
31 | + $this->datetime_model = $datetime_model; |
|
32 | + $this->registration_model = $registration_model; |
|
33 | + } |
|
34 | 34 | |
35 | - /** |
|
36 | - * Calculates the total spaces available on the datetime, taking into account |
|
37 | - * ticket limits too. |
|
38 | - * |
|
39 | - * @see EE_Datetime::spaces_remaining( true ) |
|
40 | - * @param array $wpdb_row |
|
41 | - * @param WP_REST_Request $request |
|
42 | - * @param DatetimeControllerBase $controller |
|
43 | - * @return int |
|
44 | - * @throws EE_Error |
|
45 | - * @throws InvalidDataTypeException |
|
46 | - * @throws InvalidInterfaceException |
|
47 | - * @throws InvalidArgumentException |
|
48 | - * @throws ReflectionException |
|
49 | - */ |
|
50 | - public function spacesRemainingConsideringTickets($wpdb_row, $request, $controller) |
|
51 | - { |
|
52 | - if (is_array($wpdb_row) && isset($wpdb_row['Datetime.DTT_ID'])) { |
|
53 | - $dtt_obj = $this->datetime_model->get_one_by_ID($wpdb_row['Datetime.DTT_ID']); |
|
54 | - } else { |
|
55 | - $dtt_obj = null; |
|
56 | - } |
|
57 | - if ($dtt_obj instanceof EE_Datetime) { |
|
58 | - return $dtt_obj->spaces_remaining(true); |
|
59 | - } |
|
60 | - throw new EE_Error( |
|
61 | - sprintf( |
|
62 | - esc_html__( |
|
63 | - // @codingStandardsIgnoreStart |
|
64 | - 'Cannot calculate spaces_remaining_considering_tickets because the datetime with ID %1$s (from database row %2$s) was not found', |
|
65 | - // @codingStandardsIgnoreEnd |
|
66 | - 'event_espresso' |
|
67 | - ), |
|
68 | - $wpdb_row['Datetime.DTT_ID'], |
|
69 | - print_r($wpdb_row, true) |
|
70 | - ) |
|
71 | - ); |
|
72 | - } |
|
35 | + /** |
|
36 | + * Calculates the total spaces available on the datetime, taking into account |
|
37 | + * ticket limits too. |
|
38 | + * |
|
39 | + * @see EE_Datetime::spaces_remaining( true ) |
|
40 | + * @param array $wpdb_row |
|
41 | + * @param WP_REST_Request $request |
|
42 | + * @param DatetimeControllerBase $controller |
|
43 | + * @return int |
|
44 | + * @throws EE_Error |
|
45 | + * @throws InvalidDataTypeException |
|
46 | + * @throws InvalidInterfaceException |
|
47 | + * @throws InvalidArgumentException |
|
48 | + * @throws ReflectionException |
|
49 | + */ |
|
50 | + public function spacesRemainingConsideringTickets($wpdb_row, $request, $controller) |
|
51 | + { |
|
52 | + if (is_array($wpdb_row) && isset($wpdb_row['Datetime.DTT_ID'])) { |
|
53 | + $dtt_obj = $this->datetime_model->get_one_by_ID($wpdb_row['Datetime.DTT_ID']); |
|
54 | + } else { |
|
55 | + $dtt_obj = null; |
|
56 | + } |
|
57 | + if ($dtt_obj instanceof EE_Datetime) { |
|
58 | + return $dtt_obj->spaces_remaining(true); |
|
59 | + } |
|
60 | + throw new EE_Error( |
|
61 | + sprintf( |
|
62 | + esc_html__( |
|
63 | + // @codingStandardsIgnoreStart |
|
64 | + 'Cannot calculate spaces_remaining_considering_tickets because the datetime with ID %1$s (from database row %2$s) was not found', |
|
65 | + // @codingStandardsIgnoreEnd |
|
66 | + 'event_espresso' |
|
67 | + ), |
|
68 | + $wpdb_row['Datetime.DTT_ID'], |
|
69 | + print_r($wpdb_row, true) |
|
70 | + ) |
|
71 | + ); |
|
72 | + } |
|
73 | 73 | |
74 | 74 | |
75 | - /** |
|
76 | - * Counts registrations who have checked into this datetime |
|
77 | - * |
|
78 | - * @param array $wpdb_row |
|
79 | - * @param WP_REST_Request $request |
|
80 | - * @param DatetimeControllerBase $controller |
|
81 | - * @return int |
|
82 | - * @throws EE_Error |
|
83 | - * @throws InvalidArgumentException |
|
84 | - * @throws InvalidDataTypeException |
|
85 | - * @throws InvalidInterfaceException |
|
86 | - * @throws RestException |
|
87 | - */ |
|
88 | - public function registrationsCheckedInCount($wpdb_row, $request, $controller) |
|
89 | - { |
|
90 | - if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
91 | - throw new EE_Error( |
|
92 | - sprintf( |
|
93 | - esc_html__( |
|
94 | - // @codingStandardsIgnoreStart |
|
95 | - 'Cannot calculate registrations_checked_in_count because the database row %1$s does not have an entry for "Datetime.DTT_ID"', |
|
96 | - // @codingStandardsIgnoreEnd |
|
97 | - 'event_espresso' |
|
98 | - ), |
|
99 | - print_r($wpdb_row, true) |
|
100 | - ) |
|
101 | - ); |
|
102 | - } |
|
103 | - $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_in_count'); |
|
104 | - return $this->registration_model |
|
105 | - ->count_registrations_checked_into_datetime($wpdb_row['Datetime.DTT_ID'], true); |
|
106 | - } |
|
75 | + /** |
|
76 | + * Counts registrations who have checked into this datetime |
|
77 | + * |
|
78 | + * @param array $wpdb_row |
|
79 | + * @param WP_REST_Request $request |
|
80 | + * @param DatetimeControllerBase $controller |
|
81 | + * @return int |
|
82 | + * @throws EE_Error |
|
83 | + * @throws InvalidArgumentException |
|
84 | + * @throws InvalidDataTypeException |
|
85 | + * @throws InvalidInterfaceException |
|
86 | + * @throws RestException |
|
87 | + */ |
|
88 | + public function registrationsCheckedInCount($wpdb_row, $request, $controller) |
|
89 | + { |
|
90 | + if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
91 | + throw new EE_Error( |
|
92 | + sprintf( |
|
93 | + esc_html__( |
|
94 | + // @codingStandardsIgnoreStart |
|
95 | + 'Cannot calculate registrations_checked_in_count because the database row %1$s does not have an entry for "Datetime.DTT_ID"', |
|
96 | + // @codingStandardsIgnoreEnd |
|
97 | + 'event_espresso' |
|
98 | + ), |
|
99 | + print_r($wpdb_row, true) |
|
100 | + ) |
|
101 | + ); |
|
102 | + } |
|
103 | + $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_in_count'); |
|
104 | + return $this->registration_model |
|
105 | + ->count_registrations_checked_into_datetime($wpdb_row['Datetime.DTT_ID'], true); |
|
106 | + } |
|
107 | 107 | |
108 | 108 | |
109 | - /** |
|
110 | - * Counts registrations who have checked out of this datetime |
|
111 | - * |
|
112 | - * @param array $wpdb_row |
|
113 | - * @param WP_REST_Request $request |
|
114 | - * @param DatetimeControllerBase $controller |
|
115 | - * @return int |
|
116 | - * @throws EE_Error |
|
117 | - * @throws InvalidArgumentException |
|
118 | - * @throws InvalidDataTypeException |
|
119 | - * @throws InvalidInterfaceException |
|
120 | - * @throws RestException |
|
121 | - */ |
|
122 | - public function registrationsCheckedOutCount($wpdb_row, $request, $controller) |
|
123 | - { |
|
124 | - if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
125 | - throw new EE_Error( |
|
126 | - sprintf( |
|
127 | - esc_html__( |
|
128 | - // @codingStandardsIgnoreStart |
|
129 | - 'Cannot calculate registrations_checked_out_count because the database row %1$s does not have an entry for "Datetime.DTT_ID"', |
|
130 | - // @codingStandardsIgnoreEnd |
|
131 | - 'event_espresso' |
|
132 | - ), |
|
133 | - print_r($wpdb_row, true) |
|
134 | - ) |
|
135 | - ); |
|
136 | - } |
|
137 | - $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_out_count'); |
|
138 | - return $this->registration_model |
|
139 | - ->count_registrations_checked_into_datetime($wpdb_row['Datetime.DTT_ID'], false); |
|
140 | - } |
|
109 | + /** |
|
110 | + * Counts registrations who have checked out of this datetime |
|
111 | + * |
|
112 | + * @param array $wpdb_row |
|
113 | + * @param WP_REST_Request $request |
|
114 | + * @param DatetimeControllerBase $controller |
|
115 | + * @return int |
|
116 | + * @throws EE_Error |
|
117 | + * @throws InvalidArgumentException |
|
118 | + * @throws InvalidDataTypeException |
|
119 | + * @throws InvalidInterfaceException |
|
120 | + * @throws RestException |
|
121 | + */ |
|
122 | + public function registrationsCheckedOutCount($wpdb_row, $request, $controller) |
|
123 | + { |
|
124 | + if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
125 | + throw new EE_Error( |
|
126 | + sprintf( |
|
127 | + esc_html__( |
|
128 | + // @codingStandardsIgnoreStart |
|
129 | + 'Cannot calculate registrations_checked_out_count because the database row %1$s does not have an entry for "Datetime.DTT_ID"', |
|
130 | + // @codingStandardsIgnoreEnd |
|
131 | + 'event_espresso' |
|
132 | + ), |
|
133 | + print_r($wpdb_row, true) |
|
134 | + ) |
|
135 | + ); |
|
136 | + } |
|
137 | + $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_out_count'); |
|
138 | + return $this->registration_model |
|
139 | + ->count_registrations_checked_into_datetime($wpdb_row['Datetime.DTT_ID'], false); |
|
140 | + } |
|
141 | 141 | |
142 | 142 | |
143 | - /** |
|
144 | - * Counts the number of pending-payment registrations for this event (regardless |
|
145 | - * of how many datetimes each registrations' ticket purchase is for) |
|
146 | - * |
|
147 | - * @param array $wpdb_row |
|
148 | - * @param WP_REST_Request $request |
|
149 | - * @param DatetimeControllerBase $controller |
|
150 | - * @return int |
|
151 | - * @throws EE_Error |
|
152 | - * @throws InvalidArgumentException |
|
153 | - * @throws InvalidDataTypeException |
|
154 | - * @throws InvalidInterfaceException |
|
155 | - * @throws RestException |
|
156 | - */ |
|
157 | - public function spotsTakenPendingPayment($wpdb_row, $request, $controller) |
|
158 | - { |
|
159 | - if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
160 | - throw new EE_Error( |
|
161 | - sprintf( |
|
162 | - esc_html__( |
|
163 | - // @codingStandardsIgnoreStart |
|
164 | - 'Cannot calculate spots_taken_pending_payment because the database row %1$s does not have an entry for "Datetime.DTT_ID"', |
|
165 | - // @codingStandardsIgnoreEnd |
|
166 | - 'event_espresso' |
|
167 | - ), |
|
168 | - print_r($wpdb_row, true) |
|
169 | - ) |
|
170 | - ); |
|
171 | - } |
|
172 | - $this->verifyCurrentUserCan('ee_read_registrations', 'spots_taken_pending_payment'); |
|
173 | - return $this->registration_model->count( |
|
174 | - array( |
|
175 | - array( |
|
176 | - 'Ticket.Datetime.DTT_ID' => $wpdb_row['Datetime.DTT_ID'], |
|
177 | - 'STS_ID' => EEM_Registration::status_id_pending_payment, |
|
178 | - ), |
|
179 | - ), |
|
180 | - 'REG_ID', |
|
181 | - true |
|
182 | - ); |
|
183 | - } |
|
143 | + /** |
|
144 | + * Counts the number of pending-payment registrations for this event (regardless |
|
145 | + * of how many datetimes each registrations' ticket purchase is for) |
|
146 | + * |
|
147 | + * @param array $wpdb_row |
|
148 | + * @param WP_REST_Request $request |
|
149 | + * @param DatetimeControllerBase $controller |
|
150 | + * @return int |
|
151 | + * @throws EE_Error |
|
152 | + * @throws InvalidArgumentException |
|
153 | + * @throws InvalidDataTypeException |
|
154 | + * @throws InvalidInterfaceException |
|
155 | + * @throws RestException |
|
156 | + */ |
|
157 | + public function spotsTakenPendingPayment($wpdb_row, $request, $controller) |
|
158 | + { |
|
159 | + if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
160 | + throw new EE_Error( |
|
161 | + sprintf( |
|
162 | + esc_html__( |
|
163 | + // @codingStandardsIgnoreStart |
|
164 | + 'Cannot calculate spots_taken_pending_payment because the database row %1$s does not have an entry for "Datetime.DTT_ID"', |
|
165 | + // @codingStandardsIgnoreEnd |
|
166 | + 'event_espresso' |
|
167 | + ), |
|
168 | + print_r($wpdb_row, true) |
|
169 | + ) |
|
170 | + ); |
|
171 | + } |
|
172 | + $this->verifyCurrentUserCan('ee_read_registrations', 'spots_taken_pending_payment'); |
|
173 | + return $this->registration_model->count( |
|
174 | + array( |
|
175 | + array( |
|
176 | + 'Ticket.Datetime.DTT_ID' => $wpdb_row['Datetime.DTT_ID'], |
|
177 | + 'STS_ID' => EEM_Registration::status_id_pending_payment, |
|
178 | + ), |
|
179 | + ), |
|
180 | + 'REG_ID', |
|
181 | + true |
|
182 | + ); |
|
183 | + } |
|
184 | 184 | |
185 | 185 | |
186 | - /** |
|
187 | - * Provides an array for all the calculations possible that outlines a json schema for those calculations. |
|
188 | - * Array is indexed by calculation (snake case) and value is the schema for that calculation. |
|
189 | - * |
|
190 | - * @since 4.9.68.p |
|
191 | - * @return array |
|
192 | - */ |
|
193 | - public function schemaForCalculations() |
|
194 | - { |
|
195 | - return array( |
|
196 | - 'spaces_remaining_considering_tickets' => array( |
|
197 | - 'description' => esc_html__( |
|
198 | - 'Calculates the total spaces available on the datetime, taking into account ticket limits too.', |
|
199 | - 'event_espresso' |
|
200 | - ), |
|
201 | - 'type' => 'number', |
|
202 | - 'protected' => true, |
|
203 | - ), |
|
204 | - 'registrations_checked_in_count' => array( |
|
205 | - 'description' => esc_html__( |
|
206 | - 'Counts registrations who have checked into this datetime.', |
|
207 | - 'event_espresso' |
|
208 | - ), |
|
209 | - 'type' => 'number', |
|
210 | - 'protected' => true, |
|
211 | - ), |
|
212 | - 'registrations_checked_out_count' => array( |
|
213 | - 'description' => esc_html__( |
|
214 | - 'Counts registrations who have checked out of this datetime.', |
|
215 | - 'event_espresso' |
|
216 | - ), |
|
217 | - 'type' => 'number', |
|
218 | - 'protected' => true, |
|
219 | - ), |
|
220 | - 'spots_taken_pending_payment' => array( |
|
221 | - 'description' => esc_html__( |
|
222 | - 'The count of pending-payment registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for', |
|
223 | - 'event_espresso' |
|
224 | - ), |
|
225 | - 'type' => 'number', |
|
226 | - 'protected' => true, |
|
227 | - ), |
|
228 | - ); |
|
229 | - } |
|
186 | + /** |
|
187 | + * Provides an array for all the calculations possible that outlines a json schema for those calculations. |
|
188 | + * Array is indexed by calculation (snake case) and value is the schema for that calculation. |
|
189 | + * |
|
190 | + * @since 4.9.68.p |
|
191 | + * @return array |
|
192 | + */ |
|
193 | + public function schemaForCalculations() |
|
194 | + { |
|
195 | + return array( |
|
196 | + 'spaces_remaining_considering_tickets' => array( |
|
197 | + 'description' => esc_html__( |
|
198 | + 'Calculates the total spaces available on the datetime, taking into account ticket limits too.', |
|
199 | + 'event_espresso' |
|
200 | + ), |
|
201 | + 'type' => 'number', |
|
202 | + 'protected' => true, |
|
203 | + ), |
|
204 | + 'registrations_checked_in_count' => array( |
|
205 | + 'description' => esc_html__( |
|
206 | + 'Counts registrations who have checked into this datetime.', |
|
207 | + 'event_espresso' |
|
208 | + ), |
|
209 | + 'type' => 'number', |
|
210 | + 'protected' => true, |
|
211 | + ), |
|
212 | + 'registrations_checked_out_count' => array( |
|
213 | + 'description' => esc_html__( |
|
214 | + 'Counts registrations who have checked out of this datetime.', |
|
215 | + 'event_espresso' |
|
216 | + ), |
|
217 | + 'type' => 'number', |
|
218 | + 'protected' => true, |
|
219 | + ), |
|
220 | + 'spots_taken_pending_payment' => array( |
|
221 | + 'description' => esc_html__( |
|
222 | + 'The count of pending-payment registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for', |
|
223 | + 'event_espresso' |
|
224 | + ), |
|
225 | + 'type' => 'number', |
|
226 | + 'protected' => true, |
|
227 | + ), |
|
228 | + ); |
|
229 | + } |
|
230 | 230 | } |
@@ -87,7 +87,7 @@ discard block |
||
87 | 87 | */ |
88 | 88 | public function registrationsCheckedInCount($wpdb_row, $request, $controller) |
89 | 89 | { |
90 | - if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
90 | + if ( ! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
91 | 91 | throw new EE_Error( |
92 | 92 | sprintf( |
93 | 93 | esc_html__( |
@@ -121,7 +121,7 @@ discard block |
||
121 | 121 | */ |
122 | 122 | public function registrationsCheckedOutCount($wpdb_row, $request, $controller) |
123 | 123 | { |
124 | - if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
124 | + if ( ! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
125 | 125 | throw new EE_Error( |
126 | 126 | sprintf( |
127 | 127 | esc_html__( |
@@ -156,7 +156,7 @@ discard block |
||
156 | 156 | */ |
157 | 157 | public function spotsTakenPendingPayment($wpdb_row, $request, $controller) |
158 | 158 | { |
159 | - if (! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
159 | + if ( ! is_array($wpdb_row) || ! isset($wpdb_row['Datetime.DTT_ID'])) { |
|
160 | 160 | throw new EE_Error( |
161 | 161 | sprintf( |
162 | 162 | esc_html__( |
@@ -26,571 +26,571 @@ |
||
26 | 26 | */ |
27 | 27 | class Event extends EventCalculationBase |
28 | 28 | { |
29 | - /** |
|
30 | - * @var EEM_Event |
|
31 | - */ |
|
32 | - protected $event_model; |
|
33 | - |
|
34 | - /** |
|
35 | - * @var EEM_Registration |
|
36 | - */ |
|
37 | - protected $registration_model; |
|
38 | - public function __construct(EEM_Event $event_model, EEM_Registration $registration_model) |
|
39 | - { |
|
40 | - $this->event_model = $event_model; |
|
41 | - $this->registration_model = $registration_model; |
|
42 | - } |
|
43 | - |
|
44 | - /** |
|
45 | - * Calculates the total spaces on the event (not subtracting sales, but taking |
|
46 | - * sales into account; so this is the optimum sales that CAN still be achieved) |
|
47 | - * See EE_Event::total_available_spaces( true ); |
|
48 | - * |
|
49 | - * @param array $wpdb_row |
|
50 | - * @param WP_REST_Request $request |
|
51 | - * @param EventControllerBase $controller |
|
52 | - * @return int |
|
53 | - * @throws EE_Error |
|
54 | - * @throws DomainException |
|
55 | - * @throws InvalidDataTypeException |
|
56 | - * @throws InvalidInterfaceException |
|
57 | - * @throws UnexpectedEntityException |
|
58 | - * @throws InvalidArgumentException |
|
59 | - */ |
|
60 | - public function optimumSalesAtStart($wpdb_row, $request, $controller) |
|
61 | - { |
|
62 | - $event_obj = null; |
|
63 | - if (Event::wpdbRowHasEventId($wpdb_row)) { |
|
64 | - $event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']); |
|
65 | - } |
|
66 | - if ($event_obj instanceof EE_Event) { |
|
67 | - return $event_obj->total_available_spaces(); |
|
68 | - } |
|
69 | - throw new EE_Error( |
|
70 | - sprintf( |
|
71 | - esc_html__( |
|
72 | - // @codingStandardsIgnoreStart |
|
73 | - 'Cannot calculate optimum_sales_at_start because the event with ID %1$s (from database row %2$s) was not found', |
|
74 | - // @codingStandardsIgnoreEnd |
|
75 | - 'event_espresso' |
|
76 | - ), |
|
77 | - $wpdb_row['Event_CPT.ID'], |
|
78 | - print_r($wpdb_row, true) |
|
79 | - ) |
|
80 | - ); |
|
81 | - } |
|
82 | - |
|
83 | - |
|
84 | - /** |
|
85 | - * Calculates the total spaces on the event (ignoring all sales; so this is the optimum |
|
86 | - * sales that COULD have been achieved) |
|
87 | - * See EE_Event::total_available_spaces( true ); |
|
88 | - * |
|
89 | - * @param array $wpdb_row |
|
90 | - * @param WP_REST_Request $request |
|
91 | - * @param EventControllerBase $controller |
|
92 | - * @return int |
|
93 | - * @throws DomainException |
|
94 | - * @throws EE_Error |
|
95 | - * @throws InvalidArgumentException |
|
96 | - * @throws InvalidDataTypeException |
|
97 | - * @throws InvalidInterfaceException |
|
98 | - * @throws UnexpectedEntityException |
|
99 | - */ |
|
100 | - public function optimumSalesNow($wpdb_row, $request, $controller) |
|
101 | - { |
|
102 | - $event_obj = null; |
|
103 | - if (Event::wpdbRowHasEventId($wpdb_row)) { |
|
104 | - $event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']); |
|
105 | - } |
|
106 | - if ($event_obj instanceof EE_Event) { |
|
107 | - return $event_obj->total_available_spaces(true); |
|
108 | - } |
|
109 | - throw new EE_Error( |
|
110 | - sprintf( |
|
111 | - esc_html__( |
|
112 | - // @codingStandardsIgnoreStart |
|
113 | - 'Cannot calculate optimum_sales_now because the event with ID %1$s (from database row %2$s) was not found', |
|
114 | - // @codingStandardsIgnoreEnd |
|
115 | - 'event_espresso' |
|
116 | - ), |
|
117 | - $wpdb_row['Event_CPT.ID'], |
|
118 | - print_r($wpdb_row, true) |
|
119 | - ) |
|
120 | - ); |
|
121 | - } |
|
122 | - |
|
123 | - |
|
124 | - /** |
|
125 | - * Like optimum_sales_now, but minus total sales so far. |
|
126 | - * See EE_Event::spaces_remaining_for_sale( true ); |
|
127 | - * |
|
128 | - * @param array $wpdb_row |
|
129 | - * @param WP_REST_Request $request |
|
130 | - * @param EventControllerBase $controller |
|
131 | - * @return int |
|
132 | - * @throws DomainException |
|
133 | - * @throws EE_Error |
|
134 | - * @throws InvalidArgumentException |
|
135 | - * @throws InvalidDataTypeException |
|
136 | - * @throws InvalidInterfaceException |
|
137 | - * @throws UnexpectedEntityException |
|
138 | - */ |
|
139 | - public function spacesRemaining($wpdb_row, $request, $controller) |
|
140 | - { |
|
141 | - $event_obj = null; |
|
142 | - if (Event::wpdbRowHasEventId($wpdb_row)) { |
|
143 | - $event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']); |
|
144 | - } |
|
145 | - if ($event_obj instanceof EE_Event) { |
|
146 | - return $event_obj->spaces_remaining_for_sale(); |
|
147 | - } |
|
148 | - throw new EE_Error( |
|
149 | - sprintf( |
|
150 | - esc_html__( |
|
151 | - // @codingStandardsIgnoreStart |
|
152 | - 'Cannot calculate spaces_remaining because the event with ID %1$s (from database row %2$s) was not found', |
|
153 | - // @codingStandardsIgnoreEnd |
|
154 | - 'event_espresso' |
|
155 | - ), |
|
156 | - $wpdb_row['Event_CPT.ID'], |
|
157 | - print_r($wpdb_row, true) |
|
158 | - ) |
|
159 | - ); |
|
160 | - } |
|
161 | - |
|
162 | - |
|
163 | - /** |
|
164 | - * Counts the number of approved registrations for this event (regardless |
|
165 | - * of how many datetimes each registrations' ticket purchase is for) |
|
166 | - * |
|
167 | - * @param array $wpdb_row |
|
168 | - * @param WP_REST_Request $request |
|
169 | - * @param EventControllerBase $controller |
|
170 | - * @return int |
|
171 | - * @throws EE_Error |
|
172 | - * @throws InvalidArgumentException |
|
173 | - * @throws InvalidDataTypeException |
|
174 | - * @throws InvalidInterfaceException |
|
175 | - */ |
|
176 | - public function spotsTaken($wpdb_row, $request, $controller) |
|
177 | - { |
|
178 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
179 | - throw new EE_Error( |
|
180 | - sprintf( |
|
181 | - esc_html__( |
|
182 | - // @codingStandardsIgnoreStart |
|
183 | - 'Cannot calculate spots_taken because the database row %1$s does not have a valid entry for "Event_CPT.ID"', |
|
184 | - // @codingStandardsIgnoreEnd |
|
185 | - 'event_espresso' |
|
186 | - ), |
|
187 | - print_r($wpdb_row, true) |
|
188 | - ) |
|
189 | - ); |
|
190 | - } |
|
191 | - return $this->registration_model->count( |
|
192 | - array( |
|
193 | - array( |
|
194 | - 'EVT_ID' => $wpdb_row['Event_CPT.ID'], |
|
195 | - 'STS_ID' => EEM_Registration::status_id_approved, |
|
196 | - ), |
|
197 | - ), |
|
198 | - 'REG_ID', |
|
199 | - true |
|
200 | - ); |
|
201 | - } |
|
202 | - |
|
203 | - |
|
204 | - /** |
|
205 | - * Counts the number of pending-payment registrations for this event (regardless |
|
206 | - * of how many datetimes each registrations' ticket purchase is for) |
|
207 | - * |
|
208 | - * @param array $wpdb_row |
|
209 | - * @param WP_REST_Request $request |
|
210 | - * @param EventControllerBase $controller |
|
211 | - * @return int |
|
212 | - * @throws EE_Error |
|
213 | - * @throws InvalidArgumentException |
|
214 | - * @throws InvalidDataTypeException |
|
215 | - * @throws InvalidInterfaceException |
|
216 | - * @throws RestException |
|
217 | - */ |
|
218 | - public function spotsTakenPendingPayment($wpdb_row, $request, $controller) |
|
219 | - { |
|
220 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
221 | - throw new EE_Error( |
|
222 | - sprintf( |
|
223 | - esc_html__( |
|
224 | - // @codingStandardsIgnoreStart |
|
225 | - 'Cannot calculate spots_taken_pending_payment because the database row %1$s does not have an entry for "Event_CPT.ID"', |
|
226 | - // @codingStandardsIgnoreEnd |
|
227 | - 'event_espresso' |
|
228 | - ), |
|
229 | - print_r($wpdb_row, true) |
|
230 | - ) |
|
231 | - ); |
|
232 | - } |
|
233 | - $this->verifyCurrentUserCan('ee_read_registrations', 'spots_taken_pending_payment'); |
|
234 | - return $this->registration_model->count( |
|
235 | - array( |
|
236 | - array( |
|
237 | - 'EVT_ID' => $wpdb_row['Event_CPT.ID'], |
|
238 | - 'STS_ID' => EEM_Registration::status_id_pending_payment, |
|
239 | - ), |
|
240 | - ), |
|
241 | - 'REG_ID', |
|
242 | - true |
|
243 | - ); |
|
244 | - } |
|
245 | - |
|
246 | - |
|
247 | - /** |
|
248 | - * Counts all the registrations who have checked into one of this events' datetimes |
|
249 | - * See EE_Event::total_available_spaces( false ); |
|
250 | - * |
|
251 | - * @param array $wpdb_row |
|
252 | - * @param WP_REST_Request $request |
|
253 | - * @param EventControllerBase $controller |
|
254 | - * @return int|null if permission denied |
|
255 | - * @throws EE_Error |
|
256 | - * @throws InvalidArgumentException |
|
257 | - * @throws InvalidDataTypeException |
|
258 | - * @throws InvalidInterfaceException |
|
259 | - * @throws RestException |
|
260 | - */ |
|
261 | - public function registrationsCheckedInCount($wpdb_row, $request, $controller) |
|
262 | - { |
|
263 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
264 | - throw new EE_Error( |
|
265 | - sprintf( |
|
266 | - esc_html__( |
|
267 | - // @codingStandardsIgnoreStart |
|
268 | - 'Cannot calculate registrations_checked_in_count because the database row %1$s does not have an entry for "Event_CPT.ID"', |
|
269 | - // @codingStandardsIgnoreEnd |
|
270 | - 'event_espresso' |
|
271 | - ), |
|
272 | - print_r($wpdb_row, true) |
|
273 | - ) |
|
274 | - ); |
|
275 | - } |
|
276 | - $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_in_count'); |
|
277 | - return $this->registration_model->count_registrations_checked_into_event($wpdb_row['Event_CPT.ID'], true); |
|
278 | - } |
|
279 | - |
|
280 | - |
|
281 | - /** |
|
282 | - * Counts all the registrations who have checked out of one of this events' datetimes |
|
283 | - * See EE_Event::total_available_spaces( false ); |
|
284 | - * |
|
285 | - * @param array $wpdb_row |
|
286 | - * @param WP_REST_Request $request |
|
287 | - * @param EventControllerBase $controller |
|
288 | - * @return int |
|
289 | - * @throws EE_Error |
|
290 | - * @throws InvalidArgumentException |
|
291 | - * @throws InvalidDataTypeException |
|
292 | - * @throws InvalidInterfaceException |
|
293 | - * @throws RestException |
|
294 | - */ |
|
295 | - public function registrationsCheckedOutCount($wpdb_row, $request, $controller) |
|
296 | - { |
|
297 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
298 | - throw new EE_Error( |
|
299 | - sprintf( |
|
300 | - esc_html__( |
|
301 | - // @codingStandardsIgnoreStart |
|
302 | - 'Cannot calculate registrations_checked_out_count because the database row %1$s does not have an entry for "Event_CPT.ID"', |
|
303 | - // @codingStandardsIgnoreEnd |
|
304 | - 'event_espresso' |
|
305 | - ), |
|
306 | - print_r($wpdb_row, true) |
|
307 | - ) |
|
308 | - ); |
|
309 | - } |
|
310 | - $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_out_count'); |
|
311 | - return $this->registration_model->count_registrations_checked_into_event($wpdb_row['Event_CPT.ID'], false); |
|
312 | - } |
|
313 | - |
|
314 | - |
|
315 | - /** |
|
316 | - * Gets the thumbnail image |
|
317 | - * |
|
318 | - * @param array $wpdb_row |
|
319 | - * @param WP_REST_Request $request |
|
320 | - * @param EventControllerBase $controller |
|
321 | - * @return array |
|
322 | - * @throws EE_Error |
|
323 | - */ |
|
324 | - public function imageThumbnail($wpdb_row, $request, $controller) |
|
325 | - { |
|
326 | - return self::calculateImageData($wpdb_row, 'thumbnail'); |
|
327 | - } |
|
328 | - |
|
329 | - |
|
330 | - /** |
|
331 | - * Gets the medium image |
|
332 | - * |
|
333 | - * @param array $wpdb_row |
|
334 | - * @param WP_REST_Request $request |
|
335 | - * @param EventControllerBase $controller |
|
336 | - * @return array |
|
337 | - * @throws EE_Error |
|
338 | - */ |
|
339 | - public function imageMedium($wpdb_row, $request, $controller) |
|
340 | - { |
|
341 | - return self::calculateImageData($wpdb_row, 'medium'); |
|
342 | - } |
|
343 | - |
|
344 | - |
|
345 | - /** |
|
346 | - * Gets the medium-large image |
|
347 | - * |
|
348 | - * @param array $wpdb_row |
|
349 | - * @param WP_REST_Request $request |
|
350 | - * @param EventControllerBase $controller |
|
351 | - * @return array |
|
352 | - * @throws EE_Error |
|
353 | - */ |
|
354 | - public function imageMediumLarge($wpdb_row, $request, $controller) |
|
355 | - { |
|
356 | - return self::calculateImageData($wpdb_row, 'medium_large'); |
|
357 | - } |
|
358 | - |
|
359 | - |
|
360 | - /** |
|
361 | - * Gets the large image |
|
362 | - * |
|
363 | - * @param array $wpdb_row |
|
364 | - * @param WP_REST_Request $request |
|
365 | - * @param EventControllerBase $controller |
|
366 | - * @return array |
|
367 | - * @throws EE_Error |
|
368 | - */ |
|
369 | - public function imageLarge($wpdb_row, $request, $controller) |
|
370 | - { |
|
371 | - return self::calculateImageData($wpdb_row, 'large'); |
|
372 | - } |
|
373 | - |
|
374 | - |
|
375 | - /** |
|
376 | - * Gets the post-thumbnail image |
|
377 | - * |
|
378 | - * @param array $wpdb_row |
|
379 | - * @param WP_REST_Request $request |
|
380 | - * @param EventControllerBase $controller |
|
381 | - * @return array |
|
382 | - * @throws EE_Error |
|
383 | - */ |
|
384 | - public function imagePostThumbnail($wpdb_row, $request, $controller) |
|
385 | - { |
|
386 | - return self::calculateImageData($wpdb_row, 'post-thumbnail'); |
|
387 | - } |
|
388 | - |
|
389 | - |
|
390 | - /** |
|
391 | - * Gets the full size image |
|
392 | - * |
|
393 | - * @param array $wpdb_row |
|
394 | - * @param WP_REST_Request $request |
|
395 | - * @param EventControllerBase $controller |
|
396 | - * @return array |
|
397 | - * @throws EE_Error |
|
398 | - */ |
|
399 | - public function imageFull($wpdb_row, $request, $controller) |
|
400 | - { |
|
401 | - return self::calculateImageData($wpdb_row, 'full'); |
|
402 | - } |
|
403 | - |
|
404 | - |
|
405 | - /** |
|
406 | - * Gets image specs and formats them for the display in the API, |
|
407 | - * according to the image size requested |
|
408 | - * |
|
409 | - * @param array $wpdb_row |
|
410 | - * @param string $image_size one of these: thumbnail, medium, medium_large, large, post-thumbnail, full |
|
411 | - * @return array|false if no such image exists. If array it will have keys 'url', 'width', 'height' and 'original' |
|
412 | - * @throws EE_Error |
|
413 | - */ |
|
414 | - protected function calculateImageData($wpdb_row, $image_size) |
|
415 | - { |
|
416 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
417 | - throw new EE_Error( |
|
418 | - sprintf( |
|
419 | - esc_html__( |
|
420 | - // @codingStandardsIgnoreStart |
|
421 | - 'Cannot calculate image because the database row %1$s does not have an entry for "Event_CPT.ID"', |
|
422 | - // @codingStandardsIgnoreEnd |
|
423 | - 'event_espresso' |
|
424 | - ), |
|
425 | - print_r($wpdb_row, true) |
|
426 | - ) |
|
427 | - ); |
|
428 | - } |
|
429 | - $EVT_ID = $wpdb_row['Event_CPT.ID']; |
|
430 | - $attachment_id = get_post_thumbnail_id($EVT_ID); |
|
431 | - $data = wp_get_attachment_image_src($attachment_id, $image_size); |
|
432 | - if (! $data) { |
|
433 | - return null; |
|
434 | - } |
|
435 | - $generated = true; |
|
436 | - if (isset($data[3])) { |
|
437 | - $generated = $data[3]; |
|
438 | - } |
|
439 | - return array( |
|
440 | - 'url' => $data[0], |
|
441 | - 'width' => $data[1], |
|
442 | - 'height' => $data[2], |
|
443 | - 'generated' => $generated, |
|
444 | - ); |
|
445 | - } |
|
446 | - |
|
447 | - |
|
448 | - /** |
|
449 | - * Returns true if the array of data contains 'Event_CPT.ID'. False otherwise |
|
450 | - * |
|
451 | - * @param array $wpdb_row |
|
452 | - * @return bool |
|
453 | - */ |
|
454 | - protected function wpdbRowHasEventId($wpdb_row) |
|
455 | - { |
|
456 | - return (is_array($wpdb_row) && isset($wpdb_row['Event_CPT.ID']) && absint($wpdb_row['Event_CPT.ID'])); |
|
457 | - } |
|
458 | - |
|
459 | - |
|
460 | - /** |
|
461 | - * Provides an array for all the calculations possible that outlines a json schema for those calculations. |
|
462 | - * Array is indexed by calculation (snake case) and value is the schema for that calculation. |
|
463 | - * |
|
464 | - * @since 4.9.68.p |
|
465 | - * @return array |
|
466 | - */ |
|
467 | - public function schemaForCalculations() |
|
468 | - { |
|
469 | - $image_object_properties = array( |
|
470 | - 'url' => array( |
|
471 | - 'type' => 'string', |
|
472 | - ), |
|
473 | - 'width' => array( |
|
474 | - 'type' => 'number', |
|
475 | - ), |
|
476 | - 'height' => array( |
|
477 | - 'type' => 'number', |
|
478 | - ), |
|
479 | - 'generated' => array( |
|
480 | - 'type' => 'boolean', |
|
481 | - ), |
|
482 | - ); |
|
483 | - return array( |
|
484 | - 'optimum_sales_at_start' => array( |
|
485 | - 'description' => esc_html__( |
|
486 | - 'The total spaces on the event (not subtracting sales, but taking sales into account; so this is the optimum sales that CAN still be achieved.', |
|
487 | - 'event_espresso' |
|
488 | - ), |
|
489 | - 'type' => 'number', |
|
490 | - 'protected' => true, |
|
491 | - ), |
|
492 | - 'optimum_sales_now' => array( |
|
493 | - 'description' => esc_html__( |
|
494 | - 'The total spaces on the event (ignoring all sales; so this is the optimum sales that could have been achieved.', |
|
495 | - 'event_espresso' |
|
496 | - ), |
|
497 | - 'type' => 'number', |
|
498 | - 'protected' => true, |
|
499 | - ), |
|
500 | - 'spaces_remaining' => array( |
|
501 | - 'description' => esc_html__( |
|
502 | - 'The optimum_sales_number result, minus total sales so far.', |
|
503 | - 'event_espresso' |
|
504 | - ), |
|
505 | - 'type' => 'number', |
|
506 | - 'protected' => true, |
|
507 | - ), |
|
508 | - 'spots_taken' => array( |
|
509 | - 'description' => esc_html__( |
|
510 | - 'The number of approved registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for)', |
|
511 | - 'event_espresso' |
|
512 | - ), |
|
513 | - 'type' => 'number', |
|
514 | - 'protected' => true, |
|
515 | - ), |
|
516 | - 'spots_taken_pending_payment' => array( |
|
517 | - 'description' => esc_html__( |
|
518 | - 'The number of pending-payment registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for)', |
|
519 | - 'event_espresso' |
|
520 | - ), |
|
521 | - 'type' => 'number', |
|
522 | - 'protected' => true, |
|
523 | - ), |
|
524 | - 'registrations_checked_in_count' => array( |
|
525 | - 'description' => esc_html__( |
|
526 | - 'The count of all the registrations who have checked into one of this event\'s datetimes.', |
|
527 | - 'event_espresso' |
|
528 | - ), |
|
529 | - 'type' => 'number', |
|
530 | - 'protected' => true, |
|
531 | - ), |
|
532 | - 'registrations_checked_out_count' => array( |
|
533 | - 'description' => esc_html__( |
|
534 | - 'The count of all registrations who have checked out of one of this event\'s datetimes.', |
|
535 | - 'event_espresso' |
|
536 | - ), |
|
537 | - 'type' => 'number', |
|
538 | - 'protected' => true, |
|
539 | - ), |
|
540 | - 'image_thumbnail' => array( |
|
541 | - 'description' => esc_html__( |
|
542 | - 'The thumbnail image data.', |
|
543 | - 'event_espresso' |
|
544 | - ), |
|
545 | - 'type' => 'object', |
|
546 | - 'properties' => $image_object_properties, |
|
547 | - 'additionalProperties' => false, |
|
548 | - ), |
|
549 | - 'image_medium' => array( |
|
550 | - 'description' => esc_html__( |
|
551 | - 'The medium image data.', |
|
552 | - 'event_espresso' |
|
553 | - ), |
|
554 | - 'type' => 'object', |
|
555 | - 'properties' => $image_object_properties, |
|
556 | - 'additionalProperties' => false, |
|
557 | - ), |
|
558 | - 'image_medium_large' => array( |
|
559 | - 'description' => esc_html__( |
|
560 | - 'The medium-large image data.', |
|
561 | - 'event_espresso' |
|
562 | - ), |
|
563 | - 'type' => 'object', |
|
564 | - 'properties' => $image_object_properties, |
|
565 | - 'additionalProperties' => false, |
|
566 | - ), |
|
567 | - 'image_large' => array( |
|
568 | - 'description' => esc_html__( |
|
569 | - 'The large image data.', |
|
570 | - 'event_espresso' |
|
571 | - ), |
|
572 | - 'type' => 'object', |
|
573 | - 'properties' => $image_object_properties, |
|
574 | - 'additionalProperties' => false, |
|
575 | - ), |
|
576 | - 'image_post_thumbnail' => array( |
|
577 | - 'description' => esc_html__( |
|
578 | - 'The post-thumbnail image data.', |
|
579 | - 'event_espresso' |
|
580 | - ), |
|
581 | - 'type' => 'object', |
|
582 | - 'properties' => $image_object_properties, |
|
583 | - 'additionalProperties' => false, |
|
584 | - ), |
|
585 | - 'image_full' => array( |
|
586 | - 'description' => esc_html__( |
|
587 | - 'The full size image data', |
|
588 | - 'event_espresso' |
|
589 | - ), |
|
590 | - 'type' => 'object', |
|
591 | - 'properties' => $image_object_properties, |
|
592 | - 'additionalProperties' => false, |
|
593 | - ), |
|
594 | - ); |
|
595 | - } |
|
29 | + /** |
|
30 | + * @var EEM_Event |
|
31 | + */ |
|
32 | + protected $event_model; |
|
33 | + |
|
34 | + /** |
|
35 | + * @var EEM_Registration |
|
36 | + */ |
|
37 | + protected $registration_model; |
|
38 | + public function __construct(EEM_Event $event_model, EEM_Registration $registration_model) |
|
39 | + { |
|
40 | + $this->event_model = $event_model; |
|
41 | + $this->registration_model = $registration_model; |
|
42 | + } |
|
43 | + |
|
44 | + /** |
|
45 | + * Calculates the total spaces on the event (not subtracting sales, but taking |
|
46 | + * sales into account; so this is the optimum sales that CAN still be achieved) |
|
47 | + * See EE_Event::total_available_spaces( true ); |
|
48 | + * |
|
49 | + * @param array $wpdb_row |
|
50 | + * @param WP_REST_Request $request |
|
51 | + * @param EventControllerBase $controller |
|
52 | + * @return int |
|
53 | + * @throws EE_Error |
|
54 | + * @throws DomainException |
|
55 | + * @throws InvalidDataTypeException |
|
56 | + * @throws InvalidInterfaceException |
|
57 | + * @throws UnexpectedEntityException |
|
58 | + * @throws InvalidArgumentException |
|
59 | + */ |
|
60 | + public function optimumSalesAtStart($wpdb_row, $request, $controller) |
|
61 | + { |
|
62 | + $event_obj = null; |
|
63 | + if (Event::wpdbRowHasEventId($wpdb_row)) { |
|
64 | + $event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']); |
|
65 | + } |
|
66 | + if ($event_obj instanceof EE_Event) { |
|
67 | + return $event_obj->total_available_spaces(); |
|
68 | + } |
|
69 | + throw new EE_Error( |
|
70 | + sprintf( |
|
71 | + esc_html__( |
|
72 | + // @codingStandardsIgnoreStart |
|
73 | + 'Cannot calculate optimum_sales_at_start because the event with ID %1$s (from database row %2$s) was not found', |
|
74 | + // @codingStandardsIgnoreEnd |
|
75 | + 'event_espresso' |
|
76 | + ), |
|
77 | + $wpdb_row['Event_CPT.ID'], |
|
78 | + print_r($wpdb_row, true) |
|
79 | + ) |
|
80 | + ); |
|
81 | + } |
|
82 | + |
|
83 | + |
|
84 | + /** |
|
85 | + * Calculates the total spaces on the event (ignoring all sales; so this is the optimum |
|
86 | + * sales that COULD have been achieved) |
|
87 | + * See EE_Event::total_available_spaces( true ); |
|
88 | + * |
|
89 | + * @param array $wpdb_row |
|
90 | + * @param WP_REST_Request $request |
|
91 | + * @param EventControllerBase $controller |
|
92 | + * @return int |
|
93 | + * @throws DomainException |
|
94 | + * @throws EE_Error |
|
95 | + * @throws InvalidArgumentException |
|
96 | + * @throws InvalidDataTypeException |
|
97 | + * @throws InvalidInterfaceException |
|
98 | + * @throws UnexpectedEntityException |
|
99 | + */ |
|
100 | + public function optimumSalesNow($wpdb_row, $request, $controller) |
|
101 | + { |
|
102 | + $event_obj = null; |
|
103 | + if (Event::wpdbRowHasEventId($wpdb_row)) { |
|
104 | + $event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']); |
|
105 | + } |
|
106 | + if ($event_obj instanceof EE_Event) { |
|
107 | + return $event_obj->total_available_spaces(true); |
|
108 | + } |
|
109 | + throw new EE_Error( |
|
110 | + sprintf( |
|
111 | + esc_html__( |
|
112 | + // @codingStandardsIgnoreStart |
|
113 | + 'Cannot calculate optimum_sales_now because the event with ID %1$s (from database row %2$s) was not found', |
|
114 | + // @codingStandardsIgnoreEnd |
|
115 | + 'event_espresso' |
|
116 | + ), |
|
117 | + $wpdb_row['Event_CPT.ID'], |
|
118 | + print_r($wpdb_row, true) |
|
119 | + ) |
|
120 | + ); |
|
121 | + } |
|
122 | + |
|
123 | + |
|
124 | + /** |
|
125 | + * Like optimum_sales_now, but minus total sales so far. |
|
126 | + * See EE_Event::spaces_remaining_for_sale( true ); |
|
127 | + * |
|
128 | + * @param array $wpdb_row |
|
129 | + * @param WP_REST_Request $request |
|
130 | + * @param EventControllerBase $controller |
|
131 | + * @return int |
|
132 | + * @throws DomainException |
|
133 | + * @throws EE_Error |
|
134 | + * @throws InvalidArgumentException |
|
135 | + * @throws InvalidDataTypeException |
|
136 | + * @throws InvalidInterfaceException |
|
137 | + * @throws UnexpectedEntityException |
|
138 | + */ |
|
139 | + public function spacesRemaining($wpdb_row, $request, $controller) |
|
140 | + { |
|
141 | + $event_obj = null; |
|
142 | + if (Event::wpdbRowHasEventId($wpdb_row)) { |
|
143 | + $event_obj = $this->event_model->get_one_by_ID($wpdb_row['Event_CPT.ID']); |
|
144 | + } |
|
145 | + if ($event_obj instanceof EE_Event) { |
|
146 | + return $event_obj->spaces_remaining_for_sale(); |
|
147 | + } |
|
148 | + throw new EE_Error( |
|
149 | + sprintf( |
|
150 | + esc_html__( |
|
151 | + // @codingStandardsIgnoreStart |
|
152 | + 'Cannot calculate spaces_remaining because the event with ID %1$s (from database row %2$s) was not found', |
|
153 | + // @codingStandardsIgnoreEnd |
|
154 | + 'event_espresso' |
|
155 | + ), |
|
156 | + $wpdb_row['Event_CPT.ID'], |
|
157 | + print_r($wpdb_row, true) |
|
158 | + ) |
|
159 | + ); |
|
160 | + } |
|
161 | + |
|
162 | + |
|
163 | + /** |
|
164 | + * Counts the number of approved registrations for this event (regardless |
|
165 | + * of how many datetimes each registrations' ticket purchase is for) |
|
166 | + * |
|
167 | + * @param array $wpdb_row |
|
168 | + * @param WP_REST_Request $request |
|
169 | + * @param EventControllerBase $controller |
|
170 | + * @return int |
|
171 | + * @throws EE_Error |
|
172 | + * @throws InvalidArgumentException |
|
173 | + * @throws InvalidDataTypeException |
|
174 | + * @throws InvalidInterfaceException |
|
175 | + */ |
|
176 | + public function spotsTaken($wpdb_row, $request, $controller) |
|
177 | + { |
|
178 | + if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
179 | + throw new EE_Error( |
|
180 | + sprintf( |
|
181 | + esc_html__( |
|
182 | + // @codingStandardsIgnoreStart |
|
183 | + 'Cannot calculate spots_taken because the database row %1$s does not have a valid entry for "Event_CPT.ID"', |
|
184 | + // @codingStandardsIgnoreEnd |
|
185 | + 'event_espresso' |
|
186 | + ), |
|
187 | + print_r($wpdb_row, true) |
|
188 | + ) |
|
189 | + ); |
|
190 | + } |
|
191 | + return $this->registration_model->count( |
|
192 | + array( |
|
193 | + array( |
|
194 | + 'EVT_ID' => $wpdb_row['Event_CPT.ID'], |
|
195 | + 'STS_ID' => EEM_Registration::status_id_approved, |
|
196 | + ), |
|
197 | + ), |
|
198 | + 'REG_ID', |
|
199 | + true |
|
200 | + ); |
|
201 | + } |
|
202 | + |
|
203 | + |
|
204 | + /** |
|
205 | + * Counts the number of pending-payment registrations for this event (regardless |
|
206 | + * of how many datetimes each registrations' ticket purchase is for) |
|
207 | + * |
|
208 | + * @param array $wpdb_row |
|
209 | + * @param WP_REST_Request $request |
|
210 | + * @param EventControllerBase $controller |
|
211 | + * @return int |
|
212 | + * @throws EE_Error |
|
213 | + * @throws InvalidArgumentException |
|
214 | + * @throws InvalidDataTypeException |
|
215 | + * @throws InvalidInterfaceException |
|
216 | + * @throws RestException |
|
217 | + */ |
|
218 | + public function spotsTakenPendingPayment($wpdb_row, $request, $controller) |
|
219 | + { |
|
220 | + if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
221 | + throw new EE_Error( |
|
222 | + sprintf( |
|
223 | + esc_html__( |
|
224 | + // @codingStandardsIgnoreStart |
|
225 | + 'Cannot calculate spots_taken_pending_payment because the database row %1$s does not have an entry for "Event_CPT.ID"', |
|
226 | + // @codingStandardsIgnoreEnd |
|
227 | + 'event_espresso' |
|
228 | + ), |
|
229 | + print_r($wpdb_row, true) |
|
230 | + ) |
|
231 | + ); |
|
232 | + } |
|
233 | + $this->verifyCurrentUserCan('ee_read_registrations', 'spots_taken_pending_payment'); |
|
234 | + return $this->registration_model->count( |
|
235 | + array( |
|
236 | + array( |
|
237 | + 'EVT_ID' => $wpdb_row['Event_CPT.ID'], |
|
238 | + 'STS_ID' => EEM_Registration::status_id_pending_payment, |
|
239 | + ), |
|
240 | + ), |
|
241 | + 'REG_ID', |
|
242 | + true |
|
243 | + ); |
|
244 | + } |
|
245 | + |
|
246 | + |
|
247 | + /** |
|
248 | + * Counts all the registrations who have checked into one of this events' datetimes |
|
249 | + * See EE_Event::total_available_spaces( false ); |
|
250 | + * |
|
251 | + * @param array $wpdb_row |
|
252 | + * @param WP_REST_Request $request |
|
253 | + * @param EventControllerBase $controller |
|
254 | + * @return int|null if permission denied |
|
255 | + * @throws EE_Error |
|
256 | + * @throws InvalidArgumentException |
|
257 | + * @throws InvalidDataTypeException |
|
258 | + * @throws InvalidInterfaceException |
|
259 | + * @throws RestException |
|
260 | + */ |
|
261 | + public function registrationsCheckedInCount($wpdb_row, $request, $controller) |
|
262 | + { |
|
263 | + if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
264 | + throw new EE_Error( |
|
265 | + sprintf( |
|
266 | + esc_html__( |
|
267 | + // @codingStandardsIgnoreStart |
|
268 | + 'Cannot calculate registrations_checked_in_count because the database row %1$s does not have an entry for "Event_CPT.ID"', |
|
269 | + // @codingStandardsIgnoreEnd |
|
270 | + 'event_espresso' |
|
271 | + ), |
|
272 | + print_r($wpdb_row, true) |
|
273 | + ) |
|
274 | + ); |
|
275 | + } |
|
276 | + $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_in_count'); |
|
277 | + return $this->registration_model->count_registrations_checked_into_event($wpdb_row['Event_CPT.ID'], true); |
|
278 | + } |
|
279 | + |
|
280 | + |
|
281 | + /** |
|
282 | + * Counts all the registrations who have checked out of one of this events' datetimes |
|
283 | + * See EE_Event::total_available_spaces( false ); |
|
284 | + * |
|
285 | + * @param array $wpdb_row |
|
286 | + * @param WP_REST_Request $request |
|
287 | + * @param EventControllerBase $controller |
|
288 | + * @return int |
|
289 | + * @throws EE_Error |
|
290 | + * @throws InvalidArgumentException |
|
291 | + * @throws InvalidDataTypeException |
|
292 | + * @throws InvalidInterfaceException |
|
293 | + * @throws RestException |
|
294 | + */ |
|
295 | + public function registrationsCheckedOutCount($wpdb_row, $request, $controller) |
|
296 | + { |
|
297 | + if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
298 | + throw new EE_Error( |
|
299 | + sprintf( |
|
300 | + esc_html__( |
|
301 | + // @codingStandardsIgnoreStart |
|
302 | + 'Cannot calculate registrations_checked_out_count because the database row %1$s does not have an entry for "Event_CPT.ID"', |
|
303 | + // @codingStandardsIgnoreEnd |
|
304 | + 'event_espresso' |
|
305 | + ), |
|
306 | + print_r($wpdb_row, true) |
|
307 | + ) |
|
308 | + ); |
|
309 | + } |
|
310 | + $this->verifyCurrentUserCan('ee_read_checkins', 'registrations_checked_out_count'); |
|
311 | + return $this->registration_model->count_registrations_checked_into_event($wpdb_row['Event_CPT.ID'], false); |
|
312 | + } |
|
313 | + |
|
314 | + |
|
315 | + /** |
|
316 | + * Gets the thumbnail image |
|
317 | + * |
|
318 | + * @param array $wpdb_row |
|
319 | + * @param WP_REST_Request $request |
|
320 | + * @param EventControllerBase $controller |
|
321 | + * @return array |
|
322 | + * @throws EE_Error |
|
323 | + */ |
|
324 | + public function imageThumbnail($wpdb_row, $request, $controller) |
|
325 | + { |
|
326 | + return self::calculateImageData($wpdb_row, 'thumbnail'); |
|
327 | + } |
|
328 | + |
|
329 | + |
|
330 | + /** |
|
331 | + * Gets the medium image |
|
332 | + * |
|
333 | + * @param array $wpdb_row |
|
334 | + * @param WP_REST_Request $request |
|
335 | + * @param EventControllerBase $controller |
|
336 | + * @return array |
|
337 | + * @throws EE_Error |
|
338 | + */ |
|
339 | + public function imageMedium($wpdb_row, $request, $controller) |
|
340 | + { |
|
341 | + return self::calculateImageData($wpdb_row, 'medium'); |
|
342 | + } |
|
343 | + |
|
344 | + |
|
345 | + /** |
|
346 | + * Gets the medium-large image |
|
347 | + * |
|
348 | + * @param array $wpdb_row |
|
349 | + * @param WP_REST_Request $request |
|
350 | + * @param EventControllerBase $controller |
|
351 | + * @return array |
|
352 | + * @throws EE_Error |
|
353 | + */ |
|
354 | + public function imageMediumLarge($wpdb_row, $request, $controller) |
|
355 | + { |
|
356 | + return self::calculateImageData($wpdb_row, 'medium_large'); |
|
357 | + } |
|
358 | + |
|
359 | + |
|
360 | + /** |
|
361 | + * Gets the large image |
|
362 | + * |
|
363 | + * @param array $wpdb_row |
|
364 | + * @param WP_REST_Request $request |
|
365 | + * @param EventControllerBase $controller |
|
366 | + * @return array |
|
367 | + * @throws EE_Error |
|
368 | + */ |
|
369 | + public function imageLarge($wpdb_row, $request, $controller) |
|
370 | + { |
|
371 | + return self::calculateImageData($wpdb_row, 'large'); |
|
372 | + } |
|
373 | + |
|
374 | + |
|
375 | + /** |
|
376 | + * Gets the post-thumbnail image |
|
377 | + * |
|
378 | + * @param array $wpdb_row |
|
379 | + * @param WP_REST_Request $request |
|
380 | + * @param EventControllerBase $controller |
|
381 | + * @return array |
|
382 | + * @throws EE_Error |
|
383 | + */ |
|
384 | + public function imagePostThumbnail($wpdb_row, $request, $controller) |
|
385 | + { |
|
386 | + return self::calculateImageData($wpdb_row, 'post-thumbnail'); |
|
387 | + } |
|
388 | + |
|
389 | + |
|
390 | + /** |
|
391 | + * Gets the full size image |
|
392 | + * |
|
393 | + * @param array $wpdb_row |
|
394 | + * @param WP_REST_Request $request |
|
395 | + * @param EventControllerBase $controller |
|
396 | + * @return array |
|
397 | + * @throws EE_Error |
|
398 | + */ |
|
399 | + public function imageFull($wpdb_row, $request, $controller) |
|
400 | + { |
|
401 | + return self::calculateImageData($wpdb_row, 'full'); |
|
402 | + } |
|
403 | + |
|
404 | + |
|
405 | + /** |
|
406 | + * Gets image specs and formats them for the display in the API, |
|
407 | + * according to the image size requested |
|
408 | + * |
|
409 | + * @param array $wpdb_row |
|
410 | + * @param string $image_size one of these: thumbnail, medium, medium_large, large, post-thumbnail, full |
|
411 | + * @return array|false if no such image exists. If array it will have keys 'url', 'width', 'height' and 'original' |
|
412 | + * @throws EE_Error |
|
413 | + */ |
|
414 | + protected function calculateImageData($wpdb_row, $image_size) |
|
415 | + { |
|
416 | + if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
417 | + throw new EE_Error( |
|
418 | + sprintf( |
|
419 | + esc_html__( |
|
420 | + // @codingStandardsIgnoreStart |
|
421 | + 'Cannot calculate image because the database row %1$s does not have an entry for "Event_CPT.ID"', |
|
422 | + // @codingStandardsIgnoreEnd |
|
423 | + 'event_espresso' |
|
424 | + ), |
|
425 | + print_r($wpdb_row, true) |
|
426 | + ) |
|
427 | + ); |
|
428 | + } |
|
429 | + $EVT_ID = $wpdb_row['Event_CPT.ID']; |
|
430 | + $attachment_id = get_post_thumbnail_id($EVT_ID); |
|
431 | + $data = wp_get_attachment_image_src($attachment_id, $image_size); |
|
432 | + if (! $data) { |
|
433 | + return null; |
|
434 | + } |
|
435 | + $generated = true; |
|
436 | + if (isset($data[3])) { |
|
437 | + $generated = $data[3]; |
|
438 | + } |
|
439 | + return array( |
|
440 | + 'url' => $data[0], |
|
441 | + 'width' => $data[1], |
|
442 | + 'height' => $data[2], |
|
443 | + 'generated' => $generated, |
|
444 | + ); |
|
445 | + } |
|
446 | + |
|
447 | + |
|
448 | + /** |
|
449 | + * Returns true if the array of data contains 'Event_CPT.ID'. False otherwise |
|
450 | + * |
|
451 | + * @param array $wpdb_row |
|
452 | + * @return bool |
|
453 | + */ |
|
454 | + protected function wpdbRowHasEventId($wpdb_row) |
|
455 | + { |
|
456 | + return (is_array($wpdb_row) && isset($wpdb_row['Event_CPT.ID']) && absint($wpdb_row['Event_CPT.ID'])); |
|
457 | + } |
|
458 | + |
|
459 | + |
|
460 | + /** |
|
461 | + * Provides an array for all the calculations possible that outlines a json schema for those calculations. |
|
462 | + * Array is indexed by calculation (snake case) and value is the schema for that calculation. |
|
463 | + * |
|
464 | + * @since 4.9.68.p |
|
465 | + * @return array |
|
466 | + */ |
|
467 | + public function schemaForCalculations() |
|
468 | + { |
|
469 | + $image_object_properties = array( |
|
470 | + 'url' => array( |
|
471 | + 'type' => 'string', |
|
472 | + ), |
|
473 | + 'width' => array( |
|
474 | + 'type' => 'number', |
|
475 | + ), |
|
476 | + 'height' => array( |
|
477 | + 'type' => 'number', |
|
478 | + ), |
|
479 | + 'generated' => array( |
|
480 | + 'type' => 'boolean', |
|
481 | + ), |
|
482 | + ); |
|
483 | + return array( |
|
484 | + 'optimum_sales_at_start' => array( |
|
485 | + 'description' => esc_html__( |
|
486 | + 'The total spaces on the event (not subtracting sales, but taking sales into account; so this is the optimum sales that CAN still be achieved.', |
|
487 | + 'event_espresso' |
|
488 | + ), |
|
489 | + 'type' => 'number', |
|
490 | + 'protected' => true, |
|
491 | + ), |
|
492 | + 'optimum_sales_now' => array( |
|
493 | + 'description' => esc_html__( |
|
494 | + 'The total spaces on the event (ignoring all sales; so this is the optimum sales that could have been achieved.', |
|
495 | + 'event_espresso' |
|
496 | + ), |
|
497 | + 'type' => 'number', |
|
498 | + 'protected' => true, |
|
499 | + ), |
|
500 | + 'spaces_remaining' => array( |
|
501 | + 'description' => esc_html__( |
|
502 | + 'The optimum_sales_number result, minus total sales so far.', |
|
503 | + 'event_espresso' |
|
504 | + ), |
|
505 | + 'type' => 'number', |
|
506 | + 'protected' => true, |
|
507 | + ), |
|
508 | + 'spots_taken' => array( |
|
509 | + 'description' => esc_html__( |
|
510 | + 'The number of approved registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for)', |
|
511 | + 'event_espresso' |
|
512 | + ), |
|
513 | + 'type' => 'number', |
|
514 | + 'protected' => true, |
|
515 | + ), |
|
516 | + 'spots_taken_pending_payment' => array( |
|
517 | + 'description' => esc_html__( |
|
518 | + 'The number of pending-payment registrations for this event (regardless of how many datetimes each registration\'s ticket purchase is for)', |
|
519 | + 'event_espresso' |
|
520 | + ), |
|
521 | + 'type' => 'number', |
|
522 | + 'protected' => true, |
|
523 | + ), |
|
524 | + 'registrations_checked_in_count' => array( |
|
525 | + 'description' => esc_html__( |
|
526 | + 'The count of all the registrations who have checked into one of this event\'s datetimes.', |
|
527 | + 'event_espresso' |
|
528 | + ), |
|
529 | + 'type' => 'number', |
|
530 | + 'protected' => true, |
|
531 | + ), |
|
532 | + 'registrations_checked_out_count' => array( |
|
533 | + 'description' => esc_html__( |
|
534 | + 'The count of all registrations who have checked out of one of this event\'s datetimes.', |
|
535 | + 'event_espresso' |
|
536 | + ), |
|
537 | + 'type' => 'number', |
|
538 | + 'protected' => true, |
|
539 | + ), |
|
540 | + 'image_thumbnail' => array( |
|
541 | + 'description' => esc_html__( |
|
542 | + 'The thumbnail image data.', |
|
543 | + 'event_espresso' |
|
544 | + ), |
|
545 | + 'type' => 'object', |
|
546 | + 'properties' => $image_object_properties, |
|
547 | + 'additionalProperties' => false, |
|
548 | + ), |
|
549 | + 'image_medium' => array( |
|
550 | + 'description' => esc_html__( |
|
551 | + 'The medium image data.', |
|
552 | + 'event_espresso' |
|
553 | + ), |
|
554 | + 'type' => 'object', |
|
555 | + 'properties' => $image_object_properties, |
|
556 | + 'additionalProperties' => false, |
|
557 | + ), |
|
558 | + 'image_medium_large' => array( |
|
559 | + 'description' => esc_html__( |
|
560 | + 'The medium-large image data.', |
|
561 | + 'event_espresso' |
|
562 | + ), |
|
563 | + 'type' => 'object', |
|
564 | + 'properties' => $image_object_properties, |
|
565 | + 'additionalProperties' => false, |
|
566 | + ), |
|
567 | + 'image_large' => array( |
|
568 | + 'description' => esc_html__( |
|
569 | + 'The large image data.', |
|
570 | + 'event_espresso' |
|
571 | + ), |
|
572 | + 'type' => 'object', |
|
573 | + 'properties' => $image_object_properties, |
|
574 | + 'additionalProperties' => false, |
|
575 | + ), |
|
576 | + 'image_post_thumbnail' => array( |
|
577 | + 'description' => esc_html__( |
|
578 | + 'The post-thumbnail image data.', |
|
579 | + 'event_espresso' |
|
580 | + ), |
|
581 | + 'type' => 'object', |
|
582 | + 'properties' => $image_object_properties, |
|
583 | + 'additionalProperties' => false, |
|
584 | + ), |
|
585 | + 'image_full' => array( |
|
586 | + 'description' => esc_html__( |
|
587 | + 'The full size image data', |
|
588 | + 'event_espresso' |
|
589 | + ), |
|
590 | + 'type' => 'object', |
|
591 | + 'properties' => $image_object_properties, |
|
592 | + 'additionalProperties' => false, |
|
593 | + ), |
|
594 | + ); |
|
595 | + } |
|
596 | 596 | } |
@@ -175,7 +175,7 @@ discard block |
||
175 | 175 | */ |
176 | 176 | public function spotsTaken($wpdb_row, $request, $controller) |
177 | 177 | { |
178 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
178 | + if ( ! Event::wpdbRowHasEventId($wpdb_row)) { |
|
179 | 179 | throw new EE_Error( |
180 | 180 | sprintf( |
181 | 181 | esc_html__( |
@@ -217,7 +217,7 @@ discard block |
||
217 | 217 | */ |
218 | 218 | public function spotsTakenPendingPayment($wpdb_row, $request, $controller) |
219 | 219 | { |
220 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
220 | + if ( ! Event::wpdbRowHasEventId($wpdb_row)) { |
|
221 | 221 | throw new EE_Error( |
222 | 222 | sprintf( |
223 | 223 | esc_html__( |
@@ -260,7 +260,7 @@ discard block |
||
260 | 260 | */ |
261 | 261 | public function registrationsCheckedInCount($wpdb_row, $request, $controller) |
262 | 262 | { |
263 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
263 | + if ( ! Event::wpdbRowHasEventId($wpdb_row)) { |
|
264 | 264 | throw new EE_Error( |
265 | 265 | sprintf( |
266 | 266 | esc_html__( |
@@ -294,7 +294,7 @@ discard block |
||
294 | 294 | */ |
295 | 295 | public function registrationsCheckedOutCount($wpdb_row, $request, $controller) |
296 | 296 | { |
297 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
297 | + if ( ! Event::wpdbRowHasEventId($wpdb_row)) { |
|
298 | 298 | throw new EE_Error( |
299 | 299 | sprintf( |
300 | 300 | esc_html__( |
@@ -413,7 +413,7 @@ discard block |
||
413 | 413 | */ |
414 | 414 | protected function calculateImageData($wpdb_row, $image_size) |
415 | 415 | { |
416 | - if (! Event::wpdbRowHasEventId($wpdb_row)) { |
|
416 | + if ( ! Event::wpdbRowHasEventId($wpdb_row)) { |
|
417 | 417 | throw new EE_Error( |
418 | 418 | sprintf( |
419 | 419 | esc_html__( |
@@ -429,7 +429,7 @@ discard block |
||
429 | 429 | $EVT_ID = $wpdb_row['Event_CPT.ID']; |
430 | 430 | $attachment_id = get_post_thumbnail_id($EVT_ID); |
431 | 431 | $data = wp_get_attachment_image_src($attachment_id, $image_size); |
432 | - if (! $data) { |
|
432 | + if ( ! $data) { |
|
433 | 433 | return null; |
434 | 434 | } |
435 | 435 | $generated = true; |
@@ -15,88 +15,88 @@ |
||
15 | 15 | * ------------------------------------------------------------------------ |
16 | 16 | */ |
17 | 17 | /** |
18 | - * |
|
19 | - * Class EE_Receipt_Line_Item_Display_Strategy |
|
20 | - * |
|
21 | - * Description |
|
22 | - * |
|
23 | - * @package Event Espresso |
|
24 | - * @subpackage core |
|
25 | - * @author Brent Christensen |
|
26 | - * |
|
27 | - * |
|
28 | - */ |
|
18 | + * |
|
19 | + * Class EE_Receipt_Line_Item_Display_Strategy |
|
20 | + * |
|
21 | + * Description |
|
22 | + * |
|
23 | + * @package Event Espresso |
|
24 | + * @subpackage core |
|
25 | + * @author Brent Christensen |
|
26 | + * |
|
27 | + * |
|
28 | + */ |
|
29 | 29 | |
30 | 30 | class EE_Receipt_Line_Item_Display_Strategy implements EEI_Line_Item_Display |
31 | 31 | { |
32 | 32 | |
33 | - /** |
|
34 | - * @param EE_Line_Item $line_item |
|
35 | - * @param array $options |
|
36 | - * @return mixed |
|
37 | - */ |
|
38 | - public function display_line_item(EE_Line_Item $line_item, $options = array()) |
|
39 | - { |
|
33 | + /** |
|
34 | + * @param EE_Line_Item $line_item |
|
35 | + * @param array $options |
|
36 | + * @return mixed |
|
37 | + */ |
|
38 | + public function display_line_item(EE_Line_Item $line_item, $options = array()) |
|
39 | + { |
|
40 | 40 | |
41 | - $html = ''; |
|
42 | - // set some default options and merge with incoming |
|
43 | - $default_options = array( |
|
44 | - 'show_desc' => true, |
|
45 | - 'odd' => false |
|
46 | - ); |
|
47 | - $options = array_merge($default_options, (array) $options); |
|
48 | - switch ($line_item->type()) { |
|
49 | - case EEM_Line_Item::type_total: |
|
50 | - // loop thru children |
|
51 | - foreach ($line_item->children() as $child_line_item) { |
|
52 | - // recursively feed children back into this method |
|
41 | + $html = ''; |
|
42 | + // set some default options and merge with incoming |
|
43 | + $default_options = array( |
|
44 | + 'show_desc' => true, |
|
45 | + 'odd' => false |
|
46 | + ); |
|
47 | + $options = array_merge($default_options, (array) $options); |
|
48 | + switch ($line_item->type()) { |
|
49 | + case EEM_Line_Item::type_total: |
|
50 | + // loop thru children |
|
51 | + foreach ($line_item->children() as $child_line_item) { |
|
52 | + // recursively feed children back into this method |
|
53 | 53 | // $html .= $this->display_line_item( $child_line_item, $options ); |
54 | - } |
|
54 | + } |
|
55 | 55 | // $html .= $this->_separator_row( $options ); |
56 | 56 | // $html .= $this->_total_row( $line_item, esc_html__('Total', 'event_espresso'), $options ); |
57 | - break; |
|
57 | + break; |
|
58 | 58 | |
59 | 59 | |
60 | - case EEM_Line_Item::type_sub_total: |
|
61 | - // loop thru children |
|
62 | - foreach ($line_item->children() as $child_line_item) { |
|
63 | - // recursively feed children back into this method |
|
60 | + case EEM_Line_Item::type_sub_total: |
|
61 | + // loop thru children |
|
62 | + foreach ($line_item->children() as $child_line_item) { |
|
63 | + // recursively feed children back into this method |
|
64 | 64 | // $html .= $this->display_line_item( $child_line_item, $options ); |
65 | - } |
|
65 | + } |
|
66 | 66 | // $html .= $this->_total_row( $line_item, esc_html__('Sub-Total', 'event_espresso'), $options ); |
67 | - break; |
|
67 | + break; |
|
68 | 68 | |
69 | 69 | |
70 | - case EEM_Line_Item::type_tax_sub_total: |
|
71 | - // loop thru children |
|
72 | - foreach ($line_item->children() as $child_line_item) { |
|
73 | - // recursively feed children back into this method |
|
70 | + case EEM_Line_Item::type_tax_sub_total: |
|
71 | + // loop thru children |
|
72 | + foreach ($line_item->children() as $child_line_item) { |
|
73 | + // recursively feed children back into this method |
|
74 | 74 | // $html .= $this->display_line_item( $child_line_item, $options ); |
75 | - } |
|
75 | + } |
|
76 | 76 | // $html .= $this->_total_row( $line_item, esc_html__('Tax Total', 'event_espresso'), $options ); |
77 | - break; |
|
77 | + break; |
|
78 | 78 | |
79 | 79 | |
80 | - case EEM_Line_Item::type_line_item: |
|
81 | - // item row |
|
80 | + case EEM_Line_Item::type_line_item: |
|
81 | + // item row |
|
82 | 82 | // $html .= $this->_item_row( $line_item, $options ); |
83 | - // got any kids? |
|
84 | - foreach ($line_item->children() as $child_line_item) { |
|
83 | + // got any kids? |
|
84 | + foreach ($line_item->children() as $child_line_item) { |
|
85 | 85 | // $this->display_line_item( $child_line_item, $options ); |
86 | - } |
|
87 | - break; |
|
86 | + } |
|
87 | + break; |
|
88 | 88 | |
89 | 89 | |
90 | - case EEM_Line_Item::type_sub_line_item: |
|
90 | + case EEM_Line_Item::type_sub_line_item: |
|
91 | 91 | // $html .= $this->_sub_item_row( $line_item, $options ); |
92 | - break; |
|
92 | + break; |
|
93 | 93 | |
94 | 94 | |
95 | - case EEM_Line_Item::type_tax: |
|
95 | + case EEM_Line_Item::type_tax: |
|
96 | 96 | // $html .= $this->_tax_row( $line_item, $options ); |
97 | - break; |
|
98 | - } |
|
97 | + break; |
|
98 | + } |
|
99 | 99 | |
100 | - return $html; |
|
101 | - } |
|
100 | + return $html; |
|
101 | + } |
|
102 | 102 | } |
@@ -118,7 +118,7 @@ discard block |
||
118 | 118 | $html .= $this->_taxes_html; |
119 | 119 | $html .= $this->_total_row($line_item, $options); |
120 | 120 | if ($options['use_table_wrapper']) { |
121 | - $html = $this->_table_header($options) . $html . $this->_table_footer($options); |
|
121 | + $html = $this->_table_header($options).$html.$this->_table_footer($options); |
|
122 | 122 | } |
123 | 123 | break; |
124 | 124 | } |
@@ -157,7 +157,7 @@ discard block |
||
157 | 157 | */ |
158 | 158 | protected function _table_footer($options) |
159 | 159 | { |
160 | - return EEH_HTML::tbodyx() . EEH_HTML::tablex(); |
|
160 | + return EEH_HTML::tbodyx().EEH_HTML::tablex(); |
|
161 | 161 | } |
162 | 162 | |
163 | 163 | |
@@ -188,16 +188,16 @@ discard block |
||
188 | 188 | |
189 | 189 | |
190 | 190 | $name_html = $line_item_related_object instanceof EEI_Line_Item_Object ? $line_item_related_object->name() : $line_item->name(); |
191 | - $name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>' : $name_html; |
|
191 | + $name_html = $name_link ? '<a href="'.$name_link.'">'.$name_html.'</a>' : $name_html; |
|
192 | 192 | $name_html .= $line_item->is_taxable() ? ' *' : ''; |
193 | 193 | // maybe preface with icon? |
194 | - $name_html = $line_item_related_object instanceof EEI_Has_Icon ? $line_item_related_object->get_icon() . $name_html : $name_html; |
|
195 | - $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>'; |
|
196 | - $name_html .= sprintf( |
|
194 | + $name_html = $line_item_related_object instanceof EEI_Has_Icon ? $line_item_related_object->get_icon().$name_html : $name_html; |
|
195 | + $name_html = '<span class="ee-line-item-name linked">'.$name_html.'</span><br>'; |
|
196 | + $name_html .= sprintf( |
|
197 | 197 | _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'), |
198 | 198 | '<span class="ee-line-item-related-parent-object">', |
199 | 199 | $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->OBJ_type_i18n() : esc_html__('Item:', 'event_espresso'), |
200 | - $parent_related_object_link ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' : $parent_related_object_name, |
|
200 | + $parent_related_object_link ? '<a href="'.$parent_related_object_link.'">'.$parent_related_object_name.'</a>' : $parent_related_object_name, |
|
201 | 201 | '</span>' |
202 | 202 | ); |
203 | 203 | |
@@ -214,13 +214,13 @@ discard block |
||
214 | 214 | $type_html .= $this->_get_cancellations($line_item); |
215 | 215 | $type_html .= $line_item->OBJ_type() ? '<br />' : ''; |
216 | 216 | $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : ''; |
217 | - $type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' : ''; |
|
217 | + $type_html .= ! empty($code) ? '<span class="ee-line-item-id">'.sprintf(esc_html__('Code: %s', 'event_espresso'), $code).'</span>' : ''; |
|
218 | 218 | $html .= EEH_HTML::td($type_html, '', 'jst-left'); |
219 | 219 | |
220 | 220 | |
221 | 221 | // Amount Column |
222 | 222 | if ($line_item->is_percent()) { |
223 | - $html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght'); |
|
223 | + $html .= EEH_HTML::td($line_item->percent().'%', '', 'jst-rght'); |
|
224 | 224 | } else { |
225 | 225 | $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght'); |
226 | 226 | } |
@@ -295,7 +295,7 @@ discard block |
||
295 | 295 | // start of row |
296 | 296 | $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr'); |
297 | 297 | // name th |
298 | - $html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="4"'); |
|
298 | + $html .= EEH_HTML::th($line_item->name().'('.$line_item->get_pretty('LIN_percent').'%)', '', 'jst-rght', '', ' colspan="4"'); |
|
299 | 299 | // total th |
300 | 300 | $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
301 | 301 | // end of row |
@@ -334,7 +334,7 @@ discard block |
||
334 | 334 | // start of row |
335 | 335 | $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr'); |
336 | 336 | // Total th label |
337 | - $total_label = sprintf(esc_html__('Transaction Total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')'); |
|
337 | + $total_label = sprintf(esc_html__('Transaction Total %s', 'event_espresso'), '('.EE_Registry::instance()->CFG->currency->code.')'); |
|
338 | 338 | $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="4"'); |
339 | 339 | // total th |
340 | 340 |
@@ -13,332 +13,332 @@ |
||
13 | 13 | |
14 | 14 | class EE_Admin_Table_Line_Item_Display_Strategy implements EEI_Line_Item_Display |
15 | 15 | { |
16 | - /** |
|
17 | - * whether to display the taxes row or not |
|
18 | - * @type bool $_show_taxes |
|
19 | - */ |
|
20 | - protected $_show_taxes = false; |
|
21 | - |
|
22 | - /** |
|
23 | - * html for any tax rows |
|
24 | - * @type string $_show_taxes |
|
25 | - */ |
|
26 | - protected $_taxes_html = ''; |
|
27 | - |
|
28 | - |
|
29 | - /** |
|
30 | - * total amount including tax we can bill for at this time |
|
31 | - * @type float $_grand_total |
|
32 | - */ |
|
33 | - protected $_grand_total = 0.00; |
|
34 | - |
|
35 | - |
|
36 | - |
|
37 | - /** |
|
38 | - * @return float |
|
39 | - */ |
|
40 | - public function grand_total() |
|
41 | - { |
|
42 | - return $this->_grand_total; |
|
43 | - } |
|
44 | - |
|
45 | - |
|
46 | - |
|
47 | - /** |
|
48 | - * This is used to output a single |
|
49 | - * @param EE_Line_Item $line_item |
|
50 | - * @param array $options |
|
51 | - * @return mixed |
|
52 | - */ |
|
53 | - public function display_line_item(EE_Line_Item $line_item, $options = array()) |
|
54 | - { |
|
55 | - |
|
56 | - $html = ''; |
|
57 | - // set some default options and merge with incoming |
|
58 | - $default_options = array( |
|
59 | - 'odd' => true, |
|
60 | - 'use_table_wrapper' => true, |
|
61 | - 'table_css_class' => 'admin-primary-mbox-tbl', |
|
62 | - 'taxes_tr_css_class' => 'admin-primary-mbox-taxes-tr', |
|
63 | - 'total_tr_css_class' => 'admin-primary-mbox-total-tr' |
|
64 | - ); |
|
65 | - $options = array_merge($default_options, (array) $options); |
|
66 | - |
|
67 | - switch ($line_item->type()) { |
|
68 | - case EEM_Line_Item::type_line_item: |
|
69 | - // item row |
|
70 | - $html .= $this->_item_row($line_item, $options); |
|
71 | - break; |
|
72 | - |
|
73 | - case EEM_Line_Item::type_sub_line_item: |
|
74 | - $html .= $this->_sub_item_row($line_item, $options); |
|
75 | - break; |
|
76 | - |
|
77 | - case EEM_Line_Item::type_sub_total: |
|
78 | - if ($line_item->quantity() === 0) { |
|
79 | - return $html; |
|
80 | - } |
|
81 | - // loop through children |
|
82 | - $child_line_items = $line_item->children(); |
|
83 | - // loop through children |
|
84 | - foreach ($child_line_items as $child_line_item) { |
|
85 | - // recursively feed children back into this method |
|
86 | - $html .= $this->display_line_item($child_line_item, $options); |
|
87 | - } |
|
88 | - $html .= $this->_sub_total_row($line_item, $options); |
|
89 | - break; |
|
90 | - |
|
91 | - case EEM_Line_Item::type_tax: |
|
92 | - if ($this->_show_taxes) { |
|
93 | - $this->_taxes_html .= $this->_tax_row($line_item, $options); |
|
94 | - } |
|
95 | - break; |
|
96 | - |
|
97 | - case EEM_Line_Item::type_tax_sub_total: |
|
98 | - foreach ($line_item->children() as $child_line_item) { |
|
99 | - if ($child_line_item->type() == EEM_Line_Item::type_tax) { |
|
100 | - $this->display_line_item($child_line_item, $options); |
|
101 | - } |
|
102 | - } |
|
103 | - break; |
|
104 | - |
|
105 | - case EEM_Line_Item::type_total: |
|
106 | - // determine whether to display taxes or not |
|
107 | - $this->_show_taxes = $line_item->get_total_tax() > 0 ? true : false; |
|
108 | - // get all child line items |
|
109 | - $children = $line_item->children(); |
|
110 | - |
|
111 | - // loop thru all non-tax child line items |
|
112 | - foreach ($children as $child_line_item) { |
|
113 | - $html .= $this->display_line_item($child_line_item, $options); |
|
114 | - } |
|
115 | - |
|
116 | - $html .= $this->_taxes_html; |
|
117 | - $html .= $this->_total_row($line_item, $options); |
|
118 | - if ($options['use_table_wrapper']) { |
|
119 | - $html = $this->_table_header($options) . $html . $this->_table_footer($options); |
|
120 | - } |
|
121 | - break; |
|
122 | - } |
|
123 | - |
|
124 | - return $html; |
|
125 | - } |
|
126 | - |
|
127 | - |
|
128 | - |
|
129 | - /** |
|
130 | - * Table header for display. |
|
131 | - * @since 4.8 |
|
132 | - * @param array $options |
|
133 | - * @return string |
|
134 | - */ |
|
135 | - protected function _table_header($options) |
|
136 | - { |
|
137 | - $html = EEH_HTML::table('', '', $options['table_css_class']); |
|
138 | - $html .= EEH_HTML::thead(); |
|
139 | - $html .= EEH_HTML::tr(); |
|
140 | - $html .= EEH_HTML::th(esc_html__('Name', 'event_espresso'), '', 'jst-left'); |
|
141 | - $html .= EEH_HTML::th(esc_html__('Type', 'event_espresso'), '', 'jst-left'); |
|
142 | - $html .= EEH_HTML::th(esc_html__('Amount', 'event_espresso'), '', 'jst-cntr'); |
|
143 | - $html .= EEH_HTML::th(esc_html__('Qty', 'event_espresso'), '', 'jst-cntr'); |
|
144 | - $html .= EEH_HTML::th(esc_html__('Line Total', 'event_espresso'), '', 'jst-cntr'); |
|
145 | - $html .= EEH_HTML::tbody(); |
|
146 | - return $html; |
|
147 | - } |
|
148 | - |
|
149 | - |
|
150 | - /** |
|
151 | - * Table footer for display |
|
152 | - * @since 4.8 |
|
153 | - * @param array $options array of options for the table. |
|
154 | - * @return string |
|
155 | - */ |
|
156 | - protected function _table_footer($options) |
|
157 | - { |
|
158 | - return EEH_HTML::tbodyx() . EEH_HTML::tablex(); |
|
159 | - } |
|
160 | - |
|
161 | - |
|
162 | - |
|
163 | - /** |
|
164 | - * _item_row |
|
165 | - * |
|
166 | - * @param EE_Line_Item $line_item |
|
167 | - * @param array $options |
|
168 | - * @return mixed |
|
169 | - */ |
|
170 | - protected function _item_row(EE_Line_Item $line_item, $options = array()) |
|
171 | - { |
|
172 | - $line_item_related_object = $line_item->get_object(); |
|
173 | - $parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->get_object() : null; |
|
174 | - // start of row |
|
175 | - $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
176 | - $html = EEH_HTML::tr('', '', $row_class); |
|
177 | - |
|
178 | - |
|
179 | - // Name Column |
|
180 | - $name_link = $line_item_related_object instanceof EEI_Admin_Links ? $line_item_related_object->get_admin_details_link() : ''; |
|
181 | - |
|
182 | - // related object scope. |
|
183 | - $parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object ? $parent_line_item_related_object->name() : ''; |
|
184 | - $parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->name() : $parent_related_object_name; |
|
185 | - $parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links ? $parent_line_item_related_object->get_admin_details_link() : ''; |
|
186 | - |
|
187 | - |
|
188 | - $name_html = $line_item_related_object instanceof EEI_Line_Item_Object ? $line_item_related_object->name() : $line_item->name(); |
|
189 | - $name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>' : $name_html; |
|
190 | - $name_html .= $line_item->is_taxable() ? ' *' : ''; |
|
191 | - // maybe preface with icon? |
|
192 | - $name_html = $line_item_related_object instanceof EEI_Has_Icon ? $line_item_related_object->get_icon() . $name_html : $name_html; |
|
193 | - $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>'; |
|
194 | - $name_html .= sprintf( |
|
195 | - _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'), |
|
196 | - '<span class="ee-line-item-related-parent-object">', |
|
197 | - $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->OBJ_type_i18n() : esc_html__('Item:', 'event_espresso'), |
|
198 | - $parent_related_object_link ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' : $parent_related_object_name, |
|
199 | - '</span>' |
|
200 | - ); |
|
201 | - |
|
202 | - $name_html = apply_filters( |
|
203 | - 'FHEE__EE_Admin_Table_Line_Item_Display_Strategy___item_row__name_html', |
|
204 | - $name_html, |
|
205 | - $line_item, |
|
206 | - $options |
|
207 | - ); |
|
208 | - |
|
209 | - $html .= EEH_HTML::td($name_html, '', 'jst-left'); |
|
210 | - // Type Column |
|
211 | - $type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : ''; |
|
212 | - $type_html .= $this->_get_cancellations($line_item); |
|
213 | - $type_html .= $line_item->OBJ_type() ? '<br />' : ''; |
|
214 | - $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : ''; |
|
215 | - $type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' : ''; |
|
216 | - $html .= EEH_HTML::td($type_html, '', 'jst-left'); |
|
217 | - |
|
218 | - |
|
219 | - // Amount Column |
|
220 | - if ($line_item->is_percent()) { |
|
221 | - $html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght'); |
|
222 | - } else { |
|
223 | - $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght'); |
|
224 | - } |
|
225 | - |
|
226 | - // QTY column |
|
227 | - $html .= EEH_HTML::td($line_item->quantity(), '', 'jst-rght'); |
|
228 | - |
|
229 | - // total column |
|
230 | - $html .= EEH_HTML::td(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
231 | - |
|
232 | - // finish things off and return |
|
233 | - $html .= EEH_HTML::trx(); |
|
234 | - return $html; |
|
235 | - } |
|
236 | - |
|
237 | - |
|
238 | - |
|
239 | - /** |
|
240 | - * _get_cancellations |
|
241 | - * |
|
242 | - * @param EE_Line_Item $line_item |
|
243 | - * @return string |
|
244 | - */ |
|
245 | - protected function _get_cancellations(EE_Line_Item $line_item) |
|
246 | - { |
|
247 | - $html = ''; |
|
248 | - $cancellations = $line_item->get_cancellations(); |
|
249 | - $cancellation = reset($cancellations); |
|
250 | - // \EEH_Debug_Tools::printr( $cancellation, '$cancellation', __FILE__, __LINE__ ); |
|
251 | - if ($cancellation instanceof EE_Line_Item) { |
|
252 | - $html .= ' <span class="ee-line-item-id">'; |
|
253 | - $html .= sprintf( |
|
254 | - _n( |
|
255 | - '(%1$s Cancellation)', |
|
256 | - '(%1$s Cancellations)', |
|
257 | - $cancellation->quantity(), |
|
258 | - 'event_espresso' |
|
259 | - ), |
|
260 | - $cancellation->quantity() |
|
261 | - ); |
|
262 | - $html .= '</span>'; |
|
263 | - } |
|
264 | - return $html; |
|
265 | - } |
|
266 | - |
|
267 | - |
|
268 | - |
|
269 | - /** |
|
270 | - * _sub_item_row |
|
271 | - * |
|
272 | - * @param EE_Line_Item $line_item |
|
273 | - * @param array $options |
|
274 | - * @return mixed |
|
275 | - */ |
|
276 | - protected function _sub_item_row(EE_Line_Item $line_item, $options = array()) |
|
277 | - { |
|
278 | - // for now we're not showing sub-items |
|
279 | - return ''; |
|
280 | - } |
|
281 | - |
|
282 | - |
|
283 | - |
|
284 | - /** |
|
285 | - * _tax_row |
|
286 | - * |
|
287 | - * @param EE_Line_Item $line_item |
|
288 | - * @param array $options |
|
289 | - * @return mixed |
|
290 | - */ |
|
291 | - protected function _tax_row(EE_Line_Item $line_item, $options = array()) |
|
292 | - { |
|
293 | - // start of row |
|
294 | - $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr'); |
|
295 | - // name th |
|
296 | - $html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="4"'); |
|
297 | - // total th |
|
298 | - $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
299 | - // end of row |
|
300 | - $html .= EEH_HTML::trx(); |
|
301 | - return $html; |
|
302 | - } |
|
303 | - |
|
304 | - |
|
305 | - |
|
306 | - |
|
307 | - /** |
|
308 | - * _total_row |
|
309 | - * |
|
310 | - * @param EE_Line_Item $line_item |
|
311 | - * @param string $text |
|
312 | - * @param array $options |
|
313 | - * @return mixed |
|
314 | - */ |
|
315 | - protected function _sub_total_row(EE_Line_Item $line_item, $text = '', $options = array()) |
|
316 | - { |
|
317 | - // currently not showing subtotal row |
|
318 | - return ''; |
|
319 | - } |
|
320 | - |
|
321 | - |
|
322 | - |
|
323 | - /** |
|
324 | - * _total_row |
|
325 | - * |
|
326 | - * @param EE_Line_Item $line_item |
|
327 | - * @param array $options |
|
328 | - * @return mixed |
|
329 | - */ |
|
330 | - protected function _total_row(EE_Line_Item $line_item, $options = array()) |
|
331 | - { |
|
332 | - // start of row |
|
333 | - $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr'); |
|
334 | - // Total th label |
|
335 | - $total_label = sprintf(esc_html__('Transaction Total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')'); |
|
336 | - $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="4"'); |
|
337 | - // total th |
|
338 | - |
|
339 | - $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
340 | - // end of row |
|
341 | - $html .= EEH_HTML::trx(); |
|
342 | - return $html; |
|
343 | - } |
|
16 | + /** |
|
17 | + * whether to display the taxes row or not |
|
18 | + * @type bool $_show_taxes |
|
19 | + */ |
|
20 | + protected $_show_taxes = false; |
|
21 | + |
|
22 | + /** |
|
23 | + * html for any tax rows |
|
24 | + * @type string $_show_taxes |
|
25 | + */ |
|
26 | + protected $_taxes_html = ''; |
|
27 | + |
|
28 | + |
|
29 | + /** |
|
30 | + * total amount including tax we can bill for at this time |
|
31 | + * @type float $_grand_total |
|
32 | + */ |
|
33 | + protected $_grand_total = 0.00; |
|
34 | + |
|
35 | + |
|
36 | + |
|
37 | + /** |
|
38 | + * @return float |
|
39 | + */ |
|
40 | + public function grand_total() |
|
41 | + { |
|
42 | + return $this->_grand_total; |
|
43 | + } |
|
44 | + |
|
45 | + |
|
46 | + |
|
47 | + /** |
|
48 | + * This is used to output a single |
|
49 | + * @param EE_Line_Item $line_item |
|
50 | + * @param array $options |
|
51 | + * @return mixed |
|
52 | + */ |
|
53 | + public function display_line_item(EE_Line_Item $line_item, $options = array()) |
|
54 | + { |
|
55 | + |
|
56 | + $html = ''; |
|
57 | + // set some default options and merge with incoming |
|
58 | + $default_options = array( |
|
59 | + 'odd' => true, |
|
60 | + 'use_table_wrapper' => true, |
|
61 | + 'table_css_class' => 'admin-primary-mbox-tbl', |
|
62 | + 'taxes_tr_css_class' => 'admin-primary-mbox-taxes-tr', |
|
63 | + 'total_tr_css_class' => 'admin-primary-mbox-total-tr' |
|
64 | + ); |
|
65 | + $options = array_merge($default_options, (array) $options); |
|
66 | + |
|
67 | + switch ($line_item->type()) { |
|
68 | + case EEM_Line_Item::type_line_item: |
|
69 | + // item row |
|
70 | + $html .= $this->_item_row($line_item, $options); |
|
71 | + break; |
|
72 | + |
|
73 | + case EEM_Line_Item::type_sub_line_item: |
|
74 | + $html .= $this->_sub_item_row($line_item, $options); |
|
75 | + break; |
|
76 | + |
|
77 | + case EEM_Line_Item::type_sub_total: |
|
78 | + if ($line_item->quantity() === 0) { |
|
79 | + return $html; |
|
80 | + } |
|
81 | + // loop through children |
|
82 | + $child_line_items = $line_item->children(); |
|
83 | + // loop through children |
|
84 | + foreach ($child_line_items as $child_line_item) { |
|
85 | + // recursively feed children back into this method |
|
86 | + $html .= $this->display_line_item($child_line_item, $options); |
|
87 | + } |
|
88 | + $html .= $this->_sub_total_row($line_item, $options); |
|
89 | + break; |
|
90 | + |
|
91 | + case EEM_Line_Item::type_tax: |
|
92 | + if ($this->_show_taxes) { |
|
93 | + $this->_taxes_html .= $this->_tax_row($line_item, $options); |
|
94 | + } |
|
95 | + break; |
|
96 | + |
|
97 | + case EEM_Line_Item::type_tax_sub_total: |
|
98 | + foreach ($line_item->children() as $child_line_item) { |
|
99 | + if ($child_line_item->type() == EEM_Line_Item::type_tax) { |
|
100 | + $this->display_line_item($child_line_item, $options); |
|
101 | + } |
|
102 | + } |
|
103 | + break; |
|
104 | + |
|
105 | + case EEM_Line_Item::type_total: |
|
106 | + // determine whether to display taxes or not |
|
107 | + $this->_show_taxes = $line_item->get_total_tax() > 0 ? true : false; |
|
108 | + // get all child line items |
|
109 | + $children = $line_item->children(); |
|
110 | + |
|
111 | + // loop thru all non-tax child line items |
|
112 | + foreach ($children as $child_line_item) { |
|
113 | + $html .= $this->display_line_item($child_line_item, $options); |
|
114 | + } |
|
115 | + |
|
116 | + $html .= $this->_taxes_html; |
|
117 | + $html .= $this->_total_row($line_item, $options); |
|
118 | + if ($options['use_table_wrapper']) { |
|
119 | + $html = $this->_table_header($options) . $html . $this->_table_footer($options); |
|
120 | + } |
|
121 | + break; |
|
122 | + } |
|
123 | + |
|
124 | + return $html; |
|
125 | + } |
|
126 | + |
|
127 | + |
|
128 | + |
|
129 | + /** |
|
130 | + * Table header for display. |
|
131 | + * @since 4.8 |
|
132 | + * @param array $options |
|
133 | + * @return string |
|
134 | + */ |
|
135 | + protected function _table_header($options) |
|
136 | + { |
|
137 | + $html = EEH_HTML::table('', '', $options['table_css_class']); |
|
138 | + $html .= EEH_HTML::thead(); |
|
139 | + $html .= EEH_HTML::tr(); |
|
140 | + $html .= EEH_HTML::th(esc_html__('Name', 'event_espresso'), '', 'jst-left'); |
|
141 | + $html .= EEH_HTML::th(esc_html__('Type', 'event_espresso'), '', 'jst-left'); |
|
142 | + $html .= EEH_HTML::th(esc_html__('Amount', 'event_espresso'), '', 'jst-cntr'); |
|
143 | + $html .= EEH_HTML::th(esc_html__('Qty', 'event_espresso'), '', 'jst-cntr'); |
|
144 | + $html .= EEH_HTML::th(esc_html__('Line Total', 'event_espresso'), '', 'jst-cntr'); |
|
145 | + $html .= EEH_HTML::tbody(); |
|
146 | + return $html; |
|
147 | + } |
|
148 | + |
|
149 | + |
|
150 | + /** |
|
151 | + * Table footer for display |
|
152 | + * @since 4.8 |
|
153 | + * @param array $options array of options for the table. |
|
154 | + * @return string |
|
155 | + */ |
|
156 | + protected function _table_footer($options) |
|
157 | + { |
|
158 | + return EEH_HTML::tbodyx() . EEH_HTML::tablex(); |
|
159 | + } |
|
160 | + |
|
161 | + |
|
162 | + |
|
163 | + /** |
|
164 | + * _item_row |
|
165 | + * |
|
166 | + * @param EE_Line_Item $line_item |
|
167 | + * @param array $options |
|
168 | + * @return mixed |
|
169 | + */ |
|
170 | + protected function _item_row(EE_Line_Item $line_item, $options = array()) |
|
171 | + { |
|
172 | + $line_item_related_object = $line_item->get_object(); |
|
173 | + $parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->get_object() : null; |
|
174 | + // start of row |
|
175 | + $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
176 | + $html = EEH_HTML::tr('', '', $row_class); |
|
177 | + |
|
178 | + |
|
179 | + // Name Column |
|
180 | + $name_link = $line_item_related_object instanceof EEI_Admin_Links ? $line_item_related_object->get_admin_details_link() : ''; |
|
181 | + |
|
182 | + // related object scope. |
|
183 | + $parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object ? $parent_line_item_related_object->name() : ''; |
|
184 | + $parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->name() : $parent_related_object_name; |
|
185 | + $parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links ? $parent_line_item_related_object->get_admin_details_link() : ''; |
|
186 | + |
|
187 | + |
|
188 | + $name_html = $line_item_related_object instanceof EEI_Line_Item_Object ? $line_item_related_object->name() : $line_item->name(); |
|
189 | + $name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>' : $name_html; |
|
190 | + $name_html .= $line_item->is_taxable() ? ' *' : ''; |
|
191 | + // maybe preface with icon? |
|
192 | + $name_html = $line_item_related_object instanceof EEI_Has_Icon ? $line_item_related_object->get_icon() . $name_html : $name_html; |
|
193 | + $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>'; |
|
194 | + $name_html .= sprintf( |
|
195 | + _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'), |
|
196 | + '<span class="ee-line-item-related-parent-object">', |
|
197 | + $line_item->parent() instanceof EE_Line_Item ? $line_item->parent()->OBJ_type_i18n() : esc_html__('Item:', 'event_espresso'), |
|
198 | + $parent_related_object_link ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' : $parent_related_object_name, |
|
199 | + '</span>' |
|
200 | + ); |
|
201 | + |
|
202 | + $name_html = apply_filters( |
|
203 | + 'FHEE__EE_Admin_Table_Line_Item_Display_Strategy___item_row__name_html', |
|
204 | + $name_html, |
|
205 | + $line_item, |
|
206 | + $options |
|
207 | + ); |
|
208 | + |
|
209 | + $html .= EEH_HTML::td($name_html, '', 'jst-left'); |
|
210 | + // Type Column |
|
211 | + $type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : ''; |
|
212 | + $type_html .= $this->_get_cancellations($line_item); |
|
213 | + $type_html .= $line_item->OBJ_type() ? '<br />' : ''; |
|
214 | + $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : ''; |
|
215 | + $type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' : ''; |
|
216 | + $html .= EEH_HTML::td($type_html, '', 'jst-left'); |
|
217 | + |
|
218 | + |
|
219 | + // Amount Column |
|
220 | + if ($line_item->is_percent()) { |
|
221 | + $html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght'); |
|
222 | + } else { |
|
223 | + $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght'); |
|
224 | + } |
|
225 | + |
|
226 | + // QTY column |
|
227 | + $html .= EEH_HTML::td($line_item->quantity(), '', 'jst-rght'); |
|
228 | + |
|
229 | + // total column |
|
230 | + $html .= EEH_HTML::td(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
231 | + |
|
232 | + // finish things off and return |
|
233 | + $html .= EEH_HTML::trx(); |
|
234 | + return $html; |
|
235 | + } |
|
236 | + |
|
237 | + |
|
238 | + |
|
239 | + /** |
|
240 | + * _get_cancellations |
|
241 | + * |
|
242 | + * @param EE_Line_Item $line_item |
|
243 | + * @return string |
|
244 | + */ |
|
245 | + protected function _get_cancellations(EE_Line_Item $line_item) |
|
246 | + { |
|
247 | + $html = ''; |
|
248 | + $cancellations = $line_item->get_cancellations(); |
|
249 | + $cancellation = reset($cancellations); |
|
250 | + // \EEH_Debug_Tools::printr( $cancellation, '$cancellation', __FILE__, __LINE__ ); |
|
251 | + if ($cancellation instanceof EE_Line_Item) { |
|
252 | + $html .= ' <span class="ee-line-item-id">'; |
|
253 | + $html .= sprintf( |
|
254 | + _n( |
|
255 | + '(%1$s Cancellation)', |
|
256 | + '(%1$s Cancellations)', |
|
257 | + $cancellation->quantity(), |
|
258 | + 'event_espresso' |
|
259 | + ), |
|
260 | + $cancellation->quantity() |
|
261 | + ); |
|
262 | + $html .= '</span>'; |
|
263 | + } |
|
264 | + return $html; |
|
265 | + } |
|
266 | + |
|
267 | + |
|
268 | + |
|
269 | + /** |
|
270 | + * _sub_item_row |
|
271 | + * |
|
272 | + * @param EE_Line_Item $line_item |
|
273 | + * @param array $options |
|
274 | + * @return mixed |
|
275 | + */ |
|
276 | + protected function _sub_item_row(EE_Line_Item $line_item, $options = array()) |
|
277 | + { |
|
278 | + // for now we're not showing sub-items |
|
279 | + return ''; |
|
280 | + } |
|
281 | + |
|
282 | + |
|
283 | + |
|
284 | + /** |
|
285 | + * _tax_row |
|
286 | + * |
|
287 | + * @param EE_Line_Item $line_item |
|
288 | + * @param array $options |
|
289 | + * @return mixed |
|
290 | + */ |
|
291 | + protected function _tax_row(EE_Line_Item $line_item, $options = array()) |
|
292 | + { |
|
293 | + // start of row |
|
294 | + $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr'); |
|
295 | + // name th |
|
296 | + $html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="4"'); |
|
297 | + // total th |
|
298 | + $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
299 | + // end of row |
|
300 | + $html .= EEH_HTML::trx(); |
|
301 | + return $html; |
|
302 | + } |
|
303 | + |
|
304 | + |
|
305 | + |
|
306 | + |
|
307 | + /** |
|
308 | + * _total_row |
|
309 | + * |
|
310 | + * @param EE_Line_Item $line_item |
|
311 | + * @param string $text |
|
312 | + * @param array $options |
|
313 | + * @return mixed |
|
314 | + */ |
|
315 | + protected function _sub_total_row(EE_Line_Item $line_item, $text = '', $options = array()) |
|
316 | + { |
|
317 | + // currently not showing subtotal row |
|
318 | + return ''; |
|
319 | + } |
|
320 | + |
|
321 | + |
|
322 | + |
|
323 | + /** |
|
324 | + * _total_row |
|
325 | + * |
|
326 | + * @param EE_Line_Item $line_item |
|
327 | + * @param array $options |
|
328 | + * @return mixed |
|
329 | + */ |
|
330 | + protected function _total_row(EE_Line_Item $line_item, $options = array()) |
|
331 | + { |
|
332 | + // start of row |
|
333 | + $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr'); |
|
334 | + // Total th label |
|
335 | + $total_label = sprintf(esc_html__('Transaction Total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')'); |
|
336 | + $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="4"'); |
|
337 | + // total th |
|
338 | + |
|
339 | + $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
340 | + // end of row |
|
341 | + $html .= EEH_HTML::trx(); |
|
342 | + return $html; |
|
343 | + } |
|
344 | 344 | } |
@@ -14,191 +14,191 @@ |
||
14 | 14 | class EE_Admin_Table_Registration_Line_Item_Display_Strategy extends EE_Admin_Table_Line_Item_Display_Strategy |
15 | 15 | { |
16 | 16 | |
17 | - /** |
|
18 | - * Table header for display. |
|
19 | - * @since 4.8 |
|
20 | - * @param array $options |
|
21 | - * @return string |
|
22 | - */ |
|
23 | - protected function _table_header($options) |
|
24 | - { |
|
25 | - $html = EEH_HTML::table('', '', $options['table_css_class']); |
|
26 | - $html .= EEH_HTML::thead(); |
|
27 | - $html .= EEH_HTML::tr(); |
|
28 | - $html .= EEH_HTML::th(esc_html__('Name', 'event_espresso'), '', 'jst-left'); |
|
29 | - $html .= EEH_HTML::th(esc_html__('Type', 'event_espresso'), '', 'jst-left'); |
|
30 | - $html .= EEH_HTML::th(esc_html__('Date(s)', 'event_espresso'), '', 'jst-left'); |
|
31 | - $html .= EEH_HTML::th(esc_html__('Amount', 'event_espresso'), '', 'jst-cntr'); |
|
32 | - $html .= EEH_HTML::tbody(); |
|
33 | - return $html; |
|
34 | - } |
|
35 | - |
|
36 | - |
|
37 | - |
|
38 | - |
|
39 | - |
|
40 | - /** |
|
41 | - * _item_row |
|
42 | - * |
|
43 | - * @param EE_Line_Item $line_item |
|
44 | - * @param array $options |
|
45 | - * @return mixed |
|
46 | - */ |
|
47 | - protected function _item_row(EE_Line_Item $line_item, $options = array()) |
|
48 | - { |
|
49 | - $line_item_related_object = $line_item->get_object(); |
|
50 | - $parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item |
|
51 | - ? $line_item->parent()->get_object() |
|
52 | - : null; |
|
53 | - // start of row |
|
54 | - $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
55 | - $html = EEH_HTML::tr('', '', $row_class); |
|
56 | - |
|
57 | - |
|
58 | - // Name Column |
|
59 | - $name_link = $line_item_related_object instanceof EEI_Admin_Links ? $line_item_related_object->get_admin_details_link() : ''; |
|
60 | - |
|
61 | - // related object scope. |
|
62 | - $parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object |
|
63 | - ? $parent_line_item_related_object->name() |
|
64 | - : ''; |
|
65 | - $parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item |
|
66 | - ? $line_item->parent()->name() |
|
67 | - : $parent_related_object_name; |
|
68 | - $parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links |
|
69 | - ? $parent_line_item_related_object->get_admin_details_link() |
|
70 | - : ''; |
|
71 | - |
|
72 | - |
|
73 | - $name_html = $line_item_related_object instanceof EEI_Line_Item_Object |
|
74 | - ? $line_item_related_object->name() : $line_item->name(); |
|
75 | - $name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>' |
|
76 | - : $name_html; |
|
77 | - $name_html .= $line_item->is_taxable() ? ' *' : ''; |
|
78 | - // maybe preface with icon? |
|
79 | - $name_html = $line_item_related_object instanceof EEI_Has_Icon |
|
80 | - ? $line_item_related_object->get_icon() . $name_html |
|
81 | - : $name_html; |
|
82 | - $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>'; |
|
83 | - $name_html .= sprintf( |
|
84 | - _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'), |
|
85 | - '<span class="ee-line-item-related-parent-object">', |
|
86 | - $line_item->parent() instanceof EE_Line_Item |
|
87 | - ? $line_item->parent()->OBJ_type_i18n() |
|
88 | - : esc_html__('Item:', 'event_espresso'), |
|
89 | - $parent_related_object_link |
|
90 | - ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' |
|
91 | - : $parent_related_object_name, |
|
92 | - '</span>' |
|
93 | - ); |
|
94 | - |
|
95 | - $name_html = apply_filters( |
|
96 | - 'FHEE__EE_Admin_Table_Registration_Line_Item_Display_Strategy___item_row__name_html', |
|
97 | - $name_html, |
|
98 | - $line_item, |
|
99 | - $options |
|
100 | - ); |
|
101 | - |
|
102 | - $html .= EEH_HTML::td($name_html, '', 'jst-left'); |
|
103 | - // Type Column |
|
104 | - $type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : ''; |
|
105 | - $type_html .= $this->_get_cancellations($line_item); |
|
106 | - $type_html .= $line_item->OBJ_type() ? '<br />' : ''; |
|
107 | - $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : ''; |
|
108 | - $type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' : ''; |
|
109 | - $html .= EEH_HTML::td($type_html, '', 'jst-left'); |
|
110 | - |
|
111 | - // Date column |
|
112 | - $datetime_content = ''; |
|
113 | - if ($line_item_related_object instanceof EE_Ticket) { |
|
114 | - $datetimes = $line_item_related_object->datetimes(); |
|
115 | - foreach ($datetimes as $datetime) { |
|
116 | - if ($datetime instanceof EE_Datetime) { |
|
117 | - $datetime_content .= $datetime->get_dtt_display_name() . '<br>'; |
|
118 | - } |
|
119 | - } |
|
120 | - } |
|
121 | - $html .= EEH_HTML::td($datetime_content, '', 'jst-left'); |
|
122 | - |
|
123 | - // Amount Column |
|
124 | - if ($line_item->is_percent()) { |
|
125 | - $html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght'); |
|
126 | - } else { |
|
127 | - $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght'); |
|
128 | - } |
|
129 | - |
|
130 | - |
|
131 | - // finish things off and return |
|
132 | - $html .= EEH_HTML::trx(); |
|
133 | - return $html; |
|
134 | - } |
|
135 | - |
|
136 | - |
|
137 | - |
|
138 | - /** |
|
139 | - * _tax_row |
|
140 | - * |
|
141 | - * @param EE_Line_Item $line_item |
|
142 | - * @param array $options |
|
143 | - * @return mixed |
|
144 | - */ |
|
145 | - protected function _tax_row(EE_Line_Item $line_item, $options = array()) |
|
146 | - { |
|
147 | - // start of row |
|
148 | - $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr'); |
|
149 | - // name th |
|
150 | - $html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="3"'); |
|
151 | - // total th |
|
152 | - $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
153 | - // end of row |
|
154 | - $html .= EEH_HTML::trx(); |
|
155 | - return $html; |
|
156 | - } |
|
157 | - |
|
158 | - |
|
159 | - |
|
160 | - |
|
161 | - |
|
162 | - /** |
|
163 | - * _total_row |
|
164 | - * |
|
165 | - * @param EE_Line_Item $line_item |
|
166 | - * @param array $options |
|
167 | - * @return mixed |
|
168 | - */ |
|
169 | - protected function _total_row(EE_Line_Item $line_item, $options = array()) |
|
170 | - { |
|
171 | - |
|
172 | - $registration = isset($options['EE_Registration']) ? $options['EE_Registration'] : null; |
|
173 | - $registration_total = $registration instanceof EE_Registration ? $registration->pretty_final_price() : 0; |
|
174 | - // if no valid registration object then we're not going to show the approximate text. |
|
175 | - $total_match = $registration instanceof EE_Registration |
|
176 | - ? $registration->final_price() === $line_item->total() |
|
177 | - : true; |
|
178 | - |
|
179 | - // start of row |
|
180 | - $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr'); |
|
181 | - // Total th label |
|
182 | - if ($total_match) { |
|
183 | - $total_label = sprintf(esc_html__('This registration\'s total %s:', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')'); |
|
184 | - } else { |
|
185 | - $total_label = sprintf(esc_html__('This registration\'s approximate total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')'); |
|
186 | - $total_label .= '<br>'; |
|
187 | - $total_label .= '<p class="ee-footnote-text">' |
|
188 | - . sprintf( |
|
189 | - esc_html__('The registrations\' share of the transaction total is approximate because it might not be possible to evenly divide the transaction total among each registration, and so some registrations may need to pay a penny more than others. This registration\'s final share is actually %1$s%2$s%3$s.', 'event_espresso'), |
|
190 | - '<strong>', |
|
191 | - $registration_total, |
|
192 | - '</strong>' |
|
193 | - ) |
|
194 | - . '</p>'; |
|
195 | - } |
|
196 | - $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="3"'); |
|
197 | - // total th |
|
198 | - |
|
199 | - $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
200 | - // end of row |
|
201 | - $html .= EEH_HTML::trx(); |
|
202 | - return $html; |
|
203 | - } |
|
17 | + /** |
|
18 | + * Table header for display. |
|
19 | + * @since 4.8 |
|
20 | + * @param array $options |
|
21 | + * @return string |
|
22 | + */ |
|
23 | + protected function _table_header($options) |
|
24 | + { |
|
25 | + $html = EEH_HTML::table('', '', $options['table_css_class']); |
|
26 | + $html .= EEH_HTML::thead(); |
|
27 | + $html .= EEH_HTML::tr(); |
|
28 | + $html .= EEH_HTML::th(esc_html__('Name', 'event_espresso'), '', 'jst-left'); |
|
29 | + $html .= EEH_HTML::th(esc_html__('Type', 'event_espresso'), '', 'jst-left'); |
|
30 | + $html .= EEH_HTML::th(esc_html__('Date(s)', 'event_espresso'), '', 'jst-left'); |
|
31 | + $html .= EEH_HTML::th(esc_html__('Amount', 'event_espresso'), '', 'jst-cntr'); |
|
32 | + $html .= EEH_HTML::tbody(); |
|
33 | + return $html; |
|
34 | + } |
|
35 | + |
|
36 | + |
|
37 | + |
|
38 | + |
|
39 | + |
|
40 | + /** |
|
41 | + * _item_row |
|
42 | + * |
|
43 | + * @param EE_Line_Item $line_item |
|
44 | + * @param array $options |
|
45 | + * @return mixed |
|
46 | + */ |
|
47 | + protected function _item_row(EE_Line_Item $line_item, $options = array()) |
|
48 | + { |
|
49 | + $line_item_related_object = $line_item->get_object(); |
|
50 | + $parent_line_item_related_object = $line_item->parent() instanceof EE_Line_Item |
|
51 | + ? $line_item->parent()->get_object() |
|
52 | + : null; |
|
53 | + // start of row |
|
54 | + $row_class = $options['odd'] ? 'item odd' : 'item'; |
|
55 | + $html = EEH_HTML::tr('', '', $row_class); |
|
56 | + |
|
57 | + |
|
58 | + // Name Column |
|
59 | + $name_link = $line_item_related_object instanceof EEI_Admin_Links ? $line_item_related_object->get_admin_details_link() : ''; |
|
60 | + |
|
61 | + // related object scope. |
|
62 | + $parent_related_object_name = $parent_line_item_related_object instanceof EEI_Line_Item_Object |
|
63 | + ? $parent_line_item_related_object->name() |
|
64 | + : ''; |
|
65 | + $parent_related_object_name = empty($parent_related_object_name) && $line_item->parent() instanceof EE_Line_Item |
|
66 | + ? $line_item->parent()->name() |
|
67 | + : $parent_related_object_name; |
|
68 | + $parent_related_object_link = $parent_line_item_related_object instanceof EEI_Admin_Links |
|
69 | + ? $parent_line_item_related_object->get_admin_details_link() |
|
70 | + : ''; |
|
71 | + |
|
72 | + |
|
73 | + $name_html = $line_item_related_object instanceof EEI_Line_Item_Object |
|
74 | + ? $line_item_related_object->name() : $line_item->name(); |
|
75 | + $name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>' |
|
76 | + : $name_html; |
|
77 | + $name_html .= $line_item->is_taxable() ? ' *' : ''; |
|
78 | + // maybe preface with icon? |
|
79 | + $name_html = $line_item_related_object instanceof EEI_Has_Icon |
|
80 | + ? $line_item_related_object->get_icon() . $name_html |
|
81 | + : $name_html; |
|
82 | + $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>'; |
|
83 | + $name_html .= sprintf( |
|
84 | + _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'), |
|
85 | + '<span class="ee-line-item-related-parent-object">', |
|
86 | + $line_item->parent() instanceof EE_Line_Item |
|
87 | + ? $line_item->parent()->OBJ_type_i18n() |
|
88 | + : esc_html__('Item:', 'event_espresso'), |
|
89 | + $parent_related_object_link |
|
90 | + ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' |
|
91 | + : $parent_related_object_name, |
|
92 | + '</span>' |
|
93 | + ); |
|
94 | + |
|
95 | + $name_html = apply_filters( |
|
96 | + 'FHEE__EE_Admin_Table_Registration_Line_Item_Display_Strategy___item_row__name_html', |
|
97 | + $name_html, |
|
98 | + $line_item, |
|
99 | + $options |
|
100 | + ); |
|
101 | + |
|
102 | + $html .= EEH_HTML::td($name_html, '', 'jst-left'); |
|
103 | + // Type Column |
|
104 | + $type_html = $line_item->OBJ_type() ? $line_item->OBJ_type_i18n() : ''; |
|
105 | + $type_html .= $this->_get_cancellations($line_item); |
|
106 | + $type_html .= $line_item->OBJ_type() ? '<br />' : ''; |
|
107 | + $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : ''; |
|
108 | + $type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' : ''; |
|
109 | + $html .= EEH_HTML::td($type_html, '', 'jst-left'); |
|
110 | + |
|
111 | + // Date column |
|
112 | + $datetime_content = ''; |
|
113 | + if ($line_item_related_object instanceof EE_Ticket) { |
|
114 | + $datetimes = $line_item_related_object->datetimes(); |
|
115 | + foreach ($datetimes as $datetime) { |
|
116 | + if ($datetime instanceof EE_Datetime) { |
|
117 | + $datetime_content .= $datetime->get_dtt_display_name() . '<br>'; |
|
118 | + } |
|
119 | + } |
|
120 | + } |
|
121 | + $html .= EEH_HTML::td($datetime_content, '', 'jst-left'); |
|
122 | + |
|
123 | + // Amount Column |
|
124 | + if ($line_item->is_percent()) { |
|
125 | + $html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght'); |
|
126 | + } else { |
|
127 | + $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght'); |
|
128 | + } |
|
129 | + |
|
130 | + |
|
131 | + // finish things off and return |
|
132 | + $html .= EEH_HTML::trx(); |
|
133 | + return $html; |
|
134 | + } |
|
135 | + |
|
136 | + |
|
137 | + |
|
138 | + /** |
|
139 | + * _tax_row |
|
140 | + * |
|
141 | + * @param EE_Line_Item $line_item |
|
142 | + * @param array $options |
|
143 | + * @return mixed |
|
144 | + */ |
|
145 | + protected function _tax_row(EE_Line_Item $line_item, $options = array()) |
|
146 | + { |
|
147 | + // start of row |
|
148 | + $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr'); |
|
149 | + // name th |
|
150 | + $html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="3"'); |
|
151 | + // total th |
|
152 | + $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
153 | + // end of row |
|
154 | + $html .= EEH_HTML::trx(); |
|
155 | + return $html; |
|
156 | + } |
|
157 | + |
|
158 | + |
|
159 | + |
|
160 | + |
|
161 | + |
|
162 | + /** |
|
163 | + * _total_row |
|
164 | + * |
|
165 | + * @param EE_Line_Item $line_item |
|
166 | + * @param array $options |
|
167 | + * @return mixed |
|
168 | + */ |
|
169 | + protected function _total_row(EE_Line_Item $line_item, $options = array()) |
|
170 | + { |
|
171 | + |
|
172 | + $registration = isset($options['EE_Registration']) ? $options['EE_Registration'] : null; |
|
173 | + $registration_total = $registration instanceof EE_Registration ? $registration->pretty_final_price() : 0; |
|
174 | + // if no valid registration object then we're not going to show the approximate text. |
|
175 | + $total_match = $registration instanceof EE_Registration |
|
176 | + ? $registration->final_price() === $line_item->total() |
|
177 | + : true; |
|
178 | + |
|
179 | + // start of row |
|
180 | + $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr'); |
|
181 | + // Total th label |
|
182 | + if ($total_match) { |
|
183 | + $total_label = sprintf(esc_html__('This registration\'s total %s:', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')'); |
|
184 | + } else { |
|
185 | + $total_label = sprintf(esc_html__('This registration\'s approximate total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')'); |
|
186 | + $total_label .= '<br>'; |
|
187 | + $total_label .= '<p class="ee-footnote-text">' |
|
188 | + . sprintf( |
|
189 | + esc_html__('The registrations\' share of the transaction total is approximate because it might not be possible to evenly divide the transaction total among each registration, and so some registrations may need to pay a penny more than others. This registration\'s final share is actually %1$s%2$s%3$s.', 'event_espresso'), |
|
190 | + '<strong>', |
|
191 | + $registration_total, |
|
192 | + '</strong>' |
|
193 | + ) |
|
194 | + . '</p>'; |
|
195 | + } |
|
196 | + $html .= EEH_HTML::th($total_label, '', 'jst-rght', '', ' colspan="3"'); |
|
197 | + // total th |
|
198 | + |
|
199 | + $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
|
200 | + // end of row |
|
201 | + $html .= EEH_HTML::trx(); |
|
202 | + return $html; |
|
203 | + } |
|
204 | 204 | } |
@@ -72,22 +72,22 @@ discard block |
||
72 | 72 | |
73 | 73 | $name_html = $line_item_related_object instanceof EEI_Line_Item_Object |
74 | 74 | ? $line_item_related_object->name() : $line_item->name(); |
75 | - $name_html = $name_link ? '<a href="' . $name_link . '">' . $name_html . '</a>' |
|
75 | + $name_html = $name_link ? '<a href="'.$name_link.'">'.$name_html.'</a>' |
|
76 | 76 | : $name_html; |
77 | 77 | $name_html .= $line_item->is_taxable() ? ' *' : ''; |
78 | 78 | // maybe preface with icon? |
79 | 79 | $name_html = $line_item_related_object instanceof EEI_Has_Icon |
80 | - ? $line_item_related_object->get_icon() . $name_html |
|
80 | + ? $line_item_related_object->get_icon().$name_html |
|
81 | 81 | : $name_html; |
82 | - $name_html = '<span class="ee-line-item-name linked">' . $name_html . '</span><br>'; |
|
83 | - $name_html .= sprintf( |
|
82 | + $name_html = '<span class="ee-line-item-name linked">'.$name_html.'</span><br>'; |
|
83 | + $name_html .= sprintf( |
|
84 | 84 | _x('%1$sfor the %2$s: %3$s%4$s', 'eg. "for the Event: My Cool Event"', 'event_espresso'), |
85 | 85 | '<span class="ee-line-item-related-parent-object">', |
86 | 86 | $line_item->parent() instanceof EE_Line_Item |
87 | 87 | ? $line_item->parent()->OBJ_type_i18n() |
88 | 88 | : esc_html__('Item:', 'event_espresso'), |
89 | 89 | $parent_related_object_link |
90 | - ? '<a href="' . $parent_related_object_link . '">' . $parent_related_object_name . '</a>' |
|
90 | + ? '<a href="'.$parent_related_object_link.'">'.$parent_related_object_name.'</a>' |
|
91 | 91 | : $parent_related_object_name, |
92 | 92 | '</span>' |
93 | 93 | ); |
@@ -105,7 +105,7 @@ discard block |
||
105 | 105 | $type_html .= $this->_get_cancellations($line_item); |
106 | 106 | $type_html .= $line_item->OBJ_type() ? '<br />' : ''; |
107 | 107 | $code = $line_item_related_object instanceof EEI_Has_Code ? $line_item_related_object->code() : ''; |
108 | - $type_html .= ! empty($code) ? '<span class="ee-line-item-id">' . sprintf(esc_html__('Code: %s', 'event_espresso'), $code) . '</span>' : ''; |
|
108 | + $type_html .= ! empty($code) ? '<span class="ee-line-item-id">'.sprintf(esc_html__('Code: %s', 'event_espresso'), $code).'</span>' : ''; |
|
109 | 109 | $html .= EEH_HTML::td($type_html, '', 'jst-left'); |
110 | 110 | |
111 | 111 | // Date column |
@@ -114,7 +114,7 @@ discard block |
||
114 | 114 | $datetimes = $line_item_related_object->datetimes(); |
115 | 115 | foreach ($datetimes as $datetime) { |
116 | 116 | if ($datetime instanceof EE_Datetime) { |
117 | - $datetime_content .= $datetime->get_dtt_display_name() . '<br>'; |
|
117 | + $datetime_content .= $datetime->get_dtt_display_name().'<br>'; |
|
118 | 118 | } |
119 | 119 | } |
120 | 120 | } |
@@ -122,7 +122,7 @@ discard block |
||
122 | 122 | |
123 | 123 | // Amount Column |
124 | 124 | if ($line_item->is_percent()) { |
125 | - $html .= EEH_HTML::td($line_item->percent() . '%', '', 'jst-rght'); |
|
125 | + $html .= EEH_HTML::td($line_item->percent().'%', '', 'jst-rght'); |
|
126 | 126 | } else { |
127 | 127 | $html .= EEH_HTML::td($line_item->unit_price_no_code(), '', 'jst-rght'); |
128 | 128 | } |
@@ -147,7 +147,7 @@ discard block |
||
147 | 147 | // start of row |
148 | 148 | $html = EEH_HTML::tr('', 'admin-primary-mbox-taxes-tr'); |
149 | 149 | // name th |
150 | - $html .= EEH_HTML::th($line_item->name() . '(' . $line_item->get_pretty('LIN_percent') . '%)', '', 'jst-rght', '', ' colspan="3"'); |
|
150 | + $html .= EEH_HTML::th($line_item->name().'('.$line_item->get_pretty('LIN_percent').'%)', '', 'jst-rght', '', ' colspan="3"'); |
|
151 | 151 | // total th |
152 | 152 | $html .= EEH_HTML::th(EEH_Template::format_currency($line_item->total(), false, false), '', 'jst-rght'); |
153 | 153 | // end of row |
@@ -180,9 +180,9 @@ discard block |
||
180 | 180 | $html = EEH_HTML::tr('', '', 'admin-primary-mbox-total-tr'); |
181 | 181 | // Total th label |
182 | 182 | if ($total_match) { |
183 | - $total_label = sprintf(esc_html__('This registration\'s total %s:', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')'); |
|
183 | + $total_label = sprintf(esc_html__('This registration\'s total %s:', 'event_espresso'), '('.EE_Registry::instance()->CFG->currency->code.')'); |
|
184 | 184 | } else { |
185 | - $total_label = sprintf(esc_html__('This registration\'s approximate total %s', 'event_espresso'), '(' . EE_Registry::instance()->CFG->currency->code . ')'); |
|
185 | + $total_label = sprintf(esc_html__('This registration\'s approximate total %s', 'event_espresso'), '('.EE_Registry::instance()->CFG->currency->code.')'); |
|
186 | 186 | $total_label .= '<br>'; |
187 | 187 | $total_label .= '<p class="ee-footnote-text">' |
188 | 188 | . sprintf( |