Completed
Push — master ( c336cf...9cad87 )
by David
30:41
created

Wordlift_Publisher_Service::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Services: Publisher Service.
4
 *
5
 * The Publisher service provides functions to list potential publishers.
6
 *
7
 * @since      3.11.0
8
 * @package    Wordlift
9
 * @subpackage Wordlift/includes
10
 */
11
12
/**
13
 * Define the {@link Wordlift_Publisher_Service} class.
14
 *
15
 * @since      3.11.0
16
 * @package    Wordlift
17
 * @subpackage Wordlift/includes
18
 */
19
class Wordlift_Publisher_Service {
20
21
	/**
22
	 * The {@link Wordlift_Configuration_Service} instance.
23
	 *
24
	 * @since  3.19.0
25
	 * @access private
26
	 * @var \Wordlift_Configuration_Service $configuration_service The {@link Wordlift_Configuration_Service} instance.
27
	 */
28
	private $configuration_service;
29
30
	/**
31
	 * The {@link Wordlift_Publisher_Service} instance.
32
	 *
33
	 * @since 3.19.0
34
	 *
35
	 * @param \Wordlift_Configuration_Service $configuration_service The {@link Wordlift_Configuration_Service} instance.
36
	 */
37
	public function __construct( $configuration_service ) {
38
		$this->configuration_service = $configuration_service;
39
	}
40
41
	/**
42
	 * Counts the number of potential publishers.
43
	 *
44
	 * @since 3.11.0
45
	 *
46
	 * @return int The number of potential publishers.
47
	 */
48 View Code Duplication
	public function count() {
0 ignored issues
show
Duplication introduced by
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...
49
50
		// Search for entities which are either a Person
51
		// or Organization.
52
53
		// Get only the ids as all we need is the count.
54
		$entities = get_posts( array(
55
			'post_type'      => Wordlift_Entity_Service::valid_entity_post_types(),
56
			'post_status'    => 'publish',
57
			'posts_per_page' => - 1,
58
			'tax_query'      => array(
59
				array(
60
					'taxonomy' => Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME,
61
					'field'    => 'slug',
62
					'terms'    => array( 'organization', 'person' ),
63
				),
64
			),
65
			'fields'         => 'ids',
66
		) );
67
68
		// Finally return the count.
69
		return count( $entities );
70
	}
71
72
	/**
73
	 * Search SQL filter for matching against post title only.
74
	 *
75
	 * @link    http://wordpress.stackexchange.com/a/11826/1685
76
	 *
77
	 * @since   3.15.0
78
	 *
79
	 * @param   string   $search   The search string.
80
	 * @param   WP_Query $wp_query The {@link WP_Query} instance.
81
	 *
82
	 * @return array|string An array of results.
83
	 */
84
	public function limit_search_to_title( $search, $wp_query ) {
85
86
		// Bail out if the search or the `search_terms` haven't been set.
87
		if ( empty( $search ) || empty( $wp_query->query_vars['search_terms'] ) ) {
88
			return $search;
89
		}
90
91
		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...
92
93
		$query_vars = $wp_query->query_vars;
94
		$percent    = ! empty( $query_vars['exact'] ) ? '' : '%';
95
		$search     = array();
96
97
		foreach ( (array) $query_vars['search_terms'] as $term ) {
98
			$search[] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $percent . $wpdb->esc_like( $term ) . $percent );
99
		}
100
101
		if ( ! is_user_logged_in() ) {
102
			$search[] = "$wpdb->posts.post_password = ''";
103
		}
104
105
		$search = ' AND ' . implode( ' AND ', $search );
106
107
		return $search;
108
	}
109
110
	/**
111
	 * Query WP for potential publishers, i.e. {@link WP_Post}s which are associated`
112
	 * with `wl_entity_type` (taxonomy) terms of `Organization` or `Person`.
113
	 *
114
	 * @since 3.11.0
115
	 *
116
	 * @param string $filter The title filter.
117
	 *
118
	 * @return array An array of results in a select2 friendly format.
119
	 */
