This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Amarkal\Taxonomy; |
||
4 | |||
5 | /** |
||
6 | * WordPress taxonomy form utilities |
||
7 | */ |
||
8 | class Form |
||
9 | { |
||
10 | /** |
||
11 | * @var Singleton The reference to *Singleton* instance of this class |
||
12 | */ |
||
13 | private static $instance; |
||
14 | |||
15 | /** |
||
16 | * @var Array Stores a form for each taxonomy |
||
17 | */ |
||
18 | private $forms = array(); |
||
19 | |||
20 | /** |
||
21 | * Returns the *Singleton* instance of this class. |
||
22 | * |
||
23 | * @return Singleton The *Singleton* instance. |
||
24 | */ |
||
25 | public static function get_instance() |
||
26 | { |
||
27 | if( null === static::$instance ) |
||
0 ignored issues
–
show
|
|||
28 | { |
||
29 | static::$instance = new static(); |
||
0 ignored issues
–
show
Since
$instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self , or increasing the visibility of $instance to at least protected.
Let’s assume you have a class which uses late-static binding: class YourClass
{
private static $someVariable;
public static function getSomeVariable()
{
return static::$someVariable;
}
}
The code above will run fine in your PHP runtime. However, if you now create a
sub-class and call the class YourSubClass extends YourClass { }
YourSubClass::getSomeVariable(); // Will cause an access error.
In the case above, it makes sense to update class SomeClass
{
private static $someVariable;
public static function getSomeVariable()
{
return self::$someVariable; // self works fine with private.
}
}
![]() It seems like
new static() of type this<Amarkal\Taxonomy\Form> is incompatible with the declared type object<Amarkal\Taxonomy\Singleton> of property $instance .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
30 | } |
||
31 | return static::$instance; |
||
0 ignored issues
–
show
Since
$instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self , or increasing the visibility of $instance to at least protected.
Let’s assume you have a class which uses late-static binding: class YourClass
{
private static $someVariable;
public static function getSomeVariable()
{
return static::$someVariable;
}
}
The code above will run fine in your PHP runtime. However, if you now create a
sub-class and call the class YourSubClass extends YourClass { }
YourSubClass::getSomeVariable(); // Will cause an access error.
In the case above, it makes sense to update class SomeClass
{
private static $someVariable;
public static function getSomeVariable()
{
return self::$someVariable; // self works fine with private.
}
}
![]() |
|||
32 | } |
||
33 | |||
34 | /** |
||
35 | * Add a form field to both the add & edit forms for a given taxonomy. |
||
36 | * |
||
37 | * @param string $taxonomy_name |
||
38 | * @param array $component |
||
39 | * @throws \RuntimeException if duplicate names are registered under the same taxonomy |
||
40 | */ |
||
41 | public function add_field( $taxonomy_name, $component ) |
||
42 | { |
||
43 | if( !isset($this->forms[$taxonomy_name]) ) |
||
44 | { |
||
45 | // Add fields to taxonomy add and edit forms |
||
46 | add_action( "{$taxonomy_name}_add_form_fields", array($this, 'render_add_form') ); |
||
47 | add_action( "{$taxonomy_name}_edit_form_fields", array($this, 'render_edit_form') ); |
||
48 | |||
49 | // Save the data from taxonomy add and edit forms |
||
50 | add_action( "create_{$taxonomy_name}", array($this, 'update_term') ); |
||
51 | add_action( "edited_{$taxonomy_name}", array($this, 'update_term') ); |
||
52 | |||
53 | // Modify the taxonomy term table |
||
54 | add_filter( "manage_edit-{$taxonomy_name}_columns", array($this, 'modify_table_columns') ); |
||
55 | add_filter( "manage_{$taxonomy_name}_custom_column", array($this, 'modify_table_content'), 10, 3 ); |
||
56 | add_filter( "manage_edit-{$taxonomy_name}_sortable_columns", array($this, 'modify_table_sortable_columns') ); |
||
57 | add_filter( 'terms_clauses', array($this, 'sort_custom_column'), 10, 3 ); |
||
58 | |||
59 | $this->forms[$taxonomy_name] = new \Amarkal\UI\Form(); |
||
60 | } |
||
61 | |||
62 | $this->forms[$taxonomy_name]->add_component( |
||
63 | array_merge( $this->default_props(), $component ) |
||
64 | ); |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * Render the 'edit term' form for a given taxonomy |
||
69 | * |
||
70 | * @param object $term Taxonomy term |
||
71 | */ |
||
72 | public function render_edit_form( $term ) |
||
73 | { |
||
74 | $form = $this->forms[$term->taxonomy]; |
||
75 | $new_instance = array(); |
||
76 | |||
77 | foreach( $form->get_components() as $component ) |
||
78 | { |
||
79 | $new_instance[$component->name] = \get_term_meta($term->term_id, $component->name, true); |
||
80 | } |
||
81 | |||
82 | $form->update($new_instance); |
||
83 | |||
84 | include __DIR__.'/EditForm.phtml'; |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * Render the 'add new term' form for a given taxonomy |
||
89 | * |
||
90 | * @param string $taxonomy Taxonomy name |
||
91 | */ |
||
92 | public function render_add_form( $taxonomy ) |
||
93 | { |
||
94 | $form = $this->forms[$taxonomy]; |
||
95 | $form->update(); |
||
96 | |||
97 | include __DIR__.'/AddForm.phtml'; |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * Update the meta values for a given term. Called once one of the add/edit |
||
102 | * forms is saved. |
||
103 | * |
||
104 | * @param type $term_id |
||
105 | */ |
||
106 | function update_term( $term_id ) |
||
107 | { |
||
108 | $term = \get_term( $term_id ); |
||
109 | |||
110 | foreach( $this->forms[$term->taxonomy]->get_components() as $component ) |
||
111 | { |
||
112 | $term_meta = filter_input(INPUT_POST, $component->name); |
||
113 | if( null !== $term_meta ) |
||
114 | { |
||
115 | \update_term_meta($term_id, $component->name, $term_meta); |
||
116 | } |
||
117 | } |
||
118 | } |
||
119 | |||
120 | /** |
||
121 | * Add additional columns to the term table. |
||
122 | * |
||
123 | * @param array $columns |
||
124 | * @return array |
||
125 | */ |
||
126 | View Code Duplication | function modify_table_columns( $columns ) |
|
127 | { |
||
128 | $this->traverse_components(function( $taxonomy, $component ) use ( &$columns ) |
||
129 | { |
||
130 | if( $component->table['show'] ) |
||
131 | { |
||
132 | $columns[$component->name] = $component->title; |
||
133 | } |
||
134 | }); |
||
135 | return $columns; |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Retrieve the data for a given column in the term table. |
||
140 | * |
||
141 | * @see https://developer.wordpress.org/reference/hooks/manage_this-screen-taxonomy_custom_column/ |
||
142 | * |
||
143 | * @param type $content |
||
144 | * @param type $column_name |
||
145 | * @param type $term_id |
||
146 | * @return type |
||
147 | */ |
||
148 | function modify_table_content( $content, $column_name, $term_id ) |
||
149 | { |
||
150 | $term = \get_term($term_id); |
||
151 | $this->traverse_components(function( $taxonomy, $component ) use ( &$content, $column_name, $term ) |
||
152 | { |
||
153 | if( $component->table['show'] && |
||
154 | $term->taxonomy === $taxonomy && |
||
155 | $component->name === $column_name |
||
156 | ) { |
||
157 | $content = \get_term_meta($term->term_id, $component->name, true); |
||
158 | } |
||
159 | }); |
||
160 | return $content; |
||
161 | } |
||
162 | |||
163 | /** |
||
164 | * Make custom table columns sortable. |
||
165 | * |
||
166 | * @param array $columns |
||
167 | * @return string |
||
168 | */ |
||
169 | View Code Duplication | function modify_table_sortable_columns( $columns ) |
|
170 | { |
||
171 | $this->traverse_components(function( $taxonomy, $component ) use ( &$columns ) |
||
172 | { |
||
173 | if( $component->table['show'] && |
||
174 | $component->table['sortable'] |
||
175 | ) { |
||
176 | $columns[$component->name] = $component->name; |
||
177 | } |
||
178 | }); |
||
179 | return $columns; |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * Modify terms_clauses to allow sorting custom WordPress Admin Table Columns by a custom Taxonomy Term meta |
||
184 | * |
||
185 | * @see https://developer.wordpress.org/reference/hooks/terms_clauses/ |
||
186 | * |
||
187 | * @global type $wpdb |
||
188 | * @param type $clauses |
||
189 | * @param type $taxonomies |
||
190 | * @param type $args |
||
191 | * @return string |
||
192 | */ |
||
193 | public function sort_custom_column( $clauses, $taxonomies, $args ) |
||
194 | { |
||
195 | $this->traverse_components(function( $taxonomy, $component ) use ( &$clauses, $args ) |
||
196 | { |
||
197 | if( in_array($taxonomy, $args['taxonomy']) && |
||
198 | $component->table['sortable'] && |
||
199 | $component->name === $args['orderby'] |
||
200 | ) |
||
201 | { |
||
202 | global $wpdb; |
||
203 | // tt refers to the $wpdb->term_taxonomy table |
||
204 | $clauses['join'] .= " LEFT JOIN {$wpdb->termmeta} AS tm ON t.term_id = tm.term_id"; |
||
205 | $clauses['where'] = "tt.taxonomy = '{$taxonomy}' AND (tm.meta_key = '{$component->name}' OR tm.meta_key IS NULL)"; |
||
206 | $clauses['orderby'] = "ORDER BY tm.meta_value"; |
||
207 | } |
||
208 | }); |
||
209 | return $clauses; |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * The default form field properties. This is merged with the user given |
||
214 | * properties. When the component is rendered, this will be merged with the |
||
215 | * component's properties as well. |
||
216 | * |
||
217 | * @return array |
||
218 | */ |
||
219 | private function default_props() |
||
220 | { |
||
221 | return array( |
||
222 | 'type' => null, |
||
223 | 'title' => null, |
||
224 | 'description' => null, |
||
225 | 'table' => array( |
||
226 | 'show' => false, |
||
227 | 'sortable' => false |
||
228 | ) |
||
229 | ); |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * Treverse the $fields array. |
||
234 | * |
||
235 | * @param collable $callback Called on each iteration |
||
236 | */ |
||
237 | private function traverse_components( $callback ) |
||
238 | { |
||
239 | foreach( $this->forms as $taxonomy => $form ) |
||
240 | { |
||
241 | foreach( $form->get_components() as $component ) |
||
242 | { |
||
243 | $callback( $taxonomy, $component ); |
||
244 | } |
||
245 | } |
||
246 | } |
||
247 | } |
Let’s assume you have a class which uses late-static binding:
The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the
getSomeVariable()
on that sub-class, you will receive a runtime error:In the case above, it makes sense to update
SomeClass
to useself
instead: