Completed
Push — master ( eef885...465d0c )
by
unknown
30:08 queued 12:49
created

Term_Class   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 272
Duplicated Lines 9.93 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 27
loc 272
rs 10
c 0
b 0
f 0
wmc 28
lcom 1
cbo 3

9 Methods

Rating   Name   Duplication   Size   Complexity  
A construct() 0 1 1
A get_schema() 0 5 1
C get() 27 58 13
A create() 0 3 1
C update() 0 37 8
A delete() 0 3 1
A get_taxonomy() 0 3 1
A get_post_type() 0 3 1
A get_identifier_helper() 0 3 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Gestion des termes (POST, PUT, GET, DELETE)
4
 *
5
 * @author Jimmy Latour <[email protected]>
6
 * @since 1.0.0.0
7
 * @version 1.3.0.0
8
 * @copyright 2015-2017
9
 * @package wpeo_model
10
 * @subpackage class
11
 */
12
13
namespace eoxia;
14
15
if ( ! defined( 'ABSPATH' ) ) { exit; }
16
17
if ( ! class_exists( '\eoxia\Term_Class' ) ) {
18
	/**
19
	 * Gestion des termes (POST, PUT, GET, DELETE)
20
	 */
21
	class Term_Class extends Singleton_Util {
22
23
		/**
24
		 * Le nom du modèle
25
		 *
26
		 * @var string
27
		 */
28
		protected $model_name = 'term_model';
29
30
		/**
31
		 * La clé principale pour post_meta
32
		 *
33
		 * @var string
34
		 */
35
		protected $meta_key = '_wpeo_term';
36
37
		/**
38
		 * Le nom de la taxonomie
39
		 *
40
		 * @var string
41
		 */
42
		protected $taxonomy = 'category';
43
44
		/**
45
		 * Utiles pour récupérer la clé unique
46
		 *
47
		 * @todo Rien à faire ici
48
		 * @var string
49
		 */
50
		protected $identifier_helper = 'term';
51
52
		/**
53
		 * Fonction de callback après avoir récupérer le modèle en mode GET.
54
		 *
55
		 * @var array
56
		 */
57
		protected $after_get_function = array();
58
59
		/**
60
		 * Fonction de callback avant d'insérer les données en mode POST.
61
		 *
62
		 * @var array
63
		 */
64
		protected $before_post_function = array();
65
66
		/**
67
		 * Fonction de callback après avoir inséré les données en mode POST.
68
		 *
69
		 * @var array
70
		 */
71
		protected $after_post_function = array();
72
73
		/**
74
		 * Fonction de callback avant de mêttre à jour les données en mode PUT.
75
		 *
76
		 * @var array
77
		 */
78
		protected $before_put_function = array();
79
80
		/**
81
		 * Fonction de callback après avoir mis à jour les données en mode PUT.
82
		 *
83
		 * @var array
84
		 */
85
		protected $after_put_function = array();
86
87
		/**
88
		 * Le constructeur
89
		 *
90
		 * @return void
91
		 *
92
		 * @since 1.0.0.0
93
		 * @version 1.3.0.0
94
		 */
95
		protected function construct() {}
96
97
		/**
98
		 * Permet de récupérer le schéma avec les données du modèle par défault.
99
		 *
100
		 * @since 1.0.0.0
101
		 * @version 1.3.0.0
102
		 *
103
		 * @return Object
104
		 */
105
		public function get_schema() {
106
			$model_name = $this->model_name;
107
			$model = new $model_name( array(), array() );
108
			return $model->get_model();
109
		}
110
111
		/**
112
		 * Récupères les données selon le modèle définis.
113
		 *
114
		 * @since 1.0.0.0
115
		 * @version 1.3.0.0
116
		 *
117
		 * @param array   $args Les paramètres de get_terms @https://codex.wordpress.org/Function_Reference/get_terms.
118
		 * @param boolean $single Si on veut récupérer un tableau, ou qu'une seule entrée.
119
		 *
120
		 * @return Object
121
		 */
122
		public function get( $args = array(), $single = false ) {
123
			$list_term = array();
124
			$array_term = array();
125
126
			$model_name = $this->model_name;
127
128
			$term_final_args = array_merge( $args, array(
129
				'hide_empty' => false,
130
			) );
131
132
			if ( ! empty( $args['id'] ) ) {
133
				$array_term[] = get_term_by( 'id', $args['id'], $this->taxonomy, ARRAY_A );
134
			} elseif ( ! empty( $args['post_id'] ) ) {
135
				$array_term = wp_get_post_terms( $args['post_id'], $this->taxonomy, $term_final_args );
136
137
				if ( empty( $array_term ) ) {
138
					$array_term[] = array();
139
				}
140
			} elseif ( isset( $args['schema'] ) ) {
141
				$array_term[] = array();
142
			} else {
143
				$array_term = get_terms( $this->taxonomy, $term_final_args );
144
			}
145
146 View Code Duplication
			if ( ! empty( $array_term ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
147
				foreach ( $array_term as $key => $term ) {
148
					$term = (array) $term;
149
150
					if ( ! empty( $args['post_id'] ) ) {
151
						$term['post_id'] = $args['post_id'];
152
					}
153
154
					if ( ! empty( $term['term_id'] ) ) {
155
						$list_meta = get_term_meta( $term['term_id'] );
156
						foreach ( $list_meta as &$meta ) {
157
							$meta = array_shift( $meta );
158
						}
159
160
						$term = array_merge( $term, $list_meta );
161
162
						if ( ! empty( $term[ $this->meta_key ] ) ) {
163
							$term = array_merge( $term, json_decode( $term[ $this->meta_key ], true ) );
164
							unset( $term[ $this->meta_key ] );
165
						}
166
					}
167
168
					$list_term[ $key ] = new $model_name( $term );
169
170
					$list_term[ $key ] = Model_Util::exec_callback( $list_term[ $key ], $this->after_get_function );
171
				}
172
			}
173
174
			if ( true === $single && 1 === count( $list_term ) ) {
175
				$list_term = $list_term[0];
176
			}
177
178
			return $list_term;
179
		}
180
181
		/**
182
		 * Appelle la méthode update.
183
		 *
184
		 * @since 1.0.0.0
185
		 * @version 1.3.0.0
186
		 *
187
		 * @param  Array $data Les données.
188
		 * @return Array $data Les données
189
		 */
190
		public function create( $data ) {
191
			return $this->update( $data );
192
		}
193
194
		/**
195
		 * Insère ou met à jour les données dans la base de donnée.
196
		 *
197
		 * @since 1.0.0.0
198
		 * @version 1.3.0.0
199
		 *
200
		 * @param  Array $data Les données a insérer ou à mêttre à jour.
201
		 * @return Object      L'objet construit grâce au modèle.
202
		 */
203
		public function update( $data ) {
204
			$model_name = $this->model_name;
205
			$object = new $model_name( (array) $data );
206
207
			/**	Sauvegarde des données dans la base de données / Save data into database	*/
208
			if ( empty( $object->id ) ) {
209
				$object = Model_Util::exec_callback( $object, $this->before_post_function );
210
				$wp_category_danger = wp_insert_term( $object->name, $this->get_taxonomy(), array(
211
					'description'	=> ! empty( $object->description ) ? $object->description : '',
212
					'slug'	=> ! empty( $object->slug ) ? $object->slug : sanitize_title( $object->name ),
213
					'parent'	=> ! empty( $object->parent_id ) ? (int) $object->parent_id : 0,
214
				) );
215
				$object = Model_Util::exec_callback( $object, $this->after_post_function );
216
			} else {
217
				$object = Model_Util::exec_callback( $object, $this->before_put_function );
218
				$wp_category_danger = wp_update_term( $object->id, $this->get_taxonomy(), $object->do_wp_object() );
219
				$object = Model_Util::exec_callback( $object, $this->after_put_function );
220
			}
221
222
			if ( ! is_wp_error( $wp_category_danger ) ) {
223
				$object->id = $wp_category_danger['term_id'];
224
				$object->term_taxonomy_id = $wp_category_danger['term_taxonomy_id'];
225
226
				save_meta_class::g()->save_meta_data( $object, 'update_term_meta', $this->meta_key );
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class eoxia\Singleton_Util as the method save_meta_data() does only exist in the following sub-classes of eoxia\Singleton_Util: eoxia\Save_Meta_Class. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
227
			} else {
228
				if ( ! empty( $wp_category_danger->error_data['term_exists'] ) && is_int( $wp_category_danger->error_data['term_exists'] ) ) {
229
					$list_term_model = $this->get( array(
230
						'id' => $wp_category_danger->error_data['term_exists'],
231
					) );
232
					return $list_term_model[0];
233
				} else {
234
					return array();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array(); (array) is incompatible with the return type documented by eoxia\Term_Class::update of type object.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
235
				}
236
			}
237
238
			return $object;
239
		}
240
241
		/**
242
		 * Supprime un term
243
		 *
244
		 * @todo: Inutile ?
245
		 *
246
		 * @since 1.0.0.0
247
		 * @version 1.3.0.0
248
		 *
249
		 * @param int $id L'ID du term (term_id).
250
		 */
251
		public function delete( $id ) {
252
			wp_delete_term( $id );
253
		}
254
255
		/**
256
		 * Récupères la taxonomie
257
		 *
258
		 * @since 1.0.0.0
259
		 * @version 1.3.6.0
260
		 *
261
		 * @return string Le nom de la taxonomie
262
		 */
263
		public function get_taxonomy() {
264
			return $this->taxonomy;
265
		}
266
267
		/**
268
		 * Retourne la taxonomie
269
		 *
270
		 * @since 1.0.0.0
271
		 * @version 1.3.0.0
272
		 *
273
		 * @return string Le post type
274
		 *
275
		 * @todo: Doublon
276
		 */
277
		public function get_post_type() {
278
			return $this->get_taxonomy();
279
		}
280
281
		/**
282
		 * Utile uniquement pour DigiRisk.
283
		 *
284
		 * @since 1.0.0.0
285
		 * @version 1.3.0.0
286
		 *
287
		 * @return string L'identifiant des commentaires pour DigiRisk.
288
		 */
289
		public function get_identifier_helper() {
290
			return $this->identifier_helper;
291
		}
292
	}
293
} // End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% 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...
294