Completed
Push — develop ( 723be8...e4b26f )
by David
04:03
created

Wordlift_Uri_Service::build_uri()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 6
nop 4
dl 0
loc 57
rs 8.9381
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Services: URI Service.
4
 *
5
 * Define the {@link Wordlift_Uri_Service} responsible for managing entity URIs
6
 * (for posts, entities, authors, ...).
7
 *
8
 * @since   3.7.1
9
 * @package Wordlift
10
 */
11
12
/**
13
 * The {@link Wordlift_Uri_Service} class.
14
 *
15
 * @since   3.7.1
16
 * @package Wordlift
17
 */
18
class Wordlift_Uri_Service {
19
20
	/**
21
	 * The title regex to sanitize titles in paths.
22
	 *
23
	 * According to RFC2396 (http://www.ietf.org/rfc/rfc2396.txt) these characters are reserved:
24
	 * ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
25
	 * "$" | ","
26
	 *
27
	 * We also remove the space and the UTF-8 BOM sequence.
28
	 *
29
	 * @since 3.7.1
30
	 */
31
	const INVALID_CHARACTERS = "/[ ;\\/?:@&=\\+\\\$,]|(?:\\xEF\\xBB\\xBF)/";
32
33
	/**
34
	 * A {@link Wordlift_Log_Service} instance.
35
	 *
36
	 * @since  3.6.0
37
	 * @access private
38
	 * @var \Wordlift_Log_Service $log A {@link Wordlift_Log_Service} instance.
39
	 */
40
	private $log;
41
42
	/**
43
	 * The global WordPress database connection.
44
	 *
45
	 * @since  3.6.0
46
	 * @access private
47
	 * @var \wpdb $wpdb The global WordPress database connection.
48
	 */
49
	private $wpdb;
50
51
	/**
52
	 * The {@link Wordlift_Uri_Service} singleton instance.
53
	 *
54
	 * @since  3.7.2
55
	 * @access private
56
	 * @var \Wordlift_Uri_Service The {@link Wordlift_Uri_Service} singleton instance.
57
	 */
58
	private static $instance;
59
60
	/**
61
	 * Create an instance of Wordlift_Uri_Service.
62
	 *
63
	 * @since 3.6.0
64
	 *
65
	 * @param \wpdb $wpdb The global WordPress database connection.
66
	 */
67
	public function __construct( $wpdb ) {
68
69
		$this->log = Wordlift_Log_Service::get_logger( 'Wordlift_Uri_Service' );
70
71
		$this->wpdb = $wpdb;
72
73
		self::$instance = $this;
74
75
	}
76
77
	/**
78
	 * Get the {@link Wordlift_Uri_Service} singleton instance.
79
	 *
80
	 * @since 3.7.2
81
	 * @return \Wordlift_Uri_Service The {@link Wordlift_Uri_Service} singleton instance.
82
	 */
83
	public static function get_instance() {
84
85
		return self::$instance;
86
	}
87
88
	/**
89
	 * Delete all generated URIs from the database.
90
	 *
91
	 * @since 3.6.0
92
	 */
93
	public function delete_all() {
94
95
		$this->log->trace( 'Going to delete all the `entity_url` post metas...' );
96
97
		// Delete URIs associated with posts/entities.
98
		$this->wpdb->delete( $this->wpdb->postmeta, array( 'meta_key' => 'entity_url' ) );
99
100
		$this->log->trace( 'Going to delete all the `_wl_uri` user metas...' );
101
102
		// Delete URIs associated with authors.
103
		$this->wpdb->delete( $this->wpdb->usermeta, array( 'meta_key' => '_wl_uri' ) );
104
105
		$this->log->debug( '`entity_url` post metas and `_wl_uri` user metas deleted.' );
106
107
	}
108
109
	/**
110
	 * Sanitizes an URI path by replacing the non allowed characters with an underscore.
111
	 *
112
	 * @since 3.7.2
113
	 * @uses  sanitize_title() to manage not ASCII chars
114
	 *
115
	 * @see   https://codex.wordpress.org/Function_Reference/sanitize_title
116
	 *
117
	 * @param string $path The path to sanitize.
118
	 * @param string $char The replacement character (by default an underscore).
119
	 *
120
	 * @return string The sanitized path.
121
	 */
122
	public function sanitize_path( $path, $char = '_' ) {
123
124
		// Ensure the path is ASCII.
125
		// see https://github.com/insideout10/wordlift-plugin/issues/386
126
//		$path_ascii = mb_convert_encoding( $path, 'ASCII' );
127
128
		return sanitize_title( preg_replace( self::INVALID_CHARACTERS, $char, stripslashes( $path ) ) );
129
	}
130
131
	/**
132
	 * Build an entity uri for a given title. The uri is composed using a given
133
	 * post_type and a title. If already exists an entity e2 with a given uri a
134
	 * numeric suffix is added. If a schema type is given entities with same label
135
	 * and same type are overridden.
136
	 *
137
	 * @since 3.5.0
138
	 *
139
	 * @param string  $title A post title.
140
	 * @param string  $post_type A post type. Default value is 'entity'
141
	 * @param string  $schema_type A schema org type.
142
	 * @param integer $increment_digit A digit used to call recursively the same function.
143
	 *
144
	 * @return string Returns an uri.
145
	 */
146
	public function build_uri( $title, $post_type, $schema_type = null, $increment_digit = 0 ) {
147
148
		// Get the entity slug suffix digit
149
		$suffix_digit = $increment_digit + 1;
150
151
		// Get a sanitized uri for a given title.
152
		/*
153
		 * The call takes into consideration URL encoding.
154
		 *
155
		 * @see https://github.com/insideout10/wordlift-plugin/issues/885
156
		 *
157
		 * @since 3.20.0
158
		 */
159
		$entity_slug = urldecode( wl_sanitize_uri_path( $title ) )
0 ignored issues
show
Deprecated Code introduced by
The function wl_sanitize_uri_path() has been deprecated with message: use Wordlift_Uri_Service::get_instance()->sanitize_path();

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
160
		               . ( 0 === $increment_digit ? '' : '_' . $suffix_digit );
161
162
		// Compose a candidate uri.
163
		$new_entity_uri = sprintf( '%s/%s/%s',
164
			wl_configuration_get_redlink_dataset_uri(),
0 ignored issues
show
Deprecated Code introduced by
The function wl_configuration_get_redlink_dataset_uri() has been deprecated with message: use Wordlift_Configuration_Service::get_instance()->get_dataset_uri();

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
165
			$post_type,
166
			$entity_slug
167
		);
168
169
		$this->log->trace( "Going to check if uri is used [ new_entity_uri :: $new_entity_uri ] [ increment_digit :: $increment_digit ]" );
170
171
		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 global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
172
173
		// Check if the candidated uri already is used
174
		$stmt = $wpdb->prepare(
175
			"SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s LIMIT 1",
176
			WL_ENTITY_URL_META_NAME,
177
			$new_entity_uri
178
		);
179
180
		// Perform the query
181
		$post_id = $wpdb->get_var( $stmt );
182
183
		// If the post does not exist, then the new uri is returned
184
		if ( ! is_numeric( $post_id ) ) {
185
			$this->log->trace( "Going to return uri [ new_entity_uri :: $new_entity_uri ]" );
186
187
			return $new_entity_uri;
188
		}
189
190
		// If schema_type is equal to schema org type of post x, then the new uri is returned
191
		$schema_post_type = Wordlift_Entity_Type_Service::get_instance()->get( $post_id );
192
193
		// @todo: we shouldn't rely on css classes to take such decisions.
194
		if ( $schema_type === $schema_post_type['css_class'] ) {
195
			$this->log->trace( "An entity with the same title and type already exists! Return uri [ new_entity_uri :: $new_entity_uri ]" );
196
197
			return $new_entity_uri;
198
		}
199
200
		// Otherwise the same function is called recursively
201
		return $this->build_uri( $title, $post_type, $schema_type, ++ $increment_digit );
202
	}
203
204
}
205