Completed
Push — develop ( c91d29...a4aae9 )
by
unknown
03:24
created

Wordlift_Dashboard_Service::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
/**
4
 * Wordlift Dashboard Widget 
5
 * 
6
 * @since 3.4.0
7
 */
8
9
/**
10
 * Wordlift_Dashboard_Service Class
11
 *
12
 * Handles the dashboard widget.
13
 */
14
class Wordlift_Dashboard_Service {
15
	
16
17
	/**
18
	 * Transient Name
19
	 * 
20
	 * @since  3.4.0
21
	 */
22
	const TRANSIENT_NAME = 'wl_dashboard_stats';
23
24
	/**
25
	 * Transient Expiration (in seconds)
26
	 * 
27
	 * @since  3.4.0
28
	 */
29
	const TRANSIENT_EXPIRATION = 86400;
30
31
	/**
32
	 * The Entity service.
33
	 *
34
	 * @since 3.4.0
35
	 * @access private
36
	 * @var \Wordlift_Entity_Service $entity_service The Entity service.
37
	 */
38
	private $entity_service;
39
40
	/**
41
	 * Create a Wordlift_Entity_List_Service.
42
	 *
43
	 * @since 3.4.0
44
	 *
45
	 * @param \Wordlift_Entity_Service $entity_service The Entity service.
46
	 */
47
	public function __construct( $entity_service ) {
48
49
		$this->log_service = Wordlift_Log_Service::get_logger( 'Wordlift_Dashboard_Service' );
0 ignored issues
show
Bug introduced by
The property log_service does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
50
51
		$this->entity_service = $entity_service;
52
53
	}
54
55
	/**
56
	 * Return stats layout
57
	 *
58
	 * @since 3.4.0
59
	 *
60
	 * @return string Dashboard widget html markup
61
	 */
62
	public function dashboard_widget_callback( $post ) {
0 ignored issues
show
Unused Code introduced by
The parameter $post is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
63
64
		$enriched_posts_title = __( 'enriched posts', 'wordlift' ); 
65
		$enriched_posts_caption = sprintf( wp_kses(
66
			__( '%1$s, of your <a href="%2$s">posts</a> are annotated. This means %3$s annotated posts on %4$s.', 'wordlift' ), 
67
			array(  'a' => array( 'href' => array() ) ) ), 
68
			$this->render_stat_param( 'annotated_posts_percentage' ),
69
			esc_url( admin_url( 'edit.php' ) ),
70
			$this->render_stat_param( 'posts' ),
71
			$this->render_stat_param( 'annotated_posts' )  
72
		); 
73
74
		$rating_title = __( 'avarage entity rating', 'wordlift' ); 
75
		$rating_caption = sprintf( wp_kses(
76
			__( 'You have %1$s entities in your <a href="%2$s">vocabulary</a> with an avarage rating of %3$s.', 'wordlift' ), 
77
			array(  'a' => array( 'href' => array() ) ) ), 
78
			$this->render_stat_param( 'entities' ),
79
			esc_url( admin_url( 'edit.php?post_type=entity' ) ),
80
			$this->render_stat_param( 'rating' )
81
		); 
82
83
		$graph_title = __( 'triples in your graph', 'wordlift' ); 
84
		$graph_caption = sprintf( wp_kses(
85
			__( 'Your graphs size corresponds to %1$s of <a href="%2$s">Wikidata</a>.', 'wordlift' ), 
86
			array(  'a' => array( 'href' => array() ) ) ), 
87
			$this->render_stat_param( 'wikidata' ),
88
			esc_url( 'https://www.wikidata.org/' )
89
		); 
90
91
		$triples_label = __( 'triples', 'wordlift' ); 
92
		
93
		echo <<<EOF
94
	<div id="wl-dashboard-widget-inner-wrapper">
95
		<div class="wl-stat-card">
96
			<div class="wl-stat-graph-wrapper">
97
				<h4>$enriched_posts_title <a href=""><i class="wl-info"></i></a></h4>
98
				<svg id="wl-posts-pie-chart" viewBox="0 0 32 32"><circle r="16" cx="16" cy="16" /></svg>
99
			</div>
100
			<p>$enriched_posts_caption</p>
101
		</div>
102
		<div class="wl-stat-card">
103
			<div class="wl-stat-graph-wrapper">
104
				<h4>$rating_title <a href=""><i class="wl-info"></i></a></h4>
105
				<svg id="wl-entities-gauge-chart" viewBox="0 0 32 32"><circle r="16" cx="16" cy="16" class="baseline" /><circle r="16" cx="16" cy="16" class="stat" /></svg>
106
			</div>
107
			<p>$rating_caption</p>
108
		</div>
109
		<div class="wl-stat-card">
110
			<div class="wl-stat-graph-wrapper">
111
				<h4>$graph_title <a href=""><i class="wl-info"></i></a></h4>
112
				<div class="wl-triples">
113
					<span id="wl-dashboard-widget-triples"></span>
114
					<span class="wl-triples-label">$triples_label</span>
115
				</div>
116
			</div>
117
			<p>$graph_caption</p>
118
		</div>
119
	</div>
120
EOF;
121
122
	}
123
124
	/**
125
	 * Return stats
126
	 *
127
	 * @since 3.4.0
128
	 *
129
	 * @return string markup
130
	 */
131
	public function add_dashboard_widgets() {
132
		wp_add_dashboard_widget('wordlift-dashboard-widget', 'WordLift Dashboard', array( $this, 'dashboard_widget_callback' ) );
133
	}
134
135
	/**
136
	 * Return stats
137
	 * @uses https://codex.wordpress.org/Function_Reference/set_transient
138
	 *
139
	 * @since 3.4.0
140
	 *
141
	 * @return string JSON obj with all available stats.
142
	 */
143
	public function ajax_get_stats() {
144
		
145
		// Try to retrieve the transient
146
		$stats = get_transient( self::TRANSIENT_NAME );
147
148
		if ( !$stats ) {
149
			// Calculate stats
150
			$stats = array(
151
				'entities'	=>	$this->count_entities(),
152
				'posts'	=>	$this->count_posts(),
153
				'annotated_posts'	=>	$this->count_annotated_posts(),
154
				'triples'	=> $this->count_triples(),
155
				'rating' => $this->avarage_entities_rating(),
156
			);	
157
			// Cache stats results trough transient
158
			set_transient( self::TRANSIENT_NAME, $stats, self::TRANSIENT_EXPIRATION );
159
		}
160
		// Return stats as json object
161
		wl_core_send_json( $stats );
162
	}
163
164
	/**
165
	 * Calculate total number of published posts
166
	 * @uses https://codex.wordpress.org/it:Riferimento_funzioni/wp_count_posts
167
	 * @since 3.4.0
168
	 *
169
	 * @return int Total number of published posts.
170
	 */
171
	public function count_posts() {
172
		
173
		return (int) wp_count_posts()->publish;		
174
	}
175
176
	/**
177
	 * Calculate total number of annotated published posts
178
	 * @since 3.4.0
179
	 *
180
	 * @return int Total number of annotated published posts.
181
	 */
182
	public function count_annotated_posts() {
183
		
184
		// Prepare interaction with db
185
    	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...
186
    	// Retrieve Wordlift relation instances table name
187
    	$table_name = wl_core_get_relation_instances_table_name();
188
    	// Calculate sql statement
189
		$sql_statement = <<<EOF
190
    		SELECT COUNT(*) FROM $wpdb->posts as p JOIN $table_name as r ON p.id = r.subject_id AND p.post_type = 'post' AND p.post_status = 'publish';
191
EOF;
192
		// Perform the query
193
		return (int) $wpdb->get_var( $sql_statement ); 
194
		
195
	}
196
197
	/**
198
	 * Calculate the avarage entities rating
199
	 * @since 3.4.0
200
	 *
201
	 * @return int Avarage entities rating.
202
	 */
203
	public function avarage_entities_rating() {
204
		
205
		// Prepare interaction with db
206
    	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...
207
		$query = $wpdb->prepare( 
208
			"SELECT AVG(meta_value) FROM $wpdb->postmeta where meta_key = %s",
209
   			Wordlift_Entity_Service::RATING_RAW_SCORE_META_KEY
210
			);
211
		// Perform the query
212
		return $this->entity_service->convert_raw_score_to_percentage( $wpdb->get_var( $query ) ); 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
213
	}
214
215
	/**
216
	 * Calculate total number of published entities
217
	 * @uses https://codex.wordpress.org/it:Riferimento_funzioni/wp_count_posts
218
	 * @since 3.4.0
219
	 *
220
	 * @return int Total number of posts.
221
	 */
222
	public function count_entities() {
223
		
224
		return (int) wp_count_posts( Wordlift_Entity_Service::TYPE_NAME )->publish;		
225
	}
226
227
	/**
228
	 * Calculate total number of published rdf triples
229
	 * @since 3.4.0
230
	 *
231
	 * @return int Total number of triples.
232
	 */
233
	public function count_triples() {
234
		
235
		// Set the SPARQL query.
236
		$sparql = 'SELECT (COUNT(*) AS ?no) { ?s ?p ?o  }';
237
		// Send the request.
238
		$response = $this->rl_sparql_select( $sparql );
239
240
		// Return the error in case of failure.
241
		if ( is_wp_error( $response ) || 200 !== (int) $response['response']['code'] ) {
242
			return (int) FALSE;
243
		}
244
245
		// Get the body.
246
		$body = $response['body'];
247
		// Get the values.
248
		$matches = array();
249
		if ( 1 === preg_match( '/(\d+)/im', $body, $matches ) && 2 === count( $matches ) ) {
250
			// Return the counts.
251
			return (int) $matches[1];
252
		}
253
		
254
		return (int) FALSE;
255
	}
256
257
	private function rl_sparql_select( $query ) {
258
259
		// Prepare the SPARQL statement by prepending the default namespaces.
260
		$sparql = rl_sparql_prefixes() . "\n" . $query;
261
		// Get the SPARQL SELECT URL.
262
		$url = wl_configuration_get_query_select_url( 'csv' ) . urlencode( $sparql );
263
		// Prepare the request.
264
		$args = unserialize( WL_REDLINK_API_HTTP_OPTIONS );
265
266
		return wp_remote_get( $url, $args );
267
	}
268
269
	private function render_stat_param( $param ) {
270
271
		return '<span id="wl-dashboard-widget-' . $param . '" class="wl-stat-value"></span>';
272
	}
273
274
}
275