amarkal /
amarkal-taxonomy
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 all the registered fields for each taxonomy |
||
| 17 | */ |
||
| 18 | private $fields = 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 ) |
||
| 28 | { |
||
| 29 | static::$instance = new static(); |
||
| 30 | } |
||
| 31 | return static::$instance; |
||
| 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 string $field_name |
||
| 39 | * @param array $field_props |
||
| 40 | * @throws \RuntimeException if duplicate names are registered under the same taxonomy |
||
| 41 | */ |
||
| 42 | public function add_field( $taxonomy_name, $field_name, $field_props ) |
||
| 43 | { |
||
| 44 | if( !isset($this->fields[$taxonomy_name]) ) |
||
| 45 | { |
||
| 46 | // Add fields to taxonomy add and edit forms |
||
| 47 | add_action( "{$taxonomy_name}_add_form_fields", array($this, 'render_add_form') ); |
||
| 48 | add_action( "{$taxonomy_name}_edit_form_fields", array($this, 'render_edit_form') ); |
||
| 49 | |||
| 50 | // Save the data from taxonomy add and edit forms |
||
| 51 | add_action( "create_{$taxonomy_name}", array($this, 'update_term') ); |
||
| 52 | add_action( "edited_{$taxonomy_name}", array($this, 'update_term') ); |
||
| 53 | |||
| 54 | // Modify the taxonomy term table |
||
| 55 | add_filter( "manage_edit-{$taxonomy_name}_columns", array($this, 'modify_table_columns') ); |
||
| 56 | add_filter( "manage_{$taxonomy_name}_custom_column", array($this, 'modify_table_content'), 10, 3 ); |
||
| 57 | add_filter( "manage_edit-{$taxonomy_name}_sortable_columns", array($this, 'modify_table_sortable_columns') ); |
||
| 58 | add_filter( 'terms_clauses', array($this, 'sort_custom_column'), 10, 3 ); |
||
| 59 | |||
| 60 | $this->fields[$taxonomy_name] = array(); |
||
| 61 | } |
||
| 62 | |||
| 63 | if( !isset($this->fields[$taxonomy_name][$field_name])) |
||
| 64 | { |
||
| 65 | $this->fields[$taxonomy_name][$field_name] = array_merge( $this->default_props(), $field_props ); |
||
| 66 | } |
||
| 67 | else throw new \RuntimeException("A field named '$field_name' has already been registered in '$taxonomy_name'"); |
||
| 68 | } |
||
| 69 | |||
| 70 | /** |
||
| 71 | * Render the 'edit term' form for a given taxonomy |
||
| 72 | * |
||
| 73 | * @param object $term Taxonomy term |
||
| 74 | */ |
||
| 75 | public function render_edit_form( $term ) |
||
| 76 | { |
||
| 77 | $fields = $this->fields[$term->taxonomy]; |
||
| 78 | |||
| 79 | foreach( $fields as $name => $props ) |
||
| 80 | { |
||
| 81 | $props['name'] = $name; |
||
| 82 | $props['term_id'] = $term->term_id; |
||
| 83 | $field = new EditField($props); |
||
| 84 | echo $field->render(); |
||
| 85 | } |
||
| 86 | } |
||
| 87 | |||
| 88 | /** |
||
| 89 | * Render the 'add new term' form for a given taxonomy |
||
| 90 | * |
||
| 91 | * @param string $taxonomy Taxonomy name |
||
| 92 | */ |
||
| 93 | public function render_add_form( $taxonomy ) |
||
| 94 | { |
||
| 95 | $fields = $this->fields[$taxonomy]; |
||
| 96 | |||
| 97 | foreach( $fields as $name => $props ) |
||
| 98 | { |
||
| 99 | $props['name'] = $name; |
||
| 100 | $field = new AddField($props); |
||
| 101 | echo $field->render(); |
||
| 102 | } |
||
| 103 | } |
||
| 104 | |||
| 105 | /** |
||
| 106 | * Update the meta values for a given term. Called once one of the add/edit |
||
| 107 | * forms is saved. |
||
| 108 | * |
||
| 109 | * @param type $term_id |
||
| 110 | */ |
||
| 111 | function update_term( $term_id ) |
||
| 112 | { |
||
| 113 | $term = \get_term( $term_id ); |
||
| 114 | |||
| 115 | foreach( $this->fields[$term->taxonomy] as $name => $props ) |
||
| 116 | { |
||
| 117 | if( isset($_POST[$name]) ) |
||
| 118 | { |
||
| 119 | update_term_meta($term_id, $name, filter_input(INPUT_POST, $name)); |
||
| 120 | } |
||
| 121 | } |
||
| 122 | } |
||
| 123 | |||
| 124 | /** |
||
| 125 | * Add additional columns to the term table. |
||
| 126 | * |
||
| 127 | * @param array $columns |
||
| 128 | * @return array |
||
| 129 | */ |
||
| 130 | View Code Duplication | function modify_table_columns( $columns ) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 131 | { |
||
| 132 | foreach( $this->fields as $fields ) |
||
| 133 | { |
||
| 134 | foreach( $fields as $name => $props ) |
||
| 135 | { |
||
| 136 | if( $props['table']['show'] ) |
||
| 137 | { |
||
| 138 | $columns[$name] = $props['label']; |
||
| 139 | } |
||
| 140 | } |
||
| 141 | } |
||
| 142 | return $columns; |
||
| 143 | } |
||
| 144 | |||
| 145 | /** |
||
| 146 | * Retrieve the data for a given column in the term table. |
||
| 147 | * |
||
| 148 | * @see https://developer.wordpress.org/reference/hooks/manage_this-screen-taxonomy_custom_column/ |
||
| 149 | * |
||
| 150 | * @param type $content |
||
| 151 | * @param type $column_name |
||
| 152 | * @param type $term_id |
||
| 153 | * @return type |
||
| 154 | */ |
||
| 155 | function modify_table_content( $content, $column_name, $term_id ) |
||
|
0 ignored issues
–
show
|
|||
| 156 | { |
||
| 157 | $term = \get_term($term_id); |
||
| 158 | foreach( $this->fields as $taxonomy => $fields ) |
||
| 159 | { |
||
| 160 | foreach( $fields as $name => $props ) |
||
| 161 | { |
||
| 162 | if( $props['table']['show'] && |
||
| 163 | $term->taxonomy === $taxonomy && |
||
| 164 | $name === $column_name |
||
| 165 | ) { |
||
| 166 | $content = \get_term_meta($term_id, $name, true); |
||
| 167 | } |
||
| 168 | } |
||
| 169 | } |
||
| 170 | return $content; |
||
| 171 | } |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Make custom table columns sortable. |
||
| 175 | * |
||
| 176 | * @param array $columns |
||
| 177 | * @return string |
||
| 178 | */ |
||
| 179 | View Code Duplication | function modify_table_sortable_columns( $columns ) |
|
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. Loading history...
|
|||
| 180 | { |
||
| 181 | foreach( $this->fields as $taxonomy => $fields ) |
||
| 182 | { |
||
| 183 | foreach( $fields as $name => $props ) |
||
| 184 | { |
||
| 185 | if( $props['table']['show'] && |
||
| 186 | $props['table']['sortable'] |
||
| 187 | ) { |
||
| 188 | $columns[$name] = $name; |
||
| 189 | } |
||
| 190 | } |
||
| 191 | } |
||
| 192 | return $columns; |
||
| 193 | } |
||
| 194 | |||
| 195 | /** |
||
| 196 | * Modify terms_clauses to allow sorting custom WordPress Admin Table Columns by a custom Taxonomy Term meta |
||
| 197 | * |
||
| 198 | * @see https://developer.wordpress.org/reference/hooks/terms_clauses/ |
||
| 199 | * |
||
| 200 | * @global type $wpdb |
||
| 201 | * @param type $clauses |
||
| 202 | * @param type $taxonomies |
||
| 203 | * @param type $args |
||
| 204 | * @return string |
||
| 205 | */ |
||
| 206 | function sort_custom_column( $clauses, $taxonomies, $args ) |
||
|
0 ignored issues
–
show
|
|||
| 207 | { |
||
| 208 | foreach( $this->fields as $taxonomy => $fields ) |
||
| 209 | { |
||
| 210 | // if( in_array($taxonomy, $args['taxonomy']) && 'icon' === $args['orderby']) |
||
|
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
66% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. Loading history...
|
|||
| 211 | foreach( $fields as $name => $props ) |
||
| 212 | { |
||
| 213 | if( in_array($taxonomy, $args['taxonomy']) && |
||
| 214 | $props['table']['show'] && |
||
| 215 | $props['table']['sortable'] && |
||
| 216 | $name === $args['orderby'] |
||
| 217 | ) |
||
| 218 | { |
||
| 219 | $this->modify_term_clauses( $clauses, $taxonomy, $name ); |
||
| 220 | } |
||
| 221 | } |
||
| 222 | } |
||
| 223 | return $clauses; |
||
| 224 | } |
||
| 225 | |||
| 226 | /** |
||
| 227 | * Modify the orderby clauses for a given taxonomy |
||
| 228 | * |
||
| 229 | * @param array $clauses |
||
| 230 | * @param string $taxonomy |
||
| 231 | * @param string $termmeta |
||
| 232 | */ |
||
| 233 | function modify_term_clauses( &$clauses, $taxonomy, $termmeta ) |
||
|
0 ignored issues
–
show
|
|||
| 234 | { |
||
| 235 | global $wpdb; |
||
|
0 ignored issues
–
show
Compatibility
Best Practice
introduced
by
Use of
global functionality is not recommended; it makes your code harder to test, and less reusable.
Instead of relying on 1. Pass all data via parametersfunction myFunction($a, $b) {
// Do something
}
2. Create a class that maintains your stateclass MyClass {
private $a;
private $b;
public function __construct($a, $b) {
$this->a = $a;
$this->b = $b;
}
public function myFunction() {
// Do something
}
}
Loading history...
|
|||
| 236 | // tt refers to the $wpdb->term_taxonomy table |
||
| 237 | $clauses['join'] .= " LEFT JOIN {$wpdb->termmeta} AS tm ON t.term_id = tm.term_id"; |
||
| 238 | $clauses['where'] = "tt.taxonomy = '{$taxonomy}' AND (tm.meta_key = '{$termmeta}' OR tm.meta_key IS NULL)"; |
||
| 239 | $clauses['orderby'] = "ORDER BY tm.meta_value"; |
||
| 240 | } |
||
| 241 | |||
| 242 | /** |
||
| 243 | * The default form field properties. This is merged with the user given |
||
| 244 | * properties. When the component is rendered, this will be merged with the |
||
| 245 | * component's properties as well. |
||
| 246 | * |
||
| 247 | * @return array |
||
| 248 | */ |
||
| 249 | private function default_props() |
||
| 250 | { |
||
| 251 | return array( |
||
| 252 | 'type' => null, |
||
| 253 | 'label' => null, |
||
| 254 | 'description' => null, |
||
| 255 | 'table' => array( |
||
| 256 | 'show' => false, |
||
| 257 | 'sortable' => false |
||
| 258 | ) |
||
| 259 | ); |
||
| 260 | } |
||
| 261 | } |
Adding explicit visibility (
private,protected, orpublic) is generally recommend to communicate to other developers how, and from where this method is intended to be used.