PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.2.7
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.2.7
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / classes / WriteFile / AbstractIISDirConfFile.php

AbstractIISDirConfFile.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.2.7, at classes/WriteFile/AbstractIISDirConfFile.php

284 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Imagify\WriteFile;
3
4 defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
5
6 /**
7 * Abstract class used to add and remove contents to the web.config file.
8 *
9 * @since 1.9
10 * @author Grégory Viguier
11 */
12 abstract class AbstractIISDirConfFile extends AbstractWriteDirConfFile {
13
14 /**
15 * Insert new contents into the directory conf file.
16 * Replaces existing marked info. Creates file if none exists.
17 *
18 * @since 1.9
19 * @access protected
20 * @author Grégory Viguier
21 *
22 * @param string $new_contents Contents to insert.
23 * @return bool|\WP_Error True on write success, a \WP_Error object on failure.
24 */
25 protected function insert_contents( $new_contents ) {
26 $doc = $this->get_file_contents();
27
28 if ( is_wp_error( $doc ) ) {
29 return $doc;
30 }
31
32 $marker = static::TAG_NAME;
33 $xpath = new \DOMXPath( $doc );
34
35 // Remove previous rules.
36 $old_nodes = $xpath->query( ".//*[starts-with(@name,'$marker')]" );
37
38 if ( $old_nodes->length > 0 ) {
39 foreach ( $old_nodes as $old_node ) {
40 $old_node->parentNode->removeChild( $old_node );
41 }
42 }
43
44 // No new contents? Stop here.
45 if ( ! $new_contents ) {
46 return $this->put_file_contents( $doc );
47 }
48
49 $new_contents = preg_split( '/<!--\s+@parent\s+(.+?)\s+-->/', $new_contents, -1, PREG_SPLIT_DELIM_CAPTURE );
50 unset( $new_contents[0] );
51 $new_contents = array_chunk( $new_contents, 2 );
52
53 foreach ( $new_contents as $i => $new_content ) {
54 $path = rtrim( $new_content[0], '/' );
55 $new_content = trim( $new_content[1] );
56
57 if ( '' === $new_content ) {
58 continue;
59 }
60
61 $fragment = $doc->createDocumentFragment();
62 $fragment->appendXML( $new_content );
63
64 $this->get_node( $doc, $xpath, $path, $fragment );
65 }
66
67 return $this->put_file_contents( $doc );
68 }
69
70 /**
71 * Get the unfiltered path to the file.
72 *
73 * @since 1.9
74 * @access protected
75 * @author Grégory Viguier
76 *
77 * @return string
78 */
79 protected function get_raw_file_path() {
80 return $this->filesystem->get_site_root() . 'web.config';
81 }
82
83 /** ----------------------------------------------------------------------------------------- */
84 /** OTHER TOOLS ============================================================================= */
85 /** ----------------------------------------------------------------------------------------- */
86
87 /**
88 * Tell if the file is writable.
89 *
90 * @since 1.9
91 * @access public
92 * @author Grégory Viguier
93 *
94 * @return bool|\WP_Error True if writable. A \WP_Error object if not.
95 */
96 public function is_file_writable() {
97 $file_path = $this->get_file_path();
98 $file_name = $this->filesystem->make_path_relative( $file_path );
99
100 if ( $this->is_conf_edition_disabled() ) {
101 return new \WP_Error(
102 'edition_disabled',
103 sprintf(
104 /* translators: %s is a file name. */
105 __( 'Edition of the %s file is disabled.', 'imagify' ),
106 '<code>' . esc_html( $file_name ) . '</code>'
107 )
108 );
109 }
110
111 if ( ! class_exists( '\DOMDocument' ) ) {
112 return new \WP_Error(
113 'not_domdocument',
114 sprintf(
115 /* translators: 1 is a php class name, 2 is a file name. */
116 __( 'The class %1$s is not present on your server, a %2$s file cannot be created nor edited.', 'imagify' ),
117 '<code>DOMDocument</code>',
118 '<code>' . esc_html( $file_name ) . '</code>'
119 )
120 );
121 }
122
123 if ( ! $this->filesystem->exists( $file_path ) ) {
124 $dir_path = $this->filesystem->dir_path( $file_path );
125
126 $this->filesystem->make_dir( $dir_path );
127
128 if ( ! $this->filesystem->is_writable( $dir_path ) ) {
129 return new \WP_Error(
130 'parent_not_writable',
131 sprintf(
132 /* translators: %s is a file name. */
133 __( '%s’s parent folder is not writable.', 'imagify' ),
134 '<code>' . esc_html( $file_name ) . '</code>'
135 )
136 );
137 }
138 if ( ! $this->filesystem->exists( $file_path ) ) {
139 $result = $this->filesystem->put_contents( $file_path, '<configuration/>' );
140
141 if ( ! $result ) {
142 return new \WP_Error(
143 'not_created',
144 sprintf(
145 /* translators: %s is a file name. */
146 __( 'The %s file could not be created.', 'imagify' ),
147 '<code>' . esc_html( $file_name ) . '</code>'
148 )
149 );
150 }
151 }
152 } elseif ( ! $this->filesystem->is_writable( $file_path ) ) {
153 return new \WP_Error(
154 'not_writable',
155 sprintf(
156 /* translators: %s is a file name. */
157 __( 'The %s file is not writable.', 'imagify' ),
158 '<code>' . esc_html( $file_name ) . '</code>'
159 )
160 );
161 }
162
163 return true;
164 }
165
166 /**
167 * Get the file contents.
168 *
169 * @since 1.9
170 * @access protected
171 * @author Grégory Viguier
172 *
173 * @return \DOMDocument|\WP_Error A \DOMDocument object on success, a \WP_Error object on failure.
174 */
175 protected function get_file_contents() {
176 $writable = $this->is_file_writable();
177
178 if ( is_wp_error( $writable ) ) {
179 return $writable;
180 }
181
182 $file_path = $this->get_file_path();
183 $doc = new \DOMDocument();
184
185 $doc->preserveWhiteSpace = false;
186
187 if ( false === $doc->load( $file_path ) ) {
188 $file_path = $this->get_file_path();
189 $file_name = $this->filesystem->make_path_relative( $file_path );
190
191 return new \WP_Error(
192 'not_read',
193 sprintf(
194 /* translators: %s is a file name. */
195 __( 'The %s file could not be read.', 'imagify' ),
196 '<code>' . esc_html( $file_name ) . '</code>'
197 )
198 );
199 }
200
201 return $doc;
202 }
203
204 /**
205 * Put new contents into the file.
206 *
207 * @since 1.9
208 * @access protected
209 * @author Grégory Viguier
210 *
211 * @param \DOMDocument $contents A \DOMDocument object.
212 * @return bool|\WP_Error True on success, a \WP_Error object on failure.
213 */
214 protected function put_file_contents( $contents ) {
215 $contents->encoding = 'UTF-8';
216 $contents->formatOutput = true;
217
218 saveDomDocument( $contents, $this->get_file_path() );
219
220 return true;
221 }
222
223
224 /**
225 * Get a DOMNode node.
226 * If it does not exist it is created recursively.
227 *
228 * @since 1.9
229 * @access protected
230 * @author Grégory Viguier
231 *
232 * @param \DOMDocument $doc A \DOMDocument element.
233 * @param \DOMXPath $xpath A \DOMXPath element.
234 * @param string $path Path to the desired node.
235 * @param \DOMNode $child A \DOMNode to be prepended.
236 * @return \DOMNode The \DOMNode node.
237 */
238 protected function get_node( $doc, $xpath, $path, $child ) {
239 $nodelist = $xpath->query( $path );
240
241 if ( $nodelist->length > 0 ) {
242 return $this->prepend_node( $nodelist->item( 0 ), $child );
243 }
244
245 $path = explode( '/', $path );
246 $node = array_pop( $path );
247 $path = implode( '/', $path );
248
249 $final_node = $doc->createElement( $node );
250
251 if ( $child ) {
252 $final_node->appendChild( $child );
253 }
254
255 return $this->get_node( $doc, $xpath, $path, $final_node );
256 }
257
258
259 /**
260 * Prepend a DOMNode node.
261 *
262 * @since 1.9
263 * @access protected
264 * @author Grégory Viguier
265 *
266 * @param \DOMNode $container_node The \DOMNode that will contain the new node.
267 * @param \DOMNode $new_node The \DOMNode to be prepended.
268 * @return \DOMNode The \DOMNode containing the new node.
269 */
270 protected function prepend_node( $container_node, $new_node ) {
271 if ( ! $new_node ) {
272 return $container_node;
273 }
274
275 if ( $container_node->hasChildNodes() ) {
276 $container_node->insertBefore( $new_node, $container_node->firstChild );
277 } else {
278 $container_node->appendChild( $new_node );
279 }
280
281 return $container_node;
282 }
283 }
284