@@ -14,172 +14,172 @@ |
||
14 | 14 | */ |
15 | 15 | abstract class EES_Shortcode extends EE_Base |
16 | 16 | { |
17 | - /** |
|
18 | - * @protected public |
|
19 | - * @var array $_attributes |
|
20 | - */ |
|
21 | - protected $_attributes = []; |
|
22 | - |
|
23 | - |
|
24 | - /** |
|
25 | - * class constructor - should ONLY be instantiated by EE_Front_Controller |
|
26 | - */ |
|
27 | - final public function __construct() |
|
28 | - { |
|
29 | - $shortcode = LegacyShortcodesManager::generateShortcodeTagFromClassName(get_class($this)); |
|
30 | - // assign shortcode to the preferred callback, which overwrites the "fallback shortcode processor" assigned earlier |
|
31 | - add_shortcode($shortcode, [$this, 'process_shortcode']); |
|
32 | - // make sure system knows this is an EE page |
|
33 | - /** @var CurrentPage $current_page */ |
|
34 | - $current_page = LoaderFactory::getLoader()->getShared(CurrentPage::class); |
|
35 | - $current_page->setEspressoPage(true); |
|
36 | - } |
|
37 | - |
|
38 | - |
|
39 | - /** |
|
40 | - * run - initial shortcode module setup called during "parse_request" hook by |
|
41 | - * \EE_Front_Controller::_initialize_shortcodes() IF this shortcode is going to execute during this request ! |
|
42 | - * It may also get called by \EES_Shortcode::fallback_shortcode_processor() if the shortcode is being implemented |
|
43 | - * by a theme or plugin in a non-standard way. |
|
44 | - * Basically this method is primarily used for loading resources and assets like CSS or JS |
|
45 | - * that will be required by the shortcode when it is actually processed. |
|
46 | - * Please note that assets may not load if the fallback_shortcode_processor() is being used. |
|
47 | - * |
|
48 | - * @param WP $WP |
|
49 | - * @return void |
|
50 | - */ |
|
51 | - abstract public function run(WP $WP); |
|
52 | - |
|
53 | - |
|
54 | - /** |
|
55 | - * process_shortcode |
|
56 | - * this method is the callback function for the actual shortcode, and is what runs when WP encounters the |
|
57 | - * shortcode within the_content |
|
58 | - * |
|
59 | - * @param array|string $attributes |
|
60 | - * @return mixed |
|
61 | - */ |
|
62 | - abstract public function process_shortcode($attributes = []); |
|
63 | - |
|
64 | - |
|
65 | - /** |
|
66 | - * instance - returns instance of child class object |
|
67 | - * |
|
68 | - * @param string|null $shortcode_class |
|
69 | - * @return EES_Shortcode |
|
70 | - */ |
|
71 | - final public static function instance(string $shortcode_class = ''): ?EES_Shortcode |
|
72 | - { |
|
73 | - $shortcode_class = ! empty($shortcode_class) ? $shortcode_class : get_called_class(); |
|
74 | - if ($shortcode_class === 'EES_Shortcode' || empty($shortcode_class)) { |
|
75 | - return null; |
|
76 | - } |
|
77 | - $shortcode = LegacyShortcodesManager::generateShortcodeTagFromClassName($shortcode_class); |
|
78 | - $shortcode_obj = isset(EE_Registry::instance()->shortcodes->{$shortcode}) |
|
79 | - ? EE_Registry::instance()->shortcodes->{$shortcode} |
|
80 | - : null; |
|
81 | - return $shortcode_obj instanceof $shortcode_class || $shortcode_class === 'self' |
|
82 | - ? $shortcode_obj |
|
83 | - : new $shortcode_class(); |
|
84 | - } |
|
85 | - |
|
86 | - |
|
87 | - /** |
|
88 | - * fallback_shortcode_processor - create instance and call process_shortcode |
|
89 | - * NOTE: shortcode may not function perfectly dues to missing assets, but it's better than not having things |
|
90 | - * work at all |
|
91 | - * |
|
92 | - * @param array|string $attributes |
|
93 | - * @return mixed |
|
94 | - */ |
|
95 | - final public static function fallback_shortcode_processor($attributes = null) |
|
96 | - { |
|
97 | - if (EE_Maintenance_Mode::disable_frontend_for_maintenance()) { |
|
98 | - return null; |
|
99 | - } |
|
100 | - // what shortcode was actually parsed ? |
|
101 | - $shortcode_class = get_called_class(); |
|
102 | - // notify rest of system that fallback processor was triggered |
|
103 | - add_filter('FHEE__fallback_shortcode_processor__' . $shortcode_class, '__return_true'); |
|
104 | - // get instance of actual shortcode |
|
105 | - $shortcode_obj = self::instance($shortcode_class); |
|
106 | - // verify class |
|
107 | - if ($shortcode_obj instanceof EES_Shortcode) { |
|
108 | - global $wp; |
|
109 | - $shortcode_obj->run($wp); |
|
110 | - // set attributes and run the shortcode |
|
111 | - $shortcode_obj->_attributes = (array) $attributes; |
|
112 | - return $shortcode_obj->process_shortcode($shortcode_obj->_attributes); |
|
113 | - } |
|
114 | - return null; |
|
115 | - } |
|
116 | - |
|
117 | - |
|
118 | - /** |
|
119 | - * invalid_shortcode_processor - used in cases where we know the shortcode is invalid, most likely due to a |
|
120 | - * deactivated addon, and simply returns an empty string |
|
121 | - * |
|
122 | - * @param $attributes |
|
123 | - * @return string |
|
124 | - */ |
|
125 | - final public static function invalid_shortcode_processor($attributes): string |
|
126 | - { |
|
127 | - return ''; |
|
128 | - } |
|
129 | - |
|
130 | - |
|
131 | - /** |
|
132 | - * Performs basic sanitization on shortcode attributes |
|
133 | - * Since incoming attributes from the shortcode usage in the WP editor will all be strings, |
|
134 | - * most attributes will by default be sanitized using the sanitize_text_field() function. |
|
135 | - * This can be overridden by supplying an array for the $custom_sanitization param, |
|
136 | - * where keys match keys in your attributes array, |
|
137 | - * and values represent the sanitization function you wish to be applied to that attribute. |
|
138 | - * So for example, if you had an integer attribute named "event_id" |
|
139 | - * that you wanted to be sanitized using absint(), |
|
140 | - * then you would pass the following for your $custom_sanitization array: |
|
141 | - * array('event_id' => 'absint') |
|
142 | - * all other attributes would be sanitized using the defaults in the switch statement below |
|
143 | - * |
|
144 | - * @param array $attributes |
|
145 | - * @param array $custom_sanitization |
|
146 | - * @return array |
|
147 | - */ |
|
148 | - public static function sanitize_attributes(array $attributes, array $custom_sanitization = []): array |
|
149 | - { |
|
150 | - foreach ($attributes as $key => $value) { |
|
151 | - // is a custom sanitization callback specified ? |
|
152 | - if (isset($custom_sanitization[ $key ])) { |
|
153 | - $callback = $custom_sanitization[ $key ]; |
|
154 | - if ($callback === 'skip_sanitization') { |
|
155 | - $attributes[ $key ] = $value; |
|
156 | - continue; |
|
157 | - } elseif (function_exists($callback)) { |
|
158 | - $attributes[ $key ] = $callback($value); |
|
159 | - continue; |
|
160 | - } |
|
161 | - } |
|
162 | - switch (true) { |
|
163 | - case $value === null: |
|
164 | - case is_int($value): |
|
165 | - case is_float($value): |
|
166 | - // typical booleans |
|
167 | - case in_array($value, [true, 'true', '1', 'on', 'yes', false, 'false', '0', 'off', 'no'], true): |
|
168 | - $attributes[ $key ] = $value; |
|
169 | - break; |
|
170 | - case is_string($value): |
|
171 | - $attributes[ $key ] = sanitize_text_field($value); |
|
172 | - break; |
|
173 | - case is_array($value): |
|
174 | - $attributes[ $key ] = EES_Shortcode::sanitize_attributes($value); |
|
175 | - break; |
|
176 | - default: |
|
177 | - // only remaining data types are Object and Resource |
|
178 | - // which are not allowed as shortcode attributes |
|
179 | - $attributes[ $key ] = null; |
|
180 | - break; |
|
181 | - } |
|
182 | - } |
|
183 | - return $attributes; |
|
184 | - } |
|
17 | + /** |
|
18 | + * @protected public |
|
19 | + * @var array $_attributes |
|
20 | + */ |
|
21 | + protected $_attributes = []; |
|
22 | + |
|
23 | + |
|
24 | + /** |
|
25 | + * class constructor - should ONLY be instantiated by EE_Front_Controller |
|
26 | + */ |
|
27 | + final public function __construct() |
|
28 | + { |
|
29 | + $shortcode = LegacyShortcodesManager::generateShortcodeTagFromClassName(get_class($this)); |
|
30 | + // assign shortcode to the preferred callback, which overwrites the "fallback shortcode processor" assigned earlier |
|
31 | + add_shortcode($shortcode, [$this, 'process_shortcode']); |
|
32 | + // make sure system knows this is an EE page |
|
33 | + /** @var CurrentPage $current_page */ |
|
34 | + $current_page = LoaderFactory::getLoader()->getShared(CurrentPage::class); |
|
35 | + $current_page->setEspressoPage(true); |
|
36 | + } |
|
37 | + |
|
38 | + |
|
39 | + /** |
|
40 | + * run - initial shortcode module setup called during "parse_request" hook by |
|
41 | + * \EE_Front_Controller::_initialize_shortcodes() IF this shortcode is going to execute during this request ! |
|
42 | + * It may also get called by \EES_Shortcode::fallback_shortcode_processor() if the shortcode is being implemented |
|
43 | + * by a theme or plugin in a non-standard way. |
|
44 | + * Basically this method is primarily used for loading resources and assets like CSS or JS |
|
45 | + * that will be required by the shortcode when it is actually processed. |
|
46 | + * Please note that assets may not load if the fallback_shortcode_processor() is being used. |
|
47 | + * |
|
48 | + * @param WP $WP |
|
49 | + * @return void |
|
50 | + */ |
|
51 | + abstract public function run(WP $WP); |
|
52 | + |
|
53 | + |
|
54 | + /** |
|
55 | + * process_shortcode |
|
56 | + * this method is the callback function for the actual shortcode, and is what runs when WP encounters the |
|
57 | + * shortcode within the_content |
|
58 | + * |
|
59 | + * @param array|string $attributes |
|
60 | + * @return mixed |
|
61 | + */ |
|
62 | + abstract public function process_shortcode($attributes = []); |
|
63 | + |
|
64 | + |
|
65 | + /** |
|
66 | + * instance - returns instance of child class object |
|
67 | + * |
|
68 | + * @param string|null $shortcode_class |
|
69 | + * @return EES_Shortcode |
|
70 | + */ |
|
71 | + final public static function instance(string $shortcode_class = ''): ?EES_Shortcode |
|
72 | + { |
|
73 | + $shortcode_class = ! empty($shortcode_class) ? $shortcode_class : get_called_class(); |
|
74 | + if ($shortcode_class === 'EES_Shortcode' || empty($shortcode_class)) { |
|
75 | + return null; |
|
76 | + } |
|
77 | + $shortcode = LegacyShortcodesManager::generateShortcodeTagFromClassName($shortcode_class); |
|
78 | + $shortcode_obj = isset(EE_Registry::instance()->shortcodes->{$shortcode}) |
|
79 | + ? EE_Registry::instance()->shortcodes->{$shortcode} |
|
80 | + : null; |
|
81 | + return $shortcode_obj instanceof $shortcode_class || $shortcode_class === 'self' |
|
82 | + ? $shortcode_obj |
|
83 | + : new $shortcode_class(); |
|
84 | + } |
|
85 | + |
|
86 | + |
|
87 | + /** |
|
88 | + * fallback_shortcode_processor - create instance and call process_shortcode |
|
89 | + * NOTE: shortcode may not function perfectly dues to missing assets, but it's better than not having things |
|
90 | + * work at all |
|
91 | + * |
|
92 | + * @param array|string $attributes |
|
93 | + * @return mixed |
|
94 | + */ |
|
95 | + final public static function fallback_shortcode_processor($attributes = null) |
|
96 | + { |
|
97 | + if (EE_Maintenance_Mode::disable_frontend_for_maintenance()) { |
|
98 | + return null; |
|
99 | + } |
|
100 | + // what shortcode was actually parsed ? |
|
101 | + $shortcode_class = get_called_class(); |
|
102 | + // notify rest of system that fallback processor was triggered |
|
103 | + add_filter('FHEE__fallback_shortcode_processor__' . $shortcode_class, '__return_true'); |
|
104 | + // get instance of actual shortcode |
|
105 | + $shortcode_obj = self::instance($shortcode_class); |
|
106 | + // verify class |
|
107 | + if ($shortcode_obj instanceof EES_Shortcode) { |
|
108 | + global $wp; |
|
109 | + $shortcode_obj->run($wp); |
|
110 | + // set attributes and run the shortcode |
|
111 | + $shortcode_obj->_attributes = (array) $attributes; |
|
112 | + return $shortcode_obj->process_shortcode($shortcode_obj->_attributes); |
|
113 | + } |
|
114 | + return null; |
|
115 | + } |
|
116 | + |
|
117 | + |
|
118 | + /** |
|
119 | + * invalid_shortcode_processor - used in cases where we know the shortcode is invalid, most likely due to a |
|
120 | + * deactivated addon, and simply returns an empty string |
|
121 | + * |
|
122 | + * @param $attributes |
|
123 | + * @return string |
|
124 | + */ |
|
125 | + final public static function invalid_shortcode_processor($attributes): string |
|
126 | + { |
|
127 | + return ''; |
|
128 | + } |
|
129 | + |
|
130 | + |
|
131 | + /** |
|
132 | + * Performs basic sanitization on shortcode attributes |
|
133 | + * Since incoming attributes from the shortcode usage in the WP editor will all be strings, |
|
134 | + * most attributes will by default be sanitized using the sanitize_text_field() function. |
|
135 | + * This can be overridden by supplying an array for the $custom_sanitization param, |
|
136 | + * where keys match keys in your attributes array, |
|
137 | + * and values represent the sanitization function you wish to be applied to that attribute. |
|
138 | + * So for example, if you had an integer attribute named "event_id" |
|
139 | + * that you wanted to be sanitized using absint(), |
|
140 | + * then you would pass the following for your $custom_sanitization array: |
|
141 | + * array('event_id' => 'absint') |
|
142 | + * all other attributes would be sanitized using the defaults in the switch statement below |
|
143 | + * |
|
144 | + * @param array $attributes |
|
145 | + * @param array $custom_sanitization |
|
146 | + * @return array |
|
147 | + */ |
|
148 | + public static function sanitize_attributes(array $attributes, array $custom_sanitization = []): array |
|
149 | + { |
|
150 | + foreach ($attributes as $key => $value) { |
|
151 | + // is a custom sanitization callback specified ? |
|
152 | + if (isset($custom_sanitization[ $key ])) { |
|
153 | + $callback = $custom_sanitization[ $key ]; |
|
154 | + if ($callback === 'skip_sanitization') { |
|
155 | + $attributes[ $key ] = $value; |
|
156 | + continue; |
|
157 | + } elseif (function_exists($callback)) { |
|
158 | + $attributes[ $key ] = $callback($value); |
|
159 | + continue; |
|
160 | + } |
|
161 | + } |
|
162 | + switch (true) { |
|
163 | + case $value === null: |
|
164 | + case is_int($value): |
|
165 | + case is_float($value): |
|
166 | + // typical booleans |
|
167 | + case in_array($value, [true, 'true', '1', 'on', 'yes', false, 'false', '0', 'off', 'no'], true): |
|
168 | + $attributes[ $key ] = $value; |
|
169 | + break; |
|
170 | + case is_string($value): |
|
171 | + $attributes[ $key ] = sanitize_text_field($value); |
|
172 | + break; |
|
173 | + case is_array($value): |
|
174 | + $attributes[ $key ] = EES_Shortcode::sanitize_attributes($value); |
|
175 | + break; |
|
176 | + default: |
|
177 | + // only remaining data types are Object and Resource |
|
178 | + // which are not allowed as shortcode attributes |
|
179 | + $attributes[ $key ] = null; |
|
180 | + break; |
|
181 | + } |
|
182 | + } |
|
183 | + return $attributes; |
|
184 | + } |
|
185 | 185 | } |
@@ -18,146 +18,146 @@ |
||
18 | 18 | */ |
19 | 19 | class FqcnLocator extends Locator |
20 | 20 | { |
21 | - protected array $FQCNs = []; |
|
22 | - |
|
23 | - protected array $namespaces = []; |
|
24 | - |
|
25 | - |
|
26 | - /** |
|
27 | - * @param string|null $namespace |
|
28 | - * @param string|null $namespace_base_dir |
|
29 | - */ |
|
30 | - protected function setNamespace(?string $namespace, ?string $namespace_base_dir) |
|
31 | - { |
|
32 | - if (! is_string($namespace)) { |
|
33 | - throw new InvalidDataTypeException('$namespace', $namespace, 'string'); |
|
34 | - } |
|
35 | - if (! is_string($namespace_base_dir)) { |
|
36 | - throw new InvalidDataTypeException('$namespace_base_dir', $namespace_base_dir, 'string'); |
|
37 | - } |
|
38 | - $this->namespaces[ $namespace ] = $namespace_base_dir; |
|
39 | - } |
|
40 | - |
|
41 | - |
|
42 | - /** |
|
43 | - * @return array |
|
44 | - */ |
|
45 | - public function getFQCNs(): array |
|
46 | - { |
|
47 | - return $this->FQCNs; |
|
48 | - } |
|
49 | - |
|
50 | - |
|
51 | - /** |
|
52 | - * @return int |
|
53 | - */ |
|
54 | - public function count(): int |
|
55 | - { |
|
56 | - return count($this->FQCNs); |
|
57 | - } |
|
58 | - |
|
59 | - |
|
60 | - /** |
|
61 | - * given a valid namespace, will find all files that match the provided mask |
|
62 | - * |
|
63 | - * @param string|array $namespaces |
|
64 | - * @return array |
|
65 | - * @throws InvalidClassException |
|
66 | - * @throws InvalidDataTypeException |
|
67 | - * @throws EE_Error |
|
68 | - */ |
|
69 | - public function locate($namespaces): array |
|
70 | - { |
|
71 | - if (! (is_string($namespaces) || is_array($namespaces))) { |
|
72 | - throw new InvalidDataTypeException('$namespaces', $namespaces, 'string or array'); |
|
73 | - } |
|
74 | - foreach ((array) $namespaces as $namespace) { |
|
75 | - foreach ($this->findFQCNsByNamespace($namespace) as $key => $file) { |
|
76 | - $this->FQCNs[ $key ] = $file; |
|
77 | - } |
|
78 | - } |
|
79 | - return $this->FQCNs; |
|
80 | - } |
|
81 | - |
|
82 | - |
|
83 | - /** |
|
84 | - * given a partial namespace, will find all files in that folder |
|
85 | - * ** PLZ NOTE ** |
|
86 | - * This assumes that all files within the specified folder should be loaded |
|
87 | - * |
|
88 | - * @param string $partial_namespace |
|
89 | - * @return array |
|
90 | - * @throws InvalidClassException |
|
91 | - * @throws InvalidDataTypeException |
|
92 | - * @throws EE_Error |
|
93 | - */ |
|
94 | - protected function findFQCNsByNamespace(string $partial_namespace): array |
|
95 | - { |
|
96 | - $iterator = new FilesystemIterator( |
|
97 | - $this->getDirectoryFromPartialNamespace($partial_namespace) |
|
98 | - ); |
|
99 | - $iterator->setFlags(FilesystemIterator::CURRENT_AS_FILEINFO); |
|
100 | - $iterator->setFlags(FilesystemIterator::UNIX_PATHS); |
|
101 | - if (iterator_count($iterator) === 0) { |
|
102 | - return []; |
|
103 | - } |
|
104 | - foreach ($iterator as $file) { |
|
105 | - if ($file->isFile() && $file->getExtension() === 'php') { |
|
106 | - $file = $file->getPath() . '/' . $file->getBasename('.php'); |
|
107 | - foreach ($this->namespaces as $namespace => $base_dir) { |
|
108 | - $namespace .= Psr4Autoloader::NS; |
|
109 | - if (strpos($file, $base_dir) === 0) { |
|
110 | - $this->FQCNs[] = Psr4Autoloader::NS . str_replace( |
|
111 | - [$base_dir, '/'], |
|
112 | - [$namespace, Psr4Autoloader::NS], |
|
113 | - $file |
|
114 | - ); |
|
115 | - } |
|
116 | - } |
|
117 | - } |
|
118 | - } |
|
119 | - return $this->FQCNs; |
|
120 | - } |
|
121 | - |
|
122 | - |
|
123 | - /** |
|
124 | - * getDirectoryFromPartialNamespace |
|
125 | - * |
|
126 | - * @param string $partial_namespace almost fully qualified class name ? |
|
127 | - * @return string |
|
128 | - * @throws InvalidDataTypeException |
|
129 | - * @throws InvalidClassException |
|
130 | - * @throws EE_Error |
|
131 | - */ |
|
132 | - protected function getDirectoryFromPartialNamespace(string $partial_namespace): string |
|
133 | - { |
|
134 | - if (empty($partial_namespace)) { |
|
135 | - throw new InvalidClassException($partial_namespace); |
|
136 | - } |
|
137 | - // load our PSR-4 Autoloader so we can get the list of registered namespaces from it |
|
138 | - $psr4_loader = EE_Psr4AutoloaderInit::psr4_loader(); |
|
139 | - // breakup the incoming namespace into segments so we can loop thru them |
|
140 | - $namespace_segments = explode(Psr4Autoloader::NS, trim($partial_namespace, Psr4Autoloader::NS)); |
|
141 | - // we're only interested in the Vendor and secondary base, so pull those from the array |
|
142 | - $vendor_base = array_slice($namespace_segments, 0, 2); |
|
143 | - $namespace = $prefix = null; |
|
144 | - while (! empty($vendor_base)) { |
|
145 | - $namespace = implode(Psr4Autoloader::NS, $vendor_base); |
|
146 | - // check if there's a base directory registered for that namespace |
|
147 | - $prefix = $psr4_loader->prefixes($namespace . Psr4Autoloader::NS); |
|
148 | - if (! empty($prefix) && ! empty($prefix[0])) { |
|
149 | - // found one! |
|
150 | - break; |
|
151 | - } |
|
152 | - // remove base and try vendor only portion of namespace |
|
153 | - array_pop($vendor_base); |
|
154 | - } |
|
155 | - // nope? then the incoming namespace is invalid |
|
156 | - if (empty($prefix) || empty($prefix[0])) { |
|
157 | - throw new InvalidClassException($partial_namespace); |
|
158 | - } |
|
159 | - $this->setNamespace($namespace, $prefix[0]); |
|
160 | - // but if it's good, add that base directory to the rest of the path, and return it |
|
161 | - return $prefix[0] . implode('/', array_diff($namespace_segments, $vendor_base)) . '/'; |
|
162 | - } |
|
21 | + protected array $FQCNs = []; |
|
22 | + |
|
23 | + protected array $namespaces = []; |
|
24 | + |
|
25 | + |
|
26 | + /** |
|
27 | + * @param string|null $namespace |
|
28 | + * @param string|null $namespace_base_dir |
|
29 | + */ |
|
30 | + protected function setNamespace(?string $namespace, ?string $namespace_base_dir) |
|
31 | + { |
|
32 | + if (! is_string($namespace)) { |
|
33 | + throw new InvalidDataTypeException('$namespace', $namespace, 'string'); |
|
34 | + } |
|
35 | + if (! is_string($namespace_base_dir)) { |
|
36 | + throw new InvalidDataTypeException('$namespace_base_dir', $namespace_base_dir, 'string'); |
|
37 | + } |
|
38 | + $this->namespaces[ $namespace ] = $namespace_base_dir; |
|
39 | + } |
|
40 | + |
|
41 | + |
|
42 | + /** |
|
43 | + * @return array |
|
44 | + */ |
|
45 | + public function getFQCNs(): array |
|
46 | + { |
|
47 | + return $this->FQCNs; |
|
48 | + } |
|
49 | + |
|
50 | + |
|
51 | + /** |
|
52 | + * @return int |
|
53 | + */ |
|
54 | + public function count(): int |
|
55 | + { |
|
56 | + return count($this->FQCNs); |
|
57 | + } |
|
58 | + |
|
59 | + |
|
60 | + /** |
|
61 | + * given a valid namespace, will find all files that match the provided mask |
|
62 | + * |
|
63 | + * @param string|array $namespaces |
|
64 | + * @return array |
|
65 | + * @throws InvalidClassException |
|
66 | + * @throws InvalidDataTypeException |
|
67 | + * @throws EE_Error |
|
68 | + */ |
|
69 | + public function locate($namespaces): array |
|
70 | + { |
|
71 | + if (! (is_string($namespaces) || is_array($namespaces))) { |
|
72 | + throw new InvalidDataTypeException('$namespaces', $namespaces, 'string or array'); |
|
73 | + } |
|
74 | + foreach ((array) $namespaces as $namespace) { |
|
75 | + foreach ($this->findFQCNsByNamespace($namespace) as $key => $file) { |
|
76 | + $this->FQCNs[ $key ] = $file; |
|
77 | + } |
|
78 | + } |
|
79 | + return $this->FQCNs; |
|
80 | + } |
|
81 | + |
|
82 | + |
|
83 | + /** |
|
84 | + * given a partial namespace, will find all files in that folder |
|
85 | + * ** PLZ NOTE ** |
|
86 | + * This assumes that all files within the specified folder should be loaded |
|
87 | + * |
|
88 | + * @param string $partial_namespace |
|
89 | + * @return array |
|
90 | + * @throws InvalidClassException |
|
91 | + * @throws InvalidDataTypeException |
|
92 | + * @throws EE_Error |
|
93 | + */ |
|
94 | + protected function findFQCNsByNamespace(string $partial_namespace): array |
|
95 | + { |
|
96 | + $iterator = new FilesystemIterator( |
|
97 | + $this->getDirectoryFromPartialNamespace($partial_namespace) |
|
98 | + ); |
|
99 | + $iterator->setFlags(FilesystemIterator::CURRENT_AS_FILEINFO); |
|
100 | + $iterator->setFlags(FilesystemIterator::UNIX_PATHS); |
|
101 | + if (iterator_count($iterator) === 0) { |
|
102 | + return []; |
|
103 | + } |
|
104 | + foreach ($iterator as $file) { |
|
105 | + if ($file->isFile() && $file->getExtension() === 'php') { |
|
106 | + $file = $file->getPath() . '/' . $file->getBasename('.php'); |
|
107 | + foreach ($this->namespaces as $namespace => $base_dir) { |
|
108 | + $namespace .= Psr4Autoloader::NS; |
|
109 | + if (strpos($file, $base_dir) === 0) { |
|
110 | + $this->FQCNs[] = Psr4Autoloader::NS . str_replace( |
|
111 | + [$base_dir, '/'], |
|
112 | + [$namespace, Psr4Autoloader::NS], |
|
113 | + $file |
|
114 | + ); |
|
115 | + } |
|
116 | + } |
|
117 | + } |
|
118 | + } |
|
119 | + return $this->FQCNs; |
|
120 | + } |
|
121 | + |
|
122 | + |
|
123 | + /** |
|
124 | + * getDirectoryFromPartialNamespace |
|
125 | + * |
|
126 | + * @param string $partial_namespace almost fully qualified class name ? |
|
127 | + * @return string |
|
128 | + * @throws InvalidDataTypeException |
|
129 | + * @throws InvalidClassException |
|
130 | + * @throws EE_Error |
|
131 | + */ |
|
132 | + protected function getDirectoryFromPartialNamespace(string $partial_namespace): string |
|
133 | + { |
|
134 | + if (empty($partial_namespace)) { |
|
135 | + throw new InvalidClassException($partial_namespace); |
|
136 | + } |
|
137 | + // load our PSR-4 Autoloader so we can get the list of registered namespaces from it |
|
138 | + $psr4_loader = EE_Psr4AutoloaderInit::psr4_loader(); |
|
139 | + // breakup the incoming namespace into segments so we can loop thru them |
|
140 | + $namespace_segments = explode(Psr4Autoloader::NS, trim($partial_namespace, Psr4Autoloader::NS)); |
|
141 | + // we're only interested in the Vendor and secondary base, so pull those from the array |
|
142 | + $vendor_base = array_slice($namespace_segments, 0, 2); |
|
143 | + $namespace = $prefix = null; |
|
144 | + while (! empty($vendor_base)) { |
|
145 | + $namespace = implode(Psr4Autoloader::NS, $vendor_base); |
|
146 | + // check if there's a base directory registered for that namespace |
|
147 | + $prefix = $psr4_loader->prefixes($namespace . Psr4Autoloader::NS); |
|
148 | + if (! empty($prefix) && ! empty($prefix[0])) { |
|
149 | + // found one! |
|
150 | + break; |
|
151 | + } |
|
152 | + // remove base and try vendor only portion of namespace |
|
153 | + array_pop($vendor_base); |
|
154 | + } |
|
155 | + // nope? then the incoming namespace is invalid |
|
156 | + if (empty($prefix) || empty($prefix[0])) { |
|
157 | + throw new InvalidClassException($partial_namespace); |
|
158 | + } |
|
159 | + $this->setNamespace($namespace, $prefix[0]); |
|
160 | + // but if it's good, add that base directory to the rest of the path, and return it |
|
161 | + return $prefix[0] . implode('/', array_diff($namespace_segments, $vendor_base)) . '/'; |
|
162 | + } |
|
163 | 163 | } |
@@ -29,13 +29,13 @@ discard block |
||
29 | 29 | */ |
30 | 30 | protected function setNamespace(?string $namespace, ?string $namespace_base_dir) |
31 | 31 | { |
32 | - if (! is_string($namespace)) { |
|
32 | + if ( ! is_string($namespace)) { |
|
33 | 33 | throw new InvalidDataTypeException('$namespace', $namespace, 'string'); |
34 | 34 | } |
35 | - if (! is_string($namespace_base_dir)) { |
|
35 | + if ( ! is_string($namespace_base_dir)) { |
|
36 | 36 | throw new InvalidDataTypeException('$namespace_base_dir', $namespace_base_dir, 'string'); |
37 | 37 | } |
38 | - $this->namespaces[ $namespace ] = $namespace_base_dir; |
|
38 | + $this->namespaces[$namespace] = $namespace_base_dir; |
|
39 | 39 | } |
40 | 40 | |
41 | 41 | |
@@ -68,12 +68,12 @@ discard block |
||
68 | 68 | */ |
69 | 69 | public function locate($namespaces): array |
70 | 70 | { |
71 | - if (! (is_string($namespaces) || is_array($namespaces))) { |
|
71 | + if ( ! (is_string($namespaces) || is_array($namespaces))) { |
|
72 | 72 | throw new InvalidDataTypeException('$namespaces', $namespaces, 'string or array'); |
73 | 73 | } |
74 | 74 | foreach ((array) $namespaces as $namespace) { |
75 | 75 | foreach ($this->findFQCNsByNamespace($namespace) as $key => $file) { |
76 | - $this->FQCNs[ $key ] = $file; |
|
76 | + $this->FQCNs[$key] = $file; |
|
77 | 77 | } |
78 | 78 | } |
79 | 79 | return $this->FQCNs; |
@@ -103,11 +103,11 @@ discard block |
||
103 | 103 | } |
104 | 104 | foreach ($iterator as $file) { |
105 | 105 | if ($file->isFile() && $file->getExtension() === 'php') { |
106 | - $file = $file->getPath() . '/' . $file->getBasename('.php'); |
|
106 | + $file = $file->getPath().'/'.$file->getBasename('.php'); |
|
107 | 107 | foreach ($this->namespaces as $namespace => $base_dir) { |
108 | 108 | $namespace .= Psr4Autoloader::NS; |
109 | 109 | if (strpos($file, $base_dir) === 0) { |
110 | - $this->FQCNs[] = Psr4Autoloader::NS . str_replace( |
|
110 | + $this->FQCNs[] = Psr4Autoloader::NS.str_replace( |
|
111 | 111 | [$base_dir, '/'], |
112 | 112 | [$namespace, Psr4Autoloader::NS], |
113 | 113 | $file |
@@ -141,11 +141,11 @@ discard block |
||
141 | 141 | // we're only interested in the Vendor and secondary base, so pull those from the array |
142 | 142 | $vendor_base = array_slice($namespace_segments, 0, 2); |
143 | 143 | $namespace = $prefix = null; |
144 | - while (! empty($vendor_base)) { |
|
144 | + while ( ! empty($vendor_base)) { |
|
145 | 145 | $namespace = implode(Psr4Autoloader::NS, $vendor_base); |
146 | 146 | // check if there's a base directory registered for that namespace |
147 | - $prefix = $psr4_loader->prefixes($namespace . Psr4Autoloader::NS); |
|
148 | - if (! empty($prefix) && ! empty($prefix[0])) { |
|
147 | + $prefix = $psr4_loader->prefixes($namespace.Psr4Autoloader::NS); |
|
148 | + if ( ! empty($prefix) && ! empty($prefix[0])) { |
|
149 | 149 | // found one! |
150 | 150 | break; |
151 | 151 | } |
@@ -158,6 +158,6 @@ discard block |
||
158 | 158 | } |
159 | 159 | $this->setNamespace($namespace, $prefix[0]); |
160 | 160 | // but if it's good, add that base directory to the rest of the path, and return it |
161 | - return $prefix[0] . implode('/', array_diff($namespace_segments, $vendor_base)) . '/'; |
|
161 | + return $prefix[0].implode('/', array_diff($namespace_segments, $vendor_base)).'/'; |
|
162 | 162 | } |
163 | 163 | } |
@@ -18,79 +18,79 @@ |
||
18 | 18 | */ |
19 | 19 | class GraphQLEndpoint extends WordPressOption |
20 | 20 | { |
21 | - const DEFAULT_ENDPOINT = 'graphql'; |
|
21 | + const DEFAULT_ENDPOINT = 'graphql'; |
|
22 | 22 | |
23 | - const OPTION_NAME = 'ee-graphql-endpoint'; |
|
23 | + const OPTION_NAME = 'ee-graphql-endpoint'; |
|
24 | 24 | |
25 | - private bool $is_gql_request = false; |
|
25 | + private bool $is_gql_request = false; |
|
26 | 26 | |
27 | 27 | |
28 | - /** |
|
29 | - * GraphQLEndpoint constructor. |
|
30 | - */ |
|
31 | - public function __construct() |
|
32 | - { |
|
33 | - parent::__construct(GraphQLEndpoint::OPTION_NAME, GraphQLEndpoint::DEFAULT_ENDPOINT, true); |
|
34 | - add_action('graphql_register_settings', [$this, 'verifyAndSetEndpoint'], 20); |
|
35 | - if (! defined('GRAPHQL_DEBUG') || ! GRAPHQL_DEBUG) { |
|
36 | - // disable WPGraphQL admin by default. |
|
37 | - add_filter('graphql_show_admin', '__return_false'); |
|
38 | - add_filter('graphql_enable_graphiql', '__return_false'); |
|
39 | - } |
|
40 | - } |
|
28 | + /** |
|
29 | + * GraphQLEndpoint constructor. |
|
30 | + */ |
|
31 | + public function __construct() |
|
32 | + { |
|
33 | + parent::__construct(GraphQLEndpoint::OPTION_NAME, GraphQLEndpoint::DEFAULT_ENDPOINT, true); |
|
34 | + add_action('graphql_register_settings', [$this, 'verifyAndSetEndpoint'], 20); |
|
35 | + if (! defined('GRAPHQL_DEBUG') || ! GRAPHQL_DEBUG) { |
|
36 | + // disable WPGraphQL admin by default. |
|
37 | + add_filter('graphql_show_admin', '__return_false'); |
|
38 | + add_filter('graphql_enable_graphiql', '__return_false'); |
|
39 | + } |
|
40 | + } |
|
41 | 41 | |
42 | 42 | |
43 | - /** |
|
44 | - * @return false|mixed|void |
|
45 | - */ |
|
46 | - public function getEndpoint() |
|
47 | - { |
|
48 | - return $this->loadOption(); |
|
49 | - } |
|
43 | + /** |
|
44 | + * @return false|mixed|void |
|
45 | + */ |
|
46 | + public function getEndpoint() |
|
47 | + { |
|
48 | + return $this->loadOption(); |
|
49 | + } |
|
50 | 50 | |
51 | 51 | |
52 | - /** |
|
53 | - * @return mixed|void|bool |
|
54 | - */ |
|
55 | - public function isGraphqlRequest() |
|
56 | - { |
|
57 | - if (! isset($this->is_gql_request)) { |
|
58 | - // grab the GQL endpoint that we saved in the future... wait... wut? |
|
59 | - $endpoint = $this->getEndpoint(); |
|
60 | - // set our saved endpoint on the WP GQL Pouter class |
|
61 | - // don't worry, this is a static property that they overwrite when they initialize things, |
|
62 | - // and we are essentially getting the value from them anyways, so it should be ok (fingers crossed) |
|
63 | - Router::$route = $endpoint; |
|
64 | - // now call their function for checking if this is a GQL request |
|
65 | - // because they use a bunch of filters and stuff we don't want to duplicate here |
|
66 | - $this->is_gql_request = Router::is_graphql_http_request(); |
|
67 | - } |
|
68 | - return $this->is_gql_request; |
|
69 | - } |
|
52 | + /** |
|
53 | + * @return mixed|void|bool |
|
54 | + */ |
|
55 | + public function isGraphqlRequest() |
|
56 | + { |
|
57 | + if (! isset($this->is_gql_request)) { |
|
58 | + // grab the GQL endpoint that we saved in the future... wait... wut? |
|
59 | + $endpoint = $this->getEndpoint(); |
|
60 | + // set our saved endpoint on the WP GQL Pouter class |
|
61 | + // don't worry, this is a static property that they overwrite when they initialize things, |
|
62 | + // and we are essentially getting the value from them anyways, so it should be ok (fingers crossed) |
|
63 | + Router::$route = $endpoint; |
|
64 | + // now call their function for checking if this is a GQL request |
|
65 | + // because they use a bunch of filters and stuff we don't want to duplicate here |
|
66 | + $this->is_gql_request = Router::is_graphql_http_request(); |
|
67 | + } |
|
68 | + return $this->is_gql_request; |
|
69 | + } |
|
70 | 70 | |
71 | 71 | |
72 | - /** |
|
73 | - * callback hooked into the graphql_register_settings action |
|
74 | - * basically grabs the value for the 'graphql_endpoint' setting and saves it to our own WP option. |
|
75 | - * i know, i know, i know... |
|
76 | - * WHY are we saving the graphql_endpoint to a WP option if WP GraphQL is already doing the same ?!?! |
|
77 | - * Because we perform our request type detection during `plugins_loaded`, |
|
78 | - * but they don't settle on their endpoint until `after_setup_theme` has run, |
|
79 | - * which is too late for us, so we are just going to save this separately so that we have it. |
|
80 | - * Oh, and this will essentially recheck this value on EVERY request |
|
81 | - * but will only update our saved value if it has actually changed |
|
82 | - */ |
|
83 | - public function verifyAndSetEndpoint() |
|
84 | - { |
|
85 | - try { |
|
86 | - $this->updateOption( |
|
87 | - get_graphql_setting( |
|
88 | - 'graphql_endpoint', |
|
89 | - apply_filters('graphql_endpoint', GraphQLEndpoint::DEFAULT_ENDPOINT) |
|
90 | - ) |
|
91 | - ); |
|
92 | - } catch (Throwable $t) { |
|
93 | - // eat it |
|
94 | - } |
|
95 | - } |
|
72 | + /** |
|
73 | + * callback hooked into the graphql_register_settings action |
|
74 | + * basically grabs the value for the 'graphql_endpoint' setting and saves it to our own WP option. |
|
75 | + * i know, i know, i know... |
|
76 | + * WHY are we saving the graphql_endpoint to a WP option if WP GraphQL is already doing the same ?!?! |
|
77 | + * Because we perform our request type detection during `plugins_loaded`, |
|
78 | + * but they don't settle on their endpoint until `after_setup_theme` has run, |
|
79 | + * which is too late for us, so we are just going to save this separately so that we have it. |
|
80 | + * Oh, and this will essentially recheck this value on EVERY request |
|
81 | + * but will only update our saved value if it has actually changed |
|
82 | + */ |
|
83 | + public function verifyAndSetEndpoint() |
|
84 | + { |
|
85 | + try { |
|
86 | + $this->updateOption( |
|
87 | + get_graphql_setting( |
|
88 | + 'graphql_endpoint', |
|
89 | + apply_filters('graphql_endpoint', GraphQLEndpoint::DEFAULT_ENDPOINT) |
|
90 | + ) |
|
91 | + ); |
|
92 | + } catch (Throwable $t) { |
|
93 | + // eat it |
|
94 | + } |
|
95 | + } |
|
96 | 96 | } |
@@ -32,7 +32,7 @@ discard block |
||
32 | 32 | { |
33 | 33 | parent::__construct(GraphQLEndpoint::OPTION_NAME, GraphQLEndpoint::DEFAULT_ENDPOINT, true); |
34 | 34 | add_action('graphql_register_settings', [$this, 'verifyAndSetEndpoint'], 20); |
35 | - if (! defined('GRAPHQL_DEBUG') || ! GRAPHQL_DEBUG) { |
|
35 | + if ( ! defined('GRAPHQL_DEBUG') || ! GRAPHQL_DEBUG) { |
|
36 | 36 | // disable WPGraphQL admin by default. |
37 | 37 | add_filter('graphql_show_admin', '__return_false'); |
38 | 38 | add_filter('graphql_enable_graphiql', '__return_false'); |
@@ -54,7 +54,7 @@ discard block |
||
54 | 54 | */ |
55 | 55 | public function isGraphqlRequest() |
56 | 56 | { |
57 | - if (! isset($this->is_gql_request)) { |
|
57 | + if ( ! isset($this->is_gql_request)) { |
|
58 | 58 | // grab the GQL endpoint that we saved in the future... wait... wut? |
59 | 59 | $endpoint = $this->getEndpoint(); |
60 | 60 | // set our saved endpoint on the WP GQL Pouter class |
@@ -16,184 +16,184 @@ |
||
16 | 16 | */ |
17 | 17 | class Attributes implements JsonableInterface |
18 | 18 | { |
19 | - /** |
|
20 | - * @var JsonDataHandler |
|
21 | - */ |
|
22 | - private $json_data_handler; |
|
23 | - |
|
24 | - /** |
|
25 | - * @var InputTypes |
|
26 | - */ |
|
27 | - private $input_types; |
|
28 | - |
|
29 | - /** |
|
30 | - * @var array |
|
31 | - */ |
|
32 | - private $attributes = []; |
|
33 | - |
|
34 | - /** |
|
35 | - * @var array |
|
36 | - */ |
|
37 | - private $attribute_types = [ |
|
38 | - 'accept' => 'string', |
|
39 | - 'accesskey' => 'string', |
|
40 | - 'alt' => 'string', |
|
41 | - 'autocomplete' => 'bool', |
|
42 | - 'autofocus' => 'bool', |
|
43 | - 'checked' => 'bool', |
|
44 | - // Custom HTML classes to be applied to the form input's container |
|
45 | - 'class' => 'string', |
|
46 | - 'contenteditable' => 'bool', |
|
47 | - 'dir' => 'string', |
|
48 | - 'disabled' => 'bool', |
|
49 | - 'height' => 'string', |
|
50 | - 'hidden' => 'bool', |
|
51 | - 'id' => 'string', |
|
52 | - 'list' => 'string', |
|
53 | - // Maximum numeric value allowed for form input answer. |
|
54 | - 'max' => 'int', |
|
55 | - // Maximum characters allowed for form input answer. |
|
56 | - 'maxlength' => 'int', |
|
57 | - // Minimum numeric value allowed for form input answer. |
|
58 | - 'min' => 'int', |
|
59 | - 'multiple' => 'bool', |
|
60 | - 'name' => 'string', |
|
61 | - 'pattern' => 'string', |
|
62 | - // Example text displayed within an input to assist users with completing the form. |
|
63 | - 'placeholder' => 'string', |
|
64 | - 'readonly' => 'bool', |
|
65 | - 'size' => 'int', |
|
66 | - 'spellcheck' => 'bool', |
|
67 | - 'step' => 'float', |
|
68 | - 'style' => 'string', |
|
69 | - 'tabindex' => 'int', |
|
70 | - 'title' => 'string', |
|
71 | - 'translate' => 'bool', |
|
72 | - // Form input type. Values correspond to the Input::TYPE_* constants. |
|
73 | - 'type' => 'string', |
|
74 | - 'value' => 'string', |
|
75 | - 'width' => 'string', |
|
76 | - ]; |
|
77 | - |
|
78 | - |
|
79 | - /** |
|
80 | - * Attributes constructor. |
|
81 | - * |
|
82 | - * @param JsonDataHandler $json_data_handler |
|
83 | - * @param InputTypes $element_types |
|
84 | - * @param array $attributes |
|
85 | - */ |
|
86 | - public function __construct(JsonDataHandler $json_data_handler, array $attributes, InputTypes $element_types) |
|
87 | - { |
|
88 | - $this->json_data_handler = $json_data_handler; |
|
89 | - $this->input_types = $element_types; |
|
90 | - $this->setAttributes($attributes); |
|
91 | - } |
|
92 | - |
|
93 | - |
|
94 | - /** |
|
95 | - * @param string $json |
|
96 | - * @return Attributes |
|
97 | - */ |
|
98 | - public static function fromJson(string $json): Attributes |
|
99 | - { |
|
100 | - $json_data_handler = new JsonDataHandler(); |
|
101 | - $json_data_handler->configure(JsonDataHandler::DATA_TYPE_ARRAY); |
|
102 | - $attributes = $json_data_handler->decodeJson($json); |
|
103 | - /** @var InputTypes */ |
|
104 | - $element_types = LoaderFactory::getShared('EventEspresso\core\services\form\meta\InputTypes'); |
|
105 | - return LoaderFactory::getNew(Attributes::class, [$json_data_handler, (array) $attributes, $element_types]); |
|
106 | - } |
|
107 | - |
|
108 | - |
|
109 | - /** |
|
110 | - * @return array |
|
111 | - */ |
|
112 | - public function toArray(): array |
|
113 | - { |
|
114 | - return $this->attributes(); |
|
115 | - } |
|
116 | - |
|
117 | - |
|
118 | - /** |
|
119 | - * @return string |
|
120 | - */ |
|
121 | - public function toJson(): string |
|
122 | - { |
|
123 | - return $this->json_data_handler->encodeData($this->attributes()); |
|
124 | - } |
|
125 | - |
|
126 | - |
|
127 | - /** |
|
128 | - * @param string $attribute |
|
129 | - * @param bool|float|int|string $value |
|
130 | - * @return bool|float|int|string |
|
131 | - */ |
|
132 | - private function sanitize(string $attribute, $value) |
|
133 | - { |
|
134 | - if ($attribute === 'type') { |
|
135 | - $valid_types = $this->input_types->validTypeOptions(); |
|
136 | - return in_array($value, $valid_types, true) ?: Text::TYPE_TEXT; |
|
137 | - } |
|
138 | - $type = $this->attribute_types[ $attribute ] ?? 'string'; |
|
139 | - switch ($type) { |
|
140 | - case 'bool': |
|
141 | - return filter_var($value, FILTER_VALIDATE_BOOLEAN); |
|
142 | - case 'int': |
|
143 | - return filter_var($value, FILTER_SANITIZE_NUMBER_INT); |
|
144 | - case 'float': |
|
145 | - return filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); |
|
146 | - case 'string': |
|
147 | - default: |
|
148 | - return filter_var( |
|
149 | - $value, |
|
150 | - FILTER_SANITIZE_STRING, |
|
151 | - FILTER_FLAG_ENCODE_LOW | FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_AMP |
|
152 | - ); |
|
153 | - } |
|
154 | - } |
|
155 | - |
|
156 | - |
|
157 | - /** |
|
158 | - * Custom HTML classes to be applied to this form input's help text. |
|
159 | - * returns a concatenated string unless $as_array is set to true |
|
160 | - * |
|
161 | - * @return array |
|
162 | - */ |
|
163 | - public function attributes(): array |
|
164 | - { |
|
165 | - return $this->attributes; |
|
166 | - } |
|
167 | - |
|
168 | - |
|
169 | - /** |
|
170 | - * @param string $attribute |
|
171 | - * @param bool|float|int|string $value |
|
172 | - */ |
|
173 | - public function addAttribute(string $attribute, $value): void |
|
174 | - { |
|
175 | - if (array_key_exists($attribute, $this->attribute_types)) { |
|
176 | - $this->attributes[ $attribute ] = $this->sanitize($attribute, $value); |
|
177 | - } |
|
178 | - } |
|
179 | - |
|
180 | - |
|
181 | - /** |
|
182 | - * @param string $attribute |
|
183 | - */ |
|
184 | - public function removeAttribute(string $attribute): void |
|
185 | - { |
|
186 | - unset($this->attributes[ $attribute ]); |
|
187 | - } |
|
188 | - |
|
189 | - |
|
190 | - /** |
|
191 | - * @param array $attributes array where keys are the attribute name and values are the attribute's value |
|
192 | - */ |
|
193 | - public function setAttributes(array $attributes): void |
|
194 | - { |
|
195 | - foreach ($attributes as $attribute => $value) { |
|
196 | - $this->addAttribute($attribute, $value); |
|
197 | - } |
|
198 | - } |
|
19 | + /** |
|
20 | + * @var JsonDataHandler |
|
21 | + */ |
|
22 | + private $json_data_handler; |
|
23 | + |
|
24 | + /** |
|
25 | + * @var InputTypes |
|
26 | + */ |
|
27 | + private $input_types; |
|
28 | + |
|
29 | + /** |
|
30 | + * @var array |
|
31 | + */ |
|
32 | + private $attributes = []; |
|
33 | + |
|
34 | + /** |
|
35 | + * @var array |
|
36 | + */ |
|
37 | + private $attribute_types = [ |
|
38 | + 'accept' => 'string', |
|
39 | + 'accesskey' => 'string', |
|
40 | + 'alt' => 'string', |
|
41 | + 'autocomplete' => 'bool', |
|
42 | + 'autofocus' => 'bool', |
|
43 | + 'checked' => 'bool', |
|
44 | + // Custom HTML classes to be applied to the form input's container |
|
45 | + 'class' => 'string', |
|
46 | + 'contenteditable' => 'bool', |
|
47 | + 'dir' => 'string', |
|
48 | + 'disabled' => 'bool', |
|
49 | + 'height' => 'string', |
|
50 | + 'hidden' => 'bool', |
|
51 | + 'id' => 'string', |
|
52 | + 'list' => 'string', |
|
53 | + // Maximum numeric value allowed for form input answer. |
|
54 | + 'max' => 'int', |
|
55 | + // Maximum characters allowed for form input answer. |
|
56 | + 'maxlength' => 'int', |
|
57 | + // Minimum numeric value allowed for form input answer. |
|
58 | + 'min' => 'int', |
|
59 | + 'multiple' => 'bool', |
|
60 | + 'name' => 'string', |
|
61 | + 'pattern' => 'string', |
|
62 | + // Example text displayed within an input to assist users with completing the form. |
|
63 | + 'placeholder' => 'string', |
|
64 | + 'readonly' => 'bool', |
|
65 | + 'size' => 'int', |
|
66 | + 'spellcheck' => 'bool', |
|
67 | + 'step' => 'float', |
|
68 | + 'style' => 'string', |
|
69 | + 'tabindex' => 'int', |
|
70 | + 'title' => 'string', |
|
71 | + 'translate' => 'bool', |
|
72 | + // Form input type. Values correspond to the Input::TYPE_* constants. |
|
73 | + 'type' => 'string', |
|
74 | + 'value' => 'string', |
|
75 | + 'width' => 'string', |
|
76 | + ]; |
|
77 | + |
|
78 | + |
|
79 | + /** |
|
80 | + * Attributes constructor. |
|
81 | + * |
|
82 | + * @param JsonDataHandler $json_data_handler |
|
83 | + * @param InputTypes $element_types |
|
84 | + * @param array $attributes |
|
85 | + */ |
|
86 | + public function __construct(JsonDataHandler $json_data_handler, array $attributes, InputTypes $element_types) |
|
87 | + { |
|
88 | + $this->json_data_handler = $json_data_handler; |
|
89 | + $this->input_types = $element_types; |
|
90 | + $this->setAttributes($attributes); |
|
91 | + } |
|
92 | + |
|
93 | + |
|
94 | + /** |
|
95 | + * @param string $json |
|
96 | + * @return Attributes |
|
97 | + */ |
|
98 | + public static function fromJson(string $json): Attributes |
|
99 | + { |
|
100 | + $json_data_handler = new JsonDataHandler(); |
|
101 | + $json_data_handler->configure(JsonDataHandler::DATA_TYPE_ARRAY); |
|
102 | + $attributes = $json_data_handler->decodeJson($json); |
|
103 | + /** @var InputTypes */ |
|
104 | + $element_types = LoaderFactory::getShared('EventEspresso\core\services\form\meta\InputTypes'); |
|
105 | + return LoaderFactory::getNew(Attributes::class, [$json_data_handler, (array) $attributes, $element_types]); |
|
106 | + } |
|
107 | + |
|
108 | + |
|
109 | + /** |
|
110 | + * @return array |
|
111 | + */ |
|
112 | + public function toArray(): array |
|
113 | + { |
|
114 | + return $this->attributes(); |
|
115 | + } |
|
116 | + |
|
117 | + |
|
118 | + /** |
|
119 | + * @return string |
|
120 | + */ |
|
121 | + public function toJson(): string |
|
122 | + { |
|
123 | + return $this->json_data_handler->encodeData($this->attributes()); |
|
124 | + } |
|
125 | + |
|
126 | + |
|
127 | + /** |
|
128 | + * @param string $attribute |
|
129 | + * @param bool|float|int|string $value |
|
130 | + * @return bool|float|int|string |
|
131 | + */ |
|
132 | + private function sanitize(string $attribute, $value) |
|
133 | + { |
|
134 | + if ($attribute === 'type') { |
|
135 | + $valid_types = $this->input_types->validTypeOptions(); |
|
136 | + return in_array($value, $valid_types, true) ?: Text::TYPE_TEXT; |
|
137 | + } |
|
138 | + $type = $this->attribute_types[ $attribute ] ?? 'string'; |
|
139 | + switch ($type) { |
|
140 | + case 'bool': |
|
141 | + return filter_var($value, FILTER_VALIDATE_BOOLEAN); |
|
142 | + case 'int': |
|
143 | + return filter_var($value, FILTER_SANITIZE_NUMBER_INT); |
|
144 | + case 'float': |
|
145 | + return filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); |
|
146 | + case 'string': |
|
147 | + default: |
|
148 | + return filter_var( |
|
149 | + $value, |
|
150 | + FILTER_SANITIZE_STRING, |
|
151 | + FILTER_FLAG_ENCODE_LOW | FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_AMP |
|
152 | + ); |
|
153 | + } |
|
154 | + } |
|
155 | + |
|
156 | + |
|
157 | + /** |
|
158 | + * Custom HTML classes to be applied to this form input's help text. |
|
159 | + * returns a concatenated string unless $as_array is set to true |
|
160 | + * |
|
161 | + * @return array |
|
162 | + */ |
|
163 | + public function attributes(): array |
|
164 | + { |
|
165 | + return $this->attributes; |
|
166 | + } |
|
167 | + |
|
168 | + |
|
169 | + /** |
|
170 | + * @param string $attribute |
|
171 | + * @param bool|float|int|string $value |
|
172 | + */ |
|
173 | + public function addAttribute(string $attribute, $value): void |
|
174 | + { |
|
175 | + if (array_key_exists($attribute, $this->attribute_types)) { |
|
176 | + $this->attributes[ $attribute ] = $this->sanitize($attribute, $value); |
|
177 | + } |
|
178 | + } |
|
179 | + |
|
180 | + |
|
181 | + /** |
|
182 | + * @param string $attribute |
|
183 | + */ |
|
184 | + public function removeAttribute(string $attribute): void |
|
185 | + { |
|
186 | + unset($this->attributes[ $attribute ]); |
|
187 | + } |
|
188 | + |
|
189 | + |
|
190 | + /** |
|
191 | + * @param array $attributes array where keys are the attribute name and values are the attribute's value |
|
192 | + */ |
|
193 | + public function setAttributes(array $attributes): void |
|
194 | + { |
|
195 | + foreach ($attributes as $attribute => $value) { |
|
196 | + $this->addAttribute($attribute, $value); |
|
197 | + } |
|
198 | + } |
|
199 | 199 | } |
@@ -135,7 +135,7 @@ discard block |
||
135 | 135 | $valid_types = $this->input_types->validTypeOptions(); |
136 | 136 | return in_array($value, $valid_types, true) ?: Text::TYPE_TEXT; |
137 | 137 | } |
138 | - $type = $this->attribute_types[ $attribute ] ?? 'string'; |
|
138 | + $type = $this->attribute_types[$attribute] ?? 'string'; |
|
139 | 139 | switch ($type) { |
140 | 140 | case 'bool': |
141 | 141 | return filter_var($value, FILTER_VALIDATE_BOOLEAN); |
@@ -173,7 +173,7 @@ discard block |
||
173 | 173 | public function addAttribute(string $attribute, $value): void |
174 | 174 | { |
175 | 175 | if (array_key_exists($attribute, $this->attribute_types)) { |
176 | - $this->attributes[ $attribute ] = $this->sanitize($attribute, $value); |
|
176 | + $this->attributes[$attribute] = $this->sanitize($attribute, $value); |
|
177 | 177 | } |
178 | 178 | } |
179 | 179 | |
@@ -183,7 +183,7 @@ discard block |
||
183 | 183 | */ |
184 | 184 | public function removeAttribute(string $attribute): void |
185 | 185 | { |
186 | - unset($this->attributes[ $attribute ]); |
|
186 | + unset($this->attributes[$attribute]); |
|
187 | 187 | } |
188 | 188 | |
189 | 189 |
@@ -14,106 +14,106 @@ |
||
14 | 14 | */ |
15 | 15 | class InputOptions implements JsonableInterface |
16 | 16 | { |
17 | - /** |
|
18 | - * @var JsonDataHandler |
|
19 | - */ |
|
20 | - private $json_data_handler; |
|
21 | - |
|
22 | - /** |
|
23 | - * Options for ENUM type inputs like checkboxes, radio buttons, select inputs, etc |
|
24 | - * |
|
25 | - * @var array |
|
26 | - */ |
|
27 | - private $options = []; |
|
28 | - |
|
29 | - |
|
30 | - /** |
|
31 | - * HelpText constructor. |
|
32 | - * |
|
33 | - * @param JsonDataHandler $json_data_handler |
|
34 | - * @param array $options |
|
35 | - */ |
|
36 | - public function __construct(JsonDataHandler $json_data_handler, array $options) |
|
37 | - { |
|
38 | - $this->json_data_handler = $json_data_handler; |
|
39 | - $this->setOptions($options); |
|
40 | - } |
|
41 | - |
|
42 | - |
|
43 | - /** |
|
44 | - * @param string $json |
|
45 | - * @return InputOptions |
|
46 | - */ |
|
47 | - public static function fromJson(string $json): InputOptions |
|
48 | - { |
|
49 | - $json_data_handler = new JsonDataHandler(); |
|
50 | - $json_data_handler->configure(JsonDataHandler::DATA_TYPE_ARRAY); |
|
51 | - $data = $json_data_handler->decodeJson($json); |
|
52 | - return new InputOptions($json_data_handler, (array) $data ?? []); |
|
53 | - } |
|
54 | - |
|
55 | - |
|
56 | - /** |
|
57 | - * @return array |
|
58 | - */ |
|
59 | - public function toArray(): array |
|
60 | - { |
|
61 | - return array_values($this->options); |
|
62 | - } |
|
63 | - |
|
64 | - |
|
65 | - /** |
|
66 | - * @return string |
|
67 | - */ |
|
68 | - public function toJson(): string |
|
69 | - { |
|
70 | - return $this->json_data_handler->encodeData($this->toArray()); |
|
71 | - } |
|
72 | - |
|
73 | - |
|
74 | - /** |
|
75 | - * an array where keys are option values and values are option labels |
|
76 | - * |
|
77 | - * @return array |
|
78 | - */ |
|
79 | - public function options(): array |
|
80 | - { |
|
81 | - return $this->options; |
|
82 | - } |
|
83 | - |
|
84 | - |
|
85 | - /** |
|
86 | - * @param array $option |
|
87 | - */ |
|
88 | - public function addOption(array $option): void |
|
89 | - { |
|
90 | - if (isset($option['label'], $option['value'])) { |
|
91 | - $label = sanitize_text_field($option['label']); |
|
92 | - $value = sanitize_key($option['value']); |
|
93 | - |
|
94 | - // use `value` as key |
|
95 | - $this->options[ $value ] = compact('label', 'value'); |
|
96 | - } |
|
97 | - } |
|
98 | - |
|
99 | - |
|
100 | - /** |
|
101 | - * @param int|float|string $option_value |
|
102 | - */ |
|
103 | - public function removeOption(string $option_value): void |
|
104 | - { |
|
105 | - $option_value = sanitize_key($option_value); |
|
106 | - unset($this->options[ $option_value ]); |
|
107 | - } |
|
108 | - |
|
109 | - |
|
110 | - /** |
|
111 | - * @param array $options an array where keys are option values and values are option labels |
|
112 | - */ |
|
113 | - public function setOptions(array $options): void |
|
114 | - { |
|
115 | - foreach ($options as $option) { |
|
116 | - $this->addOption((array) $option); |
|
117 | - } |
|
118 | - } |
|
17 | + /** |
|
18 | + * @var JsonDataHandler |
|
19 | + */ |
|
20 | + private $json_data_handler; |
|
21 | + |
|
22 | + /** |
|
23 | + * Options for ENUM type inputs like checkboxes, radio buttons, select inputs, etc |
|
24 | + * |
|
25 | + * @var array |
|
26 | + */ |
|
27 | + private $options = []; |
|
28 | + |
|
29 | + |
|
30 | + /** |
|
31 | + * HelpText constructor. |
|
32 | + * |
|
33 | + * @param JsonDataHandler $json_data_handler |
|
34 | + * @param array $options |
|
35 | + */ |
|
36 | + public function __construct(JsonDataHandler $json_data_handler, array $options) |
|
37 | + { |
|
38 | + $this->json_data_handler = $json_data_handler; |
|
39 | + $this->setOptions($options); |
|
40 | + } |
|
41 | + |
|
42 | + |
|
43 | + /** |
|
44 | + * @param string $json |
|
45 | + * @return InputOptions |
|
46 | + */ |
|
47 | + public static function fromJson(string $json): InputOptions |
|
48 | + { |
|
49 | + $json_data_handler = new JsonDataHandler(); |
|
50 | + $json_data_handler->configure(JsonDataHandler::DATA_TYPE_ARRAY); |
|
51 | + $data = $json_data_handler->decodeJson($json); |
|
52 | + return new InputOptions($json_data_handler, (array) $data ?? []); |
|
53 | + } |
|
54 | + |
|
55 | + |
|
56 | + /** |
|
57 | + * @return array |
|
58 | + */ |
|
59 | + public function toArray(): array |
|
60 | + { |
|
61 | + return array_values($this->options); |
|
62 | + } |
|
63 | + |
|
64 | + |
|
65 | + /** |
|
66 | + * @return string |
|
67 | + */ |
|
68 | + public function toJson(): string |
|
69 | + { |
|
70 | + return $this->json_data_handler->encodeData($this->toArray()); |
|
71 | + } |
|
72 | + |
|
73 | + |
|
74 | + /** |
|
75 | + * an array where keys are option values and values are option labels |
|
76 | + * |
|
77 | + * @return array |
|
78 | + */ |
|
79 | + public function options(): array |
|
80 | + { |
|
81 | + return $this->options; |
|
82 | + } |
|
83 | + |
|
84 | + |
|
85 | + /** |
|
86 | + * @param array $option |
|
87 | + */ |
|
88 | + public function addOption(array $option): void |
|
89 | + { |
|
90 | + if (isset($option['label'], $option['value'])) { |
|
91 | + $label = sanitize_text_field($option['label']); |
|
92 | + $value = sanitize_key($option['value']); |
|
93 | + |
|
94 | + // use `value` as key |
|
95 | + $this->options[ $value ] = compact('label', 'value'); |
|
96 | + } |
|
97 | + } |
|
98 | + |
|
99 | + |
|
100 | + /** |
|
101 | + * @param int|float|string $option_value |
|
102 | + */ |
|
103 | + public function removeOption(string $option_value): void |
|
104 | + { |
|
105 | + $option_value = sanitize_key($option_value); |
|
106 | + unset($this->options[ $option_value ]); |
|
107 | + } |
|
108 | + |
|
109 | + |
|
110 | + /** |
|
111 | + * @param array $options an array where keys are option values and values are option labels |
|
112 | + */ |
|
113 | + public function setOptions(array $options): void |
|
114 | + { |
|
115 | + foreach ($options as $option) { |
|
116 | + $this->addOption((array) $option); |
|
117 | + } |
|
118 | + } |
|
119 | 119 | } |
@@ -12,66 +12,66 @@ |
||
12 | 12 | */ |
13 | 13 | class DataType |
14 | 14 | { |
15 | - const ARRAY = 'array'; |
|
15 | + const ARRAY = 'array'; |
|
16 | 16 | |
17 | - const BOOL = 'bool'; |
|
17 | + const BOOL = 'bool'; |
|
18 | 18 | |
19 | - const BOOLEAN = 'bool'; |
|
19 | + const BOOLEAN = 'bool'; |
|
20 | 20 | |
21 | - const DOUBLE = 'float'; |
|
21 | + const DOUBLE = 'float'; |
|
22 | 22 | |
23 | - const FLOAT = 'float'; |
|
23 | + const FLOAT = 'float'; |
|
24 | 24 | |
25 | - const EDITOR = 'editor'; |
|
25 | + const EDITOR = 'editor'; |
|
26 | 26 | |
27 | - const EMAIL = 'email'; |
|
27 | + const EMAIL = 'email'; |
|
28 | 28 | |
29 | - const FQCN = 'fqcn'; |
|
29 | + const FQCN = 'fqcn'; |
|
30 | 30 | |
31 | - const HTML = 'html'; |
|
31 | + const HTML = 'html'; |
|
32 | 32 | |
33 | - const INT = 'int'; |
|
33 | + const INT = 'int'; |
|
34 | 34 | |
35 | - const INTEGER = 'int'; |
|
35 | + const INTEGER = 'int'; |
|
36 | 36 | |
37 | - const KEY = 'key'; |
|
37 | + const KEY = 'key'; |
|
38 | 38 | |
39 | - const OBJECT = 'object'; |
|
39 | + const OBJECT = 'object'; |
|
40 | 40 | |
41 | - const NULL = 'null'; |
|
41 | + const NULL = 'null'; |
|
42 | 42 | |
43 | - const TITLE = 'title'; |
|
43 | + const TITLE = 'title'; |
|
44 | 44 | |
45 | - const URL = 'url'; |
|
45 | + const URL = 'url'; |
|
46 | 46 | |
47 | - const STRING = 'string'; |
|
47 | + const STRING = 'string'; |
|
48 | 48 | |
49 | 49 | |
50 | - /** |
|
51 | - * @param mixed $param |
|
52 | - * @param string $type |
|
53 | - * @return mixed |
|
54 | - */ |
|
55 | - public static function setDataType($param, string $type) |
|
56 | - { |
|
57 | - switch ($type) { |
|
58 | - case DataType::NULL: |
|
59 | - return null; |
|
60 | - case DataType::OBJECT: |
|
61 | - return $param; |
|
62 | - case DataType::EDITOR: |
|
63 | - case DataType::EMAIL: |
|
64 | - case DataType::FQCN: |
|
65 | - case DataType::HTML: |
|
66 | - case DataType::KEY: |
|
67 | - case DataType::STRING: |
|
68 | - case DataType::TITLE: |
|
69 | - case DataType::URL: |
|
70 | - settype($param, DataType::STRING); |
|
71 | - break; |
|
72 | - default: |
|
73 | - settype($param, $type); |
|
74 | - } |
|
75 | - return $param; |
|
76 | - } |
|
50 | + /** |
|
51 | + * @param mixed $param |
|
52 | + * @param string $type |
|
53 | + * @return mixed |
|
54 | + */ |
|
55 | + public static function setDataType($param, string $type) |
|
56 | + { |
|
57 | + switch ($type) { |
|
58 | + case DataType::NULL: |
|
59 | + return null; |
|
60 | + case DataType::OBJECT: |
|
61 | + return $param; |
|
62 | + case DataType::EDITOR: |
|
63 | + case DataType::EMAIL: |
|
64 | + case DataType::FQCN: |
|
65 | + case DataType::HTML: |
|
66 | + case DataType::KEY: |
|
67 | + case DataType::STRING: |
|
68 | + case DataType::TITLE: |
|
69 | + case DataType::URL: |
|
70 | + settype($param, DataType::STRING); |
|
71 | + break; |
|
72 | + default: |
|
73 | + settype($param, $type); |
|
74 | + } |
|
75 | + return $param; |
|
76 | + } |
|
77 | 77 | } |
@@ -22,299 +22,299 @@ |
||
22 | 22 | */ |
23 | 23 | class CurrentPage |
24 | 24 | { |
25 | - private EE_CPT_Strategy $cpt_strategy; |
|
26 | - |
|
27 | - private bool $initialized; |
|
28 | - |
|
29 | - private ?bool $is_espresso_page = null; |
|
30 | - |
|
31 | - private int $post_id = 0; |
|
32 | - |
|
33 | - private string $post_name = ''; |
|
34 | - |
|
35 | - private array $post_type = []; |
|
36 | - |
|
37 | - private RequestInterface $request; |
|
38 | - |
|
39 | - |
|
40 | - /** |
|
41 | - * CurrentPage constructor. |
|
42 | - * |
|
43 | - * @param EE_CPT_Strategy $cpt_strategy |
|
44 | - * @param RequestInterface $request |
|
45 | - */ |
|
46 | - public function __construct(EE_CPT_Strategy $cpt_strategy, RequestInterface $request) |
|
47 | - { |
|
48 | - $this->cpt_strategy = $cpt_strategy; |
|
49 | - $this->request = $request; |
|
50 | - $this->initialized = is_admin(); |
|
51 | - // analyse the incoming WP request |
|
52 | - add_action('parse_request', [$this, 'parseQueryVars'], 2); |
|
53 | - } |
|
54 | - |
|
55 | - |
|
56 | - /** |
|
57 | - * @param WP|null $WP |
|
58 | - * @return void |
|
59 | - */ |
|
60 | - public function parseQueryVars(WP $WP = null) |
|
61 | - { |
|
62 | - if ($this->initialized) { |
|
63 | - return; |
|
64 | - } |
|
65 | - // if somebody forgot to provide us with WP, that's ok because its global |
|
66 | - if (! $WP instanceof WP) { |
|
67 | - global $WP; |
|
68 | - } |
|
69 | - $this->post_id = $this->getPostId($WP); |
|
70 | - $this->post_name = $this->getPostName($WP); |
|
71 | - $this->post_type = $this->getPostType($WP); |
|
72 | - // true or false ? is this page being used by EE ? |
|
73 | - $this->setEspressoPage(); |
|
74 | - remove_action('parse_request', [$this, 'parseQueryVars'], 2); |
|
75 | - $this->initialized = true; |
|
76 | - } |
|
77 | - |
|
78 | - |
|
79 | - /** |
|
80 | - * Just a helper method for getting the url for the displayed page. |
|
81 | - * |
|
82 | - * @param WP|null $WP |
|
83 | - * @return string |
|
84 | - */ |
|
85 | - public function getPermalink(WP $WP = null): string |
|
86 | - { |
|
87 | - $post_id = $this->post_id ?: $this->getPostId($WP); |
|
88 | - if ($post_id) { |
|
89 | - return get_permalink($post_id); |
|
90 | - } |
|
91 | - if (! $WP instanceof WP) { |
|
92 | - global $WP; |
|
93 | - } |
|
94 | - if ($WP instanceof WP && $WP->request) { |
|
95 | - return site_url($WP->request); |
|
96 | - } |
|
97 | - return esc_url_raw(site_url($_SERVER['REQUEST_URI'])); |
|
98 | - } |
|
99 | - |
|
100 | - |
|
101 | - /** |
|
102 | - * @return array |
|
103 | - */ |
|
104 | - public function espressoPostType(): array |
|
105 | - { |
|
106 | - return array_filter( |
|
107 | - $this->post_type, |
|
108 | - function ($post_type) { |
|
109 | - return strpos($post_type, 'espresso_') === 0; |
|
110 | - } |
|
111 | - ); |
|
112 | - } |
|
113 | - |
|
114 | - |
|
115 | - /** |
|
116 | - * pokes and prods the WP object query_vars in an attempt to shake out a page/post ID |
|
117 | - * |
|
118 | - * @param WP|null $WP $WP |
|
119 | - * @return int |
|
120 | - */ |
|
121 | - private function getPostId(WP $WP = null): ?int |
|
122 | - { |
|
123 | - $post_id = 0; |
|
124 | - if ($WP instanceof WP) { |
|
125 | - // look for the post ID in the aptly named 'p' query var |
|
126 | - if (isset($WP->query_vars['p'])) { |
|
127 | - $post_id = $WP->query_vars['p']; |
|
128 | - } |
|
129 | - // not a post? what about a page? |
|
130 | - if (! $post_id && isset($WP->query_vars['page_id'])) { |
|
131 | - $post_id = $WP->query_vars['page_id']; |
|
132 | - } |
|
133 | - // ok... maybe pretty permalinks are off and the ID is set in the raw request... |
|
134 | - // but hasn't been processed yet ie: this method is being called too early :\ |
|
135 | - if (! $post_id && $WP->request !== null && is_numeric(basename($WP->request))) { |
|
136 | - $post_id = basename($WP->request); |
|
137 | - } |
|
138 | - } |
|
139 | - // none of the above? ok what about an explicit "post_id" URL parameter? |
|
140 | - if (! $post_id && $this->request->requestParamIsSet('post_id')) { |
|
141 | - $post_id = $this->request->getRequestParam('post_id', 0, DataType::INT); |
|
142 | - } |
|
143 | - return (int) $post_id; |
|
144 | - } |
|
145 | - |
|
146 | - |
|
147 | - /** |
|
148 | - * similar to getPostId() above but attempts to obtain the "name" for the current page/post |
|
149 | - * |
|
150 | - * @param WP|null $WP $WP |
|
151 | - * @return string|null |
|
152 | - */ |
|
153 | - private function getPostName(WP $WP = null): ?string |
|
154 | - { |
|
155 | - global $wpdb; |
|
156 | - $post_name = ''; |
|
157 | - if ($WP instanceof WP) { |
|
158 | - // if this is a post, then is the post name set? |
|
159 | - if (isset($WP->query_vars['name']) && ! empty($WP->query_vars['name'])) { |
|
160 | - $post_name = is_array($WP->query_vars['name']) ? $WP->query_vars['name'][0] : $WP->query_vars['name']; |
|
161 | - } |
|
162 | - // what about the page name? |
|
163 | - if (! $post_name && isset($WP->query_vars['pagename']) && ! empty($WP->query_vars['pagename'])) { |
|
164 | - $post_name = is_array($WP->query_vars['pagename']) ? $WP->query_vars['pagename'][0] |
|
165 | - : $WP->query_vars['pagename']; |
|
166 | - } |
|
167 | - // this stinks but let's run a query to try and get the post name from the URL |
|
168 | - // (assuming pretty permalinks are on) |
|
169 | - if (! $post_name && ! empty($WP->request)) { |
|
170 | - $possible_post_name = basename($WP->request); |
|
171 | - if (! is_numeric($possible_post_name)) { |
|
172 | - $SQL = "SELECT ID from $wpdb->posts"; |
|
173 | - $SQL .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')"; |
|
174 | - $SQL .= ' AND post_name=%s'; |
|
175 | - $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name)); |
|
176 | - if ($possible_post_name) { |
|
177 | - $post_name = $possible_post_name; |
|
178 | - } |
|
179 | - } |
|
180 | - } |
|
181 | - } |
|
182 | - // ug... ok... nothing yet... but do we have a post ID? |
|
183 | - // if so then... sigh... run a query to get the post name :\ |
|
184 | - if (! $post_name && $this->post_id) { |
|
185 | - $SQL = "SELECT post_name from $wpdb->posts"; |
|
186 | - $SQL .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')"; |
|
187 | - $SQL .= ' AND ID=%d'; |
|
188 | - $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->post_id)); |
|
189 | - if ($possible_post_name) { |
|
190 | - $post_name = $possible_post_name; |
|
191 | - } |
|
192 | - } |
|
193 | - // still nothing? ok what about an explicit 'post_name' URL parameter? |
|
194 | - if (! $post_name && $this->request->requestParamIsSet('post_name')) { |
|
195 | - $post_name = $this->request->getRequestParam('post_name'); |
|
196 | - } |
|
197 | - return $post_name; |
|
198 | - } |
|
199 | - |
|
200 | - |
|
201 | - /** |
|
202 | - * also similar to getPostId() and getPostName() above but not as insane |
|
203 | - * |
|
204 | - * @param WP|null $WP $WP |
|
205 | - * @return array |
|
206 | - */ |
|
207 | - private function getPostType(WP $WP = null): array |
|
208 | - { |
|
209 | - $post_types = []; |
|
210 | - if ($WP instanceof WP) { |
|
211 | - $post_types = isset($WP->query_vars['post_type']) |
|
212 | - ? (array) $WP->query_vars['post_type'] |
|
213 | - : []; |
|
214 | - } |
|
215 | - if (empty($post_types) && $this->request->requestParamIsSet('post_type')) { |
|
216 | - $post_types = $this->request->getRequestParam('post_type', [], DataType::STRING, true); |
|
217 | - } |
|
218 | - return (array) $post_types; |
|
219 | - } |
|
220 | - |
|
221 | - |
|
222 | - /** |
|
223 | - * if TRUE, then the current page is somehow utilizing EE logic |
|
224 | - * |
|
225 | - * @return bool |
|
226 | - */ |
|
227 | - public function isEspressoPage(): bool |
|
228 | - { |
|
229 | - if ($this->is_espresso_page === null) { |
|
230 | - $this->setEspressoPage(); |
|
231 | - } |
|
232 | - return $this->is_espresso_page; |
|
233 | - } |
|
234 | - |
|
235 | - |
|
236 | - /** |
|
237 | - * @return int |
|
238 | - */ |
|
239 | - public function postId(): int |
|
240 | - { |
|
241 | - return $this->post_id; |
|
242 | - } |
|
243 | - |
|
244 | - |
|
245 | - /** |
|
246 | - * @return string|null |
|
247 | - */ |
|
248 | - public function postName(): ?string |
|
249 | - { |
|
250 | - return $this->post_name; |
|
251 | - } |
|
252 | - |
|
253 | - |
|
254 | - /** |
|
255 | - * @return array |
|
256 | - */ |
|
257 | - public function postType(): array |
|
258 | - { |
|
259 | - return $this->post_type; |
|
260 | - } |
|
261 | - |
|
262 | - |
|
263 | - /** |
|
264 | - * for manually indicating the current page will utilize EE logic |
|
265 | - * |
|
266 | - * @param bool|int|string|null $value |
|
267 | - * @return void |
|
268 | - */ |
|
269 | - public function setEspressoPage($value = null) |
|
270 | - { |
|
271 | - $this->is_espresso_page = $value !== null |
|
272 | - ? filter_var($value, FILTER_VALIDATE_BOOLEAN) |
|
273 | - : $this->testForEspressoPage(); |
|
274 | - } |
|
275 | - |
|
276 | - |
|
277 | - /** |
|
278 | - * attempts to determine if the current page/post is an EE related page/post |
|
279 | - * because it utilizes one of our CPT taxonomies, endpoints, or post types |
|
280 | - * |
|
281 | - * @return bool |
|
282 | - */ |
|
283 | - private function testForEspressoPage(): bool |
|
284 | - { |
|
285 | - // in case it has already been set |
|
286 | - if ($this->is_espresso_page) { |
|
287 | - return true; |
|
288 | - } |
|
289 | - global $WP; |
|
290 | - $espresso_CPT_taxonomies = $this->cpt_strategy->get_CPT_taxonomies(); |
|
291 | - if (is_array($espresso_CPT_taxonomies)) { |
|
292 | - foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) { |
|
293 | - if (isset($WP->query_vars, $WP->query_vars[ $espresso_CPT_taxonomy ])) { |
|
294 | - return true; |
|
295 | - } |
|
296 | - } |
|
297 | - } |
|
298 | - // load espresso CPT endpoints |
|
299 | - $espresso_CPT_endpoints = $this->cpt_strategy->get_CPT_endpoints(); |
|
300 | - $post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints); |
|
301 | - foreach ($this->post_type as $post_type) { |
|
302 | - // was a post name passed ? |
|
303 | - if (isset($post_type_CPT_endpoints[ $post_type ])) { |
|
304 | - // kk we know this is an espresso page, but is it a specific post ? |
|
305 | - if (! $this->post_name) { |
|
306 | - $espresso_post_type = $this->request->getRequestParam('post_type'); |
|
307 | - // there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events |
|
308 | - // this essentially sets the post_name to "events" (or whatever EE CPT) |
|
309 | - $post_name = $post_type_CPT_endpoints[ $espresso_post_type ] ?? ''; |
|
310 | - // if the post type matches one of ours then set the post name to the endpoint |
|
311 | - if ($post_name) { |
|
312 | - $this->post_name = $post_name; |
|
313 | - } |
|
314 | - } |
|
315 | - return true; |
|
316 | - } |
|
317 | - } |
|
318 | - return false; |
|
319 | - } |
|
25 | + private EE_CPT_Strategy $cpt_strategy; |
|
26 | + |
|
27 | + private bool $initialized; |
|
28 | + |
|
29 | + private ?bool $is_espresso_page = null; |
|
30 | + |
|
31 | + private int $post_id = 0; |
|
32 | + |
|
33 | + private string $post_name = ''; |
|
34 | + |
|
35 | + private array $post_type = []; |
|
36 | + |
|
37 | + private RequestInterface $request; |
|
38 | + |
|
39 | + |
|
40 | + /** |
|
41 | + * CurrentPage constructor. |
|
42 | + * |
|
43 | + * @param EE_CPT_Strategy $cpt_strategy |
|
44 | + * @param RequestInterface $request |
|
45 | + */ |
|
46 | + public function __construct(EE_CPT_Strategy $cpt_strategy, RequestInterface $request) |
|
47 | + { |
|
48 | + $this->cpt_strategy = $cpt_strategy; |
|
49 | + $this->request = $request; |
|
50 | + $this->initialized = is_admin(); |
|
51 | + // analyse the incoming WP request |
|
52 | + add_action('parse_request', [$this, 'parseQueryVars'], 2); |
|
53 | + } |
|
54 | + |
|
55 | + |
|
56 | + /** |
|
57 | + * @param WP|null $WP |
|
58 | + * @return void |
|
59 | + */ |
|
60 | + public function parseQueryVars(WP $WP = null) |
|
61 | + { |
|
62 | + if ($this->initialized) { |
|
63 | + return; |
|
64 | + } |
|
65 | + // if somebody forgot to provide us with WP, that's ok because its global |
|
66 | + if (! $WP instanceof WP) { |
|
67 | + global $WP; |
|
68 | + } |
|
69 | + $this->post_id = $this->getPostId($WP); |
|
70 | + $this->post_name = $this->getPostName($WP); |
|
71 | + $this->post_type = $this->getPostType($WP); |
|
72 | + // true or false ? is this page being used by EE ? |
|
73 | + $this->setEspressoPage(); |
|
74 | + remove_action('parse_request', [$this, 'parseQueryVars'], 2); |
|
75 | + $this->initialized = true; |
|
76 | + } |
|
77 | + |
|
78 | + |
|
79 | + /** |
|
80 | + * Just a helper method for getting the url for the displayed page. |
|
81 | + * |
|
82 | + * @param WP|null $WP |
|
83 | + * @return string |
|
84 | + */ |
|
85 | + public function getPermalink(WP $WP = null): string |
|
86 | + { |
|
87 | + $post_id = $this->post_id ?: $this->getPostId($WP); |
|
88 | + if ($post_id) { |
|
89 | + return get_permalink($post_id); |
|
90 | + } |
|
91 | + if (! $WP instanceof WP) { |
|
92 | + global $WP; |
|
93 | + } |
|
94 | + if ($WP instanceof WP && $WP->request) { |
|
95 | + return site_url($WP->request); |
|
96 | + } |
|
97 | + return esc_url_raw(site_url($_SERVER['REQUEST_URI'])); |
|
98 | + } |
|
99 | + |
|
100 | + |
|
101 | + /** |
|
102 | + * @return array |
|
103 | + */ |
|
104 | + public function espressoPostType(): array |
|
105 | + { |
|
106 | + return array_filter( |
|
107 | + $this->post_type, |
|
108 | + function ($post_type) { |
|
109 | + return strpos($post_type, 'espresso_') === 0; |
|
110 | + } |
|
111 | + ); |
|
112 | + } |
|
113 | + |
|
114 | + |
|
115 | + /** |
|
116 | + * pokes and prods the WP object query_vars in an attempt to shake out a page/post ID |
|
117 | + * |
|
118 | + * @param WP|null $WP $WP |
|
119 | + * @return int |
|
120 | + */ |
|
121 | + private function getPostId(WP $WP = null): ?int |
|
122 | + { |
|
123 | + $post_id = 0; |
|
124 | + if ($WP instanceof WP) { |
|
125 | + // look for the post ID in the aptly named 'p' query var |
|
126 | + if (isset($WP->query_vars['p'])) { |
|
127 | + $post_id = $WP->query_vars['p']; |
|
128 | + } |
|
129 | + // not a post? what about a page? |
|
130 | + if (! $post_id && isset($WP->query_vars['page_id'])) { |
|
131 | + $post_id = $WP->query_vars['page_id']; |
|
132 | + } |
|
133 | + // ok... maybe pretty permalinks are off and the ID is set in the raw request... |
|
134 | + // but hasn't been processed yet ie: this method is being called too early :\ |
|
135 | + if (! $post_id && $WP->request !== null && is_numeric(basename($WP->request))) { |
|
136 | + $post_id = basename($WP->request); |
|
137 | + } |
|
138 | + } |
|
139 | + // none of the above? ok what about an explicit "post_id" URL parameter? |
|
140 | + if (! $post_id && $this->request->requestParamIsSet('post_id')) { |
|
141 | + $post_id = $this->request->getRequestParam('post_id', 0, DataType::INT); |
|
142 | + } |
|
143 | + return (int) $post_id; |
|
144 | + } |
|
145 | + |
|
146 | + |
|
147 | + /** |
|
148 | + * similar to getPostId() above but attempts to obtain the "name" for the current page/post |
|
149 | + * |
|
150 | + * @param WP|null $WP $WP |
|
151 | + * @return string|null |
|
152 | + */ |
|
153 | + private function getPostName(WP $WP = null): ?string |
|
154 | + { |
|
155 | + global $wpdb; |
|
156 | + $post_name = ''; |
|
157 | + if ($WP instanceof WP) { |
|
158 | + // if this is a post, then is the post name set? |
|
159 | + if (isset($WP->query_vars['name']) && ! empty($WP->query_vars['name'])) { |
|
160 | + $post_name = is_array($WP->query_vars['name']) ? $WP->query_vars['name'][0] : $WP->query_vars['name']; |
|
161 | + } |
|
162 | + // what about the page name? |
|
163 | + if (! $post_name && isset($WP->query_vars['pagename']) && ! empty($WP->query_vars['pagename'])) { |
|
164 | + $post_name = is_array($WP->query_vars['pagename']) ? $WP->query_vars['pagename'][0] |
|
165 | + : $WP->query_vars['pagename']; |
|
166 | + } |
|
167 | + // this stinks but let's run a query to try and get the post name from the URL |
|
168 | + // (assuming pretty permalinks are on) |
|
169 | + if (! $post_name && ! empty($WP->request)) { |
|
170 | + $possible_post_name = basename($WP->request); |
|
171 | + if (! is_numeric($possible_post_name)) { |
|
172 | + $SQL = "SELECT ID from $wpdb->posts"; |
|
173 | + $SQL .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')"; |
|
174 | + $SQL .= ' AND post_name=%s'; |
|
175 | + $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name)); |
|
176 | + if ($possible_post_name) { |
|
177 | + $post_name = $possible_post_name; |
|
178 | + } |
|
179 | + } |
|
180 | + } |
|
181 | + } |
|
182 | + // ug... ok... nothing yet... but do we have a post ID? |
|
183 | + // if so then... sigh... run a query to get the post name :\ |
|
184 | + if (! $post_name && $this->post_id) { |
|
185 | + $SQL = "SELECT post_name from $wpdb->posts"; |
|
186 | + $SQL .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')"; |
|
187 | + $SQL .= ' AND ID=%d'; |
|
188 | + $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->post_id)); |
|
189 | + if ($possible_post_name) { |
|
190 | + $post_name = $possible_post_name; |
|
191 | + } |
|
192 | + } |
|
193 | + // still nothing? ok what about an explicit 'post_name' URL parameter? |
|
194 | + if (! $post_name && $this->request->requestParamIsSet('post_name')) { |
|
195 | + $post_name = $this->request->getRequestParam('post_name'); |
|
196 | + } |
|
197 | + return $post_name; |
|
198 | + } |
|
199 | + |
|
200 | + |
|
201 | + /** |
|
202 | + * also similar to getPostId() and getPostName() above but not as insane |
|
203 | + * |
|
204 | + * @param WP|null $WP $WP |
|
205 | + * @return array |
|
206 | + */ |
|
207 | + private function getPostType(WP $WP = null): array |
|
208 | + { |
|
209 | + $post_types = []; |
|
210 | + if ($WP instanceof WP) { |
|
211 | + $post_types = isset($WP->query_vars['post_type']) |
|
212 | + ? (array) $WP->query_vars['post_type'] |
|
213 | + : []; |
|
214 | + } |
|
215 | + if (empty($post_types) && $this->request->requestParamIsSet('post_type')) { |
|
216 | + $post_types = $this->request->getRequestParam('post_type', [], DataType::STRING, true); |
|
217 | + } |
|
218 | + return (array) $post_types; |
|
219 | + } |
|
220 | + |
|
221 | + |
|
222 | + /** |
|
223 | + * if TRUE, then the current page is somehow utilizing EE logic |
|
224 | + * |
|
225 | + * @return bool |
|
226 | + */ |
|
227 | + public function isEspressoPage(): bool |
|
228 | + { |
|
229 | + if ($this->is_espresso_page === null) { |
|
230 | + $this->setEspressoPage(); |
|
231 | + } |
|
232 | + return $this->is_espresso_page; |
|
233 | + } |
|
234 | + |
|
235 | + |
|
236 | + /** |
|
237 | + * @return int |
|
238 | + */ |
|
239 | + public function postId(): int |
|
240 | + { |
|
241 | + return $this->post_id; |
|
242 | + } |
|
243 | + |
|
244 | + |
|
245 | + /** |
|
246 | + * @return string|null |
|
247 | + */ |
|
248 | + public function postName(): ?string |
|
249 | + { |
|
250 | + return $this->post_name; |
|
251 | + } |
|
252 | + |
|
253 | + |
|
254 | + /** |
|
255 | + * @return array |
|
256 | + */ |
|
257 | + public function postType(): array |
|
258 | + { |
|
259 | + return $this->post_type; |
|
260 | + } |
|
261 | + |
|
262 | + |
|
263 | + /** |
|
264 | + * for manually indicating the current page will utilize EE logic |
|
265 | + * |
|
266 | + * @param bool|int|string|null $value |
|
267 | + * @return void |
|
268 | + */ |
|
269 | + public function setEspressoPage($value = null) |
|
270 | + { |
|
271 | + $this->is_espresso_page = $value !== null |
|
272 | + ? filter_var($value, FILTER_VALIDATE_BOOLEAN) |
|
273 | + : $this->testForEspressoPage(); |
|
274 | + } |
|
275 | + |
|
276 | + |
|
277 | + /** |
|
278 | + * attempts to determine if the current page/post is an EE related page/post |
|
279 | + * because it utilizes one of our CPT taxonomies, endpoints, or post types |
|
280 | + * |
|
281 | + * @return bool |
|
282 | + */ |
|
283 | + private function testForEspressoPage(): bool |
|
284 | + { |
|
285 | + // in case it has already been set |
|
286 | + if ($this->is_espresso_page) { |
|
287 | + return true; |
|
288 | + } |
|
289 | + global $WP; |
|
290 | + $espresso_CPT_taxonomies = $this->cpt_strategy->get_CPT_taxonomies(); |
|
291 | + if (is_array($espresso_CPT_taxonomies)) { |
|
292 | + foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) { |
|
293 | + if (isset($WP->query_vars, $WP->query_vars[ $espresso_CPT_taxonomy ])) { |
|
294 | + return true; |
|
295 | + } |
|
296 | + } |
|
297 | + } |
|
298 | + // load espresso CPT endpoints |
|
299 | + $espresso_CPT_endpoints = $this->cpt_strategy->get_CPT_endpoints(); |
|
300 | + $post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints); |
|
301 | + foreach ($this->post_type as $post_type) { |
|
302 | + // was a post name passed ? |
|
303 | + if (isset($post_type_CPT_endpoints[ $post_type ])) { |
|
304 | + // kk we know this is an espresso page, but is it a specific post ? |
|
305 | + if (! $this->post_name) { |
|
306 | + $espresso_post_type = $this->request->getRequestParam('post_type'); |
|
307 | + // there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events |
|
308 | + // this essentially sets the post_name to "events" (or whatever EE CPT) |
|
309 | + $post_name = $post_type_CPT_endpoints[ $espresso_post_type ] ?? ''; |
|
310 | + // if the post type matches one of ours then set the post name to the endpoint |
|
311 | + if ($post_name) { |
|
312 | + $this->post_name = $post_name; |
|
313 | + } |
|
314 | + } |
|
315 | + return true; |
|
316 | + } |
|
317 | + } |
|
318 | + return false; |
|
319 | + } |
|
320 | 320 | } |
@@ -63,7 +63,7 @@ discard block |
||
63 | 63 | return; |
64 | 64 | } |
65 | 65 | // if somebody forgot to provide us with WP, that's ok because its global |
66 | - if (! $WP instanceof WP) { |
|
66 | + if ( ! $WP instanceof WP) { |
|
67 | 67 | global $WP; |
68 | 68 | } |
69 | 69 | $this->post_id = $this->getPostId($WP); |
@@ -88,7 +88,7 @@ discard block |
||
88 | 88 | if ($post_id) { |
89 | 89 | return get_permalink($post_id); |
90 | 90 | } |
91 | - if (! $WP instanceof WP) { |
|
91 | + if ( ! $WP instanceof WP) { |
|
92 | 92 | global $WP; |
93 | 93 | } |
94 | 94 | if ($WP instanceof WP && $WP->request) { |
@@ -105,7 +105,7 @@ discard block |
||
105 | 105 | { |
106 | 106 | return array_filter( |
107 | 107 | $this->post_type, |
108 | - function ($post_type) { |
|
108 | + function($post_type) { |
|
109 | 109 | return strpos($post_type, 'espresso_') === 0; |
110 | 110 | } |
111 | 111 | ); |
@@ -127,17 +127,17 @@ discard block |
||
127 | 127 | $post_id = $WP->query_vars['p']; |
128 | 128 | } |
129 | 129 | // not a post? what about a page? |
130 | - if (! $post_id && isset($WP->query_vars['page_id'])) { |
|
130 | + if ( ! $post_id && isset($WP->query_vars['page_id'])) { |
|
131 | 131 | $post_id = $WP->query_vars['page_id']; |
132 | 132 | } |
133 | 133 | // ok... maybe pretty permalinks are off and the ID is set in the raw request... |
134 | 134 | // but hasn't been processed yet ie: this method is being called too early :\ |
135 | - if (! $post_id && $WP->request !== null && is_numeric(basename($WP->request))) { |
|
135 | + if ( ! $post_id && $WP->request !== null && is_numeric(basename($WP->request))) { |
|
136 | 136 | $post_id = basename($WP->request); |
137 | 137 | } |
138 | 138 | } |
139 | 139 | // none of the above? ok what about an explicit "post_id" URL parameter? |
140 | - if (! $post_id && $this->request->requestParamIsSet('post_id')) { |
|
140 | + if ( ! $post_id && $this->request->requestParamIsSet('post_id')) { |
|
141 | 141 | $post_id = $this->request->getRequestParam('post_id', 0, DataType::INT); |
142 | 142 | } |
143 | 143 | return (int) $post_id; |
@@ -160,15 +160,15 @@ discard block |
||
160 | 160 | $post_name = is_array($WP->query_vars['name']) ? $WP->query_vars['name'][0] : $WP->query_vars['name']; |
161 | 161 | } |
162 | 162 | // what about the page name? |
163 | - if (! $post_name && isset($WP->query_vars['pagename']) && ! empty($WP->query_vars['pagename'])) { |
|
163 | + if ( ! $post_name && isset($WP->query_vars['pagename']) && ! empty($WP->query_vars['pagename'])) { |
|
164 | 164 | $post_name = is_array($WP->query_vars['pagename']) ? $WP->query_vars['pagename'][0] |
165 | 165 | : $WP->query_vars['pagename']; |
166 | 166 | } |
167 | 167 | // this stinks but let's run a query to try and get the post name from the URL |
168 | 168 | // (assuming pretty permalinks are on) |
169 | - if (! $post_name && ! empty($WP->request)) { |
|
169 | + if ( ! $post_name && ! empty($WP->request)) { |
|
170 | 170 | $possible_post_name = basename($WP->request); |
171 | - if (! is_numeric($possible_post_name)) { |
|
171 | + if ( ! is_numeric($possible_post_name)) { |
|
172 | 172 | $SQL = "SELECT ID from $wpdb->posts"; |
173 | 173 | $SQL .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')"; |
174 | 174 | $SQL .= ' AND post_name=%s'; |
@@ -181,7 +181,7 @@ discard block |
||
181 | 181 | } |
182 | 182 | // ug... ok... nothing yet... but do we have a post ID? |
183 | 183 | // if so then... sigh... run a query to get the post name :\ |
184 | - if (! $post_name && $this->post_id) { |
|
184 | + if ( ! $post_name && $this->post_id) { |
|
185 | 185 | $SQL = "SELECT post_name from $wpdb->posts"; |
186 | 186 | $SQL .= " WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash')"; |
187 | 187 | $SQL .= ' AND ID=%d'; |
@@ -191,7 +191,7 @@ discard block |
||
191 | 191 | } |
192 | 192 | } |
193 | 193 | // still nothing? ok what about an explicit 'post_name' URL parameter? |
194 | - if (! $post_name && $this->request->requestParamIsSet('post_name')) { |
|
194 | + if ( ! $post_name && $this->request->requestParamIsSet('post_name')) { |
|
195 | 195 | $post_name = $this->request->getRequestParam('post_name'); |
196 | 196 | } |
197 | 197 | return $post_name; |
@@ -290,7 +290,7 @@ discard block |
||
290 | 290 | $espresso_CPT_taxonomies = $this->cpt_strategy->get_CPT_taxonomies(); |
291 | 291 | if (is_array($espresso_CPT_taxonomies)) { |
292 | 292 | foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) { |
293 | - if (isset($WP->query_vars, $WP->query_vars[ $espresso_CPT_taxonomy ])) { |
|
293 | + if (isset($WP->query_vars, $WP->query_vars[$espresso_CPT_taxonomy])) { |
|
294 | 294 | return true; |
295 | 295 | } |
296 | 296 | } |
@@ -300,13 +300,13 @@ discard block |
||
300 | 300 | $post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints); |
301 | 301 | foreach ($this->post_type as $post_type) { |
302 | 302 | // was a post name passed ? |
303 | - if (isset($post_type_CPT_endpoints[ $post_type ])) { |
|
303 | + if (isset($post_type_CPT_endpoints[$post_type])) { |
|
304 | 304 | // kk we know this is an espresso page, but is it a specific post ? |
305 | - if (! $this->post_name) { |
|
305 | + if ( ! $this->post_name) { |
|
306 | 306 | $espresso_post_type = $this->request->getRequestParam('post_type'); |
307 | 307 | // there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events |
308 | 308 | // this essentially sets the post_name to "events" (or whatever EE CPT) |
309 | - $post_name = $post_type_CPT_endpoints[ $espresso_post_type ] ?? ''; |
|
309 | + $post_name = $post_type_CPT_endpoints[$espresso_post_type] ?? ''; |
|
310 | 310 | // if the post type matches one of ours then set the post name to the endpoint |
311 | 311 | if ($post_name) { |
312 | 312 | $this->post_name = $post_name; |
@@ -8,88 +8,88 @@ |
||
8 | 8 | class RequestSanitizer |
9 | 9 | { |
10 | 10 | |
11 | - private Basic $email_validator; |
|
11 | + private Basic $email_validator; |
|
12 | 12 | |
13 | 13 | |
14 | - /** |
|
15 | - * @param Basic $email_validator |
|
16 | - */ |
|
17 | - public function __construct(Basic $email_validator) |
|
18 | - { |
|
19 | - $this->email_validator = $email_validator; |
|
20 | - } |
|
14 | + /** |
|
15 | + * @param Basic $email_validator |
|
16 | + */ |
|
17 | + public function __construct(Basic $email_validator) |
|
18 | + { |
|
19 | + $this->email_validator = $email_validator; |
|
20 | + } |
|
21 | 21 | |
22 | 22 | |
23 | - /** |
|
24 | - * Will sanitize the supplied request parameter based on the specified data type |
|
25 | - * |
|
26 | - * @param mixed $param the supplied request parameter |
|
27 | - * @param string $type the specified data type (default: "string") |
|
28 | - * valid values: "bool", "float", "int", "key", "url", or "string" |
|
29 | - * @param bool $is_array if true, then $param will be treated as an array of $type |
|
30 | - * @param string $delimiter if $param is a CSV like value (ex: 1,2,3,4,5...) then this is the value separator |
|
31 | - * @return array|bool|float|int|string |
|
32 | - * @since 4.10.14.p |
|
33 | - */ |
|
34 | - public function clean( |
|
35 | - $param, |
|
36 | - string $type = DataType::STRING, |
|
37 | - bool $is_array = false, |
|
38 | - string $delimiter = '' |
|
39 | - ) { |
|
40 | - if ($delimiter !== '' && is_string($param)) { |
|
41 | - $param = explode($delimiter, $param); |
|
42 | - $is_array = is_array($param); |
|
43 | - // unset the delimiter else this function will recurse forever when we loop over the array of results |
|
44 | - $delimiter = ''; |
|
45 | - } |
|
46 | - // check if we are getting an improperly typed array and correct |
|
47 | - $is_array = $is_array && is_array($param); |
|
48 | - if ($is_array) { |
|
49 | - $values = []; |
|
50 | - foreach ((array) $param as $key => $value) { |
|
51 | - $values[ $key ] = $this->clean($value, $type, is_array($value), $delimiter); |
|
52 | - } |
|
53 | - return $values; |
|
54 | - } |
|
55 | - return $this->sanitizeParam($param, $type); |
|
56 | - } |
|
23 | + /** |
|
24 | + * Will sanitize the supplied request parameter based on the specified data type |
|
25 | + * |
|
26 | + * @param mixed $param the supplied request parameter |
|
27 | + * @param string $type the specified data type (default: "string") |
|
28 | + * valid values: "bool", "float", "int", "key", "url", or "string" |
|
29 | + * @param bool $is_array if true, then $param will be treated as an array of $type |
|
30 | + * @param string $delimiter if $param is a CSV like value (ex: 1,2,3,4,5...) then this is the value separator |
|
31 | + * @return array|bool|float|int|string |
|
32 | + * @since 4.10.14.p |
|
33 | + */ |
|
34 | + public function clean( |
|
35 | + $param, |
|
36 | + string $type = DataType::STRING, |
|
37 | + bool $is_array = false, |
|
38 | + string $delimiter = '' |
|
39 | + ) { |
|
40 | + if ($delimiter !== '' && is_string($param)) { |
|
41 | + $param = explode($delimiter, $param); |
|
42 | + $is_array = is_array($param); |
|
43 | + // unset the delimiter else this function will recurse forever when we loop over the array of results |
|
44 | + $delimiter = ''; |
|
45 | + } |
|
46 | + // check if we are getting an improperly typed array and correct |
|
47 | + $is_array = $is_array && is_array($param); |
|
48 | + if ($is_array) { |
|
49 | + $values = []; |
|
50 | + foreach ((array) $param as $key => $value) { |
|
51 | + $values[ $key ] = $this->clean($value, $type, is_array($value), $delimiter); |
|
52 | + } |
|
53 | + return $values; |
|
54 | + } |
|
55 | + return $this->sanitizeParam($param, $type); |
|
56 | + } |
|
57 | 57 | |
58 | 58 | |
59 | - /** |
|
60 | - * @param mixed $param |
|
61 | - * @param string $type |
|
62 | - * @return array|float|int|mixed|string|string[]|null |
|
63 | - * @since 4.10.20.p |
|
64 | - */ |
|
65 | - public function sanitizeParam($param, string $type = DataType::STRING) |
|
66 | - { |
|
67 | - switch ($type) { |
|
68 | - case DataType::BOOL: |
|
69 | - return filter_var($param, FILTER_VALIDATE_BOOLEAN); |
|
70 | - case DataType::EDITOR: |
|
71 | - $allowed_tags = AllowedTags::getWithFullTags(); |
|
72 | - return wp_kses($param, $allowed_tags); |
|
73 | - case DataType::EMAIL: |
|
74 | - return $this->email_validator->validate($param) ? $param : ''; |
|
75 | - case DataType::FLOAT: |
|
76 | - return (float) $param; |
|
77 | - case DataType::FQCN: |
|
78 | - return preg_replace('[^\\\w\d]', '', $param); |
|
79 | - case DataType::HTML: |
|
80 | - $allowed_tags = AllowedTags::getAllowedTags(); |
|
81 | - return wp_kses($param, $allowed_tags); |
|
82 | - case DataType::INT: |
|
83 | - return (int) $param; |
|
84 | - case DataType::KEY: |
|
85 | - return sanitize_key($param); |
|
86 | - case DataType::TITLE: |
|
87 | - return sanitize_title($param); |
|
88 | - case DataType::URL: |
|
89 | - return esc_url_raw($param); |
|
90 | - case DataType::STRING: |
|
91 | - default: |
|
92 | - return sanitize_text_field($param); |
|
93 | - } |
|
94 | - } |
|
59 | + /** |
|
60 | + * @param mixed $param |
|
61 | + * @param string $type |
|
62 | + * @return array|float|int|mixed|string|string[]|null |
|
63 | + * @since 4.10.20.p |
|
64 | + */ |
|
65 | + public function sanitizeParam($param, string $type = DataType::STRING) |
|
66 | + { |
|
67 | + switch ($type) { |
|
68 | + case DataType::BOOL: |
|
69 | + return filter_var($param, FILTER_VALIDATE_BOOLEAN); |
|
70 | + case DataType::EDITOR: |
|
71 | + $allowed_tags = AllowedTags::getWithFullTags(); |
|
72 | + return wp_kses($param, $allowed_tags); |
|
73 | + case DataType::EMAIL: |
|
74 | + return $this->email_validator->validate($param) ? $param : ''; |
|
75 | + case DataType::FLOAT: |
|
76 | + return (float) $param; |
|
77 | + case DataType::FQCN: |
|
78 | + return preg_replace('[^\\\w\d]', '', $param); |
|
79 | + case DataType::HTML: |
|
80 | + $allowed_tags = AllowedTags::getAllowedTags(); |
|
81 | + return wp_kses($param, $allowed_tags); |
|
82 | + case DataType::INT: |
|
83 | + return (int) $param; |
|
84 | + case DataType::KEY: |
|
85 | + return sanitize_key($param); |
|
86 | + case DataType::TITLE: |
|
87 | + return sanitize_title($param); |
|
88 | + case DataType::URL: |
|
89 | + return esc_url_raw($param); |
|
90 | + case DataType::STRING: |
|
91 | + default: |
|
92 | + return sanitize_text_field($param); |
|
93 | + } |
|
94 | + } |
|
95 | 95 | } |
@@ -6,209 +6,209 @@ |
||
6 | 6 | |
7 | 7 | class ServerParams |
8 | 8 | { |
9 | - /** |
|
10 | - * IP address for request |
|
11 | - * |
|
12 | - * @var string |
|
13 | - */ |
|
14 | - protected $ip_address; |
|
15 | - |
|
16 | - |
|
17 | - /** |
|
18 | - * @var ServerSanitizer |
|
19 | - */ |
|
20 | - protected $sanitizer; |
|
21 | - |
|
22 | - /** |
|
23 | - * sanitized $_SERVER parameters |
|
24 | - * |
|
25 | - * @var array |
|
26 | - */ |
|
27 | - protected $server; |
|
28 | - |
|
29 | - /** |
|
30 | - * @var string |
|
31 | - */ |
|
32 | - protected $request_uri; |
|
33 | - |
|
34 | - /** |
|
35 | - * @var string |
|
36 | - */ |
|
37 | - protected $user_agent; |
|
38 | - |
|
39 | - |
|
40 | - /** |
|
41 | - * ServerParams constructor. |
|
42 | - * |
|
43 | - * @param ServerSanitizer $sanitizer |
|
44 | - * @param array $server |
|
45 | - */ |
|
46 | - public function __construct(ServerSanitizer $sanitizer, array $server = []) |
|
47 | - { |
|
48 | - $this->sanitizer = $sanitizer; |
|
49 | - $this->server = $this->cleanServerParams($server); |
|
50 | - $this->ip_address = $this->setVisitorIp(); |
|
51 | - } |
|
52 | - |
|
53 | - |
|
54 | - /** |
|
55 | - * @param array $server |
|
56 | - * @return array |
|
57 | - */ |
|
58 | - private function cleanServerParams(array $server): array |
|
59 | - { |
|
60 | - $cleaned = []; |
|
61 | - foreach ($server as $key => $value) { |
|
62 | - $cleaned[ $key ] = $this->sanitizer->clean($key, $value); |
|
63 | - } |
|
64 | - return $cleaned; |
|
65 | - } |
|
66 | - |
|
67 | - |
|
68 | - /** |
|
69 | - * @return array |
|
70 | - */ |
|
71 | - public function getAllServerParams(): array |
|
72 | - { |
|
73 | - return $this->server; |
|
74 | - } |
|
75 | - |
|
76 | - |
|
77 | - /** |
|
78 | - * @param string $key |
|
79 | - * @param mixed|null $default |
|
80 | - * @return array|int|float|string |
|
81 | - */ |
|
82 | - public function getServerParam(string $key, $default = null) |
|
83 | - { |
|
84 | - return $this->serverParamIsSet($key) ? $this->server[ $key ] : $default; |
|
85 | - } |
|
86 | - |
|
87 | - |
|
88 | - /** |
|
89 | - * @param string $key |
|
90 | - * @param array|int|float|string $value |
|
91 | - * @param bool $set_global_too |
|
92 | - * @return void |
|
93 | - */ |
|
94 | - public function setServerParam(string $key, $value, bool $set_global_too = false) |
|
95 | - { |
|
96 | - $value = $this->sanitizer->clean($key, $value); |
|
97 | - $this->server[ $key ] = $value; |
|
98 | - if ($set_global_too) { |
|
99 | - $_SERVER[ $key ] = $value; |
|
100 | - } |
|
101 | - } |
|
102 | - |
|
103 | - |
|
104 | - /** |
|
105 | - * @param string $key |
|
106 | - * @param bool $unset_from_global_too |
|
107 | - * @return void |
|
108 | - */ |
|
109 | - public function unSetServerParam(string $key, bool $unset_from_global_too = false) |
|
110 | - { |
|
111 | - // because unset may not actually remove var |
|
112 | - $this->server[ $key ] = null; |
|
113 | - unset($this->server[ $key ]); |
|
114 | - if ($unset_from_global_too) { |
|
115 | - unset($_SERVER[ $key ]); |
|
116 | - } |
|
117 | - } |
|
118 | - |
|
119 | - |
|
120 | - /** |
|
121 | - * @param string $key |
|
122 | - * @return bool |
|
123 | - */ |
|
124 | - public function serverParamIsSet(string $key): bool |
|
125 | - { |
|
126 | - return isset($this->server[ $key ]); |
|
127 | - } |
|
128 | - |
|
129 | - |
|
130 | - /** |
|
131 | - * @return string |
|
132 | - */ |
|
133 | - public function ipAddress(): string |
|
134 | - { |
|
135 | - return (string) $this->ip_address; |
|
136 | - } |
|
137 | - |
|
138 | - |
|
139 | - /** |
|
140 | - * attempt to get IP address of current visitor from server |
|
141 | - * plz see: http://stackoverflow.com/a/2031935/1475279 |
|
142 | - * |
|
143 | - * @return string |
|
144 | - */ |
|
145 | - private function setVisitorIp(): string |
|
146 | - { |
|
147 | - $visitor_ip = '0.0.0.0'; |
|
148 | - $server_keys = [ |
|
149 | - 'HTTP_CLIENT_IP', |
|
150 | - 'HTTP_FORWARDED', |
|
151 | - 'HTTP_FORWARDED_FOR', |
|
152 | - 'HTTP_X_CLUSTER_CLIENT_IP', |
|
153 | - 'HTTP_X_FORWARDED', |
|
154 | - 'HTTP_X_FORWARDED_FOR', |
|
155 | - 'REMOTE_ADDR', |
|
156 | - ]; |
|
157 | - foreach ($server_keys as $key) { |
|
158 | - if (isset($this->server[ $key ])) { |
|
159 | - $potential_ip = array_map('trim', explode(',', $this->server[ $key ])); |
|
160 | - foreach ($potential_ip as $ip) { |
|
161 | - if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) { |
|
162 | - $visitor_ip = $ip; |
|
163 | - } |
|
164 | - } |
|
165 | - } |
|
166 | - } |
|
167 | - return (string) $visitor_ip; |
|
168 | - } |
|
169 | - |
|
170 | - |
|
171 | - /** |
|
172 | - * Gets the request's literal URI. Related to `requestUriAfterSiteHomeUri`, see its description for a comparison. |
|
173 | - * |
|
174 | - * @param boolean $relativeToWpRoot If home_url() is "http://mysite.com/wp/", and a request comes to |
|
175 | - * "http://mysite.com/wp/wp-json", setting $relativeToWpRoot=true will return |
|
176 | - * "/wp-json", whereas $relativeToWpRoot=false will return "/wp/wp-json/". |
|
177 | - * @return string |
|
178 | - */ |
|
179 | - public function requestUri(bool $relativeToWpRoot = false): string |
|
180 | - { |
|
181 | - if ($relativeToWpRoot) { |
|
182 | - $home_path = parse_url(home_url(), PHP_URL_PATH); |
|
183 | - $home_path = trim((string) $home_path, '/'); |
|
184 | - $home_path = ! empty($home_path) |
|
185 | - ? trailingslashit($home_path) |
|
186 | - : $home_path; |
|
187 | - return str_replace($home_path, '', (string) ($this->server['REQUEST_URI'] ?? '')); |
|
188 | - } |
|
189 | - return $this->server['REQUEST_URI']; |
|
190 | - } |
|
191 | - |
|
192 | - |
|
193 | - /** |
|
194 | - * @return string |
|
195 | - */ |
|
196 | - public function userAgent(): string |
|
197 | - { |
|
198 | - if (empty($this->user_agent)) { |
|
199 | - $this->setUserAgent(); |
|
200 | - } |
|
201 | - return (string) $this->user_agent; |
|
202 | - } |
|
203 | - |
|
204 | - |
|
205 | - /** |
|
206 | - * @param string|null $user_agent |
|
207 | - */ |
|
208 | - public function setUserAgent(?string $user_agent = '') |
|
209 | - { |
|
210 | - $this->user_agent = $user_agent === '' || ! is_string($user_agent) |
|
211 | - ? (string) $this->getServerParam('HTTP_USER_AGENT', 'unknown') |
|
212 | - : (string) esc_attr($user_agent); |
|
213 | - } |
|
9 | + /** |
|
10 | + * IP address for request |
|
11 | + * |
|
12 | + * @var string |
|
13 | + */ |
|
14 | + protected $ip_address; |
|
15 | + |
|
16 | + |
|
17 | + /** |
|
18 | + * @var ServerSanitizer |
|
19 | + */ |
|
20 | + protected $sanitizer; |
|
21 | + |
|
22 | + /** |
|
23 | + * sanitized $_SERVER parameters |
|
24 | + * |
|
25 | + * @var array |
|
26 | + */ |
|
27 | + protected $server; |
|
28 | + |
|
29 | + /** |
|
30 | + * @var string |
|
31 | + */ |
|
32 | + protected $request_uri; |
|
33 | + |
|
34 | + /** |
|
35 | + * @var string |
|
36 | + */ |
|
37 | + protected $user_agent; |
|
38 | + |
|
39 | + |
|
40 | + /** |
|
41 | + * ServerParams constructor. |
|
42 | + * |
|
43 | + * @param ServerSanitizer $sanitizer |
|
44 | + * @param array $server |
|
45 | + */ |
|
46 | + public function __construct(ServerSanitizer $sanitizer, array $server = []) |
|
47 | + { |
|
48 | + $this->sanitizer = $sanitizer; |
|
49 | + $this->server = $this->cleanServerParams($server); |
|
50 | + $this->ip_address = $this->setVisitorIp(); |
|
51 | + } |
|
52 | + |
|
53 | + |
|
54 | + /** |
|
55 | + * @param array $server |
|
56 | + * @return array |
|
57 | + */ |
|
58 | + private function cleanServerParams(array $server): array |
|
59 | + { |
|
60 | + $cleaned = []; |
|
61 | + foreach ($server as $key => $value) { |
|
62 | + $cleaned[ $key ] = $this->sanitizer->clean($key, $value); |
|
63 | + } |
|
64 | + return $cleaned; |
|
65 | + } |
|
66 | + |
|
67 | + |
|
68 | + /** |
|
69 | + * @return array |
|
70 | + */ |
|
71 | + public function getAllServerParams(): array |
|
72 | + { |
|
73 | + return $this->server; |
|
74 | + } |
|
75 | + |
|
76 | + |
|
77 | + /** |
|
78 | + * @param string $key |
|
79 | + * @param mixed|null $default |
|
80 | + * @return array|int|float|string |
|
81 | + */ |
|
82 | + public function getServerParam(string $key, $default = null) |
|
83 | + { |
|
84 | + return $this->serverParamIsSet($key) ? $this->server[ $key ] : $default; |
|
85 | + } |
|
86 | + |
|
87 | + |
|
88 | + /** |
|
89 | + * @param string $key |
|
90 | + * @param array|int|float|string $value |
|
91 | + * @param bool $set_global_too |
|
92 | + * @return void |
|
93 | + */ |
|
94 | + public function setServerParam(string $key, $value, bool $set_global_too = false) |
|
95 | + { |
|
96 | + $value = $this->sanitizer->clean($key, $value); |
|
97 | + $this->server[ $key ] = $value; |
|
98 | + if ($set_global_too) { |
|
99 | + $_SERVER[ $key ] = $value; |
|
100 | + } |
|
101 | + } |
|
102 | + |
|
103 | + |
|
104 | + /** |
|
105 | + * @param string $key |
|
106 | + * @param bool $unset_from_global_too |
|
107 | + * @return void |
|
108 | + */ |
|
109 | + public function unSetServerParam(string $key, bool $unset_from_global_too = false) |
|
110 | + { |
|
111 | + // because unset may not actually remove var |
|
112 | + $this->server[ $key ] = null; |
|
113 | + unset($this->server[ $key ]); |
|
114 | + if ($unset_from_global_too) { |
|
115 | + unset($_SERVER[ $key ]); |
|
116 | + } |
|
117 | + } |
|
118 | + |
|
119 | + |
|
120 | + /** |
|
121 | + * @param string $key |
|
122 | + * @return bool |
|
123 | + */ |
|
124 | + public function serverParamIsSet(string $key): bool |
|
125 | + { |
|
126 | + return isset($this->server[ $key ]); |
|
127 | + } |
|
128 | + |
|
129 | + |
|
130 | + /** |
|
131 | + * @return string |
|
132 | + */ |
|
133 | + public function ipAddress(): string |
|
134 | + { |
|
135 | + return (string) $this->ip_address; |
|
136 | + } |
|
137 | + |
|
138 | + |
|
139 | + /** |
|
140 | + * attempt to get IP address of current visitor from server |
|
141 | + * plz see: http://stackoverflow.com/a/2031935/1475279 |
|
142 | + * |
|
143 | + * @return string |
|
144 | + */ |
|
145 | + private function setVisitorIp(): string |
|
146 | + { |
|
147 | + $visitor_ip = '0.0.0.0'; |
|
148 | + $server_keys = [ |
|
149 | + 'HTTP_CLIENT_IP', |
|
150 | + 'HTTP_FORWARDED', |
|
151 | + 'HTTP_FORWARDED_FOR', |
|
152 | + 'HTTP_X_CLUSTER_CLIENT_IP', |
|
153 | + 'HTTP_X_FORWARDED', |
|
154 | + 'HTTP_X_FORWARDED_FOR', |
|
155 | + 'REMOTE_ADDR', |
|
156 | + ]; |
|
157 | + foreach ($server_keys as $key) { |
|
158 | + if (isset($this->server[ $key ])) { |
|
159 | + $potential_ip = array_map('trim', explode(',', $this->server[ $key ])); |
|
160 | + foreach ($potential_ip as $ip) { |
|
161 | + if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) { |
|
162 | + $visitor_ip = $ip; |
|
163 | + } |
|
164 | + } |
|
165 | + } |
|
166 | + } |
|
167 | + return (string) $visitor_ip; |
|
168 | + } |
|
169 | + |
|
170 | + |
|
171 | + /** |
|
172 | + * Gets the request's literal URI. Related to `requestUriAfterSiteHomeUri`, see its description for a comparison. |
|
173 | + * |
|
174 | + * @param boolean $relativeToWpRoot If home_url() is "http://mysite.com/wp/", and a request comes to |
|
175 | + * "http://mysite.com/wp/wp-json", setting $relativeToWpRoot=true will return |
|
176 | + * "/wp-json", whereas $relativeToWpRoot=false will return "/wp/wp-json/". |
|
177 | + * @return string |
|
178 | + */ |
|
179 | + public function requestUri(bool $relativeToWpRoot = false): string |
|
180 | + { |
|
181 | + if ($relativeToWpRoot) { |
|
182 | + $home_path = parse_url(home_url(), PHP_URL_PATH); |
|
183 | + $home_path = trim((string) $home_path, '/'); |
|
184 | + $home_path = ! empty($home_path) |
|
185 | + ? trailingslashit($home_path) |
|
186 | + : $home_path; |
|
187 | + return str_replace($home_path, '', (string) ($this->server['REQUEST_URI'] ?? '')); |
|
188 | + } |
|
189 | + return $this->server['REQUEST_URI']; |
|
190 | + } |
|
191 | + |
|
192 | + |
|
193 | + /** |
|
194 | + * @return string |
|
195 | + */ |
|
196 | + public function userAgent(): string |
|
197 | + { |
|
198 | + if (empty($this->user_agent)) { |
|
199 | + $this->setUserAgent(); |
|
200 | + } |
|
201 | + return (string) $this->user_agent; |
|
202 | + } |
|
203 | + |
|
204 | + |
|
205 | + /** |
|
206 | + * @param string|null $user_agent |
|
207 | + */ |
|
208 | + public function setUserAgent(?string $user_agent = '') |
|
209 | + { |
|
210 | + $this->user_agent = $user_agent === '' || ! is_string($user_agent) |
|
211 | + ? (string) $this->getServerParam('HTTP_USER_AGENT', 'unknown') |
|
212 | + : (string) esc_attr($user_agent); |
|
213 | + } |
|
214 | 214 | } |