120
	public function query( $filter = '' ) {
121
122
		// Search for the filter in the titles only.
123
		add_filter( 'posts_search', array(
124
			$this,
125
			'limit_search_to_title',
126
		), 10, 2 );
127
128
		/*
129
		 * Search for entities which are either a Person
130
		 * or Organization. Sort the results by title in ascending order.
131
		 */
132
		$entities = get_posts( array(
133
			'post_type'      => Wordlift_Entity_Service::valid_entity_post_types(),
134
			'post_status'    => 'publish',
135
			'posts_per_page' => - 1,
136
			'tax_query'      => array(
137
				array(
138
					'taxonomy' => Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME,
139
					'field'    => 'slug',
140
					'terms'    => array( 'organization', 'person' ),
141
				),
142
			),
143
			's'              => $filter,
144
			'orderby'        => 'title',
145
			'order'          => 'ASC',
146
		) );
147
148
		// Remove the search filter added before the query.
149
		remove_filter( 'posts_search', array(
150
			$this,
151
			'limit_search_to_title',
152
		), 10, 2 );
153
154
		// Set a reference to ourselves to pass to the closure.
155
		$publisher_service = $this;
156
157
		// Map the results in a `Select2` compatible array.
158
		return array_map( function ( $entity ) use ( $publisher_service ) {
159
			$type     = wp_get_post_terms( $entity->ID, Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME );
160
			$thumb_id = get_post_thumbnail_id( $entity->ID );
161
162
			return array(
163
				'id'            => $entity->ID,
164
				'text'          => $entity->post_title,
165
				'type'          => $type[0]->name,
166
				'thumbnail_url' => $publisher_service->get_attachment_image_url( $thumb_id ),
167
			);
168
		}, $entities );
169
	}
170
171
	/**
172
	 * Get the thumbnail's URL.
173
	 *
174
	 * @since 3.11.0
175
	 *
176
	 * @param int    $attachment_id The attachment id.
177
	 * @param string $size          The attachment size (default = 'thumbnail').
178
	 *
179
	 * @return string|bool The image URL or false if not found.
180
	 */
181
	public function get_attachment_image_url( $attachment_id, $size = 'thumbnail' ) {
182
183
		$image = wp_get_attachment_image_src( $attachment_id, $size );
184
185
		return isset( $image['0'] ) ? $image['0'] : false;
186
	}
187
188
	/**
189
	 * Add additional instructions to featured image metabox
190
	 * when the entity type is the publisher.
191
	 *
192
	 * @since  3.19.0
193
	 *
194
	 * @param  string $content Current metabox content.
195
	 *
196
	 * @return string $content metabox content with additional instructions.
197
	 */
198
	public function add_featured_image_instruction( $content ) {
199
		// Get the current post ID.
200
		$post_id = get_the_ID();
201
202
		// Get the publisher id.
203
		$publisher_id = $this->configuration_service->get_publisher_id();
204
205
206
		// Bail if for some reason the post id is not set.
207
		if (
208
			empty( $post_id ) ||
209
			$post_id !== (int) $publisher_id
210
		) {
211
			return $content;
212
		}
213
214
		$terms = wp_get_post_terms(
215
			$post_id, // The post id.
216
			Wordlift_Entity_Type_Taxonomy_Service::TAXONOMY_NAME, // The taxonomy slug.
217
			array(
218
				'fields' => 'slugs',
219
				// We don't need all fields, but only slugs.
220
			)
221
		);
222
223
		// Check that the entity type is "Organization".
224
		if ( in_array( 'organization', $terms, true ) ) {
225
			// Add the featured image description when the type is "Organization".
226
227
			$link = sprintf( '<a target="_blank" href="%s">%s</a>',
228
				esc_attr__( 'https://developers.google.com/search/docs/data-types/article#logo-guidelines', 'wordlift' ),
229
				esc_html__( 'AMP logo guidelines', 'wordlift' ) );
230
			$content .= sprintf( '<p>'
231
								 . esc_html_x( 'According to the %s, the logo should fit in a 60x600px rectangle, and either be exactly 60px high (preferred), or exactly 600px wide. For example, 450x45px would not be acceptable, even though it fits in the 600x60px rectangle. To comply with the guidelines, WordLift will automatically resize the Featured Image for structured data formats.', 'After "According to the" goes the link to the "AMP logo guidelines".', 'wordlift' )
232
								 . '</p>', $link );
233
		}
234
235
		// Finally return the content.
236
		return $content;
237
	}
238
239
}
240