Version Description
- Fix: Set default PHPMailer validator to 'php' (fixing 'setFrom' errors on PHP 7.3)
- Fix: Attachment path for file lock check
- Tweak: Don't wait for file lock if locking disabled
- Tweak: JIT loading of core documents for early requests (before init 15)
Download this release
Release Info
Developer | pomegranate |
Plugin | WooCommerce PDF Invoices & Packing Slips |
Version | 2.2.14 |
Comparing to | |
See all releases |
Code changes from version 2.2.12 to 2.2.14
- includes/class-wcpdf-documents.php +109 -105
- includes/class-wcpdf-main.php +714 -667
- includes/compatibility/class-wcpdf-compatibility-third-party-plugins.php +225 -222
- includes/documents/abstract-wcpdf-order-document-methods.php +1153 -1128
- readme.txt +356 -344
- woocommerce-pdf-invoices-packingslips.php +359 -359
includes/class-wcpdf-documents.php
CHANGED
@@ -1,106 +1,110 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPO\WC\PDF_Invoices;
|
3 |
-
|
4 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
5 |
-
exit; // Exit if accessed directly
|
6 |
-
}
|
7 |
-
|
8 |
-
if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\Documents' ) ) :
|
9 |
-
|
10 |
-
class Documents {
|
11 |
-
|
12 |
-
/** @var array Array of document classes */
|
13 |
-
public $documents = array();
|
14 |
-
|
15 |
-
/** @var Documents The single instance of the class */
|
16 |
-
protected static $_instance = null;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Main Documents Instance.
|
20 |
-
*
|
21 |
-
* Ensures only one instance of Documents is loaded or can be loaded.
|
22 |
-
*
|
23 |
-
* @since 2.0
|
24 |
-
* @static
|
25 |
-
* @return Documents Main instance
|
26 |
-
*/
|
27 |
-
public static function instance() {
|
28 |
-
if ( is_null( self::$_instance ) ) {
|
29 |
-
self::$_instance = new self();
|
30 |
-
}
|
31 |
-
return self::$_instance;
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Constructor for the document class hooks in all documents that can be created.
|
36 |
-
*
|
37 |
-
*/
|
38 |
-
public function __construct() {
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
//
|
47 |
-
include_once( dirname( __FILE__ ) . '/documents/
|
48 |
-
|
49 |
-
//
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
// Load Invoice & Packing Slip
|
57 |
-
$this->documents['\WPO\WC\PDF_Invoices\Documents\Invoice'] = include( 'documents/class-wcpdf-invoice.php' );
|
58 |
-
$this->documents['\WPO\WC\PDF_Invoices\Documents\Packing_Slip'] = include( 'documents/class-wcpdf-packing-slip.php' );
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
*
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
106 |
Â
return new Documents();
|
1 |
+
<?php
|
2 |
+
namespace WPO\WC\PDF_Invoices;
|
3 |
+
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
5 |
+
exit; // Exit if accessed directly
|
6 |
+
}
|
7 |
+
|
8 |
+
if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\Documents' ) ) :
|
9 |
+
|
10 |
+
class Documents {
|
11 |
+
|
12 |
+
/** @var array Array of document classes */
|
13 |
+
public $documents = array();
|
14 |
+
|
15 |
+
/** @var Documents The single instance of the class */
|
16 |
+
protected static $_instance = null;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Main Documents Instance.
|
20 |
+
*
|
21 |
+
* Ensures only one instance of Documents is loaded or can be loaded.
|
22 |
+
*
|
23 |
+
* @since 2.0
|
24 |
+
* @static
|
25 |
+
* @return Documents Main instance
|
26 |
+
*/
|
27 |
+
public static function instance() {
|
28 |
+
if ( is_null( self::$_instance ) ) {
|
29 |
+
self::$_instance = new self();
|
30 |
+
}
|
31 |
+
return self::$_instance;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Constructor for the document class hooks in all documents that can be created.
|
36 |
+
*
|
37 |
+
*/
|
38 |
+
public function __construct() {
|
39 |
+
// Include document abstracts
|
40 |
+
include_once( dirname( __FILE__ ) . '/documents/abstract-wcpdf-order-document.php' );
|
41 |
+
include_once( dirname( __FILE__ ) . '/documents/abstract-wcpdf-order-document-methods.php' );
|
42 |
+
// Include bulk document
|
43 |
+
include_once( dirname( __FILE__ ) . '/documents/class-wcpdf-bulk-document.php' );
|
44 |
+
// Document number formatting class
|
45 |
+
include_once( dirname( __FILE__ ) . '/documents/class-wcpdf-document-number.php' );
|
46 |
+
// Sequential number handler
|
47 |
+
include_once( dirname( __FILE__ ) . '/documents/class-wcpdf-sequential-number-store.php' );
|
48 |
+
|
49 |
+
add_action( 'init', array( $this, 'init' ), 15 ); // after regular 10 actions but before most 'follow-up' actions (usually 20+)
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Init document classes.
|
54 |
+
*/
|
55 |
+
public function init() {
|
56 |
+
// Load Invoice & Packing Slip
|
57 |
+
$this->documents['\WPO\WC\PDF_Invoices\Documents\Invoice'] = include( 'documents/class-wcpdf-invoice.php' );
|
58 |
+
$this->documents['\WPO\WC\PDF_Invoices\Documents\Packing_Slip'] = include( 'documents/class-wcpdf-packing-slip.php' );
|
59 |
+
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Return the document classes - used in admin to load settings.
|
64 |
+
*
|
65 |
+
* @return array
|
66 |
+
*/
|
67 |
+
public function get_documents( $filter = 'enabled' ) {
|
68 |
+
if ( empty($this->documents) ) {
|
69 |
+
$this->init();
|
70 |
+
}
|
71 |
+
// Allow plugins to add their own documents
|
72 |
+
$this->documents = apply_filters( 'wpo_wcpdf_document_classes', $this->documents );
|
73 |
+
|
74 |
+
if ( $filter == 'enabled' ) {
|
75 |
+
$documents = array();
|
76 |
+
foreach ($this->documents as $class_name => $document) {
|
77 |
+
if ($document->is_enabled()) {
|
78 |
+
$documents[$class_name] = $document;
|
79 |
+
}
|
80 |
+
}
|
81 |
+
return $documents;
|
82 |
+
} else {
|
83 |
+
// return all documents
|
84 |
+
return $this->documents;
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
public function get_document( $document_type, $order ) {
|
89 |
+
foreach ($this->get_documents('all') as $class_name => $document) {
|
90 |
+
if ($document->get_type() == $document_type) {
|
91 |
+
return new $class_name( $order );
|
92 |
+
}
|
93 |
+
}
|
94 |
+
// document not known, inject into legacy document
|
95 |
+
$document = include( WPO_WCPDF()->plugin_path() . '/includes/legacy/class-wcpdf-legacy-document.php' );
|
96 |
+
// set document properties, which will trigger parent construct and load data correctly
|
97 |
+
$document->set_props( array(
|
98 |
+
'type' => $document_type,
|
99 |
+
'title' => '',
|
100 |
+
'order' => $order,
|
101 |
+
) );
|
102 |
+
|
103 |
+
return $document;
|
104 |
+
}
|
105 |
+
|
106 |
+
}
|
107 |
+
|
108 |
+
endif; // class_exists
|
109 |
+
|
110 |
Â
return new Documents();
|
includes/class-wcpdf-main.php
CHANGED
@@ -1,667 +1,714 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPO\WC\PDF_Invoices;
|
3 |
-
|
4 |
-
use WPO\WC\PDF_Invoices\Compatibility\WC_Core as WCX;
|
5 |
-
use WPO\WC\PDF_Invoices\Compatibility\Order as WCX_Order;
|
6 |
-
use WPO\WC\PDF_Invoices\Compatibility\Product as WCX_Product;
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit; // Exit if accessed directly
|
10 |
-
}
|
11 |
-
|
12 |
-
if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\Main' ) ) :
|
13 |
-
|
14 |
-
class Main {
|
15 |
-
|
16 |
-
function __construct() {
|
17 |
-
add_action( 'wp_ajax_generate_wpo_wcpdf', array($this, 'generate_pdf_ajax' ) );
|
18 |
-
add_action( 'wp_ajax_nopriv_generate_wpo_wcpdf', array($this, 'generate_pdf_ajax' ) );
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
//
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
//
|
46 |
-
add_action( '
|
47 |
-
|
48 |
-
//
|
49 |
-
add_action( '
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
if
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
}
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
}
|
171 |
-
|
172 |
-
public function
|
173 |
-
$
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
$
|
193 |
-
}
|
194 |
-
}
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
$
|
204 |
-
|
205 |
-
|
206 |
-
}
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
if ( $
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
}
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
}
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
if ( $
|
288 |
-
$
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
$
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
//
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
$
|
412 |
-
|
413 |
-
$
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
'
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
//
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
$
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
if (
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
$
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
$
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
'_wcpdf_invoice_number' =>
|
650 |
-
'
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
namespace WPO\WC\PDF_Invoices;
|
3 |
+
|
4 |
+
use WPO\WC\PDF_Invoices\Compatibility\WC_Core as WCX;
|
5 |
+
use WPO\WC\PDF_Invoices\Compatibility\Order as WCX_Order;
|
6 |
+
use WPO\WC\PDF_Invoices\Compatibility\Product as WCX_Product;
|
7 |
+
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit; // Exit if accessed directly
|
10 |
+
}
|
11 |
+
|
12 |
+
if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\Main' ) ) :
|
13 |
+
|
14 |
+
class Main {
|
15 |
+
|
16 |
+
function __construct() {
|
17 |
+
add_action( 'wp_ajax_generate_wpo_wcpdf', array($this, 'generate_pdf_ajax' ) );
|
18 |
+
add_action( 'wp_ajax_nopriv_generate_wpo_wcpdf', array($this, 'generate_pdf_ajax' ) );
|
19 |
+
|
20 |
+
// email
|
21 |
+
add_filter( 'woocommerce_email_attachments', array( $this, 'attach_pdf_to_email' ), 99, 4 );
|
22 |
+
add_filter( 'wpo_wcpdf_custom_attachment_condition', array( $this, 'disable_free_attachment'), 1001, 4 );
|
23 |
+
add_filter( 'wp_mail', array( $this, 'set_phpmailer_validator'), 10, 1 );
|
24 |
+
|
25 |
+
if ( isset(WPO_WCPDF()->settings->debug_settings['enable_debug']) ) {
|
26 |
+
$this->enable_debug();
|
27 |
+
}
|
28 |
+
|
29 |
+
// include template specific custom functions
|
30 |
+
$template_path = WPO_WCPDF()->settings->get_template_path();
|
31 |
+
if ( file_exists( $template_path . '/template-functions.php' ) ) {
|
32 |
+
require_once( $template_path . '/template-functions.php' );
|
33 |
+
}
|
34 |
+
|
35 |
+
// test mode
|
36 |
+
add_filter( 'wpo_wcpdf_document_use_historical_settings', array( $this, 'test_mode_settings' ), 15, 2 );
|
37 |
+
|
38 |
+
// page numbers & currency filters
|
39 |
+
add_action( 'wpo_wcpdf_get_html', array($this, 'format_page_number_placeholders' ), 10, 2 );
|
40 |
+
add_action( 'wpo_wcpdf_after_dompdf_render', array($this, 'page_number_replacements' ), 9, 2 );
|
41 |
+
if ( isset( WPO_WCPDF()->settings->general_settings['currency_font'] ) ) {
|
42 |
+
add_action( 'wpo_wcpdf_before_pdf', array($this, 'use_currency_font' ), 10, 2 );
|
43 |
+
}
|
44 |
+
|
45 |
+
// scheduled attachments cleanup (following settings on Status tab)
|
46 |
+
add_action( 'wp_scheduled_delete', array( $this, 'attachments_cleanup') );
|
47 |
+
|
48 |
+
// remove private data
|
49 |
+
add_action( 'woocommerce_privacy_remove_order_personal_data_meta', array( $this, 'remove_order_personal_data_meta' ), 10, 1 );
|
50 |
+
add_action( 'woocommerce_privacy_remove_order_personal_data', array( $this, 'remove_order_personal_data' ), 10, 1 );
|
51 |
+
// export private data
|
52 |
+
add_action( 'woocommerce_privacy_export_order_personal_data_meta', array( $this, 'export_order_personal_data_meta' ), 10, 1 );
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Attach PDF to WooCommerce email
|
57 |
+
*/
|
58 |
+
public function attach_pdf_to_email ( $attachments, $email_id, $order, $email = null ) {
|
59 |
+
$order = apply_filters( 'wpo_wcpdf_email_attachment_order', $order, $email );
|
60 |
+
// check if all variables properly set
|
61 |
+
if ( !is_object( $order ) || !isset( $email_id ) ) {
|
62 |
+
return $attachments;
|
63 |
+
}
|
64 |
+
|
65 |
+
// Skip User emails
|
66 |
+
if ( get_class( $order ) == 'WP_User' ) {
|
67 |
+
return $attachments;
|
68 |
+
}
|
69 |
+
|
70 |
+
$order_id = WCX_Order::get_id( $order );
|
71 |
+
|
72 |
+
if ( ! ( $order instanceof \WC_Order || is_subclass_of( $order, '\WC_Abstract_Order') ) && $order_id == false ) {
|
73 |
+
return $attachments;
|
74 |
+
}
|
75 |
+
|
76 |
+
// WooCommerce Booking compatibility
|
77 |
+
if ( get_post_type( $order_id ) == 'wc_booking' && isset($order->order) ) {
|
78 |
+
// $order is actually a WC_Booking object!
|
79 |
+
$order = $order->order;
|
80 |
+
}
|
81 |
+
|
82 |
+
// do not process low stock notifications, user emails etc!
|
83 |
+
if ( in_array( $email_id, array( 'no_stock', 'low_stock', 'backorder', 'customer_new_account', 'customer_reset_password' ) ) ) {
|
84 |
+
return $attachments;
|
85 |
+
}
|
86 |
+
|
87 |
+
// final check on order object
|
88 |
+
if ( ! ( $order instanceof \WC_Order || is_subclass_of( $order, '\WC_Abstract_Order') ) ) {
|
89 |
+
return $attachments;
|
90 |
+
}
|
91 |
+
|
92 |
+
$tmp_path = $this->get_tmp_path('attachments');
|
93 |
+
|
94 |
+
// clear pdf files from temp folder (from http://stackoverflow.com/a/13468943/1446634)
|
95 |
+
// array_map('unlink', ( glob( $tmp_path.'*.pdf' ) ? glob( $tmp_path.'*.pdf' ) : array() ) );
|
96 |
+
|
97 |
+
// disable deprecation notices during email sending
|
98 |
+
add_filter( 'wcpdf_disable_deprecation_notices', '__return_true' );
|
99 |
+
|
100 |
+
// reload translations because WC may have switched to site locale (by setting the plugin_locale filter to site locale in wc_switch_to_site_locale())
|
101 |
+
WPO_WCPDF()->translations();
|
102 |
+
do_action( 'wpo_wcpdf_reload_attachment_translations' );
|
103 |
+
|
104 |
+
$attach_to_document_types = $this->get_documents_for_email( $email_id, $order );
|
105 |
+
foreach ( $attach_to_document_types as $document_type ) {
|
106 |
+
do_action( 'wpo_wcpdf_before_attachment_creation', $order, $email_id, $document_type );
|
107 |
+
|
108 |
+
try {
|
109 |
+
// prepare document
|
110 |
+
$document = wcpdf_get_document( $document_type, (array) $order_id, true );
|
111 |
+
if ( !$document ) { // something went wrong, continue trying with other documents
|
112 |
+
continue;
|
113 |
+
}
|
114 |
+
$filename = $document->get_filename();
|
115 |
+
$pdf_path = $tmp_path . $filename;
|
116 |
+
|
117 |
+
$lock_file = apply_filters( 'wpo_wcpdf_lock_attachment_file', true );
|
118 |
+
|
119 |
+
// if this file already exists in the temp path, we'll reuse it if it's not older than 60 seconds
|
120 |
+
$max_reuse_age = apply_filters( 'wpo_wcpdf_reuse_attachment_age', 60 );
|
121 |
+
if ( file_exists($pdf_path) && $max_reuse_age > 0 ) {
|
122 |
+
// get last modification date
|
123 |
+
if ($filemtime = filemtime($pdf_path)) {
|
124 |
+
$time_difference = time() - $filemtime;
|
125 |
+
if ( $time_difference < $max_reuse_age ) {
|
126 |
+
// check if file is still being written to
|
127 |
+
if ( $lock_file && $this->wait_for_file_lock( $pdf_path ) === false ) {
|
128 |
+
$attachments[] = $pdf_path;
|
129 |
+
continue;
|
130 |
+
} else {
|
131 |
+
// make sure this gets logged, but don't abort process
|
132 |
+
wcpdf_log_error( "Attachment file locked (reusing: {$pdf_path})", 'critical' );
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
// get pdf data & store
|
139 |
+
$pdf_data = $document->get_pdf();
|
140 |
+
|
141 |
+
if ( $lock_file ) {
|
142 |
+
file_put_contents ( $pdf_path, $pdf_data, LOCK_EX );
|
143 |
+
} else {
|
144 |
+
file_put_contents ( $pdf_path, $pdf_data );
|
145 |
+
}
|
146 |
+
|
147 |
+
// wait for file lock
|
148 |
+
if ( $lock_file && $this->wait_for_file_lock( $pdf_path ) === true ) {
|
149 |
+
wcpdf_log_error( "Attachment file locked ({$pdf_path})", 'critical' );
|
150 |
+
}
|
151 |
+
|
152 |
+
$attachments[] = $pdf_path;
|
153 |
+
|
154 |
+
do_action( 'wpo_wcpdf_email_attachment', $pdf_path, $document_type, $document );
|
155 |
+
} catch ( \Exception $e ) {
|
156 |
+
wcpdf_log_error( $e->getMessage(), 'critical', $e );
|
157 |
+
continue;
|
158 |
+
} catch ( \Dompdf\Exception $e ) {
|
159 |
+
wcpdf_log_error( 'DOMPDF exception: '.$e->getMessage(), 'critical', $e );
|
160 |
+
continue;
|
161 |
+
} catch ( \Error $e ) {
|
162 |
+
wcpdf_log_error( $e->getMessage(), 'critical', $e );
|
163 |
+
continue;
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
remove_filter( 'wcpdf_disable_deprecation_notices', '__return_true' );
|
168 |
+
|
169 |
+
return $attachments;
|
170 |
+
}
|
171 |
+
|
172 |
+
public function file_is_locked( $fp ) {
|
173 |
+
if (!flock($fp, LOCK_EX|LOCK_NB, $wouldblock)) {
|
174 |
+
if ($wouldblock) {
|
175 |
+
return true; // file is locked
|
176 |
+
} else {
|
177 |
+
return true; // can't lock for whatever reason (could be locked in Windows + PHP5.3)
|
178 |
+
}
|
179 |
+
} else {
|
180 |
+
flock($fp,LOCK_UN); // release lock
|
181 |
+
return false; // not locked
|
182 |
+
}
|
183 |
+
}
|
184 |
+
|
185 |
+
public function wait_for_file_lock( $path ) {
|
186 |
+
$fp = fopen($path, 'r+');
|
187 |
+
if ( $locked = $this->file_is_locked( $fp ) ) {
|
188 |
+
// optional delay (ms) to double check if the write process is finished
|
189 |
+
$delay = intval( apply_filters( 'wpo_wcpdf_attachment_locked_file_delay', 250 ) );
|
190 |
+
if ( $delay > 0 ) {
|
191 |
+
usleep( $delay * 1000 );
|
192 |
+
$locked = $this->file_is_locked( $fp );
|
193 |
+
}
|
194 |
+
}
|
195 |
+
fclose($fp);
|
196 |
+
|
197 |
+
return $locked;
|
198 |
+
}
|
199 |
+
|
200 |
+
public function get_documents_for_email( $email_id, $order ) {
|
201 |
+
$documents = WPO_WCPDF()->documents->get_documents();
|
202 |
+
|
203 |
+
$attach_documents = array();
|
204 |
+
foreach ($documents as $document) {
|
205 |
+
$attach_documents[ $document->get_type() ] = $document->get_attach_to_email_ids();
|
206 |
+
}
|
207 |
+
$attach_documents = apply_filters('wpo_wcpdf_attach_documents', $attach_documents );
|
208 |
+
|
209 |
+
$document_types = array();
|
210 |
+
foreach ($attach_documents as $document_type => $attach_to_email_ids ) {
|
211 |
+
// legacy settings: convert abbreviated email_ids
|
212 |
+
foreach ($attach_to_email_ids as $key => $attach_to_email_id) {
|
213 |
+
if ($attach_to_email_id == 'completed' || $attach_to_email_id == 'processing') {
|
214 |
+
$attach_to_email_ids[$key] = "customer_" . $attach_to_email_id . "_order";
|
215 |
+
}
|
216 |
+
}
|
217 |
+
|
218 |
+
$extra_condition = apply_filters('wpo_wcpdf_custom_attachment_condition', true, $order, $email_id, $document_type );
|
219 |
+
if ( in_array( $email_id, $attach_to_email_ids ) && $extra_condition === true ) {
|
220 |
+
$document_types[] = $document_type;
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
return $document_types;
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Load and generate the template output with ajax
|
229 |
+
*/
|
230 |
+
public function generate_pdf_ajax() {
|
231 |
+
$guest_access = isset( WPO_WCPDF()->settings->debug_settings['guest_access'] );
|
232 |
+
if ( !$guest_access && current_filter() == 'wp_ajax_nopriv_generate_wpo_wcpdf') {
|
233 |
+
wp_die( __( 'You do not have sufficient permissions to access this page.', 'woocommerce-pdf-invoices-packing-slips' ) );
|
234 |
+
}
|
235 |
+
|
236 |
+
// Check the nonce - guest access doesn't use nonces but checks the unique order key (hash)
|
237 |
+
if( empty( $_GET['action'] ) || ( !$guest_access && !check_admin_referer( $_GET['action'] ) ) ) {
|
238 |
+
wp_die( __( 'You do not have sufficient permissions to access this page.', 'woocommerce-pdf-invoices-packing-slips' ) );
|
239 |
+
}
|
240 |
+
|
241 |
+
// Check if all parameters are set
|
242 |
+
if ( empty( $_GET['document_type'] ) && !empty( $_GET['template_type'] ) ) {
|
243 |
+
$_GET['document_type'] = $_GET['template_type'];
|
244 |
+
}
|
245 |
+
|
246 |
+
if ( empty( $_GET['order_ids'] ) ) {
|
247 |
+
wp_die( __( "You haven't selected any orders", 'woocommerce-pdf-invoices-packing-slips' ) );
|
248 |
+
}
|
249 |
+
|
250 |
+
if( empty( $_GET['document_type'] ) ) {
|
251 |
+
wp_die( __( 'Some of the export parameters are missing.', 'woocommerce-pdf-invoices-packing-slips' ) );
|
252 |
+
}
|
253 |
+
|
254 |
+
// debug enabled by URL
|
255 |
+
if ( isset( $_GET['debug'] ) && !( $guest_access || isset( $_GET['my-account'] ) ) ) {
|
256 |
+
$this->enable_debug();
|
257 |
+
}
|
258 |
+
|
259 |
+
// Generate the output
|
260 |
+
$document_type = sanitize_text_field( $_GET['document_type'] );
|
261 |
+
|
262 |
+
$order_ids = (array) array_map( 'absint', explode( 'x', $_GET['order_ids'] ) );
|
263 |
+
// Process oldest first: reverse $order_ids array
|
264 |
+
$order_ids = array_reverse( $order_ids );
|
265 |
+
|
266 |
+
// set default is allowed
|
267 |
+
$allowed = true;
|
268 |
+
|
269 |
+
|
270 |
+
if ( $guest_access && isset( $_GET['order_key'] ) ) {
|
271 |
+
// Guest access with order key
|
272 |
+
if ( count( $order_ids ) > 1 ) {
|
273 |
+
$allowed = false;
|
274 |
+
} else {
|
275 |
+
$order = wc_get_order( $order_ids[0] );
|
276 |
+
if ( !$order || ! hash_equals( $order->get_order_key(), $_GET['order_key'] ) ) {
|
277 |
+
$allowed = false;
|
278 |
+
}
|
279 |
+
}
|
280 |
+
} else {
|
281 |
+
// check if user is logged in
|
282 |
+
if ( ! is_user_logged_in() ) {
|
283 |
+
$allowed = false;
|
284 |
+
}
|
285 |
+
|
286 |
+
// Check the user privileges
|
287 |
+
if( !( current_user_can( 'manage_woocommerce_orders' ) || current_user_can( 'edit_shop_orders' ) ) && !isset( $_GET['my-account'] ) ) {
|
288 |
+
$allowed = false;
|
289 |
+
}
|
290 |
+
|
291 |
+
// User call from my-account page
|
292 |
+
if ( !current_user_can('manage_options') && isset( $_GET['my-account'] ) ) {
|
293 |
+
// Only for single orders!
|
294 |
+
if ( count( $order_ids ) > 1 ) {
|
295 |
+
$allowed = false;
|
296 |
+
}
|
297 |
+
|
298 |
+
// Check if current user is owner of order IMPORTANT!!!
|
299 |
+
if ( ! current_user_can( 'view_order', $order_ids[0] ) ) {
|
300 |
+
$allowed = false;
|
301 |
+
}
|
302 |
+
}
|
303 |
+
}
|
304 |
+
|
305 |
+
$allowed = apply_filters( 'wpo_wcpdf_check_privs', $allowed, $order_ids );
|
306 |
+
|
307 |
+
if ( ! $allowed ) {
|
308 |
+
wp_die( __( 'You do not have sufficient permissions to access this page.', 'woocommerce-pdf-invoices-packing-slips' ) );
|
309 |
+
}
|
310 |
+
|
311 |
+
// if we got here, we're safe to go!
|
312 |
+
try {
|
313 |
+
$document = wcpdf_get_document( $document_type, $order_ids, true );
|
314 |
+
|
315 |
+
if ( $document ) {
|
316 |
+
$output_format = WPO_WCPDF()->settings->get_output_format( $document_type );
|
317 |
+
// allow URL override
|
318 |
+
if ( isset( $_GET['output'] ) && in_array( $_GET['output'], array( 'html', 'pdf' ) ) ) {
|
319 |
+
$output_format = $_GET['output'];
|
320 |
+
}
|
321 |
+
switch ( $output_format ) {
|
322 |
+
case 'html':
|
323 |
+
add_filter( 'wpo_wcpdf_use_path', '__return_false' );
|
324 |
+
$document->output_html();
|
325 |
+
break;
|
326 |
+
case 'pdf':
|
327 |
+
default:
|
328 |
+
if ( has_action( 'wpo_wcpdf_created_manually' ) ) {
|
329 |
+
do_action( 'wpo_wcpdf_created_manually', $document->get_pdf(), $document->get_filename() );
|
330 |
+
}
|
331 |
+
$output_mode = WPO_WCPDF()->settings->get_output_mode( $document_type );
|
332 |
+
$document->output_pdf( $output_mode );
|
333 |
+
break;
|
334 |
+
}
|
335 |
+
} else {
|
336 |
+
wp_die( sprintf( __( "Document of type '%s' for the selected order(s) could not be generated", 'woocommerce-pdf-invoices-packing-slips' ), $document_type ) );
|
337 |
+
}
|
338 |
+
} catch ( \Dompdf\Exception $e ) {
|
339 |
+
$message = 'DOMPDF Exception: '.$e->getMessage();
|
340 |
+
wcpdf_log_error( $message, 'critical', $e );
|
341 |
+
wcpdf_output_error( $message, 'critical', $e );
|
342 |
+
} catch ( \Exception $e ) {
|
343 |
+
$message = 'Exception: '.$e->getMessage();
|
344 |
+
wcpdf_log_error( $message, 'critical', $e );
|
345 |
+
wcpdf_output_error( $message, 'critical', $e );
|
346 |
+
} catch ( \Error $e ) {
|
347 |
+
$message = 'Fatal error: '.$e->getMessage();
|
348 |
+
wcpdf_log_error( $message, 'critical', $e );
|
349 |
+
wcpdf_output_error( $message, 'critical', $e );
|
350 |
+
}
|
351 |
+
exit;
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* Return tmp path for different plugin processes
|
356 |
+
*/
|
357 |
+
public function get_tmp_path ( $type = '' ) {
|
358 |
+
$tmp_base = $this->get_tmp_base();
|
359 |
+
|
360 |
+
// don't continue if we don't have an upload dir
|
361 |
+
if ($tmp_base === false) {
|
362 |
+
return false;
|
363 |
+
}
|
364 |
+
|
365 |
+
// check if tmp folder exists => if not, initialize
|
366 |
+
if ( !@is_dir( $tmp_base ) ) {
|
367 |
+
$this->init_tmp( $tmp_base );
|
368 |
+
}
|
369 |
+
|
370 |
+
if ( empty( $type ) ) {
|
371 |
+
return $tmp_base;
|
372 |
+
}
|
373 |
+
|
374 |
+
switch ( $type ) {
|
375 |
+
case 'dompdf':
|
376 |
+
$tmp_path = $tmp_base . 'dompdf';
|
377 |
+
break;
|
378 |
+
case 'font_cache':
|
379 |
+
case 'fonts':
|
380 |
+
$tmp_path = $tmp_base . 'fonts';
|
381 |
+
break;
|
382 |
+
case 'attachments':
|
383 |
+
$tmp_path = $tmp_base . 'attachments/';
|
384 |
+
break;
|
385 |
+
default:
|
386 |
+
$tmp_path = $tmp_base . $type;
|
387 |
+
break;
|
388 |
+
}
|
389 |
+
|
390 |
+
// double check for existence, in case tmp_base was installed, but subfolder not created
|
391 |
+
if ( !@is_dir( $tmp_path ) ) {
|
392 |
+
@mkdir( $tmp_path );
|
393 |
+
}
|
394 |
+
|
395 |
+
return $tmp_path;
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* return the base tmp folder (usually uploads)
|
400 |
+
*/
|
401 |
+
public function get_tmp_base () {
|
402 |
+
// wp_upload_dir() is used to set the base temp folder, under which a
|
403 |
+
// 'wpo_wcpdf' folder and several subfolders are created
|
404 |
+
//
|
405 |
+
// wp_upload_dir() will:
|
406 |
+
// * default to WP_CONTENT_DIR/uploads
|
407 |
+
// * UNLESS the ‘UPLOADS’ constant is defined in wp-config (http://codex.wordpress.org/Editing_wp-config.php#Moving_uploads_folder)
|
408 |
+
//
|
409 |
+
// May also be overridden by the wpo_wcpdf_tmp_path filter
|
410 |
+
|
411 |
+
$upload_dir = wp_upload_dir();
|
412 |
+
if (!empty($upload_dir['error'])) {
|
413 |
+
$tmp_base = false;
|
414 |
+
} else {
|
415 |
+
$upload_base = trailingslashit( $upload_dir['basedir'] );
|
416 |
+
$tmp_base = $upload_base . 'wpo_wcpdf/';
|
417 |
+
}
|
418 |
+
|
419 |
+
$tmp_base = apply_filters( 'wpo_wcpdf_tmp_path', $tmp_base );
|
420 |
+
if ($tmp_base !== false) {
|
421 |
+
$tmp_base = trailingslashit( $tmp_base );
|
422 |
+
}
|
423 |
+
|
424 |
+
return $tmp_base;
|
425 |
+
}
|
426 |
+
|
427 |
+
/**
|
428 |
+
* Install/create plugin tmp folders
|
429 |
+
*/
|
430 |
+
public function init_tmp ( $tmp_base ) {
|
431 |
+
// create plugin base temp folder
|
432 |
+
mkdir( $tmp_base );
|
433 |
+
|
434 |
+
if (!is_dir($tmp_base)) {
|
435 |
+
wcpdf_log_error( "Unable to create temp folder {$tmp_base}", 'critical' );
|
436 |
+
}
|
437 |
+
|
438 |
+
// create subfolders & protect
|
439 |
+
$subfolders = array( 'attachments', 'fonts', 'dompdf' );
|
440 |
+
foreach ( $subfolders as $subfolder ) {
|
441 |
+
$path = $tmp_base . $subfolder . '/';
|
442 |
+
mkdir( $path );
|
443 |
+
|
444 |
+
// copy font files
|
445 |
+
if ( $subfolder == 'fonts' ) {
|
446 |
+
$this->copy_fonts( $path, false );
|
447 |
+
}
|
448 |
+
|
449 |
+
// create .htaccess file and empty index.php to protect in case an open webfolder is used!
|
450 |
+
file_put_contents( $path . '.htaccess', 'deny from all' );
|
451 |
+
touch( $path . 'index.php' );
|
452 |
+
}
|
453 |
+
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Copy DOMPDF fonts to wordpress tmp folder
|
458 |
+
*/
|
459 |
+
public function copy_fonts ( $path, $merge_with_local = true ) {
|
460 |
+
$path = trailingslashit( $path );
|
461 |
+
$dompdf_font_dir = WPO_WCPDF()->plugin_path() . "/vendor/dompdf/dompdf/lib/fonts/";
|
462 |
+
|
463 |
+
// get local font dir from filtered options
|
464 |
+
$dompdf_options = apply_filters( 'wpo_wcpdf_dompdf_options', array(
|
465 |
+
'defaultFont' => 'dejavu sans',
|
466 |
+
'tempDir' => $this->get_tmp_path('dompdf'),
|
467 |
+
'logOutputFile' => $this->get_tmp_path('dompdf') . "/log.htm",
|
468 |
+
'fontDir' => $this->get_tmp_path('fonts'),
|
469 |
+
'fontCache' => $this->get_tmp_path('fonts'),
|
470 |
+
'isRemoteEnabled' => true,
|
471 |
+
'isFontSubsettingEnabled' => true,
|
472 |
+
'isHtml5ParserEnabled' => true,
|
473 |
+
) );
|
474 |
+
$fontDir = $dompdf_options['fontDir'];
|
475 |
+
|
476 |
+
// merge font family cache with local/custom if present
|
477 |
+
$font_cache_files = array(
|
478 |
+
'cache' => 'dompdf_font_family_cache.php',
|
479 |
+
'cache_dist' => 'dompdf_font_family_cache.dist.php',
|
480 |
+
);
|
481 |
+
foreach ( $font_cache_files as $font_cache_name => $font_cache_filename ) {
|
482 |
+
$plugin_fonts = @require $dompdf_font_dir . $font_cache_filename;
|
483 |
+
if ( $merge_with_local && is_readable( $path . $font_cache_filename ) ) {
|
484 |
+
$local_fonts = @require $path . $font_cache_filename;
|
485 |
+
if (is_array($local_fonts) && is_array($plugin_fonts)) {
|
486 |
+
// merge local & plugin fonts, plugin fonts overwrite (update) local fonts
|
487 |
+
// while custom local fonts are retained
|
488 |
+
$local_fonts = array_merge($local_fonts, $plugin_fonts);
|
489 |
+
// create readable array with $fontDir in place of the actual folder for portability
|
490 |
+
$fonts_export = var_export($local_fonts,true);
|
491 |
+
$fonts_export = str_replace('\'' . $fontDir , '$fontDir . \'', $fonts_export);
|
492 |
+
$cacheData = sprintf("<?php return %s;%s?>", $fonts_export, PHP_EOL );
|
493 |
+
// write file with merged cache data
|
494 |
+
file_put_contents($path . $font_cache_filename, $cacheData);
|
495 |
+
} else { // empty local file
|
496 |
+
copy( $dompdf_font_dir . $font_cache_filename, $path . $font_cache_filename );
|
497 |
+
}
|
498 |
+
} else {
|
499 |
+
// we couldn't read the local font cache file so we're simply copying over plugin cache file
|
500 |
+
copy( $dompdf_font_dir . $font_cache_filename, $path . $font_cache_filename );
|
501 |
+
}
|
502 |
+
}
|
503 |
+
|
504 |
+
// first try the easy way with glob!
|
505 |
+
if ( function_exists('glob') ) {
|
506 |
+
$files = glob($dompdf_font_dir."*.*");
|
507 |
+
foreach($files as $file){
|
508 |
+
$filename = basename($file);
|
509 |
+
if( !is_dir($file) && is_readable($file) && !in_array($filename, $font_cache_files)) {
|
510 |
+
$dest = $path . $filename;
|
511 |
+
copy($file, $dest);
|
512 |
+
}
|
513 |
+
}
|
514 |
+
} else {
|
515 |
+
// fallback method using font cache file (glob is disabled on some servers with disable_functions)
|
516 |
+
$extensions = array( '.ttf', '.ufm', '.ufm.php', '.afm', '.afm.php' );
|
517 |
+
$fontDir = untrailingslashit($dompdf_font_dir);
|
518 |
+
$plugin_fonts = @require $dompdf_font_dir . $font_cache_files['cache'];
|
519 |
+
|
520 |
+
foreach ($plugin_fonts as $font_family => $filenames) {
|
521 |
+
foreach ($filenames as $filename) {
|
522 |
+
foreach ($extensions as $extension) {
|
523 |
+
$file = $filename.$extension;
|
524 |
+
if (file_exists($file)) {
|
525 |
+
$dest = $path . basename($file);
|
526 |
+
copy($file, $dest);
|
527 |
+
}
|
528 |
+
}
|
529 |
+
}
|
530 |
+
}
|
531 |
+
}
|
532 |
+
}
|
533 |
+
|
534 |
+
public function disable_free_attachment( $attach, $order, $email_id, $document_type ) {
|
535 |
+
// prevent fatal error for non-order objects
|
536 |
+
if ( !method_exists( $order, 'get_total' ) ) {
|
537 |
+
return false;
|
538 |
+
}
|
539 |
+
|
540 |
+
$document_settings = WPO_WCPDF()->settings->get_document_settings( $document_type );
|
541 |
+
|
542 |
+
// check order total & setting
|
543 |
+
$order_total = $order->get_total();
|
544 |
+
if ( $order_total == 0 && isset( $document_settings['disable_free'] ) ) {
|
545 |
+
return false;
|
546 |
+
}
|
547 |
+
|
548 |
+
return $attach;
|
549 |
+
}
|
550 |
+
|
551 |
+
public function test_mode_settings( $use_historical_settings, $document ) {
|
552 |
+
if ( isset( WPO_WCPDF()->settings->general_settings['test_mode'] ) ) {
|
553 |
+
$use_historical_settings = false;
|
554 |
+
}
|
555 |
+
return $use_historical_settings;
|
556 |
+
}
|
557 |
+
|
558 |
+
/**
|
559 |
+
* Adds spans around placeholders to be able to make replacement (page count) and css (page number)
|
560 |
+
*/
|
561 |
+
public function format_page_number_placeholders ( $html, $document ) {
|
562 |
+
$html = str_replace('{{PAGE_COUNT}}', '<span class="pagecount">^C^</span>', $html);
|
563 |
+
$html = str_replace('{{PAGE_NUM}}', '<span class="pagenum"></span>', $html );
|
564 |
+
return $html;
|
565 |
+
}
|
566 |
+
|
567 |
+
/**
|
568 |
+
* Replace {{PAGE_COUNT}} placeholder with total page count
|
569 |
+
*/
|
570 |
+
public function page_number_replacements ( $dompdf, $html ) {
|
571 |
+
$placeholder = '^C^';
|
572 |
+
// create placeholder version with ASCII 0 spaces (dompdf 0.8)
|
573 |
+
$placeholder_0 = '';
|
574 |
+
$placeholder_chars = str_split($placeholder);
|
575 |
+
foreach ($placeholder_chars as $placeholder_char) {
|
576 |
+
$placeholder_0 .= chr(0).$placeholder_char;
|
577 |
+
}
|
578 |
+
|
579 |
+
// check if placeholder is used
|
580 |
+
if (strpos($html, $placeholder) !== false ) {
|
581 |
+
foreach ($dompdf->get_canvas()->get_cpdf()->objects as &$object) {
|
582 |
+
if (array_key_exists("c", $object) && strpos($object["c"], $placeholder) !== false ) {
|
583 |
+
$object["c"] = str_replace( array($placeholder,$placeholder_0) , $dompdf->get_canvas()->get_page_count() , $object["c"] );
|
584 |
+
} elseif (array_key_exists("c", $object) && strpos($object["c"], $placeholder_0) !== false ) {
|
585 |
+
$object["c"] = str_replace( array($placeholder,$placeholder_0) , chr(0).$dompdf->get_canvas()->get_page_count() , $object["c"] );
|
586 |
+
}
|
587 |
+
}
|
588 |
+
}
|
589 |
+
|
590 |
+
return $dompdf;
|
591 |
+
}
|
592 |
+
|
593 |
+
/**
|
594 |
+
* Use currency symbol font (when enabled in options)
|
595 |
+
*/
|
596 |
+
public function use_currency_font ( $document_type, $document ) {
|
597 |
+
add_filter( 'woocommerce_currency_symbol', array( $this, 'wrap_currency_symbol' ), 10001, 2);
|
598 |
+
add_action( 'wpo_wcpdf_custom_styles', array($this, 'currency_symbol_font_styles' ) );
|
599 |
+
}
|
600 |
+
|
601 |
+
public function wrap_currency_symbol( $currency_symbol, $currency ) {
|
602 |
+
$currency_symbol = sprintf( '<span class="wcpdf-currency-symbol">%s</span>', $currency_symbol );
|
603 |
+
return $currency_symbol;
|
604 |
+
}
|
605 |
+
|
606 |
+
public function currency_symbol_font_styles () {
|
607 |
+
?>
|
608 |
+
.wcpdf-currency-symbol { font-family: 'Currencies'; }
|
609 |
+
<?php
|
610 |
+
}
|
611 |
+
|
612 |
+
/**
|
613 |
+
* Remove attachments older than 1 week (daily, hooked into wp_scheduled_delete )
|
614 |
+
*/
|
615 |
+
public function attachments_cleanup() {
|
616 |
+
if ( !function_exists("glob") || !function_exists('filemtime') ) {
|
617 |
+
// glob is required
|
618 |
+
return;
|
619 |
+
}
|
620 |
+
|
621 |
+
|
622 |
+
if ( !isset( WPO_WCPDF()->settings->debug_settings['enable_cleanup'] ) ) {
|
623 |
+
return;
|
624 |
+
}
|
625 |
+
|
626 |
+
|
627 |
+
$cleanup_age_days = isset(WPO_WCPDF()->settings->debug_settings['cleanup_days']) ? floatval(WPO_WCPDF()->settings->debug_settings['cleanup_days']) : 7.0;
|
628 |
+
$delete_timestamp = time() - ( intval ( DAY_IN_SECONDS * $cleanup_age_days ) );
|
629 |
+
|
630 |
+
$tmp_path = $this->get_tmp_path('attachments');
|
631 |
+
|
632 |
+
if ( $files = glob( $tmp_path.'*.pdf' ) ) { // get all pdf files
|
633 |
+
foreach( $files as $file ) {
|
634 |
+
if( is_file( $file ) ) {
|
635 |
+
$file_timestamp = filemtime( $file );
|
636 |
+
if ( !empty( $file_timestamp ) && $file_timestamp < $delete_timestamp ) {
|
637 |
+
@unlink($file);
|
638 |
+
}
|
639 |
+
}
|
640 |
+
}
|
641 |
+
}
|
642 |
+
}
|
643 |
+
|
644 |
+
/**
|
645 |
+
* Remove all invoice data when requested
|
646 |
+
*/
|
647 |
+
public function remove_order_personal_data_meta( $meta_to_remove ) {
|
648 |
+
$wcpdf_private_meta = array(
|
649 |
+
'_wcpdf_invoice_number' => 'numeric_id',
|
650 |
+
'_wcpdf_invoice_number_data' => 'array',
|
651 |
+
'_wcpdf_invoice_date' => 'timestamp',
|
652 |
+
'_wcpdf_invoice_date_formatted' => 'date',
|
653 |
+
);
|
654 |
+
return $meta_to_remove + $wcpdf_private_meta;
|
655 |
+
}
|
656 |
+
|
657 |
+
/**
|
658 |
+
* Remove references to order in number store tables when removing WC data
|
659 |
+
*/
|
660 |
+
public function remove_order_personal_data( $order ) {
|
661 |
+
global $wpdb;
|
662 |
+
// remove order ID from number stores
|
663 |
+
$number_stores = apply_filters( "wpo_wcpdf_privacy_number_stores", array( 'invoice_number' ) );
|
664 |
+
foreach ( $number_stores as $store_name ) {
|
665 |
+
$order_id = $order->get_id();
|
666 |
+
$table_name = apply_filters( "wpo_wcpdf_number_store_table_name", "{$wpdb->prefix}wcpdf_{$store_name}", $store_name, 'auto_increment' ); // i.e. wp_wcpdf_invoice_number
|
667 |
+
$wpdb->query( $wpdb->prepare( "UPDATE $table_name SET order_id = 0 WHERE order_id = %s", $order_id ) );
|
668 |
+
}
|
669 |
+
}
|
670 |
+
|
671 |
+
/**
|
672 |
+
* Export all invoice data when requested
|
673 |
+
*/
|
674 |
+
public function export_order_personal_data_meta( $meta_to_export ) {
|
675 |
+
$private_address_meta = array(
|
676 |
+
// _wcpdf_invoice_number_data & _wcpdf_invoice_date are duplicates of the below and therefor not included
|
677 |
+
'_wcpdf_invoice_number' => __( 'Invoice Number', 'woocommerce-pdf-invoices-packing-slips' ),
|
678 |
+
'_wcpdf_invoice_date_formatted' => __( 'Invoice Date', 'woocommerce-pdf-invoices-packing-slips' ),
|
679 |
+
);
|
680 |
+
return $meta_to_export + $private_address_meta;
|
681 |
+
}
|
682 |
+
|
683 |
+
/**
|
684 |
+
* Set the default PHPMailer validator to 'php' ( which uses filter_var($address, FILTER_VALIDATE_EMAIL) )
|
685 |
+
* This avoids issues with the presence of attachments affecting email address validation in some distros of PHP 7.3
|
686 |
+
* See: https://wordpress.org/support/topic/invalid-address-setfrom/#post-11583815
|
687 |
+
*/
|
688 |
+
public function set_phpmailer_validator( $mailArray ) {
|
689 |
+
if ( version_compare( PHP_VERSION, '7.3', '>=' ) ) {
|
690 |
+
global $phpmailer;
|
691 |
+
if ( ! ( $phpmailer instanceof \PHPMailer ) ) {
|
692 |
+
require_once ABSPATH . WPINC . '/class-phpmailer.php';
|
693 |
+
require_once ABSPATH . WPINC . '/class-smtp.php';
|
694 |
+
$phpmailer = new \PHPMailer( true );
|
695 |
+
}
|
696 |
+
$phpmailer::$validator = 'php';
|
697 |
+
}
|
698 |
+
|
699 |
+
return $mailArray;
|
700 |
+
}
|
701 |
+
|
702 |
+
/**
|
703 |
+
* Enable PHP error output
|
704 |
+
*/
|
705 |
+
public function enable_debug () {
|
706 |
+
error_reporting( E_ALL );
|
707 |
+
ini_set( 'display_errors', 1 );
|
708 |
+
}
|
709 |
+
|
710 |
+
}
|
711 |
+
|
712 |
+
endif; // class_exists
|
713 |
+
|
714 |
+
return new Main();
|
includes/compatibility/class-wcpdf-compatibility-third-party-plugins.php
CHANGED
@@ -1,222 +1,225 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPO\WC\PDF_Invoices\Compatibility;
|
3 |
-
|
4 |
-
use WPO\WC\PDF_Invoices\Compatibility\WC_Core as WCX;
|
5 |
-
use WPO\WC\PDF_Invoices\Compatibility\Order as WCX_Order;
|
6 |
-
use WPO\WC\PDF_Invoices\Compatibility\Product as WCX_Product;
|
7 |
-
use WPO\WC\PDF_Invoices\Compatibility\WC_DateTime;
|
8 |
-
|
9 |
-
defined( 'ABSPATH' ) or exit;
|
10 |
-
|
11 |
-
if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Compatibility\\Third_Party_Plugins' ) ) :
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Third party plugin compatibility class.
|
15 |
-
*
|
16 |
-
* @since 2.0
|
17 |
-
*/
|
18 |
-
class Third_Party_Plugins {
|
19 |
-
function __construct() {
|
20 |
-
// WooCommerce Subscriptions compatibility
|
21 |
-
if ( class_exists('WC_Subscriptions') ) {
|
22 |
-
if ( version_compare( \WC_Subscriptions::$version, '2.0', '<' ) ) {
|
23 |
-
add_action( 'woocommerce_subscriptions_renewal_order_created', array( $this, 'woocommerce_subscriptions_renewal_order_created' ), 10, 4 );
|
24 |
-
} else {
|
25 |
-
add_action( 'wcs_renewal_order_created', array( $this, 'wcs_renewal_order_created' ), 10, 2 );
|
26 |
-
}
|
27 |
-
}
|
28 |
-
|
29 |
-
// WooCommerce Product Bundles compatibility (add row classes)
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
if (
|
46 |
-
|
47 |
-
}
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
return
|
106 |
-
}
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
*
|
115 |
-
* @param
|
116 |
-
* @param
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
*
|
137 |
-
* @param
|
138 |
-
* @param
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
//
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
}
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
namespace WPO\WC\PDF_Invoices\Compatibility;
|
3 |
+
|
4 |
+
use WPO\WC\PDF_Invoices\Compatibility\WC_Core as WCX;
|
5 |
+
use WPO\WC\PDF_Invoices\Compatibility\Order as WCX_Order;
|
6 |
+
use WPO\WC\PDF_Invoices\Compatibility\Product as WCX_Product;
|
7 |
+
use WPO\WC\PDF_Invoices\Compatibility\WC_DateTime;
|
8 |
+
|
9 |
+
defined( 'ABSPATH' ) or exit;
|
10 |
+
|
11 |
+
if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Compatibility\\Third_Party_Plugins' ) ) :
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Third party plugin compatibility class.
|
15 |
+
*
|
16 |
+
* @since 2.0
|
17 |
+
*/
|
18 |
+
class Third_Party_Plugins {
|
19 |
+
function __construct() {
|
20 |
+
// WooCommerce Subscriptions compatibility
|
21 |
+
if ( class_exists('WC_Subscriptions') ) {
|
22 |
+
if ( version_compare( \WC_Subscriptions::$version, '2.0', '<' ) ) {
|
23 |
+
add_action( 'woocommerce_subscriptions_renewal_order_created', array( $this, 'woocommerce_subscriptions_renewal_order_created' ), 10, 4 );
|
24 |
+
} else {
|
25 |
+
add_action( 'wcs_renewal_order_created', array( $this, 'wcs_renewal_order_created' ), 10, 2 );
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
// WooCommerce Product Bundles compatibility (add row classes)
|
30 |
+
add_filter( 'wpo_wcpdf_item_row_class', array( $this, 'add_product_bundles_classes' ), 10, 4 );
|
31 |
+
|
32 |
+
// WooCommerce Chained Products compatibility (add row classes)
|
33 |
+
add_filter( 'wpo_wcpdf_item_row_class', array( $this, 'add_chained_product_class' ), 10, 4 );
|
34 |
+
|
35 |
+
// WooCommerce Composite Products compatibility (add row classes)
|
36 |
+
add_filter( 'wpo_wcpdf_item_row_class', array( $this, 'add_composite_product_class' ), 10, 4 );
|
37 |
+
|
38 |
+
// WooCommerce Order Status & Actions Manager emails compatibility
|
39 |
+
if (class_exists('WC_Custom_Status')) {
|
40 |
+
add_filter( 'wpo_wcpdf_wc_emails', array( $this, 'wc_order_status_actions_emails' ), 10, 1 );
|
41 |
+
}
|
42 |
+
|
43 |
+
// Aelia Currency Switcher compatibility
|
44 |
+
$currency_switcher_active = !empty($GLOBALS['woocommerce-aelia-currencyswitcher']);
|
45 |
+
if ( $currency_switcher_active ) {
|
46 |
+
add_action( 'wpo_wcpdf_before_html', array( $this, 'aelia_currency_formatting' ), 10, 2 );
|
47 |
+
}
|
48 |
+
|
49 |
+
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Reset invoice data for WooCommerce subscription renewal orders
|
54 |
+
* https://wordpress.org/support/topic/subscription-renewal-duplicate-invoice-number?replies=6#post-6138110
|
55 |
+
*/
|
56 |
+
public function woocommerce_subscriptions_renewal_order_created ( $renewal_order, $original_order, $product_id, $new_order_role ) {
|
57 |
+
$this->reset_invoice_data( $renewal_order );
|
58 |
+
return $renewal_order;
|
59 |
+
}
|
60 |
+
|
61 |
+
public function wcs_renewal_order_created ( $renewal_order, $subscription ) {
|
62 |
+
$this->reset_invoice_data( $renewal_order );
|
63 |
+
return $renewal_order;
|
64 |
+
}
|
65 |
+
|
66 |
+
public function reset_invoice_data ( $order ) {
|
67 |
+
if ( ! is_object( $order ) ) {
|
68 |
+
$order = wc_get_order( $order );
|
69 |
+
}
|
70 |
+
// delete invoice number, invoice date & invoice exists meta
|
71 |
+
WCX_Order::delete_meta_data( $order, '_wcpdf_invoice_number' );
|
72 |
+
WCX_Order::delete_meta_data( $order, '_wcpdf_invoice_number_data' );
|
73 |
+
WCX_Order::delete_meta_data( $order, '_wcpdf_formatted_invoice_number' );
|
74 |
+
WCX_Order::delete_meta_data( $order, '_wcpdf_invoice_date' );
|
75 |
+
WCX_Order::delete_meta_data( $order, '_wcpdf_invoice_exists' );
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* WooCommerce Product Bundles
|
80 |
+
* @param string $classes CSS classes for item row (tr)
|
81 |
+
* @param string $document_type PDF Document type
|
82 |
+
* @param object $order WC_Order order
|
83 |
+
* @param int $item_id WooCommerce Item ID
|
84 |
+
*/
|
85 |
+
public function add_product_bundles_classes ( $classes, $document_type, $order, $item_id = '' ) {
|
86 |
+
if ( !class_exists('WC_Bundles') ) {
|
87 |
+
return $classes;
|
88 |
+
}
|
89 |
+
|
90 |
+
$item_id = !empty($item_id) ? $item_id : $this->get_item_id_from_classes( $classes );
|
91 |
+
if ( empty($item_id) ) {
|
92 |
+
return $classes;
|
93 |
+
}
|
94 |
+
|
95 |
+
if ( $bundled_by = WCX_Order::get_item_meta( $order, $item_id, '_bundled_by', true ) ) {
|
96 |
+
$classes = $classes . ' bundled-item';
|
97 |
+
|
98 |
+
// check bundled item visibility
|
99 |
+
if ( $hidden = WCX_Order::get_item_meta( $order, $item_id, '_bundled_item_hidden', true ) ) {
|
100 |
+
$classes = $classes . ' hidden';
|
101 |
+
}
|
102 |
+
|
103 |
+
return $classes;
|
104 |
+
} elseif ( $bundled_items = WCX_Order::get_item_meta( $order, $item_id, '_bundled_items', true ) ) {
|
105 |
+
return $classes . ' product-bundle';
|
106 |
+
}
|
107 |
+
|
108 |
+
return $classes;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* WooCommerce Chanined Products
|
113 |
+
* @param string $classes CSS classes for item row (tr)
|
114 |
+
* @param string $document_type PDF Document type
|
115 |
+
* @param object $order WC_Order order
|
116 |
+
* @param int $item_id WooCommerce Item ID
|
117 |
+
*/
|
118 |
+
public function add_chained_product_class ( $classes, $document_type, $order, $item_id = '' ) {
|
119 |
+
if ( !class_exists('SA_WC_Chained_Products') && !class_exists('WC_Chained_Products') ) {
|
120 |
+
return $classes;
|
121 |
+
}
|
122 |
+
|
123 |
+
$item_id = !empty($item_id) ? $item_id : $this->get_item_id_from_classes( $classes );
|
124 |
+
if ( empty($item_id) ) {
|
125 |
+
return $classes;
|
126 |
+
}
|
127 |
+
|
128 |
+
if ( $chained_product_of = WCX_Order::get_item_meta( $order, $item_id, '_chained_product_of', true ) ) {
|
129 |
+
return $classes . ' chained-product';
|
130 |
+
}
|
131 |
+
|
132 |
+
return $classes;
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* WooCommerce Composite Products
|
137 |
+
* @param string $classes CSS classes for item row (tr)
|
138 |
+
* @param string $document_type PDF Document type
|
139 |
+
* @param object $order WC_Order order
|
140 |
+
* @param int $item_id WooCommerce Item ID
|
141 |
+
*/
|
142 |
+
public function add_composite_product_class ( $classes, $document_type, $order, $item_id = '' ) {
|
143 |
+
if ( !function_exists('wc_cp_is_composited_order_item') || !function_exists('wc_cp_is_composite_container_order_item') ) {
|
144 |
+
return $classes;
|
145 |
+
}
|
146 |
+
|
147 |
+
$item_id = !empty($item_id) ? $item_id : $this->get_item_id_from_classes( $classes );
|
148 |
+
if ( empty($item_id) ) {
|
149 |
+
return $classes;
|
150 |
+
}
|
151 |
+
|
152 |
+
// get order item object
|
153 |
+
$order_items = $order->get_items();
|
154 |
+
foreach ($order_items as $order_item_id => $order_item) {
|
155 |
+
if ($order_item_id == $item_id) {
|
156 |
+
if ( wc_cp_is_composited_order_item( $order_item, $order ) ) {
|
157 |
+
$classes .= ' component_table_item';
|
158 |
+
} elseif ( wc_cp_is_composite_container_order_item( $order_item ) ) {
|
159 |
+
$classes .= ' component_container_table_item';
|
160 |
+
}
|
161 |
+
break;
|
162 |
+
}
|
163 |
+
}
|
164 |
+
|
165 |
+
return $classes;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Backwards compatibility helper function: try to get item ID from row class
|
170 |
+
* @param string $classes CSS classes for item row (tr)
|
171 |
+
*/
|
172 |
+
public function get_item_id_from_classes ( $classes ) {
|
173 |
+
$class_array = explode(' ', $classes);
|
174 |
+
foreach ($class_array as $class) {
|
175 |
+
if (is_numeric($class)) {
|
176 |
+
$item_id = $class;
|
177 |
+
break;
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
// if still empty, we lost the item id somewhere :(
|
182 |
+
if (empty($item_id)) {
|
183 |
+
return false;
|
184 |
+
} else {
|
185 |
+
return $item_id;
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* WooCommerce Order Status & Actions Manager emails compatibility
|
191 |
+
*/
|
192 |
+
public function wc_order_status_actions_emails ( $emails ) {
|
193 |
+
// get list of custom statuses from WooCommerce Custom Order Status & Actions
|
194 |
+
// status slug => status name
|
195 |
+
$custom_statuses = \WC_Custom_Status::get_status_list_names();
|
196 |
+
// append _email to slug (=email_id) and add to emails list
|
197 |
+
foreach ($custom_statuses as $status_slug => $status_name) {
|
198 |
+
$emails[$status_slug.'_email'] = $status_name;
|
199 |
+
}
|
200 |
+
return $emails;
|
201 |
+
}
|
202 |
+
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Aelia Currency Switcher compatibility
|
206 |
+
* Applies decimal & Thousand separator settings
|
207 |
+
*/
|
208 |
+
function aelia_currency_formatting( $document_type, $document ) {
|
209 |
+
add_filter( 'wc_price_args', array( $this, 'aelia_currency_price_args' ), 10, 1 );
|
210 |
+
}
|
211 |
+
|
212 |
+
function aelia_currency_price_args( $args ) {
|
213 |
+
if ( !empty( $args['currency'] ) && class_exists("\\Aelia\\WC\\CurrencySwitcher\\WC_Aelia_CurrencySwitcher") ) {
|
214 |
+
$cs_settings = \Aelia\WC\CurrencySwitcher\WC_Aelia_CurrencySwitcher::settings();
|
215 |
+
$args['decimal_separator'] = $cs_settings->get_currency_decimal_separator( $args['currency'] );
|
216 |
+
$args['thousand_separator'] = $cs_settings->get_currency_thousand_separator( $args['currency'] );
|
217 |
+
}
|
218 |
+
return $args;
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
|
223 |
+
endif; // Class exists check
|
224 |
+
|
225 |
+
return new Third_Party_Plugins();
|
includes/documents/abstract-wcpdf-order-document-methods.php
CHANGED
@@ -1,1129 +1,1154 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPO\WC\PDF_Invoices\Documents;
|
3 |
-
|
4 |
-
use WPO\WC\PDF_Invoices\Compatibility\WC_Core as WCX;
|
5 |
-
use WPO\WC\PDF_Invoices\Compatibility\Order as WCX_Order;
|
6 |
-
use WPO\WC\PDF_Invoices\Compatibility\Product as WCX_Product;
|
7 |
-
|
8 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
-
exit; // Exit if accessed directly
|
10 |
-
}
|
11 |
-
|
12 |
-
if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\Documents\\Order_Document_Methods' ) ) :
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Abstract Order Methods
|
16 |
-
*
|
17 |
-
* Collection of methods to be used on orders within a Document
|
18 |
-
* Created as abstract rather than traits to support PHP versions older than 5.4
|
19 |
-
*
|
20 |
-
* @class \WPO\WC\PDF_Invoices\Documents\Order_Document_Methods
|
21 |
-
* @version 2.0
|
22 |
-
* @category Class
|
23 |
-
* @author Ewout Fernhout
|
24 |
-
*/
|
25 |
-
|
26 |
-
abstract class Order_Document_Methods extends Order_Document {
|
27 |
-
public function is_refund( $order ) {
|
28 |
-
if ( method_exists( $order, 'get_type') ) { // WC 3.0+
|
29 |
-
$is_refund = $order->get_type() == 'shop_order_refund';
|
30 |
-
} else {
|
31 |
-
$is_refund = get_post_type( WCX_Order::get_id( $order ) ) == 'shop_order_refund';
|
32 |
-
}
|
33 |
-
|
34 |
-
return $is_refund;
|
35 |
-
}
|
36 |
-
|
37 |
-
public function get_refund_parent_id( $order ) {
|
38 |
-
if ( method_exists( $order, 'get_parent_id') ) { // WC3.0+
|
39 |
-
$parent_order_id = $order->get_parent_id();
|
40 |
-
} else {
|
41 |
-
$parent_order_id = wp_get_post_parent_id( WCX_Order::get_id( $order ) );
|
42 |
-
}
|
43 |
-
|
44 |
-
return $parent_order_id;
|
45 |
-
}
|
46 |
-
|
47 |
-
|
48 |
-
public function get_refund_parent( $order ) {
|
49 |
-
// only try if this is actually a refund
|
50 |
-
if ( ! $this->is_refund( $order ) ) {
|
51 |
-
return $order;
|
52 |
-
}
|
53 |
-
|
54 |
-
$parent_order_id = $this->get_refund_parent_id( $order );
|
55 |
-
$order = WCX::get_order( $parent_order_id );
|
56 |
-
return $order;
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Check if billing address and shipping address are equal
|
61 |
-
*/
|
62 |
-
public function ships_to_different_address() {
|
63 |
-
// always prefer parent address for refunds
|
64 |
-
if ( $this->is_refund( $this->order ) ) {
|
65 |
-
$order = $this->get_refund_parent( $this->order );
|
66 |
-
} else {
|
67 |
-
$order = $this->order;
|
68 |
-
}
|
69 |
-
|
70 |
-
// only check if there is a shipping address at all
|
71 |
-
if ( $formatted_shipping_address = $order->get_formatted_shipping_address() ) {
|
72 |
-
$address_comparison_fields = apply_filters( 'wpo_wcpdf_address_comparison_fields', array(
|
73 |
-
'first_name',
|
74 |
-
'last_name',
|
75 |
-
'company',
|
76 |
-
'address_1',
|
77 |
-
'address_2',
|
78 |
-
'city',
|
79 |
-
'state',
|
80 |
-
'postcode',
|
81 |
-
'country'
|
82 |
-
), $this );
|
83 |
-
|
84 |
-
foreach ($address_comparison_fields as $address_field) {
|
85 |
-
$billing_field = WCX_Order::get_prop( $order, "billing_{$address_field}", 'view');
|
86 |
-
$shipping_field = WCX_Order::get_prop( $order, "shipping_{$address_field}", 'view');
|
87 |
-
if ( $shipping_field != $billing_field ) {
|
88 |
-
// this address field is different -> ships to different address!
|
89 |
-
return true;
|
90 |
-
}
|
91 |
-
}
|
92 |
-
}
|
93 |
-
|
94 |
-
//if we got here, it means the addresses are equal -> doesn't ship to different address!
|
95 |
-
return apply_filters( 'wpo_wcpdf_ships_to_different_address', false, $order, $this );
|
96 |
-
}
|
97 |
-
|
98 |
-
/**
|
99 |
-
* Return/Show billing address
|
100 |
-
*/
|
101 |
-
public function get_billing_address() {
|
102 |
-
// always prefer parent billing address for refunds
|
103 |
-
if ( $this->is_refund( $this->order ) ) {
|
104 |
-
// temporarily switch order to make all filters / order calls work correctly
|
105 |
-
$refund = $this->order;
|
106 |
-
$this->order = $this->get_refund_parent( $this->order );
|
107 |
-
$address = apply_filters( 'wpo_wcpdf_billing_address', $this->order->get_formatted_billing_address(), $this );
|
108 |
-
// switch back & unset
|
109 |
-
$this->order = $refund;
|
110 |
-
unset($refund);
|
111 |
-
} elseif ( $address = $this->order->get_formatted_billing_address() ) {
|
112 |
-
// regular shop_order
|
113 |
-
$address = apply_filters( 'wpo_wcpdf_billing_address', $address, $this );
|
114 |
-
} else {
|
115 |
-
// no address
|
116 |
-
$address = apply_filters( 'wpo_wcpdf_billing_address', __('N/A', 'woocommerce-pdf-invoices-packing-slips' ), $this );
|
117 |
-
}
|
118 |
-
|
119 |
-
return $address;
|
120 |
-
}
|
121 |
-
public function billing_address() {
|
122 |
-
echo $this->get_billing_address();
|
123 |
-
}
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Return/Show billing email
|
127 |
-
*/
|
128 |
-
public function get_billing_email() {
|
129 |
-
$billing_email = WCX_Order::get_prop( $this->order, 'billing_email', 'view' );
|
130 |
-
|
131 |
-
if ( !$billing_email && $this->is_refund( $this->order ) ) {
|
132 |
-
// try parent
|
133 |
-
$parent_order = $this->get_refund_parent( $this->order );
|
134 |
-
$billing_email = WCX_Order::get_prop( $parent_order, 'billing_email', 'view' );
|
135 |
-
}
|
136 |
-
|
137 |
-
return apply_filters( 'wpo_wcpdf_billing_email', $billing_email, $this );
|
138 |
-
}
|
139 |
-
public function billing_email() {
|
140 |
-
echo $this->get_billing_email();
|
141 |
-
}
|
142 |
-
|
143 |
-
/**
|
144 |
-
* Return/Show billing phone
|
145 |
-
*/
|
146 |
-
public function get_billing_phone() {
|
147 |
-
$billing_phone = WCX_Order::get_prop( $this->order, 'billing_phone', 'view' );
|
148 |
-
|
149 |
-
if ( !$billing_phone && $this->is_refund( $this->order ) ) {
|
150 |
-
// try parent
|
151 |
-
$parent_order = $this->get_refund_parent( $this->order );
|
152 |
-
$billing_phone = WCX_Order::get_prop( $parent_order, 'billing_phone', 'view' );
|
153 |
-
}
|
154 |
-
|
155 |
-
return apply_filters( 'wpo_wcpdf_billing_phone', $billing_phone, $this );
|
156 |
-
}
|
157 |
-
public function billing_phone() {
|
158 |
-
echo $this->get_billing_phone();
|
159 |
-
}
|
160 |
-
|
161 |
-
/**
|
162 |
-
* Return/Show shipping address
|
163 |
-
*/
|
164 |
-
public function get_shipping_address() {
|
165 |
-
// always prefer parent shipping address for refunds
|
166 |
-
if ( $this->is_refund( $this->order ) ) {
|
167 |
-
// temporarily switch order to make all filters / order calls work correctly
|
168 |
-
$refund = $this->order;
|
169 |
-
$this->order = $this->get_refund_parent( $this->order );
|
170 |
-
$address = apply_filters( 'wpo_wcpdf_shipping_address', $this->order->get_formatted_shipping_address(), $this );
|
171 |
-
// switch back & unset
|
172 |
-
$this->order = $refund;
|
173 |
-
unset($refund);
|
174 |
-
} elseif ( $address = $this->order->get_formatted_shipping_address() ) {
|
175 |
-
// regular shop_order
|
176 |
-
$address = apply_filters( 'wpo_wcpdf_shipping_address', $address, $this );
|
177 |
-
} else {
|
178 |
-
// no address
|
179 |
-
// use fallback for packing slip
|
180 |
-
if ( apply_filters( 'wpo_wcpdf_shipping_address_fallback', ( $this->get_type() == 'packing-slip' ), $this ) ) {
|
181 |
-
$address = $this->get_billing_address();
|
182 |
-
} else{
|
183 |
-
$address = apply_filters( 'wpo_wcpdf_shipping_address', __('N/A', 'woocommerce-pdf-invoices-packing-slips' ), $this );
|
184 |
-
|
185 |
-
}
|
186 |
-
}
|
187 |
-
|
188 |
-
return $address;
|
189 |
-
}
|
190 |
-
public function shipping_address() {
|
191 |
-
echo $this->get_shipping_address();
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* Return/Show a custom field
|
196 |
-
*/
|
197 |
-
public function get_custom_field( $field_name ) {
|
198 |
-
if ( !$this->is_order_prop( $field_name ) ) {
|
199 |
-
$custom_field = WCX_Order::get_meta( $this->order, $field_name, true );
|
200 |
-
}
|
201 |
-
// if not found, try prefixed with underscore (not when ACF is active!)
|
202 |
-
if ( empty( $custom_field ) && substr( $field_name, 0, 1 ) !== '_' && !$this->is_order_prop( "_{$field_name}" ) && !class_exists('ACF') ) {
|
203 |
-
$custom_field = WCX_Order::get_meta( $this->order, "_{$field_name}", true );
|
204 |
-
}
|
205 |
-
|
206 |
-
// WC3.0 fallback to properties
|
207 |
-
$property = str_replace('-', '_', sanitize_title( ltrim($field_name, '_') ) );
|
208 |
-
if ( empty( $custom_field ) && is_callable( array( $this->order, "get_{$property}" ) ) ) {
|
209 |
-
$custom_field = $this->order->{"get_{$property}"}( 'view' );
|
210 |
-
}
|
211 |
-
|
212 |
-
// fallback to parent for refunds
|
213 |
-
if ( empty( $custom_field ) && $this->is_refund( $this->order ) ) {
|
214 |
-
$parent_order = $this->get_refund_parent( $this->order );
|
215 |
-
if ( !$this->is_order_prop( $field_name ) ) {
|
216 |
-
$custom_field = WCX_Order::get_meta( $parent_order, $field_name, true );
|
217 |
-
}
|
218 |
-
|
219 |
-
// WC3.0 fallback to properties
|
220 |
-
if ( empty( $custom_field ) && is_callable( array( $parent_order, "get_{$property}" ) ) ) {
|
221 |
-
$custom_field = $parent_order->{"get_{$property}"}( 'view' );
|
222 |
-
}
|
223 |
-
}
|
224 |
-
|
225 |
-
return apply_filters( 'wpo_wcpdf_billing_custom_field', $custom_field, $this );
|
226 |
-
}
|
227 |
-
public function custom_field( $field_name, $field_label = '', $display_empty = false ) {
|
228 |
-
$custom_field = $this->get_custom_field( $field_name );
|
229 |
-
if (!empty($field_label)){
|
230 |
-
// add a a trailing space to the label
|
231 |
-
$field_label .= ' ';
|
232 |
-
}
|
233 |
-
|
234 |
-
if (!empty($custom_field) || $display_empty) {
|
235 |
-
echo $field_label . nl2br ($custom_field);
|
236 |
-
}
|
237 |
-
}
|
238 |
-
|
239 |
-
public function is_order_prop( $key ) {
|
240 |
-
if ( version_compare( WOOCOMMERCE_VERSION, '3.0', '<' ) ) {
|
241 |
-
return false; // WC 2.X didn't have CRUD
|
242 |
-
}
|
243 |
-
// Taken from WC class
|
244 |
-
$order_props = array(
|
245 |
-
// Abstract order props
|
246 |
-
'parent_id',
|
247 |
-
'status',
|
248 |
-
'currency',
|
249 |
-
'version',
|
250 |
-
'prices_include_tax',
|
251 |
-
'date_created',
|
252 |
-
'date_modified',
|
253 |
-
'discount_total',
|
254 |
-
'discount_tax',
|
255 |
-
'shipping_total',
|
256 |
-
'shipping_tax',
|
257 |
-
'cart_tax',
|
258 |
-
'total',
|
259 |
-
'total_tax',
|
260 |
-
// Order props
|
261 |
-
'customer_id',
|
262 |
-
'order_key',
|
263 |
-
'billing_first_name',
|
264 |
-
'billing_last_name',
|
265 |
-
'billing_company',
|
266 |
-
'billing_address_1',
|
267 |
-
'billing_address_2',
|
268 |
-
'billing_city',
|
269 |
-
'billing_state',
|
270 |
-
'billing_postcode',
|
271 |
-
'billing_country',
|
272 |
-
'billing_email',
|
273 |
-
'billing_phone',
|
274 |
-
'shipping_first_name',
|
275 |
-
'shipping_last_name',
|
276 |
-
'shipping_company',
|
277 |
-
'shipping_address_1',
|
278 |
-
'shipping_address_2',
|
279 |
-
'shipping_city',
|
280 |
-
'shipping_state',
|
281 |
-
'shipping_postcode',
|
282 |
-
'shipping_country',
|
283 |
-
'payment_method',
|
284 |
-
'payment_method_title',
|
285 |
-
'transaction_id',
|
286 |
-
'customer_ip_address',
|
287 |
-
'customer_user_agent',
|
288 |
-
'created_via',
|
289 |
-
'customer_note',
|
290 |
-
'date_completed',
|
291 |
-
'date_paid',
|
292 |
-
'cart_hash',
|
293 |
-
);
|
294 |
-
return in_array($key, $order_props);
|
295 |
-
}
|
296 |
-
|
297 |
-
/**
|
298 |
-
* Return/show product attribute
|
299 |
-
*/
|
300 |
-
public function get_product_attribute( $attribute_name, $product ) {
|
301 |
-
// first, check the text attributes
|
302 |
-
$attributes = $product->get_attributes();
|
303 |
-
$attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
|
304 |
-
if (array_key_exists( sanitize_title( $attribute_name ), $attributes) ) {
|
305 |
-
$attribute = $product->get_attribute ( $attribute_name );
|
306 |
-
} elseif (array_key_exists( sanitize_title( $attribute_key ), $attributes) ) {
|
307 |
-
$attribute = $product->get_attribute ( $attribute_key );
|
308 |
-
}
|
309 |
-
|
310 |
-
if (empty($attribute)) {
|
311 |
-
// not a text attribute, try attribute taxonomy
|
312 |
-
$attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
|
313 |
-
$product_id = WCX_Product::get_prop($product, 'id');
|
314 |
-
$product_terms = @wc_get_product_terms( $product_id, $attribute_key, array( 'fields' => 'names' ) );
|
315 |
-
// check if not empty, then display
|
316 |
-
if ( !empty($product_terms) ) {
|
317 |
-
$attribute = array_shift( $product_terms );
|
318 |
-
}
|
319 |
-
}
|
320 |
-
|
321 |
-
// WC3.0+ fallback parent product for variations
|
322 |
-
if ( empty($attribute) && version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) && $product->is_type( 'variation' ) ) {
|
323 |
-
$product = wc_get_product( $product->get_parent_id() );
|
324 |
-
$attribute = $this->get_product_attribute( $attribute_name, $product );
|
325 |
-
}
|
326 |
-
|
327 |
-
return isset($attribute) ? $attribute : false;
|
328 |
-
}
|
329 |
-
public function product_attribute( $attribute_name, $product ) {
|
330 |
-
echo $this->get_product_attribute( $attribute_name, $product );
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
* Return/Show order notes
|
335 |
-
* could use $order->get_customer_order_notes(), but that filters out private notes already
|
336 |
-
*/
|
337 |
-
public function get_order_notes( $filter = 'customer' ) {
|
338 |
-
if ( $this->is_refund( $this->order ) ) {
|
339 |
-
$post_id = $this->get_refund_parent_id( $this->order );
|
340 |
-
} else {
|
341 |
-
$post_id = $this->order_id;
|
342 |
-
}
|
343 |
-
|
344 |
-
if ( empty( $post_id ) ) {
|
345 |
-
return; // prevent order notes from all orders showing when document is not loaded properly
|
346 |
-
}
|
347 |
-
|
348 |
-
|
349 |
-
'
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
$data
|
504 |
-
|
505 |
-
|
506 |
-
$data['
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
$data['
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
$data['
|
520 |
-
|
521 |
-
//
|
522 |
-
$data['
|
523 |
-
|
524 |
-
//
|
525 |
-
$
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
if (
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
$
|
635 |
-
|
636 |
-
$
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
}
|
652 |
-
|
653 |
-
|
654 |
-
}
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
$
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
*
|
701 |
-
*
|
702 |
-
*
|
703 |
-
*
|
704 |
-
*
|
705 |
-
* @
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
$
|
714 |
-
}
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
$
|
757 |
-
}
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
//
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
$
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
}
|
815 |
-
|
816 |
-
$totals['order_total']['value']
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
if (
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
$
|
866 |
-
'label' => __('
|
867 |
-
'value' => $
|
868 |
-
|
869 |
-
|
870 |
-
return apply_filters( '
|
871 |
-
}
|
872 |
-
public function
|
873 |
-
$
|
874 |
-
echo $
|
875 |
-
}
|
876 |
-
|
877 |
-
/**
|
878 |
-
* Return/show the
|
879 |
-
*/
|
880 |
-
public function
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
$discount_value
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
$
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
)
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
'
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
if (
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
1071 |
-
|
1072 |
-
|
1073 |
-
|
1074 |
-
|
1075 |
-
|
1076 |
-
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
$
|
1088 |
-
} else {
|
1089 |
-
$
|
1090 |
-
}
|
1091 |
-
|
1092 |
-
return $
|
1093 |
-
}
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
|
1101 |
-
|
1102 |
-
|
1103 |
-
|
1104 |
-
|
1105 |
-
|
1106 |
-
|
1107 |
-
|
1108 |
-
|
1109 |
-
|
1110 |
-
|
1111 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
1124 |
-
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
1129 |
Â
endif; // class_exists
|
1 |
+
<?php
|
2 |
+
namespace WPO\WC\PDF_Invoices\Documents;
|
3 |
+
|
4 |
+
use WPO\WC\PDF_Invoices\Compatibility\WC_Core as WCX;
|
5 |
+
use WPO\WC\PDF_Invoices\Compatibility\Order as WCX_Order;
|
6 |
+
use WPO\WC\PDF_Invoices\Compatibility\Product as WCX_Product;
|
7 |
+
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit; // Exit if accessed directly
|
10 |
+
}
|
11 |
+
|
12 |
+
if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\Documents\\Order_Document_Methods' ) ) :
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Abstract Order Methods
|
16 |
+
*
|
17 |
+
* Collection of methods to be used on orders within a Document
|
18 |
+
* Created as abstract rather than traits to support PHP versions older than 5.4
|
19 |
+
*
|
20 |
+
* @class \WPO\WC\PDF_Invoices\Documents\Order_Document_Methods
|
21 |
+
* @version 2.0
|
22 |
+
* @category Class
|
23 |
+
* @author Ewout Fernhout
|
24 |
+
*/
|
25 |
+
|
26 |
+
abstract class Order_Document_Methods extends Order_Document {
|
27 |
+
public function is_refund( $order ) {
|
28 |
+
if ( method_exists( $order, 'get_type') ) { // WC 3.0+
|
29 |
+
$is_refund = $order->get_type() == 'shop_order_refund';
|
30 |
+
} else {
|
31 |
+
$is_refund = get_post_type( WCX_Order::get_id( $order ) ) == 'shop_order_refund';
|
32 |
+
}
|
33 |
+
|
34 |
+
return $is_refund;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function get_refund_parent_id( $order ) {
|
38 |
+
if ( method_exists( $order, 'get_parent_id') ) { // WC3.0+
|
39 |
+
$parent_order_id = $order->get_parent_id();
|
40 |
+
} else {
|
41 |
+
$parent_order_id = wp_get_post_parent_id( WCX_Order::get_id( $order ) );
|
42 |
+
}
|
43 |
+
|
44 |
+
return $parent_order_id;
|
45 |
+
}
|
46 |
+
|
47 |
+
|
48 |
+
public function get_refund_parent( $order ) {
|
49 |
+
// only try if this is actually a refund
|
50 |
+
if ( ! $this->is_refund( $order ) ) {
|
51 |
+
return $order;
|
52 |
+
}
|
53 |
+
|
54 |
+
$parent_order_id = $this->get_refund_parent_id( $order );
|
55 |
+
$order = WCX::get_order( $parent_order_id );
|
56 |
+
return $order;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Check if billing address and shipping address are equal
|
61 |
+
*/
|
62 |
+
public function ships_to_different_address() {
|
63 |
+
// always prefer parent address for refunds
|
64 |
+
if ( $this->is_refund( $this->order ) ) {
|
65 |
+
$order = $this->get_refund_parent( $this->order );
|
66 |
+
} else {
|
67 |
+
$order = $this->order;
|
68 |
+
}
|
69 |
+
|
70 |
+
// only check if there is a shipping address at all
|
71 |
+
if ( $formatted_shipping_address = $order->get_formatted_shipping_address() ) {
|
72 |
+
$address_comparison_fields = apply_filters( 'wpo_wcpdf_address_comparison_fields', array(
|
73 |
+
'first_name',
|
74 |
+
'last_name',
|
75 |
+
'company',
|
76 |
+
'address_1',
|
77 |
+
'address_2',
|
78 |
+
'city',
|
79 |
+
'state',
|
80 |
+
'postcode',
|
81 |
+
'country'
|
82 |
+
), $this );
|
83 |
+
|
84 |
+
foreach ($address_comparison_fields as $address_field) {
|
85 |
+
$billing_field = WCX_Order::get_prop( $order, "billing_{$address_field}", 'view');
|
86 |
+
$shipping_field = WCX_Order::get_prop( $order, "shipping_{$address_field}", 'view');
|
87 |
+
if ( $shipping_field != $billing_field ) {
|
88 |
+
// this address field is different -> ships to different address!
|
89 |
+
return true;
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
//if we got here, it means the addresses are equal -> doesn't ship to different address!
|
95 |
+
return apply_filters( 'wpo_wcpdf_ships_to_different_address', false, $order, $this );
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Return/Show billing address
|
100 |
+
*/
|
101 |
+
public function get_billing_address() {
|
102 |
+
// always prefer parent billing address for refunds
|
103 |
+
if ( $this->is_refund( $this->order ) ) {
|
104 |
+
// temporarily switch order to make all filters / order calls work correctly
|
105 |
+
$refund = $this->order;
|
106 |
+
$this->order = $this->get_refund_parent( $this->order );
|
107 |
+
$address = apply_filters( 'wpo_wcpdf_billing_address', $this->order->get_formatted_billing_address(), $this );
|
108 |
+
// switch back & unset
|
109 |
+
$this->order = $refund;
|
110 |
+
unset($refund);
|
111 |
+
} elseif ( $address = $this->order->get_formatted_billing_address() ) {
|
112 |
+
// regular shop_order
|
113 |
+
$address = apply_filters( 'wpo_wcpdf_billing_address', $address, $this );
|
114 |
+
} else {
|
115 |
+
// no address
|
116 |
+
$address = apply_filters( 'wpo_wcpdf_billing_address', __('N/A', 'woocommerce-pdf-invoices-packing-slips' ), $this );
|
117 |
+
}
|
118 |
+
|
119 |
+
return $address;
|
120 |
+
}
|
121 |
+
public function billing_address() {
|
122 |
+
echo $this->get_billing_address();
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Return/Show billing email
|
127 |
+
*/
|
128 |
+
public function get_billing_email() {
|
129 |
+
$billing_email = WCX_Order::get_prop( $this->order, 'billing_email', 'view' );
|
130 |
+
|
131 |
+
if ( !$billing_email && $this->is_refund( $this->order ) ) {
|
132 |
+
// try parent
|
133 |
+
$parent_order = $this->get_refund_parent( $this->order );
|
134 |
+
$billing_email = WCX_Order::get_prop( $parent_order, 'billing_email', 'view' );
|
135 |
+
}
|
136 |
+
|
137 |
+
return apply_filters( 'wpo_wcpdf_billing_email', $billing_email, $this );
|
138 |
+
}
|
139 |
+
public function billing_email() {
|
140 |
+
echo $this->get_billing_email();
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Return/Show billing phone
|
145 |
+
*/
|
146 |
+
public function get_billing_phone() {
|
147 |
+
$billing_phone = WCX_Order::get_prop( $this->order, 'billing_phone', 'view' );
|
148 |
+
|
149 |
+
if ( !$billing_phone && $this->is_refund( $this->order ) ) {
|
150 |
+
// try parent
|
151 |
+
$parent_order = $this->get_refund_parent( $this->order );
|
152 |
+
$billing_phone = WCX_Order::get_prop( $parent_order, 'billing_phone', 'view' );
|
153 |
+
}
|
154 |
+
|
155 |
+
return apply_filters( 'wpo_wcpdf_billing_phone', $billing_phone, $this );
|
156 |
+
}
|
157 |
+
public function billing_phone() {
|
158 |
+
echo $this->get_billing_phone();
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Return/Show shipping address
|
163 |
+
*/
|
164 |
+
public function get_shipping_address() {
|
165 |
+
// always prefer parent shipping address for refunds
|
166 |
+
if ( $this->is_refund( $this->order ) ) {
|
167 |
+
// temporarily switch order to make all filters / order calls work correctly
|
168 |
+
$refund = $this->order;
|
169 |
+
$this->order = $this->get_refund_parent( $this->order );
|
170 |
+
$address = apply_filters( 'wpo_wcpdf_shipping_address', $this->order->get_formatted_shipping_address(), $this );
|
171 |
+
// switch back & unset
|
172 |
+
$this->order = $refund;
|
173 |
+
unset($refund);
|
174 |
+
} elseif ( $address = $this->order->get_formatted_shipping_address() ) {
|
175 |
+
// regular shop_order
|
176 |
+
$address = apply_filters( 'wpo_wcpdf_shipping_address', $address, $this );
|
177 |
+
} else {
|
178 |
+
// no address
|
179 |
+
// use fallback for packing slip
|
180 |
+
if ( apply_filters( 'wpo_wcpdf_shipping_address_fallback', ( $this->get_type() == 'packing-slip' ), $this ) ) {
|
181 |
+
$address = $this->get_billing_address();
|
182 |
+
} else{
|
183 |
+
$address = apply_filters( 'wpo_wcpdf_shipping_address', __('N/A', 'woocommerce-pdf-invoices-packing-slips' ), $this );
|
184 |
+
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
return $address;
|
189 |
+
}
|
190 |
+
public function shipping_address() {
|
191 |
+
echo $this->get_shipping_address();
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Return/Show a custom field
|
196 |
+
*/
|
197 |
+
public function get_custom_field( $field_name ) {
|
198 |
+
if ( !$this->is_order_prop( $field_name ) ) {
|
199 |
+
$custom_field = WCX_Order::get_meta( $this->order, $field_name, true );
|
200 |
+
}
|
201 |
+
// if not found, try prefixed with underscore (not when ACF is active!)
|
202 |
+
if ( empty( $custom_field ) && substr( $field_name, 0, 1 ) !== '_' && !$this->is_order_prop( "_{$field_name}" ) && !class_exists('ACF') ) {
|
203 |
+
$custom_field = WCX_Order::get_meta( $this->order, "_{$field_name}", true );
|
204 |
+
}
|
205 |
+
|
206 |
+
// WC3.0 fallback to properties
|
207 |
+
$property = str_replace('-', '_', sanitize_title( ltrim($field_name, '_') ) );
|
208 |
+
if ( empty( $custom_field ) && is_callable( array( $this->order, "get_{$property}" ) ) ) {
|
209 |
+
$custom_field = $this->order->{"get_{$property}"}( 'view' );
|
210 |
+
}
|
211 |
+
|
212 |
+
// fallback to parent for refunds
|
213 |
+
if ( empty( $custom_field ) && $this->is_refund( $this->order ) ) {
|
214 |
+
$parent_order = $this->get_refund_parent( $this->order );
|
215 |
+
if ( !$this->is_order_prop( $field_name ) ) {
|
216 |
+
$custom_field = WCX_Order::get_meta( $parent_order, $field_name, true );
|
217 |
+
}
|
218 |
+
|
219 |
+
// WC3.0 fallback to properties
|
220 |
+
if ( empty( $custom_field ) && is_callable( array( $parent_order, "get_{$property}" ) ) ) {
|
221 |
+
$custom_field = $parent_order->{"get_{$property}"}( 'view' );
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
+
return apply_filters( 'wpo_wcpdf_billing_custom_field', $custom_field, $this );
|
226 |
+
}
|
227 |
+
public function custom_field( $field_name, $field_label = '', $display_empty = false ) {
|
228 |
+
$custom_field = $this->get_custom_field( $field_name );
|
229 |
+
if (!empty($field_label)){
|
230 |
+
// add a a trailing space to the label
|
231 |
+
$field_label .= ' ';
|
232 |
+
}
|
233 |
+
|
234 |
+
if (!empty($custom_field) || $display_empty) {
|
235 |
+
echo $field_label . nl2br ($custom_field);
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
public function is_order_prop( $key ) {
|
240 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '3.0', '<' ) ) {
|
241 |
+
return false; // WC 2.X didn't have CRUD
|
242 |
+
}
|
243 |
+
// Taken from WC class
|
244 |
+
$order_props = array(
|
245 |
+
// Abstract order props
|
246 |
+
'parent_id',
|
247 |
+
'status',
|
248 |
+
'currency',
|
249 |
+
'version',
|
250 |
+
'prices_include_tax',
|
251 |
+
'date_created',
|
252 |
+
'date_modified',
|
253 |
+
'discount_total',
|
254 |
+
'discount_tax',
|
255 |
+
'shipping_total',
|
256 |
+
'shipping_tax',
|
257 |
+
'cart_tax',
|
258 |
+
'total',
|
259 |
+
'total_tax',
|
260 |
+
// Order props
|
261 |
+
'customer_id',
|
262 |
+
'order_key',
|
263 |
+
'billing_first_name',
|
264 |
+
'billing_last_name',
|
265 |
+
'billing_company',
|
266 |
+
'billing_address_1',
|
267 |
+
'billing_address_2',
|
268 |
+
'billing_city',
|
269 |
+
'billing_state',
|
270 |
+
'billing_postcode',
|
271 |
+
'billing_country',
|
272 |
+
'billing_email',
|
273 |
+
'billing_phone',
|
274 |
+
'shipping_first_name',
|
275 |
+
'shipping_last_name',
|
276 |
+
'shipping_company',
|
277 |
+
'shipping_address_1',
|
278 |
+
'shipping_address_2',
|
279 |
+
'shipping_city',
|
280 |
+
'shipping_state',
|
281 |
+
'shipping_postcode',
|
282 |
+
'shipping_country',
|
283 |
+
'payment_method',
|
284 |
+
'payment_method_title',
|
285 |
+
'transaction_id',
|
286 |
+
'customer_ip_address',
|
287 |
+
'customer_user_agent',
|
288 |
+
'created_via',
|
289 |
+
'customer_note',
|
290 |
+
'date_completed',
|
291 |
+
'date_paid',
|
292 |
+
'cart_hash',
|
293 |
+
);
|
294 |
+
return in_array($key, $order_props);
|
295 |
+
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* Return/show product attribute
|
299 |
+
*/
|
300 |
+
public function get_product_attribute( $attribute_name, $product ) {
|
301 |
+
// first, check the text attributes
|
302 |
+
$attributes = $product->get_attributes();
|
303 |
+
$attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
|
304 |
+
if (array_key_exists( sanitize_title( $attribute_name ), $attributes) ) {
|
305 |
+
$attribute = $product->get_attribute ( $attribute_name );
|
306 |
+
} elseif (array_key_exists( sanitize_title( $attribute_key ), $attributes) ) {
|
307 |
+
$attribute = $product->get_attribute ( $attribute_key );
|
308 |
+
}
|
309 |
+
|
310 |
+
if (empty($attribute)) {
|
311 |
+
// not a text attribute, try attribute taxonomy
|
312 |
+
$attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
|
313 |
+
$product_id = WCX_Product::get_prop($product, 'id');
|
314 |
+
$product_terms = @wc_get_product_terms( $product_id, $attribute_key, array( 'fields' => 'names' ) );
|
315 |
+
// check if not empty, then display
|
316 |
+
if ( !empty($product_terms) ) {
|
317 |
+
$attribute = array_shift( $product_terms );
|
318 |
+
}
|
319 |
+
}
|
320 |
+
|
321 |
+
// WC3.0+ fallback parent product for variations
|
322 |
+
if ( empty($attribute) && version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) && $product->is_type( 'variation' ) ) {
|
323 |
+
$product = wc_get_product( $product->get_parent_id() );
|
324 |
+
$attribute = $this->get_product_attribute( $attribute_name, $product );
|
325 |
+
}
|
326 |
+
|
327 |
+
return isset($attribute) ? $attribute : false;
|
328 |
+
}
|
329 |
+
public function product_attribute( $attribute_name, $product ) {
|
330 |
+
echo $this->get_product_attribute( $attribute_name, $product );
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Return/Show order notes
|
335 |
+
* could use $order->get_customer_order_notes(), but that filters out private notes already
|
336 |
+
*/
|
337 |
+
public function get_order_notes( $filter = 'customer', $include_system_notes = true ) {
|
338 |
+
if ( $this->is_refund( $this->order ) ) {
|
339 |
+
$post_id = $this->get_refund_parent_id( $this->order );
|
340 |
+
} else {
|
341 |
+
$post_id = $this->order_id;
|
342 |
+
}
|
343 |
+
|
344 |
+
if ( empty( $post_id ) ) {
|
345 |
+
return; // prevent order notes from all orders showing when document is not loaded properly
|
346 |
+
}
|
347 |
+
|
348 |
+
if ( function_exists('wc_get_order_notes') ) { // WC3.2+
|
349 |
+
$type = ( $filter == 'private' ) ? 'internal' : $filter;
|
350 |
+
$notes = wc_get_order_notes( array(
|
351 |
+
'order_id' => $post_id,
|
352 |
+
'type' => $type, // use 'internal' for admin and system notes, empty for all
|
353 |
+
) );
|
354 |
+
|
355 |
+
if ( $include_system_notes === false ) {
|
356 |
+
foreach ($notes as $key => $note) {
|
357 |
+
if ( $note->added_by == 'system' ) {
|
358 |
+
unset($notes[$key]);
|
359 |
+
}
|
360 |
+
}
|
361 |
+
}
|
362 |
+
|
363 |
+
return $notes;
|
364 |
+
} else {
|
365 |
+
|
366 |
+
$args = array(
|
367 |
+
'post_id' => $post_id,
|
368 |
+
'approve' => 'approve',
|
369 |
+
'type' => 'order_note'
|
370 |
+
);
|
371 |
+
|
372 |
+
remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
|
373 |
+
|
374 |
+
$notes = get_comments( $args );
|
375 |
+
|
376 |
+
add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
|
377 |
+
|
378 |
+
if ( $notes ) {
|
379 |
+
foreach( $notes as $key => $note ) {
|
380 |
+
if ( $filter == 'customer' && !get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
|
381 |
+
unset($notes[$key]);
|
382 |
+
}
|
383 |
+
if ( $filter == 'private' && get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
|
384 |
+
unset($notes[$key]);
|
385 |
+
}
|
386 |
+
}
|
387 |
+
return $notes;
|
388 |
+
}
|
389 |
+
}
|
390 |
+
|
391 |
+
}
|
392 |
+
public function order_notes( $filter = 'customer', $include_system_notes = true ) {
|
393 |
+
$notes = $this->get_order_notes( $filter, $include_system_notes );
|
394 |
+
if ( $notes ) {
|
395 |
+
foreach( $notes as $note ) {
|
396 |
+
$css_class = array( 'note', 'note_content' );
|
397 |
+
$css_class[] = $note->customer_note ? 'customer-note' : '';
|
398 |
+
$css_class[] = 'system' === $note->added_by ? 'system-note' : '';
|
399 |
+
$css_class = apply_filters( 'woocommerce_order_note_class', array_filter( $css_class ), $note );
|
400 |
+
$content = isset($note->content) ? $note->content : $note->comment_content;
|
401 |
+
?>
|
402 |
+
<div class="<?php echo esc_attr( implode( ' ', $css_class ) ); ?>">
|
403 |
+
<?php echo wpautop( wptexturize( wp_kses_post( $content ) ) ); ?>
|
404 |
+
</div>
|
405 |
+
<?php
|
406 |
+
}
|
407 |
+
}
|
408 |
+
}
|
409 |
+
|
410 |
+
/**
|
411 |
+
* Return/Show the current date
|
412 |
+
*/
|
413 |
+
public function get_current_date() {
|
414 |
+
return apply_filters( 'wpo_wcpdf_date', date_i18n( wc_date_format() ) );
|
415 |
+
}
|
416 |
+
public function current_date() {
|
417 |
+
echo $this->get_current_date();
|
418 |
+
}
|
419 |
+
|
420 |
+
/**
|
421 |
+
* Return/Show payment method
|
422 |
+
*/
|
423 |
+
public function get_payment_method() {
|
424 |
+
$payment_method_label = __( 'Payment method', 'woocommerce-pdf-invoices-packing-slips' );
|
425 |
+
|
426 |
+
if ( $this->is_refund( $this->order ) ) {
|
427 |
+
$parent_order = $this->get_refund_parent( $this->order );
|
428 |
+
$payment_method_title = WCX_Order::get_prop( $parent_order, 'payment_method_title', 'view' );
|
429 |
+
} else {
|
430 |
+
$payment_method_title = WCX_Order::get_prop( $this->order, 'payment_method_title', 'view' );
|
431 |
+
}
|
432 |
+
|
433 |
+
$payment_method = __( $payment_method_title, 'woocommerce' );
|
434 |
+
|
435 |
+
return apply_filters( 'wpo_wcpdf_payment_method', $payment_method, $this );
|
436 |
+
}
|
437 |
+
public function payment_method() {
|
438 |
+
echo $this->get_payment_method();
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Return/Show shipping method
|
443 |
+
*/
|
444 |
+
public function get_shipping_method() {
|
445 |
+
$shipping_method_label = __( 'Shipping method', 'woocommerce-pdf-invoices-packing-slips' );
|
446 |
+
$shipping_method = __( $this->order->get_shipping_method(), 'woocommerce' );
|
447 |
+
return apply_filters( 'wpo_wcpdf_shipping_method', $shipping_method, $this );
|
448 |
+
}
|
449 |
+
public function shipping_method() {
|
450 |
+
echo $this->get_shipping_method();
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* Return/Show order number
|
455 |
+
*/
|
456 |
+
public function get_order_number() {
|
457 |
+
// try parent first
|
458 |
+
if ( $this->is_refund( $this->order ) ) {
|
459 |
+
$parent_order = $this->get_refund_parent( $this->order );
|
460 |
+
$order_number = $parent_order->get_order_number();
|
461 |
+
} else {
|
462 |
+
$order_number = $this->order->get_order_number();
|
463 |
+
}
|
464 |
+
|
465 |
+
// Trim the hash to have a clean number but still
|
466 |
+
// support any filters that were applied before.
|
467 |
+
$order_number = ltrim($order_number, '#');
|
468 |
+
return apply_filters( 'wpo_wcpdf_order_number', $order_number, $this );
|
469 |
+
}
|
470 |
+
public function order_number() {
|
471 |
+
echo $this->get_order_number();
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Return/Show the order date
|
476 |
+
*/
|
477 |
+
public function get_order_date() {
|
478 |
+
if ( $this->is_refund( $this->order ) ) {
|
479 |
+
$parent_order = $this->get_refund_parent( $this->order );
|
480 |
+
$order_date = WCX_Order::get_prop( $parent_order, 'date_created' );
|
481 |
+
} else {
|
482 |
+
$order_date = WCX_Order::get_prop( $this->order, 'date_created' );
|
483 |
+
}
|
484 |
+
|
485 |
+
$date = $order_date->date_i18n( wc_date_format() );
|
486 |
+
$mysql_date = $order_date->date( "Y-m-d H:i:s" );
|
487 |
+
return apply_filters( 'wpo_wcpdf_order_date', $date, $mysql_date, $this );
|
488 |
+
}
|
489 |
+
public function order_date() {
|
490 |
+
echo $this->get_order_date();
|
491 |
+
}
|
492 |
+
|
493 |
+
/**
|
494 |
+
* Return the order items
|
495 |
+
*/
|
496 |
+
public function get_order_items() {
|
497 |
+
$items = $this->order->get_items();
|
498 |
+
$data_list = array();
|
499 |
+
|
500 |
+
if( sizeof( $items ) > 0 ) {
|
501 |
+
foreach ( $items as $item_id => $item ) {
|
502 |
+
// Array with data for the pdf template
|
503 |
+
$data = array();
|
504 |
+
|
505 |
+
// Set the item_id
|
506 |
+
$data['item_id'] = $item_id;
|
507 |
+
|
508 |
+
// Set the id
|
509 |
+
$data['product_id'] = $item['product_id'];
|
510 |
+
$data['variation_id'] = $item['variation_id'];
|
511 |
+
|
512 |
+
// Compatibility: WooCommerce Composit Products uses a workaround for
|
513 |
+
// setting the order before the item name filter, so we run this first
|
514 |
+
if ( class_exists('WC_Composite_Products') ) {
|
515 |
+
$order_item_class = apply_filters( 'woocommerce_order_item_class', '', $item, $this->order );
|
516 |
+
}
|
517 |
+
|
518 |
+
// Set item name
|
519 |
+
$data['name'] = apply_filters( 'woocommerce_order_item_name', $item['name'], $item, false );
|
520 |
+
|
521 |
+
// Set item quantity
|
522 |
+
$data['quantity'] = $item['qty'];
|
523 |
+
|
524 |
+
// Set the line total (=after discount)
|
525 |
+
$data['line_total'] = $this->format_price( $item['line_total'] );
|
526 |
+
$data['single_line_total'] = $this->format_price( $item['line_total'] / max( 1, abs( $item['qty'] ) ) );
|
527 |
+
$data['line_tax'] = $this->format_price( $item['line_tax'] );
|
528 |
+
$data['single_line_tax'] = $this->format_price( $item['line_tax'] / max( 1, abs( $item['qty'] ) ) );
|
529 |
+
|
530 |
+
$line_tax_data = maybe_unserialize( isset( $item['line_tax_data'] ) ? $item['line_tax_data'] : '' );
|
531 |
+
$data['tax_rates'] = $this->get_tax_rate( $item['tax_class'], $item['line_total'], $item['line_tax'], $line_tax_data, true );
|
532 |
+
$data['calculated_tax_rates'] = $this->get_tax_rate( $item['tax_class'], $item['line_total'], $item['line_tax'], $line_tax_data, false );
|
533 |
+
|
534 |
+
// Set the line subtotal (=before discount)
|
535 |
+
$data['line_subtotal'] = $this->format_price( $item['line_subtotal'] );
|
536 |
+
$data['line_subtotal_tax'] = $this->format_price( $item['line_subtotal_tax'] );
|
537 |
+
$data['ex_price'] = $this->get_formatted_item_price( $item, 'total', 'excl' );
|
538 |
+
$data['price'] = $this->get_formatted_item_price( $item, 'total' );
|
539 |
+
$data['order_price'] = $this->order->get_formatted_line_subtotal( $item ); // formatted according to WC settings
|
540 |
+
|
541 |
+
// Calculate the single price with the same rules as the formatted line subtotal (!)
|
542 |
+
// = before discount
|
543 |
+
$data['ex_single_price'] = $this->get_formatted_item_price( $item, 'single', 'excl' );
|
544 |
+
$data['single_price'] = $this->get_formatted_item_price( $item, 'single' );
|
545 |
+
|
546 |
+
// Pass complete item array
|
547 |
+
$data['item'] = $item;
|
548 |
+
|
549 |
+
// Get the product to add more info
|
550 |
+
$product = $this->order->get_product_from_item( $item );
|
551 |
+
|
552 |
+
// Checking fo existance, thanks to MDesigner0
|
553 |
+
if( !empty( $product ) ) {
|
554 |
+
// Thumbnail (full img tag)
|
555 |
+
$data['thumbnail'] = $this->get_thumbnail( $product );
|
556 |
+
|
557 |
+
// Set item SKU
|
558 |
+
$data['sku'] = $product->get_sku();
|
559 |
+
|
560 |
+
// Set item weight
|
561 |
+
$data['weight'] = $product->get_weight();
|
562 |
+
|
563 |
+
// Set item dimensions
|
564 |
+
$data['dimensions'] = WCX_Product::get_dimensions( $product );
|
565 |
+
|
566 |
+
// Pass complete product object
|
567 |
+
$data['product'] = $product;
|
568 |
+
|
569 |
+
} else {
|
570 |
+
$data['product'] = null;
|
571 |
+
}
|
572 |
+
|
573 |
+
// Set item meta
|
574 |
+
if (function_exists('wc_display_item_meta')) { // WC3.0+
|
575 |
+
$data['meta'] = wc_display_item_meta( $item, array(
|
576 |
+
'echo' => false,
|
577 |
+
) );
|
578 |
+
} else {
|
579 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '<' ) ) {
|
580 |
+
$meta = new \WC_Order_Item_Meta( $item['item_meta'], $product );
|
581 |
+
} else { // pass complete item for WC2.4+
|
582 |
+
$meta = new \WC_Order_Item_Meta( $item, $product );
|
583 |
+
}
|
584 |
+
$data['meta'] = $meta->display( false, true );
|
585 |
+
}
|
586 |
+
|
587 |
+
$data_list[$item_id] = apply_filters( 'wpo_wcpdf_order_item_data', $data, $this->order, $this->get_type() );
|
588 |
+
}
|
589 |
+
}
|
590 |
+
|
591 |
+
return apply_filters( 'wpo_wcpdf_order_items_data', $data_list, $this->order, $this->get_type() );
|
592 |
+
}
|
593 |
+
|
594 |
+
/**
|
595 |
+
* Get the tax rates/percentages for a given tax class
|
596 |
+
* @param string $tax_class tax class slug
|
597 |
+
* @return string $tax_rates imploded list of tax rates
|
598 |
+
*/
|
599 |
+
public function get_tax_rate( $tax_class, $line_total, $line_tax, $line_tax_data = '', $force_calculation = false ) {
|
600 |
+
// first try the easy wc2.2+ way, using line_tax_data
|
601 |
+
if ( !empty( $line_tax_data ) && isset($line_tax_data['total']) ) {
|
602 |
+
$tax_rates = array();
|
603 |
+
|
604 |
+
$line_taxes = $line_tax_data['subtotal'];
|
605 |
+
foreach ( $line_taxes as $tax_id => $tax ) {
|
606 |
+
if ( isset($tax) && $tax !== '' ) {
|
607 |
+
$tax_rate = $this->get_tax_rate_by_id( $tax_id );
|
608 |
+
if ( $tax_rate !== false && $force_calculation !== false ) {
|
609 |
+
$tax_rates[] = $tax_rate . ' %';
|
610 |
+
} else {
|
611 |
+
$tax_rates[] = $this->calculate_tax_rate( $line_total, $line_tax );
|
612 |
+
}
|
613 |
+
}
|
614 |
+
}
|
615 |
+
|
616 |
+
// apply decimal setting
|
617 |
+
if (function_exists('wc_get_price_decimal_separator')) {
|
618 |
+
foreach ($tax_rates as &$tax_rate) {
|
619 |
+
$tax_rate = str_replace('.', wc_get_price_decimal_separator(), strval($tax_rate) );
|
620 |
+
}
|
621 |
+
}
|
622 |
+
|
623 |
+
$tax_rates = implode(' ,', $tax_rates );
|
624 |
+
return $tax_rates;
|
625 |
+
}
|
626 |
+
|
627 |
+
if ( $line_tax == 0 ) {
|
628 |
+
return '-'; // no need to determine tax rate...
|
629 |
+
}
|
630 |
+
|
631 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 && !apply_filters( 'wpo_wcpdf_calculate_tax_rate', false ) ) {
|
632 |
+
// WC 2.1 or newer is used
|
633 |
+
$tax = new \WC_Tax();
|
634 |
+
$taxes = $tax->get_rates( $tax_class );
|
635 |
+
|
636 |
+
$tax_rates = array();
|
637 |
+
|
638 |
+
foreach ($taxes as $tax) {
|
639 |
+
$tax_rates[$tax['label']] = round( $tax['rate'], 2 ).' %';
|
640 |
+
}
|
641 |
+
|
642 |
+
if (empty($tax_rates)) {
|
643 |
+
// one last try: manually calculate
|
644 |
+
$tax_rates[] = $this->calculate_tax_rate( $line_total, $line_tax );
|
645 |
+
}
|
646 |
+
|
647 |
+
$tax_rates = implode(' ,', $tax_rates );
|
648 |
+
} else {
|
649 |
+
// Backwards compatibility/fallback: calculate tax from line items
|
650 |
+
$tax_rates[] = $this->calculate_tax_rate( $line_total, $line_tax );
|
651 |
+
}
|
652 |
+
|
653 |
+
return $tax_rates;
|
654 |
+
}
|
655 |
+
|
656 |
+
public function calculate_tax_rate( $price_ex_tax, $tax ) {
|
657 |
+
$precision = apply_filters( 'wpo_wcpdf_calculate_tax_rate_precision', 1 );
|
658 |
+
if ( $price_ex_tax != 0) {
|
659 |
+
$tax_rate = round( ($tax / $price_ex_tax)*100, $precision ).' %';
|
660 |
+
} else {
|
661 |
+
$tax_rate = '-';
|
662 |
+
}
|
663 |
+
return $tax_rate;
|
664 |
+
}
|
665 |
+
|
666 |
+
/**
|
667 |
+
* Returns the percentage rate (float) for a given tax rate ID.
|
668 |
+
* @param int $rate_id woocommerce tax rate id
|
669 |
+
* @return float $rate percentage rate
|
670 |
+
*/
|
671 |
+
public function get_tax_rate_by_id( $rate_id ) {
|
672 |
+
global $wpdb;
|
673 |
+
$rate = $wpdb->get_var( $wpdb->prepare( "SELECT tax_rate FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id ) );
|
674 |
+
if ($rate === NULL) {
|
675 |
+
return false;
|
676 |
+
} else {
|
677 |
+
return (float) $rate;
|
678 |
+
}
|
679 |
+
}
|
680 |
+
|
681 |
+
/**
|
682 |
+
* Returns a an array with rate_id => tax rate data (array) of all tax rates in woocommerce
|
683 |
+
* @return array $tax_rate_ids keyed by id
|
684 |
+
*/
|
685 |
+
public function get_tax_rate_ids() {
|
686 |
+
global $wpdb;
|
687 |
+
$rates = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates" );
|
688 |
+
|
689 |
+
$tax_rate_ids = array();
|
690 |
+
foreach ($rates as $rate) {
|
691 |
+
$rate_id = $rate->tax_rate_id;
|
692 |
+
unset($rate->tax_rate_id);
|
693 |
+
$tax_rate_ids[$rate_id] = (array) $rate;
|
694 |
+
}
|
695 |
+
|
696 |
+
return $tax_rate_ids;
|
697 |
+
}
|
698 |
+
|
699 |
+
/**
|
700 |
+
* Returns the main product image ID
|
701 |
+
* Adapted from the WC_Product class
|
702 |
+
* (does not support thumbnail sizes)
|
703 |
+
*
|
704 |
+
* @access public
|
705 |
+
* @return string
|
706 |
+
*/
|
707 |
+
public function get_thumbnail_id ( $product ) {
|
708 |
+
global $woocommerce;
|
709 |
+
|
710 |
+
$product_id = WCX_Product::get_id( $product );
|
711 |
+
|
712 |
+
if ( has_post_thumbnail( $product_id ) ) {
|
713 |
+
$thumbnail_id = get_post_thumbnail_id ( $product_id );
|
714 |
+
} elseif ( ( $parent_id = wp_get_post_parent_id( $product_id ) ) && has_post_thumbnail( $parent_id ) ) {
|
715 |
+
$thumbnail_id = get_post_thumbnail_id ( $parent_id );
|
716 |
+
} else {
|
717 |
+
$thumbnail_id = false;
|
718 |
+
}
|
719 |
+
|
720 |
+
return $thumbnail_id;
|
721 |
+
}
|
722 |
+
|
723 |
+
/**
|
724 |
+
* Returns the thumbnail image tag
|
725 |
+
*
|
726 |
+
* uses the internal WooCommerce/WP functions and extracts the image url or path
|
727 |
+
* rather than the thumbnail ID, to simplify the code and make it possible to
|
728 |
+
* filter for different thumbnail sizes
|
729 |
+
*
|
730 |
+
* @access public
|
731 |
+
* @return string
|
732 |
+
*/
|
733 |
+
public function get_thumbnail ( $product ) {
|
734 |
+
// Get default WooCommerce img tag (url/http)
|
735 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '3.3', '>=' ) ) {
|
736 |
+
$thumbnail_size = 'woocommerce_thumbnail';
|
737 |
+
} else {
|
738 |
+
$thumbnail_size = 'shop_thumbnail';
|
739 |
+
}
|
740 |
+
$size = apply_filters( 'wpo_wcpdf_thumbnail_size', $thumbnail_size );
|
741 |
+
$thumbnail_img_tag_url = $product->get_image( $size, array( 'title' => '' ) );
|
742 |
+
|
743 |
+
// Extract the url from img
|
744 |
+
preg_match('/<img(.*)src(.*)=(.*)"(.*)"/U', $thumbnail_img_tag_url, $thumbnail_url );
|
745 |
+
$thumbnail_url = array_pop($thumbnail_url);
|
746 |
+
// remove http/https from image tag url to avoid mixed origin conflicts
|
747 |
+
$contextless_thumbnail_url = ltrim( str_replace(array('http://','https://'), '', $thumbnail_url ), '/' );
|
748 |
+
|
749 |
+
// convert url to path
|
750 |
+
if ( defined('WP_CONTENT_DIR') && strpos( WP_CONTENT_DIR, ABSPATH ) !== false ) {
|
751 |
+
$forwardslash_basepath = str_replace('\\','/', ABSPATH);
|
752 |
+
$contextless_site_url = str_replace(array('http://','https://'), '', trailingslashit(get_site_url()));
|
753 |
+
} else {
|
754 |
+
// bedrock e.a
|
755 |
+
$forwardslash_basepath = str_replace('\\','/', WP_CONTENT_DIR);
|
756 |
+
$contextless_site_url = str_replace(array('http://','https://'), '', trailingslashit(WP_CONTENT_URL));
|
757 |
+
}
|
758 |
+
$thumbnail_path = str_replace( $contextless_site_url, trailingslashit( $forwardslash_basepath ), $contextless_thumbnail_url);
|
759 |
+
|
760 |
+
// fallback if thumbnail file doesn't exist
|
761 |
+
if (apply_filters('wpo_wcpdf_use_path', true) && !file_exists($thumbnail_path)) {
|
762 |
+
if ($thumbnail_id = $this->get_thumbnail_id( $product ) ) {
|
763 |
+
$thumbnail_path = get_attached_file( $thumbnail_id );
|
764 |
+
}
|
765 |
+
}
|
766 |
+
|
767 |
+
// Thumbnail (full img tag)
|
768 |
+
if ( apply_filters('wpo_wcpdf_use_path', true) && file_exists($thumbnail_path) ) {
|
769 |
+
// load img with server path by default
|
770 |
+
$thumbnail = sprintf('<img width="90" height="90" src="%s" class="attachment-shop_thumbnail wp-post-image">', $thumbnail_path );
|
771 |
+
} elseif ( apply_filters('wpo_wcpdf_use_path', true) && !file_exists($thumbnail_path) ) {
|
772 |
+
// should use paths but file not found, replace // with http(s):// for dompdf compatibility
|
773 |
+
if ( substr( $thumbnail_url, 0, 2 ) === "//" ) {
|
774 |
+
$prefix = is_ssl() ? 'https://' : 'http://';
|
775 |
+
$https_thumbnail_url = $prefix . ltrim( $thumbnail_url, '/' );
|
776 |
+
$thumbnail_img_tag_url = str_replace($thumbnail_url, $https_thumbnail_url, $thumbnail_img_tag_url);
|
777 |
+
}
|
778 |
+
$thumbnail = $thumbnail_img_tag_url;
|
779 |
+
} else {
|
780 |
+
// load img with http url when filtered
|
781 |
+
$thumbnail = $thumbnail_img_tag_url;
|
782 |
+
}
|
783 |
+
|
784 |
+
// die($thumbnail);
|
785 |
+
return $thumbnail;
|
786 |
+
}
|
787 |
+
|
788 |
+
/**
|
789 |
+
* Return the order totals listing
|
790 |
+
*/
|
791 |
+
public function get_woocommerce_totals() {
|
792 |
+
// get totals and remove the semicolon
|
793 |
+
$totals = apply_filters( 'wpo_wcpdf_raw_order_totals', $this->order->get_order_item_totals(), $this->order );
|
794 |
+
|
795 |
+
// remove the colon for every label
|
796 |
+
foreach ( $totals as $key => $total ) {
|
797 |
+
$label = $total['label'];
|
798 |
+
$colon = strrpos( $label, ':' );
|
799 |
+
if( $colon !== false ) {
|
800 |
+
$label = substr_replace( $label, '', $colon, 1 );
|
801 |
+
}
|
802 |
+
$totals[$key]['label'] = $label;
|
803 |
+
}
|
804 |
+
|
805 |
+
// WC2.4 fix order_total for refunded orders
|
806 |
+
// not if this is the actual refund!
|
807 |
+
if ( ! $this->is_refund( $this->order ) ) {
|
808 |
+
$total_refunded = method_exists($this->order, 'get_total_refunded') ? $this->order->get_total_refunded() : 0;
|
809 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '>=' ) && isset($totals['order_total']) && $total_refunded ) {
|
810 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) ) {
|
811 |
+
$tax_display = get_option( 'woocommerce_tax_display_cart' );
|
812 |
+
} else {
|
813 |
+
$tax_display = WCX_Order::get_prop( $this->order, 'tax_display_cart' );
|
814 |
+
}
|
815 |
+
|
816 |
+
$totals['order_total']['value'] = wc_price( $this->order->get_total(), array( 'currency' => WCX_Order::get_prop( $this->order, 'currency' ) ) );
|
817 |
+
$order_total = $this->order->get_total();
|
818 |
+
$tax_string = '';
|
819 |
+
|
820 |
+
// Tax for inclusive prices
|
821 |
+
if ( wc_tax_enabled() && 'incl' == $tax_display ) {
|
822 |
+
$tax_string_array = array();
|
823 |
+
if ( 'itemized' == get_option( 'woocommerce_tax_total_display' ) ) {
|
824 |
+
foreach ( $this->order->get_tax_totals() as $code => $tax ) {
|
825 |
+
$tax_amount = $tax->formatted_amount;
|
826 |
+
$tax_string_array[] = sprintf( '%s %s', $tax_amount, $tax->label );
|
827 |
+
}
|
828 |
+
} else {
|
829 |
+
$tax_string_array[] = sprintf( '%s %s', wc_price( $this->order->get_total_tax() - $this->order->get_total_tax_refunded(), array( 'currency' => WCX_Order::get_prop( $this->order, 'currency' ) ) ), WC()->countries->tax_or_vat() );
|
830 |
+
}
|
831 |
+
if ( ! empty( $tax_string_array ) ) {
|
832 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '2.6', '>=' ) ) {
|
833 |
+
$tax_string = ' ' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
|
834 |
+
} else {
|
835 |
+
// use old capitalized string
|
836 |
+
$tax_string = ' ' . sprintf( __( '(Includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
|
837 |
+
}
|
838 |
+
}
|
839 |
+
}
|
840 |
+
|
841 |
+
$totals['order_total']['value'] .= $tax_string;
|
842 |
+
}
|
843 |
+
|
844 |
+
// remove refund lines (shouldn't be in invoice)
|
845 |
+
foreach ( $totals as $key => $total ) {
|
846 |
+
if ( strpos($key, 'refund_') !== false ) {
|
847 |
+
unset( $totals[$key] );
|
848 |
+
}
|
849 |
+
}
|
850 |
+
|
851 |
+
}
|
852 |
+
|
853 |
+
return apply_filters( 'wpo_wcpdf_woocommerce_totals', $totals, $this->order, $this->get_type() );
|
854 |
+
}
|
855 |
+
|
856 |
+
/**
|
857 |
+
* Return/show the order subtotal
|
858 |
+
*/
|
859 |
+
public function get_order_subtotal( $tax = 'excl', $discount = 'incl' ) { // set $tax to 'incl' to include tax, same for $discount
|
860 |
+
//$compound = ($discount == 'incl')?true:false;
|
861 |
+
$subtotal = $this->order->get_subtotal_to_display( false, $tax );
|
862 |
+
|
863 |
+
$subtotal = ($pos = strpos($subtotal, ' <small')) ? substr($subtotal, 0, $pos) : $subtotal; //removing the 'excluding tax' text
|
864 |
+
|
865 |
+
$subtotal = array (
|
866 |
+
'label' => __('Subtotal', 'woocommerce-pdf-invoices-packing-slips' ),
|
867 |
+
'value' => $subtotal,
|
868 |
+
);
|
869 |
+
|
870 |
+
return apply_filters( 'wpo_wcpdf_order_subtotal', $subtotal, $tax, $discount, $this );
|
871 |
+
}
|
872 |
+
public function order_subtotal( $tax = 'excl', $discount = 'incl' ) {
|
873 |
+
$subtotal = $this->get_order_subtotal( $tax, $discount );
|
874 |
+
echo $subtotal['value'];
|
875 |
+
}
|
876 |
+
|
877 |
+
/**
|
878 |
+
* Return/show the order shipping costs
|
879 |
+
*/
|
880 |
+
public function get_order_shipping( $tax = 'excl' ) { // set $tax to 'incl' to include tax
|
881 |
+
$shipping_cost = WCX_Order::get_prop( $this->order, 'shipping_total', 'view' );
|
882 |
+
$shipping_tax = WCX_Order::get_prop( $this->order, 'shipping_tax', 'view' );
|
883 |
+
|
884 |
+
if ($tax == 'excl' ) {
|
885 |
+
$formatted_shipping_cost = $this->format_price( $shipping_cost );
|
886 |
+
} else {
|
887 |
+
$formatted_shipping_cost = $this->format_price( $shipping_cost + $shipping_tax );
|
888 |
+
}
|
889 |
+
|
890 |
+
$shipping = array (
|
891 |
+
'label' => __('Shipping', 'woocommerce-pdf-invoices-packing-slips' ),
|
892 |
+
'value' => $formatted_shipping_cost,
|
893 |
+
'tax' => $this->format_price( $shipping_tax ),
|
894 |
+
);
|
895 |
+
return apply_filters( 'wpo_wcpdf_order_shipping', $shipping, $tax, $this );
|
896 |
+
}
|
897 |
+
public function order_shipping( $tax = 'excl' ) {
|
898 |
+
$shipping = $this->get_order_shipping( $tax );
|
899 |
+
echo $shipping['value'];
|
900 |
+
}
|
901 |
+
|
902 |
+
/**
|
903 |
+
* Return/show the total discount
|
904 |
+
*/
|
905 |
+
public function get_order_discount( $type = 'total', $tax = 'incl' ) {
|
906 |
+
if ( $tax == 'incl' ) {
|
907 |
+
switch ($type) {
|
908 |
+
case 'cart':
|
909 |
+
// Cart Discount - pre-tax discounts. (deprecated in WC2.3)
|
910 |
+
$discount_value = $this->order->get_cart_discount();
|
911 |
+
break;
|
912 |
+
case 'order':
|
913 |
+
// Order Discount - post-tax discounts. (deprecated in WC2.3)
|
914 |
+
$discount_value = $this->order->get_order_discount();
|
915 |
+
break;
|
916 |
+
case 'total':
|
917 |
+
// Total Discount
|
918 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
|
919 |
+
$discount_value = $this->order->get_total_discount( false ); // $ex_tax = false
|
920 |
+
} else {
|
921 |
+
// WC2.2 and older: recalculate to include tax
|
922 |
+
$discount_value = 0;
|
923 |
+
$items = $this->order->get_items();;
|
924 |
+
if( sizeof( $items ) > 0 ) {
|
925 |
+
foreach( $items as $item ) {
|
926 |
+
$discount_value += ($item['line_subtotal'] + $item['line_subtotal_tax']) - ($item['line_total'] + $item['line_tax']);
|
927 |
+
}
|
928 |
+
}
|
929 |
+
}
|
930 |
+
|
931 |
+
break;
|
932 |
+
default:
|
933 |
+
// Total Discount - Cart & Order Discounts combined
|
934 |
+
$discount_value = $this->order->get_total_discount();
|
935 |
+
break;
|
936 |
+
}
|
937 |
+
} else { // calculate discount excluding tax
|
938 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
|
939 |
+
$discount_value = $this->order->get_total_discount( true ); // $ex_tax = true
|
940 |
+
} else {
|
941 |
+
// WC2.2 and older: recalculate to exclude tax
|
942 |
+
$discount_value = 0;
|
943 |
+
|
944 |
+
$items = $this->order->get_items();;
|
945 |
+
if( sizeof( $items ) > 0 ) {
|
946 |
+
foreach( $items as $item ) {
|
947 |
+
$discount_value += ($item['line_subtotal'] - $item['line_total']);
|
948 |
+
}
|
949 |
+
}
|
950 |
+
}
|
951 |
+
}
|
952 |
+
|
953 |
+
$discount = array (
|
954 |
+
'label' => __('Discount', 'woocommerce-pdf-invoices-packing-slips' ),
|
955 |
+
'value' => $this->format_price( $discount_value ),
|
956 |
+
'raw_value' => $discount_value,
|
957 |
+
);
|
958 |
+
|
959 |
+
if ( round( $discount_value, 3 ) != 0 ) {
|
960 |
+
return apply_filters( 'wpo_wcpdf_order_discount', $discount, $type, $tax, $this );
|
961 |
+
}
|
962 |
+
}
|
963 |
+
public function order_discount( $type = 'total', $tax = 'incl' ) {
|
964 |
+
$discount = $this->get_order_discount( $type, $tax );
|
965 |
+
echo $discount['value'];
|
966 |
+
}
|
967 |
+
|
968 |
+
/**
|
969 |
+
* Return the order fees
|
970 |
+
*/
|
971 |
+
public function get_order_fees( $tax = 'excl' ) {
|
972 |
+
if ( $_fees = $this->order->get_fees() ) {
|
973 |
+
foreach( $_fees as $id => $fee ) {
|
974 |
+
if ($tax == 'excl' ) {
|
975 |
+
$fee_price = $this->format_price( $fee['line_total'] );
|
976 |
+
} else {
|
977 |
+
$fee_price = $this->format_price( $fee['line_total'] + $fee['line_tax'] );
|
978 |
+
}
|
979 |
+
|
980 |
+
$fees[ $id ] = array(
|
981 |
+
'label' => $fee['name'],
|
982 |
+
'value' => $fee_price,
|
983 |
+
'line_total' => $this->format_price( $fee['line_total'] ),
|
984 |
+
'line_tax' => $this->format_price( $fee['line_tax'] )
|
985 |
+
);
|
986 |
+
}
|
987 |
+
return $fees;
|
988 |
+
}
|
989 |
+
}
|
990 |
+
|
991 |
+
/**
|
992 |
+
* Return the order taxes
|
993 |
+
*/
|
994 |
+
public function get_order_taxes() {
|
995 |
+
$tax_label = __( 'VAT', 'woocommerce-pdf-invoices-packing-slips' ); // register alternate label translation
|
996 |
+
$tax_label = __( 'Tax rate', 'woocommerce-pdf-invoices-packing-slips' );
|
997 |
+
$tax_rate_ids = $this->get_tax_rate_ids();
|
998 |
+
if ( $order_taxes = $this->order->get_taxes() ) {
|
999 |
+
foreach ( $order_taxes as $key => $tax ) {
|
1000 |
+
if ( WCX::is_wc_version_gte_3_0() ) {
|
1001 |
+
$taxes[ $key ] = array(
|
1002 |
+
'label' => $tax->get_label(),
|
1003 |
+
'value' => $this->format_price( $tax->get_tax_total() + $tax->get_shipping_tax_total() ),
|
1004 |
+
'rate_id' => $tax->get_rate_id(),
|
1005 |
+
'tax_amount' => $tax->get_tax_total(),
|
1006 |
+
'shipping_tax_amount' => $tax->get_shipping_tax_total(),
|
1007 |
+
'rate' => isset( $tax_rate_ids[ $tax->get_rate_id() ] ) ? ( (float) $tax_rate_ids[$tax->get_rate_id()]['tax_rate'] ) . ' %': '',
|
1008 |
+
);
|
1009 |
+
} else {
|
1010 |
+
$taxes[ $key ] = array(
|
1011 |
+
'label' => isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ],
|
1012 |
+
'value' => $this->format_price( ( $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ] ) ),
|
1013 |
+
'rate_id' => $tax['rate_id'],
|
1014 |
+
'tax_amount' => $tax['tax_amount'],
|
1015 |
+
'shipping_tax_amount' => $tax['shipping_tax_amount'],
|
1016 |
+
'rate' => isset( $tax_rate_ids[ $tax['rate_id'] ] ) ? ( (float) $tax_rate_ids[$tax['rate_id']]['tax_rate'] ) . ' %': '',
|
1017 |
+
);
|
1018 |
+
}
|
1019 |
+
|
1020 |
+
}
|
1021 |
+
|
1022 |
+
return apply_filters( 'wpo_wcpdf_order_taxes', $taxes, $this );
|
1023 |
+
}
|
1024 |
+
}
|
1025 |
+
|
1026 |
+
/**
|
1027 |
+
* Return/show the order grand total
|
1028 |
+
*/
|
1029 |
+
public function get_order_grand_total( $tax = 'incl' ) {
|
1030 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 ) {
|
1031 |
+
// WC 2.1 or newer is used
|
1032 |
+
$total_unformatted = $this->order->get_total();
|
1033 |
+
} else {
|
1034 |
+
// Backwards compatibility
|
1035 |
+
$total_unformatted = $this->order->get_order_total();
|
1036 |
+
}
|
1037 |
+
|
1038 |
+
if ($tax == 'excl' ) {
|
1039 |
+
$total = $this->format_price( $total_unformatted - $this->order->get_total_tax() );
|
1040 |
+
$label = __( 'Total ex. VAT', 'woocommerce-pdf-invoices-packing-slips' );
|
1041 |
+
} else {
|
1042 |
+
$total = $this->format_price( ( $total_unformatted ) );
|
1043 |
+
$label = __( 'Total', 'woocommerce-pdf-invoices-packing-slips' );
|
1044 |
+
}
|
1045 |
+
|
1046 |
+
$grand_total = array(
|
1047 |
+
'label' => $label,
|
1048 |
+
'value' => $total,
|
1049 |
+
);
|
1050 |
+
|
1051 |
+
return apply_filters( 'wpo_wcpdf_order_grand_total', $grand_total, $tax, $this );
|
1052 |
+
}
|
1053 |
+
public function order_grand_total( $tax = 'incl' ) {
|
1054 |
+
$grand_total = $this->get_order_grand_total( $tax );
|
1055 |
+
echo $grand_total['value'];
|
1056 |
+
}
|
1057 |
+
|
1058 |
+
|
1059 |
+
/**
|
1060 |
+
* Return/Show shipping notes
|
1061 |
+
*/
|
1062 |
+
public function get_shipping_notes() {
|
1063 |
+
if ( $this->is_refund( $this->order ) ) {
|
1064 |
+
// return reason for refund if order is a refund
|
1065 |
+
if ( version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) ) {
|
1066 |
+
$shipping_notes = $this->order->get_reason();
|
1067 |
+
} elseif ( method_exists($this->order, 'get_refund_reason') ) {
|
1068 |
+
$shipping_notes = $this->order->get_refund_reason();
|
1069 |
+
} else {
|
1070 |
+
$shipping_notes = wpautop( wptexturize( WCX_Order::get_prop( $this->order, 'customer_note', 'view' ) ) );
|
1071 |
+
}
|
1072 |
+
} else {
|
1073 |
+
$shipping_notes = wpautop( wptexturize( WCX_Order::get_prop( $this->order, 'customer_note', 'view' ) ) );
|
1074 |
+
}
|
1075 |
+
return apply_filters( 'wpo_wcpdf_shipping_notes', $shipping_notes, $this );
|
1076 |
+
}
|
1077 |
+
public function shipping_notes() {
|
1078 |
+
echo $this->get_shipping_notes();
|
1079 |
+
}
|
1080 |
+
|
1081 |
+
/**
|
1082 |
+
* wrapper for wc_price, ensuring currency is always passed
|
1083 |
+
*/
|
1084 |
+
public function format_price( $price, $args = array() ) {
|
1085 |
+
if ( function_exists( 'wc_price' ) ) { // WC 2.1+
|
1086 |
+
$args['currency'] = WCX_Order::get_prop( $this->order, 'currency' );
|
1087 |
+
$formatted_price = wc_price( $price, $args );
|
1088 |
+
} else {
|
1089 |
+
$formatted_price = woocommerce_price( $price );
|
1090 |
+
}
|
1091 |
+
|
1092 |
+
return $formatted_price;
|
1093 |
+
}
|
1094 |
+
public function wc_price( $price, $args = array() ) {
|
1095 |
+
return $this->format_price( $price, $args );
|
1096 |
+
}
|
1097 |
+
|
1098 |
+
/**
|
1099 |
+
* Gets price - formatted for display.
|
1100 |
+
*
|
1101 |
+
* @access public
|
1102 |
+
* @param mixed $item
|
1103 |
+
* @return string
|
1104 |
+
*/
|
1105 |
+
public function get_formatted_item_price ( $item, $type, $tax_display = '' ) {
|
1106 |
+
if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) ) {
|
1107 |
+
return;
|
1108 |
+
}
|
1109 |
+
|
1110 |
+
$divide_by = ($type == 'single' && $item['qty'] != 0 )?abs($item['qty']):1; //divide by 1 if $type is not 'single' (thus 'total')
|
1111 |
+
if ( $tax_display == 'excl' ) {
|
1112 |
+
$item_price = $this->format_price( ($this->order->get_line_subtotal( $item )) / $divide_by );
|
1113 |
+
} else {
|
1114 |
+
$item_price = $this->format_price( ($this->order->get_line_subtotal( $item, true )) / $divide_by );
|
1115 |
+
}
|
1116 |
+
|
1117 |
+
return $item_price;
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
public function get_invoice_number() {
|
1121 |
+
// Call the woocommerce_invoice_number filter and let third-party plugins set a number.
|
1122 |
+
// Default is null, so we can detect whether a plugin has set the invoice number
|
1123 |
+
$third_party_invoice_number = apply_filters( 'woocommerce_invoice_number', null, $this->order_id );
|
1124 |
+
if ($third_party_invoice_number !== null) {
|
1125 |
+
return $third_party_invoice_number;
|
1126 |
+
}
|
1127 |
+
|
1128 |
+
if ( $invoice_number = $this->get_number('invoice') ) {
|
1129 |
+
return $formatted_invoice_number = $invoice_number->get_formatted();
|
1130 |
+
} else {
|
1131 |
+
return '';
|
1132 |
+
}
|
1133 |
+
}
|
1134 |
+
|
1135 |
+
public function invoice_number() {
|
1136 |
+
echo $this->get_invoice_number();
|
1137 |
+
}
|
1138 |
+
|
1139 |
+
public function get_invoice_date() {
|
1140 |
+
if ( $invoice_date = $this->get_date('invoice') ) {
|
1141 |
+
return $invoice_date->date_i18n( apply_filters( 'wpo_wcpdf_date_format', wc_date_format(), $this ) );
|
1142 |
+
} else {
|
1143 |
+
return '';
|
1144 |
+
}
|
1145 |
+
}
|
1146 |
+
|
1147 |
+
public function invoice_date() {
|
1148 |
+
echo $this->get_invoice_date();
|
1149 |
+
}
|
1150 |
+
|
1151 |
+
|
1152 |
+
}
|
1153 |
+
|
1154 |
Â
endif; // class_exists
|
readme.txt
CHANGED
@@ -1,345 +1,357 @@
|
|
1 |
-
=== WooCommerce PDF Invoices & Packing Slips ===
|
2 |
-
Contributors: pomegranate
|
3 |
-
Donate link: https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-bundle/
|
4 |
-
Tags: woocommerce, pdf, invoices, packing slips, print, delivery notes, invoice, packing slip, export, email, bulk, automatic
|
5 |
-
Requires at least: 3.5
|
6 |
-
Tested up to: 5.
|
7 |
-
Requires PHP: 5.3
|
8 |
-
Stable tag: 2.2.
|
9 |
-
License: GPLv2 or later
|
10 |
-
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
-
|
12 |
-
Create, print & automatically email PDF invoices & packing slips for WooCommerce orders.
|
13 |
-
|
14 |
-
== Description ==
|
15 |
-
|
16 |
-
This WooCommerce extension automatically adds a PDF invoice to the order confirmation emails sent out to your customers. Includes a basic template (additional templates are available from [WP Overnight](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/)) as well as the possibility to modify/create your own templates. In addition, you can choose to download or print invoices and packing slips from the WooCommerce order admin.
|
17 |
-
|
18 |
-
= Main features =
|
19 |
-
* Automatically attach invoice PDF to WooCommerce emails of your choice
|
20 |
-
* Download the PDF invoice / packing slip from the order admin page
|
21 |
-
* Generate PDF invoices / packings slips in bulk
|
22 |
-
* **Fully customizable** HTML/CSS invoice templates
|
23 |
-
* Download invoices from the My Account page
|
24 |
-
* Sequential invoice numbers - with custom formatting
|
25 |
-
* **Available in: Czech, Dutch, English, Finnish, French, German, Hungarian, Italian, Japanese (see FAQ for adding custom fonts!), Norwegian, Polish, Romanian, Russian, Slovak, Slovenian, Spanish, Swedish & Ukrainian**
|
26 |
-
|
27 |
-
In addition to this, we offer several premium extensions:
|
28 |
-
|
29 |
-
* Create/email PDF Proforma Invoices, Credit Notes (for Refunds), email Packing Slips & more with [WooCommerce PDF Invoices & Packing Slips Professional](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-professional/)
|
30 |
-
* Upload all invoices automatically to Dropbox with [WooCommerce PDF Invoices & Packing Slips to Dropbox](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-dropbox/)
|
31 |
-
* Automatically send new orders or packing slips to your printer, as soon as the customer orders! [WooCommerce Automatic Order Printing](https://www.simbahosting.co.uk/s3/product/woocommerce-automatic-order-printing/?affiliates=2) (from our partners at Simba Hosting)
|
32 |
-
* More advanced & stylish templates with [WooCommerce PDF Invoices & Packing Slips Premium Templates](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/)
|
33 |
-
|
34 |
-
= Fully customizable =
|
35 |
-
In addition to a number of default settings (including a custom header/logo) and several layout fields that you can use out of the box, the plugin contains HTML/CSS based templates that allow for customization & full control over the PDF output. Copy the templates to your theme folder and you don't have to worry that your customizations will be overwritten when you update the plugin.
|
36 |
-
|
37 |
-
* Insert customer header image/logo
|
38 |
-
* Modify shop data / footer / disclaimer etc. on the invoices & packing slips
|
39 |
-
* Select paper size (Letter or A4)
|
40 |
-
* Translation ready
|
41 |
-
|
42 |
-
== Installation ==
|
43 |
-
|
44 |
-
= Minimum Requirements =
|
45 |
-
|
46 |
-
* WooCommerce 2.2 or later
|
47 |
-
* WordPress 3.5 or later
|
48 |
-
|
49 |
-
= Automatic installation =
|
50 |
-
Automatic installation is the easiest option as WordPress handles the file transfers itself and you don't even need to leave your web browser. To do an automatic install of WooCommerce PDF Invoices & Packing Slips, log in to your WordPress admin panel, navigate to the Plugins menu and click Add New.
|
51 |
-
|
52 |
-
In the search field type "WooCommerce PDF Invoices & Packing Slips" and click Search Plugins. You can install it by simply clicking Install Now. After clicking that link you will be asked if you're sure you want to install the plugin. Click yes and WordPress will automatically complete the installation. After installation has finished, click the 'activate plugin' link.
|
53 |
-
|
54 |
-
= Manual installation via the WordPress interface =
|
55 |
-
1. Download the plugin zip file to your computer
|
56 |
-
2. Go to the WordPress admin panel menu Plugins > Add New
|
57 |
-
3. Choose upload
|
58 |
-
4. Upload the plugin zip file, the plugin will now be installed
|
59 |
-
5. After installation has finished, click the 'activate plugin' link
|
60 |
-
|
61 |
-
= Manual installation via FTP =
|
62 |
-
1. Download the plugin file to your computer and unzip it
|
63 |
-
2. Using an FTP program, or your hosting control panel, upload the unzipped plugin folder to your WordPress installation's wp-content/plugins/ directory.
|
64 |
-
3. Activate the plugin from the Plugins menu within the WordPress admin.
|
65 |
-
|
66 |
-
== Frequently Asked Questions ==
|
67 |
-
|
68 |
-
= Where can I find the documentation? =
|
69 |
-
|
70 |
-
[WooCommerce PDF Invoices & Packing Slips documentation](http://docs.wpovernight.com/woocommerce-pdf-invoices-packing-slips/)
|
71 |
-
|
72 |
-
= It's not working! =
|
73 |
-
|
74 |
-
Check out our step by step diagnostic instructions here: https://wordpress.org/support/topic/read-this-first-9/
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
= Where can I find more templates? =
|
81 |
-
|
82 |
-
Go to [wpovernight.com](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/) to checkout more templates! These include templates with more tax details and product thumbnails. Need a custom templates? Contact us at support@wpovernight.com for more information.
|
83 |
-
|
84 |
-
= Can I create/send a proforma invoice or a credit note? =
|
85 |
-
This is a feature of our Professional extension, which can be found at [wpovernight.com](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-professional/)
|
86 |
-
|
87 |
-
= Can I contribute to the code? =
|
88 |
-
You're more than welcome! This plugin is hosted on github, where you can post issues or make pull requests.
|
89 |
-
https://github.com/wpovernight/woocommerce-pdf-invoices-packing-slips
|
90 |
-
|
91 |
-
= How can I display the HTML/CSS source for debugging/developing templates? =
|
92 |
-
There's a setting on the Status tab of the settings page that allows you to toggle HTML output. Don't forget to turn if off after you're done testing!
|
93 |
-
|
94 |
-
|
95 |
-
== Screenshots ==
|
96 |
-
|
97 |
-
1. Simple invoice PDF
|
98 |
-
2. Simple packing slip PDF
|
99 |
-
3. Quickly print individual invoices or packing slips from the order list
|
100 |
-
4. Print invoices or packing slips in bulk
|
101 |
-
5. Attach invoices to any WooCommerce email
|
102 |
-
6. Set shop name, address, header logo, etc.
|
103 |
-
|
104 |
-
== Changelog ==
|
105 |
-
|
106 |
-
= 2.2.
|
107 |
-
*
|
108 |
-
* Fix:
|
109 |
-
* Tweak:
|
110 |
-
*
|
111 |
-
|
112 |
-
= 2.2.
|
113 |
-
*
|
114 |
-
|
115 |
-
|
116 |
-
* Fix:
|
117 |
-
|
118 |
-
|
119 |
-
*
|
120 |
-
*
|
121 |
-
*
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
* Fix:
|
126 |
-
|
127 |
-
= 2.2.
|
128 |
-
*
|
129 |
-
*
|
130 |
-
*
|
131 |
-
|
132 |
-
|
133 |
-
*
|
134 |
-
|
135 |
-
|
136 |
-
*
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
*
|
141 |
-
*
|
142 |
-
*
|
143 |
-
|
144 |
-
|
145 |
-
*
|
146 |
-
|
147 |
-
|
148 |
-
*
|
149 |
-
|
150 |
-
|
151 |
-
* Fix:
|
152 |
-
* Fix:
|
153 |
-
* Fix:
|
154 |
-
*
|
155 |
-
* Tweak:
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
*
|
163 |
-
|
164 |
-
|
165 |
-
*
|
166 |
-
*
|
167 |
-
*
|
168 |
-
|
169 |
-
= 2.2.
|
170 |
-
* Fix:
|
171 |
-
* Fix:
|
172 |
-
|
173 |
-
= 2.2.
|
174 |
-
*
|
175 |
-
|
176 |
-
|
177 |
-
*
|
178 |
-
* Fix:
|
179 |
-
*
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
*
|
187 |
-
*
|
188 |
-
|
189 |
-
|
190 |
-
*
|
191 |
-
* Fix:
|
192 |
-
*
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
*
|
199 |
-
*
|
200 |
-
|
201 |
-
|
202 |
-
*
|
203 |
-
* Fix:
|
204 |
-
*
|
205 |
-
|
206 |
-
= 2.1.
|
207 |
-
* Fix:
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
* Feature:
|
213 |
-
* Fix:
|
214 |
-
* Fix:
|
215 |
-
* Fix:
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
*
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
*
|
226 |
-
* Fix:
|
227 |
-
* Fix:
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
*
|
232 |
-
|
233 |
-
|
234 |
-
*
|
235 |
-
|
236 |
-
= 2.1.
|
237 |
-
* Feature:
|
238 |
-
* Fix:
|
239 |
-
*
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
*
|
246 |
-
* Tweak:
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
*
|
252 |
-
|
253 |
-
|
254 |
-
*
|
255 |
-
|
256 |
-
= 2.0.
|
257 |
-
*
|
258 |
-
|
259 |
-
|
260 |
-
*
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
*
|
266 |
-
*
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
* Fix:
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
* Fix:
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
*
|
283 |
-
* Fix:
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
*
|
288 |
-
*
|
289 |
-
* Fix:
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
*
|
295 |
-
* Fix:
|
296 |
-
|
297 |
-
|
298 |
-
*
|
299 |
-
|
300 |
-
|
301 |
-
* Fix:
|
302 |
-
* Fix:
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
*
|
307 |
-
* Fix:
|
308 |
-
*
|
309 |
-
* Tweak:
|
310 |
-
*
|
311 |
-
|
312 |
-
= 2.0.
|
313 |
-
* Fix:
|
314 |
-
* Fix:
|
315 |
-
|
316 |
-
|
317 |
-
* Fix:
|
318 |
-
* Fix:
|
319 |
-
|
320 |
-
|
321 |
-
*
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
*
|
326 |
-
*
|
327 |
-
*
|
328 |
-
*
|
329 |
-
*
|
330 |
-
*
|
331 |
-
|
332 |
-
|
333 |
-
* Fix:
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
*
|
339 |
-
*
|
340 |
-
*
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
345 |
Â
2.X is a BIG update! Make a full site backup before upgrading if you were using version 1.X!
|
1 |
+
=== WooCommerce PDF Invoices & Packing Slips ===
|
2 |
+
Contributors: pomegranate
|
3 |
+
Donate link: https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-bundle/
|
4 |
+
Tags: woocommerce, pdf, invoices, packing slips, print, delivery notes, invoice, packing slip, export, email, bulk, automatic
|
5 |
+
Requires at least: 3.5
|
6 |
+
Tested up to: 5.2
|
7 |
+
Requires PHP: 5.3
|
8 |
+
Stable tag: 2.2.14
|
9 |
+
License: GPLv2 or later
|
10 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
+
|
12 |
+
Create, print & automatically email PDF invoices & packing slips for WooCommerce orders.
|
13 |
+
|
14 |
+
== Description ==
|
15 |
+
|
16 |
+
This WooCommerce extension automatically adds a PDF invoice to the order confirmation emails sent out to your customers. Includes a basic template (additional templates are available from [WP Overnight](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/)) as well as the possibility to modify/create your own templates. In addition, you can choose to download or print invoices and packing slips from the WooCommerce order admin.
|
17 |
+
|
18 |
+
= Main features =
|
19 |
+
* Automatically attach invoice PDF to WooCommerce emails of your choice
|
20 |
+
* Download the PDF invoice / packing slip from the order admin page
|
21 |
+
* Generate PDF invoices / packings slips in bulk
|
22 |
+
* **Fully customizable** HTML/CSS invoice templates
|
23 |
+
* Download invoices from the My Account page
|
24 |
+
* Sequential invoice numbers - with custom formatting
|
25 |
+
* **Available in: Czech, Dutch, English, Finnish, French, German, Hungarian, Italian, Japanese (see FAQ for adding custom fonts!), Norwegian, Polish, Romanian, Russian, Slovak, Slovenian, Spanish, Swedish & Ukrainian**
|
26 |
+
|
27 |
+
In addition to this, we offer several premium extensions:
|
28 |
+
|
29 |
+
* Create/email PDF Proforma Invoices, Credit Notes (for Refunds), email Packing Slips & more with [WooCommerce PDF Invoices & Packing Slips Professional](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-professional/)
|
30 |
+
* Upload all invoices automatically to Dropbox with [WooCommerce PDF Invoices & Packing Slips to Dropbox](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-dropbox/)
|
31 |
+
* Automatically send new orders or packing slips to your printer, as soon as the customer orders! [WooCommerce Automatic Order Printing](https://www.simbahosting.co.uk/s3/product/woocommerce-automatic-order-printing/?affiliates=2) (from our partners at Simba Hosting)
|
32 |
+
* More advanced & stylish templates with [WooCommerce PDF Invoices & Packing Slips Premium Templates](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/)
|
33 |
+
|
34 |
+
= Fully customizable =
|
35 |
+
In addition to a number of default settings (including a custom header/logo) and several layout fields that you can use out of the box, the plugin contains HTML/CSS based templates that allow for customization & full control over the PDF output. Copy the templates to your theme folder and you don't have to worry that your customizations will be overwritten when you update the plugin.
|
36 |
+
|
37 |
+
* Insert customer header image/logo
|
38 |
+
* Modify shop data / footer / disclaimer etc. on the invoices & packing slips
|
39 |
+
* Select paper size (Letter or A4)
|
40 |
+
* Translation ready
|
41 |
+
|
42 |
+
== Installation ==
|
43 |
+
|
44 |
+
= Minimum Requirements =
|
45 |
+
|
46 |
+
* WooCommerce 2.2 or later
|
47 |
+
* WordPress 3.5 or later
|
48 |
+
|
49 |
+
= Automatic installation =
|
50 |
+
Automatic installation is the easiest option as WordPress handles the file transfers itself and you don't even need to leave your web browser. To do an automatic install of WooCommerce PDF Invoices & Packing Slips, log in to your WordPress admin panel, navigate to the Plugins menu and click Add New.
|
51 |
+
|
52 |
+
In the search field type "WooCommerce PDF Invoices & Packing Slips" and click Search Plugins. You can install it by simply clicking Install Now. After clicking that link you will be asked if you're sure you want to install the plugin. Click yes and WordPress will automatically complete the installation. After installation has finished, click the 'activate plugin' link.
|
53 |
+
|
54 |
+
= Manual installation via the WordPress interface =
|
55 |
+
1. Download the plugin zip file to your computer
|
56 |
+
2. Go to the WordPress admin panel menu Plugins > Add New
|
57 |
+
3. Choose upload
|
58 |
+
4. Upload the plugin zip file, the plugin will now be installed
|
59 |
+
5. After installation has finished, click the 'activate plugin' link
|
60 |
+
|
61 |
+
= Manual installation via FTP =
|
62 |
+
1. Download the plugin file to your computer and unzip it
|
63 |
+
2. Using an FTP program, or your hosting control panel, upload the unzipped plugin folder to your WordPress installation's wp-content/plugins/ directory.
|
64 |
+
3. Activate the plugin from the Plugins menu within the WordPress admin.
|
65 |
+
|
66 |
+
== Frequently Asked Questions ==
|
67 |
+
|
68 |
+
= Where can I find the documentation? =
|
69 |
+
|
70 |
+
[WooCommerce PDF Invoices & Packing Slips documentation](http://docs.wpovernight.com/woocommerce-pdf-invoices-packing-slips/)
|
71 |
+
|
72 |
+
= It's not working! =
|
73 |
+
|
74 |
+
Check out our step by step diagnostic instructions here: https://wordpress.org/support/topic/read-this-first-9/
|
75 |
+
|
76 |
+
|
77 |
+
|
78 |
+
|
79 |
+
|
80 |
+
= Where can I find more templates? =
|
81 |
+
|
82 |
+
Go to [wpovernight.com](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/) to checkout more templates! These include templates with more tax details and product thumbnails. Need a custom templates? Contact us at support@wpovernight.com for more information.
|
83 |
+
|
84 |
+
= Can I create/send a proforma invoice or a credit note? =
|
85 |
+
This is a feature of our Professional extension, which can be found at [wpovernight.com](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-professional/)
|
86 |
+
|
87 |
+
= Can I contribute to the code? =
|
88 |
+
You're more than welcome! This plugin is hosted on github, where you can post issues or make pull requests.
|
89 |
+
https://github.com/wpovernight/woocommerce-pdf-invoices-packing-slips
|
90 |
+
|
91 |
+
= How can I display the HTML/CSS source for debugging/developing templates? =
|
92 |
+
There's a setting on the Status tab of the settings page that allows you to toggle HTML output. Don't forget to turn if off after you're done testing!
|
93 |
+
|
94 |
+
|
95 |
+
== Screenshots ==
|
96 |
+
|
97 |
+
1. Simple invoice PDF
|
98 |
+
2. Simple packing slip PDF
|
99 |
+
3. Quickly print individual invoices or packing slips from the order list
|
100 |
+
4. Print invoices or packing slips in bulk
|
101 |
+
5. Attach invoices to any WooCommerce email
|
102 |
+
6. Set shop name, address, header logo, etc.
|
103 |
+
|
104 |
+
== Changelog ==
|
105 |
+
|
106 |
+
= 2.2.14 =
|
107 |
+
* Fix: Set default PHPMailer validator to 'php' (fixing 'setFrom' errors on PHP 7.3)
|
108 |
+
* Fix: Attachment path for file lock check
|
109 |
+
* Tweak: Don't wait for file lock if locking disabled
|
110 |
+
* Tweak: JIT loading of core documents for early requests (before init 15)
|
111 |
+
|
112 |
+
= 2.2.13 =
|
113 |
+
* Feature: Better order notes formatting & optional filter for system notes
|
114 |
+
* Feature: add email object to attachment hook and allow order object filtering
|
115 |
+
* Fix: WooCommerce Chained Products row classes
|
116 |
+
* Fix: Issues with locked attachment files preventing the email from being sent correctly
|
117 |
+
|
118 |
+
= 2.2.12 =
|
119 |
+
* Tested up to WC3.6
|
120 |
+
* Fix: Prevent infinite loop on temporary folder creation for partially migrated sites or write permission issues
|
121 |
+
* Tweak: Removed height & width attributes from logo image (+filter `wpo_wcpdf_header_logo_img_element`)
|
122 |
+
* Dev: Enable guest access to PDF with order key in URL
|
123 |
+
|
124 |
+
= 2.2.11 =
|
125 |
+
* Fix: Fatal error on orders with multiple refunds
|
126 |
+
|
127 |
+
= 2.2.10 =
|
128 |
+
* Fix: Possible conflict with latest Subscriptions
|
129 |
+
* Fix: Load correct translations when admin user profile language is set to different locale
|
130 |
+
* Fix: Use file lock to prevent parallel processes creating the same attachment file
|
131 |
+
* Fix: Prevent notices for incorrectly loaded email classes
|
132 |
+
* Feature: Allow different invoice number column sorting methods by filter
|
133 |
+
* Feature: Filter for global prevention of creating specific document (`wpo_wcpdf_document_is_allowed`)
|
134 |
+
|
135 |
+
= 2.2.9 =
|
136 |
+
* Feature: Added customer note email to attachment options
|
137 |
+
* Fix: Prevent empty invoice dates from being saved as 1970 (fallback to current date/time)
|
138 |
+
|
139 |
+
= 2.2.8 =
|
140 |
+
* Tested up to WP5.1
|
141 |
+
* Tweak: Re-use attachment file if not older than 60 seconds (tentative fix for parallel read & write issues)
|
142 |
+
* Dev: Added URL overrides to switch between output mode (`&output=html`) and debug (`&debug=true`)
|
143 |
+
|
144 |
+
= 2.2.7 =
|
145 |
+
* Fix: Hardened permissions & security checks on several admin actions (audit by pluginvulnerabilities.com)
|
146 |
+
* Feature: Show checkmarks for existing documents on order details page buttons too
|
147 |
+
* Tweak: Product Bundles compatibility, hide items by default, following bundle settings (Simple Template)
|
148 |
+
* Tweak: Fallback to billing address on packing slip for orders without shipping address
|
149 |
+
|
150 |
+
= 2.2.6 =
|
151 |
+
* Fix: ship to different address check for empty shipping addresses
|
152 |
+
* Fix: Fix notice when using invoice number by plugin
|
153 |
+
* Fix: Underline position
|
154 |
+
* Fix: PHP 7.3 compatibility
|
155 |
+
* Tweak: Updated dompdf to 0.8.3
|
156 |
+
* Tweak: move admin menu item to the end of WooCommerce menu
|
157 |
+
* Tweak: pass document object to paper format & orientation filters
|
158 |
+
|
159 |
+
= 2.2.5 =
|
160 |
+
* Feature: Check marks to indicate whether a document exists
|
161 |
+
* Feature: Test mode to automatically apply updated settings to existing documents
|
162 |
+
* Feature: Admin bar indicator for debug mode setting
|
163 |
+
* Fix: always use latest email settings
|
164 |
+
* Fix: WooCommerce Composit Products item name compatibility
|
165 |
+
* Fix: Use woocommerce_thumbnail for WC3.3+
|
166 |
+
* Tweak: apply woocommerce_order_item_name filter (fixes compatibility with WooCommerce Product Addons 3.0)
|
167 |
+
* Tweak: Use WooCommerce date format instead of WP date format
|
168 |
+
|
169 |
+
= 2.2.4 =
|
170 |
+
* Fix: excluding some display options from historical settings
|
171 |
+
* Fix: fix notices when requesting properties as custom fields (in a custom template)
|
172 |
+
|
173 |
+
= 2.2.3 =
|
174 |
+
* Fix: issues reading shop settings
|
175 |
+
|
176 |
+
= 2.2.2 =
|
177 |
+
* Feature: Added option to always use most current settings for the invoice
|
178 |
+
* Fix: Double check for empty document numbers on initialization
|
179 |
+
* New filter: `wpo_wcpdf_output_format` to set output per document type
|
180 |
+
|
181 |
+
= 2.2.1 =
|
182 |
+
* Fix: potential number formatting issues with `wpo_wcpdf_raw_document_number` filter
|
183 |
+
* Fix: prevent direct loading of template files
|
184 |
+
|
185 |
+
= 2.2.0 =
|
186 |
+
* Feature: Document settings are now saved per order - changing settings after a PDF has been created will no longer affect the output
|
187 |
+
* Feature: Button to delete invoice or packing slip
|
188 |
+
* Feature: Better error handling and logging via WC Logger (WooCommerce > Status > Logs)
|
189 |
+
* Fix: Broader payment gateway compatibility (lower priority for documents initialization)
|
190 |
+
* Fix: undefined variable in construct when loading document programmatically (props to Christopher)
|
191 |
+
* Fix: compatibility with renamed WooCommerce plugins (settings page detection)
|
192 |
+
* Tweak: Reload translations before creating attachment
|
193 |
+
* Translations: Updated translations POT
|
194 |
+
|
195 |
+
= 2.1.10 =
|
196 |
+
* Feature: Include invoice number and date in WooCommerce data remover and exporter
|
197 |
+
* Fix: Row class for Chained Products compatibility
|
198 |
+
* Fix: Improved compatibility with Advanced Custom Fields
|
199 |
+
* Fix: Setting for diabling for free invoices should be applied even when other plugins are applying rules
|
200 |
+
|
201 |
+
= 2.1.9 =
|
202 |
+
* Feature: Automatic cleanup of temporary attachments folder (settings in Status tab)
|
203 |
+
* Fix: prevent infinite loop on sites without uploads folder
|
204 |
+
* Fix: tag replacements for externally hosted images (CDN)
|
205 |
+
|
206 |
+
= 2.1.8 =
|
207 |
+
* Fix: Fatal error on PHP 5.X
|
208 |
+
|
209 |
+
= 2.1.7 =
|
210 |
+
* Feature: add [order_number] placeholder for number format
|
211 |
+
* Feature: $order and $order_id variables now available directly template (without needing the document object)
|
212 |
+
* Feature: add actions before & after addresses
|
213 |
+
* Fix: Sorting orders by invoice number
|
214 |
+
* Fix: Aelia Currency Switcher - use decimal & Thousand separator settings
|
215 |
+
* Fix: fix jquery migrate warnings for media upload script
|
216 |
+
* Tweak: add calculated tax rate to item data
|
217 |
+
|
218 |
+
= 2.1.6 =
|
219 |
+
* Fix: Extended currency symbol setting for WooCommerce Currency Switcher by realmag777
|
220 |
+
* Fix: Apply WooCommerce decimal settings to tax rates with decimals
|
221 |
+
* Tweak: Pass document object to `wpo_wcpdf_email_attachment` filter
|
222 |
+
|
223 |
+
= 2.1.5 =
|
224 |
+
* Feature: Filter for number store table (wpo_wcpdf_number_store_table_name)
|
225 |
+
* Fix: prevent accessing order properties as custom field/order meta
|
226 |
+
* Fix: prevent wrong application of wpo_wcpdf_filename filter
|
227 |
+
* Fix: Improved tax rate calculation fallback
|
228 |
+
|
229 |
+
= 2.1.4 =
|
230 |
+
* Fix: WooCommerce 3.3 action buttons
|
231 |
+
* Feature: Added row classes for WooCommerce Composite Products
|
232 |
+
|
233 |
+
= 2.1.3 =
|
234 |
+
* Fix: Fatal PHP error on My Account page.
|
235 |
+
|
236 |
+
= 2.1.2 =
|
237 |
+
* Feature: New action wpo_wcpdf_init_document
|
238 |
+
* Fix: Use title getters for my-account and backend buttons
|
239 |
+
* Fix: Legacy Premium Templates reference
|
240 |
+
* Tweak: Skip documents overview in settings, default to invoice
|
241 |
+
|
242 |
+
= 2.1.1 =
|
243 |
+
* Fix: WooCommerce Order Status & Actions Manager emails compatibility
|
244 |
+
* Feature: sort orders by invoice number column
|
245 |
+
* Tweak: pass document object to title filters
|
246 |
+
* Tweak: use title getter in template files (instead of title string)
|
247 |
+
|
248 |
+
= 2.1.0 =
|
249 |
+
* Feature: WooCommerce Order Status & Actions Manager emails compatibility
|
250 |
+
* Fix: Better url fallback for images stored in cloud
|
251 |
+
* Update: dompdf library updated to 0.8.2 - DOMDocument parser set to default again
|
252 |
+
|
253 |
+
= 2.0.15 =
|
254 |
+
* Fix: Prevent saving invoice number/date from order details page when not edited
|
255 |
+
|
256 |
+
= 2.0.14 =
|
257 |
+
* Feature: Manually resend specific order emails in WooCommerce 3.2+
|
258 |
+
* Tweak: Show full size logo preview in settings
|
259 |
+
* Tweak: Custom field fallback to underscore prefixed meta key
|
260 |
+
* Dev: added `wpo_wcpdf_before_sequential_number_increment` action
|
261 |
+
|
262 |
+
= 2.0.13 =
|
263 |
+
* Fix: Minor XSS issue on settings screens by escaping and sanitizing 'tab' & 'section' GET variables. Discovered by Detectify.
|
264 |
+
* Fix: Pakistani Rupee Symbol
|
265 |
+
* Feature: Automatically enable extended currency symbol support for currencies not supported by Open Sans
|
266 |
+
* Dev: added `wpo_wcpdf_document_number_settings` filter
|
267 |
+
|
268 |
+
= 2.0.12 =
|
269 |
+
* Option: Use different HTML parser (debug settings)
|
270 |
+
|
271 |
+
= 2.0.11 =
|
272 |
+
* Fix: Improved fonts update routine (now preserves custom fonts)
|
273 |
+
* Fix: Enable HTML5 parser by default (fixes issues with libxml)
|
274 |
+
* Tweak: Show both PHP & WP Memory limit in Status tab
|
275 |
+
|
276 |
+
= 2.0.10 =
|
277 |
+
* Fix: Set invoice number backend button
|
278 |
+
* Fix: Thumbail paths
|
279 |
+
* Tweak: Make dompdf options filterable
|
280 |
+
|
281 |
+
= 2.0.9 =
|
282 |
+
* Feature: use `[invoice_date="ymd"]` in invoice number prefix or suffix to include a specific date format in the invoice number
|
283 |
+
* Fix: Postmeta table prefix for invoice counter
|
284 |
+
* Fix: 0% tax rates
|
285 |
+
|
286 |
+
= 2.0.8 =
|
287 |
+
* Feature: Add support for Bedrock / alternative folder structures
|
288 |
+
* Dev: Filter for merged documents
|
289 |
+
* Fix: Better attributes fallback for product variations
|
290 |
+
|
291 |
+
= 2.0.7 =
|
292 |
+
* Feature: Added button to delete legacy settings
|
293 |
+
* Feature: Option to enable font subsetting
|
294 |
+
* Fix: Invoice number sequence for databases with alternative auto_increment_increment settings
|
295 |
+
* Fix: Fallback function for MB String (mb_stripos)
|
296 |
+
|
297 |
+
= 2.0.6 =
|
298 |
+
* Feature: Improved third party invoice number filters (`wpo_wcpdf_external_invoice_number_enabled` & `wpo_wcpdf_external_invoice_number`)
|
299 |
+
* Fix: Underline position for Open Sans font
|
300 |
+
* Fix: Invoice number auto_increment for servers that restarted frequently
|
301 |
+
* Fix: Dompdf log file location (preventing open base_dir notices breaking PDF header)
|
302 |
+
* Fix: 1.6.6 Settings migration duplicates merging
|
303 |
+
* Tweak: Clear fonts folder when manually reinstalling fonts
|
304 |
+
|
305 |
+
= 2.0.5 =
|
306 |
+
* Feature: Remove temporary files (Status tab)
|
307 |
+
* Fix: Page number replacement
|
308 |
+
* Tweak: Fallback functions for MB String extension
|
309 |
+
* Tweak: Improved wpo_wcpdf_check_privs usability for my account privileges
|
310 |
+
* Legacy support: added wc_price alias for format_price method in document
|
311 |
+
|
312 |
+
= 2.0.4 =
|
313 |
+
* Fix: Apply filters for custom invoice number formatting in document too
|
314 |
+
* Fix: Parent fallback for missing dates from refunds
|
315 |
+
|
316 |
+
= 2.0.3 =
|
317 |
+
* Fix: Better support for legacy invoice number filter (`wpo_wcpdf_invoice_number` - replaced by `wpo_wcpdf_formatted_document_number`)
|
318 |
+
* Fix: Document number formatting fallback to order date if no document date available
|
319 |
+
* Fix: Updated classmap: PSR loading didn't work on some installations
|
320 |
+
* Fix: Prevent order notes from all orders showing when document is not loaded properly in filter
|
321 |
+
* Tweak: Disable deprecation notices during email sending
|
322 |
+
* Tweak: ignore outdated language packs
|
323 |
+
|
324 |
+
= 2.0.2 =
|
325 |
+
* Fix: order notes using correct order_id
|
326 |
+
* Fix: WC3.0 deprecation notice for currency
|
327 |
+
* Fix: Avoid crashing on PHP5.2 and older
|
328 |
+
* Fix: Only use PHP MB String when present
|
329 |
+
* Fix: Remote images
|
330 |
+
* Fix: Download option
|
331 |
+
|
332 |
+
= 2.0.1 =
|
333 |
+
* Fix: PHP 5.4 issue
|
334 |
+
|
335 |
+
= 2.0.0 =
|
336 |
+
* New: Better structured & more advanced settings for documents
|
337 |
+
* New: Option to enable & disable Packing Slips or Invoices
|
338 |
+
* New: Invoice number sequence stored separately for improved speed & performance
|
339 |
+
* New: Completely rewritten codebase for more flexibility & better reliability
|
340 |
+
* New: Updated PDF library to DOMPDF 0.8
|
341 |
+
* New: PDF Library made pluggable (by using the `wpo_wcpdf_pdf_maker` filter)
|
342 |
+
* New: lots of new functions & filters to allow developers to hook into the plugin
|
343 |
+
* Changed: **$wpo_wcpdf variable is now deprecated** (legacy mode available & automatically enabled on update)
|
344 |
+
* Fix: Improved PHP 7 & 7.1 support
|
345 |
+
* Fix: Positive prices for refunds
|
346 |
+
* Fix: Use parent for attributes retrieved for product variations
|
347 |
+
* Fix: Set content type to PDF for download
|
348 |
+
|
349 |
+
= 1.6.6 =
|
350 |
+
* Feature: Facilitate downgrading from 2.0 (re-installing fonts & resetting version)
|
351 |
+
* Fix: Update currencies font (added Georgian Lari)
|
352 |
+
* Translations: Added Indonesian
|
353 |
+
|
354 |
+
== Upgrade Notice ==
|
355 |
+
|
356 |
+
= 2.1.10 =
|
357 |
Â
2.X is a BIG update! Make a full site backup before upgrading if you were using version 1.X!
|
woocommerce-pdf-invoices-packingslips.php
CHANGED
@@ -1,359 +1,359 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Plugin Name: WooCommerce PDF Invoices & Packing Slips
|
4 |
-
* Plugin URI: http://www.wpovernight.com
|
5 |
-
* Description: Create, print & email PDF invoices & packing slips for WooCommerce orders.
|
6 |
-
* Version: 2.2.
|
7 |
-
* Author: Ewout Fernhout
|
8 |
-
* Author URI: http://www.wpovernight.com
|
9 |
-
* License: GPLv2 or later
|
10 |
-
* License URI: http://www.opensource.org/licenses/gpl-license.php
|
11 |
-
* Text Domain: woocommerce-pdf-invoices-packing-slips
|
12 |
-
* WC requires at least: 2.2.0
|
13 |
-
* WC tested up to: 3.6.0
|
14 |
-
*/
|
15 |
-
|
16 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
17 |
-
exit; // Exit if accessed directly
|
18 |
-
}
|
19 |
-
|
20 |
-
if ( !class_exists( 'WPO_WCPDF' ) ) :
|
21 |
-
|
22 |
-
class WPO_WCPDF {
|
23 |
-
|
24 |
-
public $version = '2.2.
|
25 |
-
public $plugin_basename;
|
26 |
-
public $legacy_mode;
|
27 |
-
|
28 |
-
protected static $_instance = null;
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Main Plugin Instance
|
32 |
-
*
|
33 |
-
* Ensures only one instance of plugin is loaded or can be loaded.
|
34 |
-
*/
|
35 |
-
public static function instance() {
|
36 |
-
if ( is_null( self::$_instance ) ) {
|
37 |
-
self::$_instance = new self();
|
38 |
-
}
|
39 |
-
return self::$_instance;
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Constructor
|
44 |
-
*/
|
45 |
-
public function __construct() {
|
46 |
-
$this->plugin_basename = plugin_basename(__FILE__);
|
47 |
-
|
48 |
-
$this->define( 'WPO_WCPDF_VERSION', $this->version );
|
49 |
-
|
50 |
-
// load the localisation & classes
|
51 |
-
add_action( 'plugins_loaded', array( $this, 'translations' ) );
|
52 |
-
add_filter( 'load_textdomain_mofile', array( $this, 'textdomain_fallback' ), 10, 2 );
|
53 |
-
add_action( 'plugins_loaded', array( $this, 'load_classes' ), 9 );
|
54 |
-
add_action( 'in_plugin_update_message-'.$this->plugin_basename, array( $this, 'in_plugin_update_message' ) );
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Define constant if not already set
|
59 |
-
* @param string $name
|
60 |
-
* @param string|bool $value
|
61 |
-
*/
|
62 |
-
private function define( $name, $value ) {
|
63 |
-
if ( ! defined( $name ) ) {
|
64 |
-
define( $name, $value );
|
65 |
-
}
|
66 |
-
}
|
67 |
-
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Load the translation / textdomain files
|
71 |
-
*
|
72 |
-
* Note: the first-loaded translation file overrides any following ones if the same translation is present
|
73 |
-
*/
|
74 |
-
public function translations() {
|
75 |
-
$locale = function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale();
|
76 |
-
$locale = apply_filters( 'plugin_locale', $locale, 'woocommerce-pdf-invoices-packing-slips' );
|
77 |
-
$dir = trailingslashit( WP_LANG_DIR );
|
78 |
-
|
79 |
-
$textdomains = array( 'woocommerce-pdf-invoices-packing-slips' );
|
80 |
-
if ( $this->legacy_mode_enabled() === true ) {
|
81 |
-
$textdomains[] = 'wpo_wcpdf';
|
82 |
-
}
|
83 |
-
|
84 |
-
/**
|
85 |
-
* Frontend/global Locale. Looks in:
|
86 |
-
*
|
87 |
-
* - WP_LANG_DIR/woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
|
88 |
-
* - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
|
89 |
-
* - woocommerce-pdf-invoices-packing-slips-pro/languages/woocommerce-pdf-invoices-packing-slips-LOCALE.mo (which if not found falls back to:)
|
90 |
-
* - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
|
91 |
-
*/
|
92 |
-
foreach ( $textdomains as $textdomain ) {
|
93 |
-
unload_textdomain( $textdomain );
|
94 |
-
load_textdomain( $textdomain, $dir . 'woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' );
|
95 |
-
load_textdomain( $textdomain, $dir . 'plugins/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' );
|
96 |
-
load_plugin_textdomain( $textdomain, false, dirname( plugin_basename(__FILE__) ) . '/languages' );
|
97 |
-
}
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Maintain backwards compatibility with old translation files
|
102 |
-
* Uses old .mo file if it exists in any of the override locations
|
103 |
-
*/
|
104 |
-
public function textdomain_fallback( $mofile, $textdomain ) {
|
105 |
-
$plugin_domain = 'woocommerce-pdf-invoices-packing-slips';
|
106 |
-
$old_domain = 'wpo_wcpdf';
|
107 |
-
|
108 |
-
if ($textdomain == $old_domain) {
|
109 |
-
$textdomain = $plugin_domain;
|
110 |
-
$mofile = str_replace( "{$old_domain}-", "{$textdomain}-", $mofile ); // with trailing dash to target file and not folder
|
111 |
-
}
|
112 |
-
|
113 |
-
if ( $textdomain === $plugin_domain ) {
|
114 |
-
$old_mofile = str_replace( "{$textdomain}-", "{$old_domain}-", $mofile ); // with trailing dash to target file and not folder
|
115 |
-
if ( file_exists( $old_mofile ) ) {
|
116 |
-
// we have an old override - use it
|
117 |
-
return $old_mofile;
|
118 |
-
}
|
119 |
-
|
120 |
-
// prevent loading outdated language packs
|
121 |
-
$pofile = str_replace('.mo', '.po', $mofile);
|
122 |
-
if ( file_exists( $pofile ) ) {
|
123 |
-
// load po file
|
124 |
-
$podata = file_get_contents($pofile);
|
125 |
-
// set revision date threshold
|
126 |
-
$block_before = strtotime( '2017-05-15' );
|
127 |
-
// read revision date
|
128 |
-
preg_match('~PO-Revision-Date: (.*?)\\\n~s',$podata,$matches);
|
129 |
-
if (isset($matches[1])) {
|
130 |
-
$revision_date = $matches[1];
|
131 |
-
if ( $revision_timestamp = strtotime($revision_date) ) {
|
132 |
-
// check if revision is before threshold date
|
133 |
-
if ( $revision_timestamp < $block_before ) {
|
134 |
-
// try bundled
|
135 |
-
$bundled_file = $this->plugin_path() . '/languages/'. basename( $mofile );
|
136 |
-
if (file_exists($bundled_file)) {
|
137 |
-
return $bundled_file;
|
138 |
-
} else {
|
139 |
-
return '';
|
140 |
-
}
|
141 |
-
// delete po & mo file if possible
|
142 |
-
// @unlink($pofile);
|
143 |
-
// @unlink($mofile);
|
144 |
-
}
|
145 |
-
}
|
146 |
-
}
|
147 |
-
}
|
148 |
-
}
|
149 |
-
|
150 |
-
return $mofile;
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* Load the main plugin classes and functions
|
155 |
-
*/
|
156 |
-
public function includes() {
|
157 |
-
// WooCommerce compatibility classes
|
158 |
-
include_once( $this->plugin_path() . '/includes/compatibility/abstract-wc-data-compatibility.php' );
|
159 |
-
include_once( $this->plugin_path() . '/includes/compatibility/class-wc-date-compatibility.php' );
|
160 |
-
include_once( $this->plugin_path() . '/includes/compatibility/class-wc-core-compatibility.php' );
|
161 |
-
include_once( $this->plugin_path() . '/includes/compatibility/class-wc-order-compatibility.php' );
|
162 |
-
include_once( $this->plugin_path() . '/includes/compatibility/class-wc-product-compatibility.php' );
|
163 |
-
include_once( $this->plugin_path() . '/includes/compatibility/wc-datetime-functions-compatibility.php' );
|
164 |
-
|
165 |
-
// Third party compatibility
|
166 |
-
include_once( $this->plugin_path() . '/includes/compatibility/class-wcpdf-compatibility-third-party-plugins.php' );
|
167 |
-
|
168 |
-
// Plugin classes
|
169 |
-
include_once( $this->plugin_path() . '/includes/wcpdf-functions.php' );
|
170 |
-
$this->settings = include_once( $this->plugin_path() . '/includes/class-wcpdf-settings.php' );
|
171 |
-
$this->documents = include_once( $this->plugin_path() . '/includes/class-wcpdf-documents.php' );
|
172 |
-
$this->main = include_once( $this->plugin_path() . '/includes/class-wcpdf-main.php' );
|
173 |
-
include_once( $this->plugin_path() . '/includes/class-wcpdf-assets.php' );
|
174 |
-
include_once( $this->plugin_path() . '/includes/class-wcpdf-admin.php' );
|
175 |
-
include_once( $this->plugin_path() . '/includes/class-wcpdf-frontend.php' );
|
176 |
-
include_once( $this->plugin_path() . '/includes/class-wcpdf-install.php' );
|
177 |
-
|
178 |
-
// Backwards compatibility with self
|
179 |
-
include_once( $this->plugin_path() . '/includes/legacy/class-wcpdf-legacy.php' );
|
180 |
-
include_once( $this->plugin_path() . '/includes/legacy/class-wcpdf-legacy-deprecated-hooks.php' );
|
181 |
-
|
182 |
-
// PHP MB String fallback functions
|
183 |
-
include_once( $this->plugin_path() . '/includes/compatibility/mb-string-compatibility.php' );
|
184 |
-
}
|
185 |
-
|
186 |
-
|
187 |
-
/**
|
188 |
-
* Instantiate classes when woocommerce is activated
|
189 |
-
*/
|
190 |
-
public function load_classes() {
|
191 |
-
if ( $this->is_woocommerce_activated() === false ) {
|
192 |
-
add_action( 'admin_notices', array ( $this, 'need_woocommerce' ) );
|
193 |
-
return;
|
194 |
-
}
|
195 |
-
|
196 |
-
if ( version_compare( PHP_VERSION, '5.3', '<' ) ) {
|
197 |
-
add_action( 'admin_notices', array ( $this, 'required_php_version' ) );
|
198 |
-
return;
|
199 |
-
}
|
200 |
-
|
201 |
-
// all systems ready - GO!
|
202 |
-
$this->includes();
|
203 |
-
}
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Check if legacy mode is enabled
|
207 |
-
*/
|
208 |
-
public function legacy_mode_enabled() {
|
209 |
-
if (!isset($this->legacy_mode)) {
|
210 |
-
$debug_settings = get_option( 'wpo_wcpdf_settings_debug' );
|
211 |
-
$this->legacy_mode = isset($debug_settings['legacy_mode']);
|
212 |
-
}
|
213 |
-
return $this->legacy_mode;
|
214 |
-
}
|
215 |
-
|
216 |
-
|
217 |
-
/**
|
218 |
-
* Check if woocommerce is activated
|
219 |
-
*/
|
220 |
-
public function is_woocommerce_activated() {
|
221 |
-
$blog_plugins = get_option( 'active_plugins', array() );
|
222 |
-
$site_plugins = is_multisite() ? (array) maybe_unserialize( get_site_option('active_sitewide_plugins' ) ) : array();
|
223 |
-
|
224 |
-
if ( in_array( 'woocommerce/woocommerce.php', $blog_plugins ) || isset( $site_plugins['woocommerce/woocommerce.php'] ) ) {
|
225 |
-
return true;
|
226 |
-
} else {
|
227 |
-
return false;
|
228 |
-
}
|
229 |
-
}
|
230 |
-
|
231 |
-
/**
|
232 |
-
* WooCommerce not active notice.
|
233 |
-
*
|
234 |
-
* @return string Fallack notice.
|
235 |
-
*/
|
236 |
-
|
237 |
-
public function need_woocommerce() {
|
238 |
-
$error = sprintf( __( 'WooCommerce PDF Invoices & Packing Slips requires %sWooCommerce%s to be installed & activated!' , 'woocommerce-pdf-invoices-packing-slips' ), '<a href="http://wordpress.org/extend/plugins/woocommerce/">', '</a>' );
|
239 |
-
|
240 |
-
$message = '<div class="error"><p>' . $error . '</p></div>';
|
241 |
-
|
242 |
-
echo $message;
|
243 |
-
}
|
244 |
-
|
245 |
-
/**
|
246 |
-
* PHP version requirement notice
|
247 |
-
*/
|
248 |
-
|
249 |
-
public function required_php_version() {
|
250 |
-
$error = __( 'WooCommerce PDF Invoices & Packing Slips requires PHP 5.3 or higher (5.6 or higher recommended).', 'woocommerce-pdf-invoices-packing-slips' );
|
251 |
-
$how_to_update = __( 'How to update your PHP version', 'woocommerce-pdf-invoices-packing-slips' );
|
252 |
-
$message = sprintf('<div class="error"><p>%s</p><p><a href="%s">%s</a></p></div>', $error, 'http://docs.wpovernight.com/general/how-to-update-your-php-version/', $how_to_update);
|
253 |
-
|
254 |
-
echo $message;
|
255 |
-
}
|
256 |
-
|
257 |
-
/**
|
258 |
-
* Show plugin changes. Code adapted from W3 Total Cache.
|
259 |
-
*/
|
260 |
-
public function in_plugin_update_message( $args ) {
|
261 |
-
$transient_name = 'wpo_wcpdf_upgrade_notice_' . $args['Version'];
|
262 |
-
|
263 |
-
if ( false === ( $upgrade_notice = get_transient( $transient_name ) ) ) {
|
264 |
-
$response = wp_safe_remote_get( 'https://plugins.svn.wordpress.org/woocommerce-pdf-invoices-packing-slips/trunk/readme.txt' );
|
265 |
-
|
266 |
-
if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) {
|
267 |
-
$upgrade_notice = self::parse_update_notice( $response['body'], $args['new_version'] );
|
268 |
-
set_transient( $transient_name, $upgrade_notice, DAY_IN_SECONDS );
|
269 |
-
}
|
270 |
-
}
|
271 |
-
|
272 |
-
echo wp_kses_post( $upgrade_notice );
|
273 |
-
}
|
274 |
-
|
275 |
-
/**
|
276 |
-
* Parse update notice from readme file.
|
277 |
-
*
|
278 |
-
* @param string $content
|
279 |
-
* @param string $new_version
|
280 |
-
* @return string
|
281 |
-
*/
|
282 |
-
private function parse_update_notice( $content, $new_version ) {
|
283 |
-
// Output Upgrade Notice.
|
284 |
-
$matches = null;
|
285 |
-
$regexp = '~==\s*Upgrade Notice\s*==\s*=\s*(.*)\s*=(.*)(=\s*' . preg_quote( $new_version ) . '\s*=|$)~Uis';
|
286 |
-
$upgrade_notice = '';
|
287 |
-
|
288 |
-
|
289 |
-
if ( preg_match( $regexp, $content, $matches ) ) {
|
290 |
-
$notices = (array) preg_split( '~[\r\n]+~', trim( $matches[2] ) );
|
291 |
-
|
292 |
-
// Convert the full version strings to minor versions.
|
293 |
-
$notice_version_parts = explode( '.', trim( $matches[1] ) );
|
294 |
-
$current_version_parts = explode( '.', $this->version );
|
295 |
-
|
296 |
-
if ( 3 !== sizeof( $notice_version_parts ) ) {
|
297 |
-
return;
|
298 |
-
}
|
299 |
-
|
300 |
-
$notice_version = $notice_version_parts[0] . '.' . $notice_version_parts[1];
|
301 |
-
$current_version = $current_version_parts[0] . '.' . $current_version_parts[1];
|
302 |
-
|
303 |
-
// Check the latest stable version and ignore trunk.
|
304 |
-
if ( version_compare( $current_version, $notice_version, '<' ) ) {
|
305 |
-
|
306 |
-
$upgrade_notice .= '</p><p class="wpo_wcpdf_upgrade_notice">';
|
307 |
-
|
308 |
-
foreach ( $notices as $index => $line ) {
|
309 |
-
$upgrade_notice .= preg_replace( '~\[([^\]]*)\]\(([^\)]*)\)~', '<a href="${2}">${1}</a>', $line );
|
310 |
-
}
|
311 |
-
}
|
312 |
-
}
|
313 |
-
|
314 |
-
return wp_kses_post( $upgrade_notice );
|
315 |
-
}
|
316 |
-
|
317 |
-
/**
|
318 |
-
* Get the plugin url.
|
319 |
-
* @return string
|
320 |
-
*/
|
321 |
-
public function plugin_url() {
|
322 |
-
return untrailingslashit( plugins_url( '/', __FILE__ ) );
|
323 |
-
}
|
324 |
-
|
325 |
-
/**
|
326 |
-
* Get the plugin path.
|
327 |
-
* @return string
|
328 |
-
*/
|
329 |
-
public function plugin_path() {
|
330 |
-
return untrailingslashit( plugin_dir_path( __FILE__ ) );
|
331 |
-
}
|
332 |
-
|
333 |
-
} // class WPO_WCPDF
|
334 |
-
|
335 |
-
endif; // class_exists
|
336 |
-
|
337 |
-
/**
|
338 |
-
* Returns the main instance of WooCommerce PDF Invoices & Packing Slips to prevent the need to use globals.
|
339 |
-
*
|
340 |
-
* @since 1.6
|
341 |
-
* @return WPO_WCPDF
|
342 |
-
*/
|
343 |
-
function WPO_WCPDF() {
|
344 |
-
return WPO_WCPDF::instance();
|
345 |
-
}
|
346 |
-
|
347 |
-
WPO_WCPDF(); // load plugin
|
348 |
-
|
349 |
-
// legacy class for plugin detecting
|
350 |
-
if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
|
351 |
-
class WooCommerce_PDF_Invoices{
|
352 |
-
public static $version;
|
353 |
-
|
354 |
-
public function __construct() {
|
355 |
-
self::$version = WPO_WCPDF()->version;
|
356 |
-
}
|
357 |
-
}
|
358 |
-
new WooCommerce_PDF_Invoices();
|
359 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Plugin Name: WooCommerce PDF Invoices & Packing Slips
|
4 |
+
* Plugin URI: http://www.wpovernight.com
|
5 |
+
* Description: Create, print & email PDF invoices & packing slips for WooCommerce orders.
|
6 |
+
* Version: 2.2.14
|
7 |
+
* Author: Ewout Fernhout
|
8 |
+
* Author URI: http://www.wpovernight.com
|
9 |
+
* License: GPLv2 or later
|
10 |
+
* License URI: http://www.opensource.org/licenses/gpl-license.php
|
11 |
+
* Text Domain: woocommerce-pdf-invoices-packing-slips
|
12 |
+
* WC requires at least: 2.2.0
|
13 |
+
* WC tested up to: 3.6.0
|
14 |
+
*/
|
15 |
+
|
16 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
17 |
+
exit; // Exit if accessed directly
|
18 |
+
}
|
19 |
+
|
20 |
+
if ( !class_exists( 'WPO_WCPDF' ) ) :
|
21 |
+
|
22 |
+
class WPO_WCPDF {
|
23 |
+
|
24 |
+
public $version = '2.2.14';
|
25 |
+
public $plugin_basename;
|
26 |
+
public $legacy_mode;
|
27 |
+
|
28 |
+
protected static $_instance = null;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Main Plugin Instance
|
32 |
+
*
|
33 |
+
* Ensures only one instance of plugin is loaded or can be loaded.
|
34 |
+
*/
|
35 |
+
public static function instance() {
|
36 |
+
if ( is_null( self::$_instance ) ) {
|
37 |
+
self::$_instance = new self();
|
38 |
+
}
|
39 |
+
return self::$_instance;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Constructor
|
44 |
+
*/
|
45 |
+
public function __construct() {
|
46 |
+
$this->plugin_basename = plugin_basename(__FILE__);
|
47 |
+
|
48 |
+
$this->define( 'WPO_WCPDF_VERSION', $this->version );
|
49 |
+
|
50 |
+
// load the localisation & classes
|
51 |
+
add_action( 'plugins_loaded', array( $this, 'translations' ) );
|
52 |
+
add_filter( 'load_textdomain_mofile', array( $this, 'textdomain_fallback' ), 10, 2 );
|
53 |
+
add_action( 'plugins_loaded', array( $this, 'load_classes' ), 9 );
|
54 |
+
add_action( 'in_plugin_update_message-'.$this->plugin_basename, array( $this, 'in_plugin_update_message' ) );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Define constant if not already set
|
59 |
+
* @param string $name
|
60 |
+
* @param string|bool $value
|
61 |
+
*/
|
62 |
+
private function define( $name, $value ) {
|
63 |
+
if ( ! defined( $name ) ) {
|
64 |
+
define( $name, $value );
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Load the translation / textdomain files
|
71 |
+
*
|
72 |
+
* Note: the first-loaded translation file overrides any following ones if the same translation is present
|
73 |
+
*/
|
74 |
+
public function translations() {
|
75 |
+
$locale = function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale();
|
76 |
+
$locale = apply_filters( 'plugin_locale', $locale, 'woocommerce-pdf-invoices-packing-slips' );
|
77 |
+
$dir = trailingslashit( WP_LANG_DIR );
|
78 |
+
|
79 |
+
$textdomains = array( 'woocommerce-pdf-invoices-packing-slips' );
|
80 |
+
if ( $this->legacy_mode_enabled() === true ) {
|
81 |
+
$textdomains[] = 'wpo_wcpdf';
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Frontend/global Locale. Looks in:
|
86 |
+
*
|
87 |
+
* - WP_LANG_DIR/woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
|
88 |
+
* - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
|
89 |
+
* - woocommerce-pdf-invoices-packing-slips-pro/languages/woocommerce-pdf-invoices-packing-slips-LOCALE.mo (which if not found falls back to:)
|
90 |
+
* - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
|
91 |
+
*/
|
92 |
+
foreach ( $textdomains as $textdomain ) {
|
93 |
+
unload_textdomain( $textdomain );
|
94 |
+
load_textdomain( $textdomain, $dir . 'woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' );
|
95 |
+
load_textdomain( $textdomain, $dir . 'plugins/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' );
|
96 |
+
load_plugin_textdomain( $textdomain, false, dirname( plugin_basename(__FILE__) ) . '/languages' );
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Maintain backwards compatibility with old translation files
|
102 |
+
* Uses old .mo file if it exists in any of the override locations
|
103 |
+
*/
|
104 |
+
public function textdomain_fallback( $mofile, $textdomain ) {
|
105 |
+
$plugin_domain = 'woocommerce-pdf-invoices-packing-slips';
|
106 |
+
$old_domain = 'wpo_wcpdf';
|
107 |
+
|
108 |
+
if ($textdomain == $old_domain) {
|
109 |
+
$textdomain = $plugin_domain;
|
110 |
+
$mofile = str_replace( "{$old_domain}-", "{$textdomain}-", $mofile ); // with trailing dash to target file and not folder
|
111 |
+
}
|
112 |
+
|
113 |
+
if ( $textdomain === $plugin_domain ) {
|
114 |
+
$old_mofile = str_replace( "{$textdomain}-", "{$old_domain}-", $mofile ); // with trailing dash to target file and not folder
|
115 |
+
if ( file_exists( $old_mofile ) ) {
|
116 |
+
// we have an old override - use it
|
117 |
+
return $old_mofile;
|
118 |
+
}
|
119 |
+
|
120 |
+
// prevent loading outdated language packs
|
121 |
+
$pofile = str_replace('.mo', '.po', $mofile);
|
122 |
+
if ( file_exists( $pofile ) ) {
|
123 |
+
// load po file
|
124 |
+
$podata = file_get_contents($pofile);
|
125 |
+
// set revision date threshold
|
126 |
+
$block_before = strtotime( '2017-05-15' );
|
127 |
+
// read revision date
|
128 |
+
preg_match('~PO-Revision-Date: (.*?)\\\n~s',$podata,$matches);
|
129 |
+
if (isset($matches[1])) {
|
130 |
+
$revision_date = $matches[1];
|
131 |
+
if ( $revision_timestamp = strtotime($revision_date) ) {
|
132 |
+
// check if revision is before threshold date
|
133 |
+
if ( $revision_timestamp < $block_before ) {
|
134 |
+
// try bundled
|
135 |
+
$bundled_file = $this->plugin_path() . '/languages/'. basename( $mofile );
|
136 |
+
if (file_exists($bundled_file)) {
|
137 |
+
return $bundled_file;
|
138 |
+
} else {
|
139 |
+
return '';
|
140 |
+
}
|
141 |
+
// delete po & mo file if possible
|
142 |
+
// @unlink($pofile);
|
143 |
+
// @unlink($mofile);
|
144 |
+
}
|
145 |
+
}
|
146 |
+
}
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
return $mofile;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Load the main plugin classes and functions
|
155 |
+
*/
|
156 |
+
public function includes() {
|
157 |
+
// WooCommerce compatibility classes
|
158 |
+
include_once( $this->plugin_path() . '/includes/compatibility/abstract-wc-data-compatibility.php' );
|
159 |
+
include_once( $this->plugin_path() . '/includes/compatibility/class-wc-date-compatibility.php' );
|
160 |
+
include_once( $this->plugin_path() . '/includes/compatibility/class-wc-core-compatibility.php' );
|
161 |
+
include_once( $this->plugin_path() . '/includes/compatibility/class-wc-order-compatibility.php' );
|
162 |
+
include_once( $this->plugin_path() . '/includes/compatibility/class-wc-product-compatibility.php' );
|
163 |
+
include_once( $this->plugin_path() . '/includes/compatibility/wc-datetime-functions-compatibility.php' );
|
164 |
+
|
165 |
+
// Third party compatibility
|
166 |
+
include_once( $this->plugin_path() . '/includes/compatibility/class-wcpdf-compatibility-third-party-plugins.php' );
|
167 |
+
|
168 |
+
// Plugin classes
|
169 |
+
include_once( $this->plugin_path() . '/includes/wcpdf-functions.php' );
|
170 |
+
$this->settings = include_once( $this->plugin_path() . '/includes/class-wcpdf-settings.php' );
|
171 |
+
$this->documents = include_once( $this->plugin_path() . '/includes/class-wcpdf-documents.php' );
|
172 |
+
$this->main = include_once( $this->plugin_path() . '/includes/class-wcpdf-main.php' );
|
173 |
+
include_once( $this->plugin_path() . '/includes/class-wcpdf-assets.php' );
|
174 |
+
include_once( $this->plugin_path() . '/includes/class-wcpdf-admin.php' );
|
175 |
+
include_once( $this->plugin_path() . '/includes/class-wcpdf-frontend.php' );
|
176 |
+
include_once( $this->plugin_path() . '/includes/class-wcpdf-install.php' );
|
177 |
+
|
178 |
+
// Backwards compatibility with self
|
179 |
+
include_once( $this->plugin_path() . '/includes/legacy/class-wcpdf-legacy.php' );
|
180 |
+
include_once( $this->plugin_path() . '/includes/legacy/class-wcpdf-legacy-deprecated-hooks.php' );
|
181 |
+
|
182 |
+
// PHP MB String fallback functions
|
183 |
+
include_once( $this->plugin_path() . '/includes/compatibility/mb-string-compatibility.php' );
|
184 |
+
}
|
185 |
+
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Instantiate classes when woocommerce is activated
|
189 |
+
*/
|
190 |
+
public function load_classes() {
|
191 |
+
if ( $this->is_woocommerce_activated() === false ) {
|
192 |
+
add_action( 'admin_notices', array ( $this, 'need_woocommerce' ) );
|
193 |
+
return;
|
194 |
+
}
|
195 |
+
|
196 |
+
if ( version_compare( PHP_VERSION, '5.3', '<' ) ) {
|
197 |
+
add_action( 'admin_notices', array ( $this, 'required_php_version' ) );
|
198 |
+
return;
|
199 |
+
}
|
200 |
+
|
201 |
+
// all systems ready - GO!
|
202 |
+
$this->includes();
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Check if legacy mode is enabled
|
207 |
+
*/
|
208 |
+
public function legacy_mode_enabled() {
|
209 |
+
if (!isset($this->legacy_mode)) {
|
210 |
+
$debug_settings = get_option( 'wpo_wcpdf_settings_debug' );
|
211 |
+
$this->legacy_mode = isset($debug_settings['legacy_mode']);
|
212 |
+
}
|
213 |
+
return $this->legacy_mode;
|
214 |
+
}
|
215 |
+
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Check if woocommerce is activated
|
219 |
+
*/
|
220 |
+
public function is_woocommerce_activated() {
|
221 |
+
$blog_plugins = get_option( 'active_plugins', array() );
|
222 |
+
$site_plugins = is_multisite() ? (array) maybe_unserialize( get_site_option('active_sitewide_plugins' ) ) : array();
|
223 |
+
|
224 |
+
if ( in_array( 'woocommerce/woocommerce.php', $blog_plugins ) || isset( $site_plugins['woocommerce/woocommerce.php'] ) ) {
|
225 |
+
return true;
|
226 |
+
} else {
|
227 |
+
return false;
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* WooCommerce not active notice.
|
233 |
+
*
|
234 |
+
* @return string Fallack notice.
|
235 |
+
*/
|
236 |
+
|
237 |
+
public function need_woocommerce() {
|
238 |
+
$error = sprintf( __( 'WooCommerce PDF Invoices & Packing Slips requires %sWooCommerce%s to be installed & activated!' , 'woocommerce-pdf-invoices-packing-slips' ), '<a href="http://wordpress.org/extend/plugins/woocommerce/">', '</a>' );
|
239 |
+
|
240 |
+
$message = '<div class="error"><p>' . $error . '</p></div>';
|
241 |
+
|
242 |
+
echo $message;
|
243 |
+
}
|
244 |
+
|
245 |
+
/**
|
246 |
+
* PHP version requirement notice
|
247 |
+
*/
|
248 |
+
|
249 |
+
public function required_php_version() {
|
250 |
+
$error = __( 'WooCommerce PDF Invoices & Packing Slips requires PHP 5.3 or higher (5.6 or higher recommended).', 'woocommerce-pdf-invoices-packing-slips' );
|
251 |
+
$how_to_update = __( 'How to update your PHP version', 'woocommerce-pdf-invoices-packing-slips' );
|
252 |
+
$message = sprintf('<div class="error"><p>%s</p><p><a href="%s">%s</a></p></div>', $error, 'http://docs.wpovernight.com/general/how-to-update-your-php-version/', $how_to_update);
|
253 |
+
|
254 |
+
echo $message;
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Show plugin changes. Code adapted from W3 Total Cache.
|
259 |
+
*/
|
260 |
+
public function in_plugin_update_message( $args ) {
|
261 |
+
$transient_name = 'wpo_wcpdf_upgrade_notice_' . $args['Version'];
|
262 |
+
|
263 |
+
if ( false === ( $upgrade_notice = get_transient( $transient_name ) ) ) {
|
264 |
+
$response = wp_safe_remote_get( 'https://plugins.svn.wordpress.org/woocommerce-pdf-invoices-packing-slips/trunk/readme.txt' );
|
265 |
+
|
266 |
+
if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) {
|
267 |
+
$upgrade_notice = self::parse_update_notice( $response['body'], $args['new_version'] );
|
268 |
+
set_transient( $transient_name, $upgrade_notice, DAY_IN_SECONDS );
|
269 |
+
}
|
270 |
+
}
|
271 |
+
|
272 |
+
echo wp_kses_post( $upgrade_notice );
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Parse update notice from readme file.
|
277 |
+
*
|
278 |
+
* @param string $content
|
279 |
+
* @param string $new_version
|
280 |
+
* @return string
|
281 |
+
*/
|
282 |
+
private function parse_update_notice( $content, $new_version ) {
|
283 |
+
// Output Upgrade Notice.
|
284 |
+
$matches = null;
|
285 |
+
$regexp = '~==\s*Upgrade Notice\s*==\s*=\s*(.*)\s*=(.*)(=\s*' . preg_quote( $new_version ) . '\s*=|$)~Uis';
|
286 |
+
$upgrade_notice = '';
|
287 |
+
|
288 |
+
|
289 |
+
if ( preg_match( $regexp, $content, $matches ) ) {
|
290 |
+
$notices = (array) preg_split( '~[\r\n]+~', trim( $matches[2] ) );
|
291 |
+
|
292 |
+
// Convert the full version strings to minor versions.
|
293 |
+
$notice_version_parts = explode( '.', trim( $matches[1] ) );
|
294 |
+
$current_version_parts = explode( '.', $this->version );
|
295 |
+
|
296 |
+
if ( 3 !== sizeof( $notice_version_parts ) ) {
|
297 |
+
return;
|
298 |
+
}
|
299 |
+
|
300 |
+
$notice_version = $notice_version_parts[0] . '.' . $notice_version_parts[1];
|
301 |
+
$current_version = $current_version_parts[0] . '.' . $current_version_parts[1];
|
302 |
+
|
303 |
+
// Check the latest stable version and ignore trunk.
|
304 |
+
if ( version_compare( $current_version, $notice_version, '<' ) ) {
|
305 |
+
|
306 |
+
$upgrade_notice .= '</p><p class="wpo_wcpdf_upgrade_notice">';
|
307 |
+
|
308 |
+
foreach ( $notices as $index => $line ) {
|
309 |
+
$upgrade_notice .= preg_replace( '~\[([^\]]*)\]\(([^\)]*)\)~', '<a href="${2}">${1}</a>', $line );
|
310 |
+
}
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
return wp_kses_post( $upgrade_notice );
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Get the plugin url.
|
319 |
+
* @return string
|
320 |
+
*/
|
321 |
+
public function plugin_url() {
|
322 |
+
return untrailingslashit( plugins_url( '/', __FILE__ ) );
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Get the plugin path.
|
327 |
+
* @return string
|
328 |
+
*/
|
329 |
+
public function plugin_path() {
|
330 |
+
return untrailingslashit( plugin_dir_path( __FILE__ ) );
|
331 |
+
}
|
332 |
+
|
333 |
+
} // class WPO_WCPDF
|
334 |
+
|
335 |
+
endif; // class_exists
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Returns the main instance of WooCommerce PDF Invoices & Packing Slips to prevent the need to use globals.
|
339 |
+
*
|
340 |
+
* @since 1.6
|
341 |
+
* @return WPO_WCPDF
|
342 |
+
*/
|
343 |
+
function WPO_WCPDF() {
|
344 |
+
return WPO_WCPDF::instance();
|
345 |
+
}
|
346 |
+
|
347 |
+
WPO_WCPDF(); // load plugin
|
348 |
+
|
349 |
+
// legacy class for plugin detecting
|
350 |
+
if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
|
351 |
+
class WooCommerce_PDF_Invoices{
|
352 |
+
public static $version;
|
353 |
+
|
354 |
+
public function __construct() {
|
355 |
+
self::$version = WPO_WCPDF()->version;
|
356 |
+
}
|
357 |
+
}
|
358 |
+
new WooCommerce_PDF_Invoices();
|
359 |
+
}
|