Completed
Push — develop ( 195cb3...f65bd6 )
by David
02:59
created

Wordlift_Relation_Rebuild_Service   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 131
rs 10
c 0
b 0
f 0
wmc 8
lcom 1
cbo 4

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A process_all() 0 15 1
B process_single() 0 25 2
A create_relations() 0 15 1
A uri_to_post_id() 0 14 2
A find() 0 17 1
1
<?php
2
3
class Wordlift_Relation_Rebuild_Service extends Wordlift_Listable {
4
	/**
5
	 * @var Wordlift_Content_Filter_Service
6
	 */
7
	private $content_filter_service;
8
9
	/**
10
	 * @var Wordlift_Entity_Service
11
	 */
12
	private $entity_service;
13
14
	/**
15
	 * A {@link Wordlift_Log_Service} instance.
16
	 *
17
	 * @since  3.14.3
18
	 * @access private
19
	 * @var \Wordlift_Log_Service $log A {@link Wordlift_Log_Service} instance.
20
	 */
21
	private $log;
22
23
24
	/**
25
	 * Wordlift_Relation_Rebuild_Service constructor.
26
	 *
27
	 * @param \Wordlift_Content_Filter_Service $content_filter_service
28
	 * @param \Wordlift_Entity_Service         $entity_service
29
	 */
30
	public function __construct( $content_filter_service, $entity_service ) {
31
32
		$this->log = Wordlift_Log_Service::get_logger( 'Wordlift_Relation_Rebuild_Service' );
33
34
		$this->content_filter_service = $content_filter_service;
35
		$this->entity_service         = $entity_service;
36
37
	}
38
39
	public function process_all() {
40
		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...
41
42
		set_time_limit( 21600 ); // 6 hours
43
44
		$this->log->debug( 'Deleting all existing relations...' );
45
46
		// Delete existing data.
47
		$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}wl_relation_instances" );
48
49
		$this->log->debug( 'Processing contents...' );
50
51
		$this->process( array( $this, 'process_single' ) );
52
53
	}
54
55
	public function process_single( $post_id ) {
56
57
		$this->log->debug( "Processing post $post_id..." );
58
59
		// Bail out if the post is not found.
60
		$post = get_post( $post_id );
61
62
		if ( null === $post ) {
63
			$this->log->error( "Post $post_id not found." );
64
65
			return;
66
		}
67
68
		// Get the URIs from the post content.
69
		$uris = $this->content_filter_service->get_entity_uris( $post->post_content );
70
71
		// Map the URIs to post IDs.
72
		$ids = $this->uri_to_post_id( $uris );
73
74
		$this->log->info( 'Found ' . count( $uris ) . ' annotation(s) and ' . count( $ids ) . ' unique relation(s).' );
75
76
		// Create the relations.
77
		$this->create_relations( $post_id, $ids );
78
79
	}
80
81
	private function create_relations( $subject_id, $object_ids ) {
82
83
		$this->log->info( "Creating relations for post $subject_id..." );
84
85
		$entity_service = $this->entity_service;
86
87
		array_walk( $object_ids, function ( $item ) use ( $subject_id, $entity_service ) {
88
			wl_core_add_relation_instance(
89
				$subject_id,
90
				$entity_service->get_classification_scope_for( $item ),
91
				$item
92
			);
93
		} );
94
95
	}
96
97
	private function uri_to_post_id( $uris ) {
98
99
		$entity_service = $this->entity_service;
100
101
		$ids = array_unique( array_map( function ( $item ) use ( $entity_service ) {
102
			$post = $entity_service->get_entity_post_by_uri( $item );
103
104
			return null === $post ? null : $post->ID;
105
		}, (array) $uris ) );
106
107
		return array_filter( $ids, function ( $item ) {
108
			return null !== $item;
109
		} );
110
	}
111
112
	/**
113
	 * @inheritdoc
114
	 */
115
	function find( $offset = 0, $limit = 10, $args = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
116
		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...
117
118
		return $wpdb->get_col( $wpdb->prepare(
119
			"
120
			SELECT id
121
			FROM $wpdb->posts
122
			WHERE post_type NOT IN ( 'attachment', 'revision' )
123
				AND post_content REGEXP %s
124
			LIMIT %d OFFSET %d
125
			",
126
			'<[a-z]+ id="urn:[^"]+" class="[^"]+" itemid="[^"]+">',
127
			$limit,
128
			$offset
129
		) );
130
131
	}
132
133
}
134