Completed
Push — develop ( 1719ba...d15620 )
by David
04:51 queued 01:38
created

Wordlift_File_Cache_Service   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 179
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 179
rs 10
c 0
b 0
f 0
wmc 15
lcom 1
cbo 1

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 2
A get_instance() 0 4 1
A get_cache() 0 18 3
A set_cache() 0 9 1
A delete_cache() 0 9 1
B flush() 0 31 6
A get_filename() 0 4 1
1
<?php
2
/**
3
 * Services: File Cache Service
4
 *
5
 * The File Cache Service provides on-disk caching.
6
 *
7
 * @since      3.16.0
8
 * @package    Wordlift
9
 * @subpackage Wordlift/includes/cache
10
 */
11
12
/**
13
 * Define the {@link Wordlift_File_Cache_Service} class.
14
 *
15
 * @since 3.16.0
16
 */
17
class Wordlift_File_Cache_Service implements Wordlift_Cache_Service {
18
19
	/**
20
	 * The cache directory.
21
	 *
22
	 * @since  3.16.0
23
	 * @access private
24
	 * @var string $cache_dir The root cache directory (ending with a trailing slash).
25
	 */
26
	private $cache_dir;
27
28
	/**
29
	 * The file extension for cache files (e.g. `.wlcache`).
30
	 *
31
	 * @since  3.16.0
32
	 * @access private
33
	 * @var string $file_extension The file extension for cache files (e.g. `.wlcache`).
34
	 */
35
	private $file_extension;
36
37
	/**
38
	 * A {@link Wordlift_Log_Service} instance.
39
	 *
40
	 * @since  3.16.0
41
	 * @access private
42
	 * @var \Wordlift_Log_Service $log A {@link Wordlift_Log_Service} instance.
43
	 */
44
	private $log;
45
46
	/**
47
	 * The {@link Wordlift_File_Cache_Service} singleton instance.
48
	 *
49
	 * @since  3.16.0
50
	 * @access private
51
	 * @var \Wordlift_File_Cache_Service $instance The {@link Wordlift_File_Cache_Service} singleton instance.
52
	 */
53
	private static $instance;
54
55
	/**
56
	 * Create a {@link Wordlift_File_Cache_Service} instance.
57
	 *
58
	 * The File Cache Service requires a base cache directory (to which a unique
59
	 * id for the current site will be appended) and a file extension for cache
60
	 * files (by default `.wlcache`) is used.
61
	 *
62
	 * @since 3.16.0
63
	 *
64
	 * @param string $cache_dir      The base cache directory.
65
	 * @param string $file_extension The file extension, by default `.wlcache`.
66
	 */
67
	public function __construct( $cache_dir, $file_extension = '.wlcache' ) {
68
69
		$this->log = Wordlift_Log_Service::get_logger( get_class() );
70
71
		// Set the cache directory using the base directory provided by the caller
72
		// and appending a hash for the unique site id.
73
		$this->cache_dir      = trailingslashit( $cache_dir ) . md5( get_site_url() ) . '/';
74
		$this->file_extension = $file_extension;
75
76
		// Create the cache dir.
77
		if ( ! file_exists( $this->cache_dir ) ) {
78
			mkdir( $this->cache_dir, 0755, true );
79
		}
80
81
		self::$instance = $this;
82
83
		$this->log->info( "File Cache service initialized on $this->cache_dir." );
84
85
	}
86
87
	/**
88
	 * Get the {@link Wordlift_File_Cache_Service} singleton instance.
89
	 *
90
	 * @since 3.16.0
91
	 * @return \Wordlift_File_Cache_Service The {@link Wordlift_File_Cache_Service} singleton instance.
92
	 */
93
	public static function get_instance() {
94
95
		return self::$instance;
96
	}
97
98
	/**
99
	 * @inheritdoc
100
	 */
101
	function get_cache( $id ) {
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...
102
103
		// Get the filename.
104
		$filename = $this->get_filename( $id );
105
106
		// Bail out if the file doesn't exist.
107
		if ( ! file_exists( $filename ) ) {
108
			return false;
109
		}
110
111
		$this->log->trace( "Trying to get cache contents for $id from $filename..." );
112
113
		// Try to decode the contents.
114
		$contents = json_decode( file_get_contents( $filename ), true );
115
116
		// Return false if decoding failed, otherwise the decoded contents.
117
		return $contents ?: false;
118
	}
119
120
	/**
121
	 * @inheritdoc
122
	 */
123
	function set_cache( $id, $contents ) {
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...
124
125
		$filename = $this->get_filename( $id );
126
127
		$this->log->trace( "Writing cache contents for $id to $filename..." );
128
129
		file_put_contents( $filename, wp_json_encode( $contents ) );
130
131
	}
132
133
	/**
134
	 * @inheritdoc
135
	 */
136
	function delete_cache( $id ) {
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...
137
138
		$filename = $this->get_filename( $id );
139
140
		$this->log->trace( "Deleting cache contents for $id, file $filename..." );
141
142
		wp_delete_file( $filename );
143
144
	}
145
146
	/**
147
	 * @inheritdoc
148
	 */
149
	function flush() {
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...
150
151
		// Bail out if the cache dir isn't set.
152
		if ( empty( $this->cache_dir ) || '/' === $this->cache_dir ) {
153
			return;
154
		}
155
156
		$this->log->trace( "Flushing cache contents..." );
157
158
		$handle = @opendir( $this->cache_dir );
159
160
		// Bail out if the directory can't be opened.
161
		if ( false === $handle ) {
162
			return;
163
		}
164
165
		// Calculate the file extension length for matching file names.
166
		$file_extension_length = strlen( $this->file_extension );
167
168
		// Loop into the directory to delete files.
169
		while ( false !== ( $entry = readdir( $handle ) ) ) {
170
			if ( $this->file_extension === substr( $entry, - $file_extension_length ) ) {
171
				$this->log->trace( "Deleting file {$this->cache_dir}{$entry}..." );
172
				wp_delete_file( $this->cache_dir . $entry );
173
			}
174
		}
175
176
		// Finally closed the directory.
177
		closedir( $handle );
178
179
	}
180
181
	/**
182
	 * Get the filename holding the cache contents for the specified `id`.
183
	 *
184
	 * @since 3.16.0
185
	 *
186
	 * @param int $id The cache `id`.
187
	 *
188
	 * @return string The filename.
189
	 */
190
	private function get_filename( $id ) {
191
192
		return $this->cache_dir . md5( $id ) . $this->file_extension;
193
	}
194
195
}
196