WooCommerce PDF Invoices & Packing Slips - Version 2.0.10

Version Description

  • Fix: Set invoice number backend button
  • Fix: Thumbail paths
  • Tweak: Make dompdf options filterable
Download this release

Release Info

Developer pomegranate
Plugin Icon 128x128 WooCommerce PDF Invoices & Packing Slips
Version 2.0.10
Comparing to
See all releases

Code changes from version 2.0.9 to 2.0.10

assets/js/order-script.js CHANGED
@@ -1,42 +1,42 @@
1
- jQuery(document).ready(function($) {
2
- $("#doaction, #doaction2").click(function (event) {
3
- var actionselected = $(this).attr("id").substr(2);
4
- var action = $('select[name="' + actionselected + '"]').val();
5
- if ( $.inArray(action, wpo_wcpdf_ajax.bulk_actions) !== -1 ) {
6
- event.preventDefault();
7
- var template = action;
8
- var checked = [];
9
- $('tbody th.check-column input[type="checkbox"]:checked').each(
10
- function() {
11
- checked.push($(this).val());
12
- }
13
- );
14
-
15
- if (!checked.length) {
16
- alert('You have to select order(s) first!');
17
- return;
18
- }
19
-
20
- var order_ids=checked.join('x');
21
-
22
- if (wpo_wcpdf_ajax.ajaxurl.indexOf("?") != -1) {
23
- url = wpo_wcpdf_ajax.ajaxurl+'&action=generate_wpo_wcpdf&document_type='+template+'&order_ids='+order_ids+'&_wpnonce='+wpo_wcpdf_ajax.nonce;
24
- } else {
25
- url = wpo_wcpdf_ajax.ajaxurl+'?action=generate_wpo_wcpdf&document_type='+template+'&order_ids='+order_ids+'&_wpnonce='+wpo_wcpdf_ajax.nonce;
26
- }
27
-
28
- window.open(url,'_blank');
29
- }
30
- });
31
-
32
- $('#wpo_wcpdf-data-input-box').insertAfter('#woocommerce-order-data');
33
-
34
- // enable invoice number edit if user initiated
35
- $( ".wpo-wcpdf-edit-date-number" ).click(function() {
36
- $form = $(this).closest('.wcpdf-data-fields');
37
- $form.find(".read-only").hide();
38
- $form.find(".editable").show();
39
- $form.find(':input').prop('disabled', false);
40
- });
41
- });
42
-
1
+ jQuery(document).ready(function($) {
2
+ $("#doaction, #doaction2").click(function (event) {
3
+ var actionselected = $(this).attr("id").substr(2);
4
+ var action = $('select[name="' + actionselected + '"]').val();
5
+ if ( $.inArray(action, wpo_wcpdf_ajax.bulk_actions) !== -1 ) {
6
+ event.preventDefault();
7
+ var template = action;
8
+ var checked = [];
9
+ $('tbody th.check-column input[type="checkbox"]:checked').each(
10
+ function() {
11
+ checked.push($(this).val());
12
+ }
13
+ );
14
+
15
+ if (!checked.length) {
16
+ alert('You have to select order(s) first!');
17
+ return;
18
+ }
19
+
20
+ var order_ids=checked.join('x');
21
+
22
+ if (wpo_wcpdf_ajax.ajaxurl.indexOf("?") != -1) {
23
+ url = wpo_wcpdf_ajax.ajaxurl+'&action=generate_wpo_wcpdf&document_type='+template+'&order_ids='+order_ids+'&_wpnonce='+wpo_wcpdf_ajax.nonce;
24
+ } else {
25
+ url = wpo_wcpdf_ajax.ajaxurl+'?action=generate_wpo_wcpdf&document_type='+template+'&order_ids='+order_ids+'&_wpnonce='+wpo_wcpdf_ajax.nonce;
26
+ }
27
+
28
+ window.open(url,'_blank');
29
+ }
30
+ });
31
+
32
+ $('#wpo_wcpdf-data-input-box').insertAfter('#woocommerce-order-data');
33
+
34
+ // enable invoice number edit if user initiated
35
+ $( ".wpo-wcpdf-set-date-number, .wpo-wcpdf-edit-date-number" ).click(function() {
36
+ $form = $(this).closest('.wcpdf-data-fields');
37
+ $form.find(".read-only").hide();
38
+ $form.find(".editable").show();
39
+ $form.find(':input').prop('disabled', false);
40
+ });
41
+ });
42
+
changelog-archive.txt ADDED
@@ -0,0 +1,437 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ = 1.6.5 =
2
+ * Fix: Duplicate invoice numbers when bulk completing orders (WC3.0)
3
+ * Fix: Hidden Invoice date when order refunded
4
+
5
+ = 1.6.4 =
6
+ * Fix: My account invoice button visibility
7
+
8
+ = 1.6.3 =
9
+ * Fix: Empty date handling
10
+ * Fix: Shipping notes on refunds (reason for refund)
11
+
12
+ = 1.6.2 =
13
+ * Fix: TM Extra Product Options compatibility (in WC3.0)
14
+ * Fix: Tax display in WC3.0
15
+
16
+ = 1.6.1 =
17
+ * Fix: Error with totals in credit notes
18
+ * Fix: Always set invoice date when invoice is create (even display is disabled in the settings)
19
+
20
+ = 1.6.0.2 =
21
+ * Fix: Don't crash with PHP 5.2 or older (5.3 or higher required, 5.6 or higher recommended)
22
+
23
+ = 1.6.0 =
24
+ * WooCommerce 3.0 Compatible
25
+ * **Requires PHP version 5.3 or higher**
26
+ * Fix: Invoice number display in mobile view
27
+ * Fix: Update formatted invoice number in order meta when number is altered
28
+ * Fix: global plugin object loading in wrapped cron methods
29
+ * Tweak: Avoid PHP7 scan false positives in DomPDF
30
+
31
+ = 1.5.39 =
32
+ * Feature: new template action hooks `wpo_wcpdf_before_document` & `wpo_wcpdf_after_document`
33
+ * Tweak: In totals, emphasize order total rather than last item
34
+ * Fix: User deprecation notices
35
+ * Translations: Updated Slovenian
36
+
37
+ = 1.5.38 =
38
+ * Fix: Thumbnail path fallback
39
+ * Fix: Edge/IE hour & minute pattern
40
+ * Fix: Skip over non-order objects
41
+ * Tweak: Let shop manager view My Account links
42
+ * Dev: added `wpo_wcpdf_before_attachment_creation` action
43
+ * Translations: Updated POT, Swedish, Dutch & Norwegian
44
+
45
+ = 1.5.37 =
46
+ * Feature: Added support for third party invoice numbers
47
+ * Feature: Enable pre-invoice number click-to-edit
48
+ * Fix: Review link for custom admins
49
+ * Fix: PHP7 compatibility
50
+ * Fix: Invoice date hour/minute pattern
51
+ * Tweak: Multisite WooCommerce check optimization
52
+
53
+ = 1.5.36 =
54
+ * Translations: Fixed Romanian (incorrect "Factură Proforma" translation for "Invoice")
55
+
56
+ = 1.5.35 =
57
+ * Translations: Fixed "Includes %s" string for WC2.6+
58
+
59
+ = 1.5.34 =
60
+ * Fix: Document check that was introduced in 1.5.33 for disable free setting
61
+
62
+ = 1.5.33 =
63
+ * Tweak: Don't apply 'disable free' setting to packing slip attachment
64
+ * Translations: Updated Romanian
65
+
66
+ = 1.5.32 =
67
+ * Fix: Updated currency font with Indian Rupee symbol
68
+ * Translations: added Formal German (currently a copy of informal German)
69
+
70
+ = 1.5.31 =
71
+ * Feature: [invoice_day] or [order_day] in invoice number format
72
+ * Fix: Link to hide all ads when premium extensions active
73
+
74
+ = 1.5.30 =
75
+ * Feature: Enable currency font for extended currency support
76
+ * Fix: Font sync on plugin update
77
+
78
+ = 1.5.29 =
79
+ * Translations: Added Croation (Thanks Neven/Spine ICT!), updated French (Thanks Sabra!)
80
+ * Tweak: filter shop address before checking if it's empty
81
+ * Dev: added $order to `wpo_wcpdf_template_file` filter
82
+
83
+ = 1.5.28 =
84
+ * Tweak: the 'Next invoice number' is now stored separately in the database for faster and more reliable retrieval. Circumventing any caching, this should prevent duplicate invoice numbers.
85
+ * Fix: Bulk actions plugin conflicts
86
+ * Experimental: page numbers (use {{PAGE_NUM}} / {{PAGE_COUNT}} in your template)
87
+
88
+ = 1.5.27 =
89
+ * Feature: Use [invoice_year] and [invoice_month] placeholders in invoice number prefix/suffix
90
+ * Feature: WooCommerce Order Status & Actions Manager emails compatibility
91
+ * Feature: Add invoice number to WC REST API
92
+ * Fix: Allow positive 'discounts' (price corrections)
93
+ * Fix: Discounts rounding
94
+ * Translations: Updated Finnish & Portugese & POT
95
+
96
+ = 1.5.26 =
97
+ * Feature: Automatically list all emails registered in WooCommerce
98
+ * Feature: Reset invoice number yearly
99
+ * Feature: WooCommerce Chained Products compatibility
100
+ * Feature: WooCommerce Product Bundles visibility settings taken into account in invoice
101
+ * Fix: Disable PDF creation from trashed order_ids
102
+ * Tweak: Alert when no orders selected for bulk export (Props to Dartui!)
103
+ * Tweak: PDF invoice settings always under WooCommerce menu (also for premium users)
104
+ * Tweak: extra $item_id passed in row class filter
105
+ * Translations: Updated Slovenian, Spanish, Dutch & POT file
106
+
107
+ = 1.5.24 =
108
+ * Hotfix: Subscriptions renewal filter arguments
109
+
110
+ = 1.5.23 =
111
+ * Fix: WooCommerce Subscriptons 2.0 deprecation notice.
112
+ * Tweak: better qTranslate-X support
113
+ * Tweak: filter for user privileges check (wpo_wcpdf_check_privs)
114
+ * Translations: French translations fix
115
+
116
+ = 1.5.22 =
117
+ * Fix: Workaround for bug in WPML (which cleared all settings)
118
+ * Translation: fixed Polish translation for invoice
119
+
120
+ = 1.5.21 =
121
+ * Translations: Added Estionan (thanks Tanel!)
122
+ * Tweak: WC2.4 compatibility
123
+
124
+ = 1.5.20 =
125
+ * Feature: Option to 'never' display My Account invoice link
126
+ * Fix: Order total for refunds in WC2.4
127
+ * Fix: notice when no custom statuses selected for My Account display
128
+ * Tweak: Product bundles styles
129
+
130
+ = 1.5.19 =
131
+ * Fix: Invoice number search (broke other custom searches)
132
+
133
+ = 1.5.18 =
134
+ * Fix: wpo_wcpdf_item_row_class packing slip filter arguments
135
+
136
+ = 1.5.17 =
137
+ * Feature: WooCommerce Product Bundles compatibility styles
138
+ * Tweak: wpo_wcpdf_item_row_class as filter instead of action
139
+
140
+ = 1.5.16 =
141
+ * Feature: Search orders by invoice number (note: search on formatted invoice number only works for new orders)
142
+ * Feature: Formatted invoice number stored in order
143
+ * Tweak: Function parameters added to some of the filters
144
+ * Tweak: WooCommerce 2.4 compatibility
145
+ * Dev feature: action to add class to items table row (wpo_wcpdf_item_row_class)
146
+ * Translations: Swedish updated (thanks Conney!)
147
+ * Translations: Norwegian updated
148
+
149
+ = 1.5.15 =
150
+ * Fix: invoice number padding didn't work for values lower than 3
151
+ * Tweak: WPML compatibility filter
152
+ * Translations: Updated French (Thanks Nicolas!)
153
+
154
+ = 1.5.14 =
155
+ * Tweak: Invoice number & date edit fields moved to separate box on order edit page
156
+ * Translations: Updated POT & Dutch
157
+
158
+ = 1.5.13 =
159
+ * Fix: Better address comparison to determine when to display alternate address
160
+ * Tweak: Filter N/A addresses
161
+ * Tweak: Use WooCommerce function for 2.3 discounts
162
+ * Translations: Czech Updated (Thanks Ivo!)
163
+ * Translations: French (minor fixes)
164
+
165
+ = 1.5.12 =
166
+ * Translations: added Danish, Updated POT & Italian
167
+
168
+ = 1.5.11 =
169
+ * Fix: Product text attributes (now checks key too)
170
+ * Fix: Status page upload explanation typos
171
+
172
+ = 1.5.10 =
173
+ * Fix: Double check to make sure plugin doesn't attach to user emails
174
+
175
+ = 1.5.9 =
176
+ * Feature: Shorthand function to display product attributes: `$wpo_wcpdf->get_product_attribute( $attribute_name, $product )`
177
+
178
+ = 1.5.8 =
179
+ * Feature: disable invoice for free orders
180
+ * Feature: action to insert data before & after item meta
181
+ * Tweak: Added classes to sku & weight
182
+ * Tweak: Hide payment method from totals (already shown in template)
183
+ * Translations: Updated POT & Dutch
184
+
185
+ = 1.5.7 =
186
+ * Feature: Setting to show email address & phone number on invoice or packing slip (does not work on custom templates based on previous versions!)
187
+
188
+ = 1.5.6 =
189
+ * Feature: Setting to show shipping address on invoice (does not work on custom templates based on previous versions!)
190
+ * Feature: My Account invoice download setting
191
+ * Feature: several new template actions
192
+ * Tweak: WooCommerce Bookings compatibility
193
+ * Tweak: Gerenal stylesheet cleanup
194
+ * Fix: temp path check/error on settings page
195
+ * Fix: Document titles for credit notes and proforma (Pro)
196
+ * Fix: Discount including tax
197
+ * Fix: Special characters on item meta (requires WooCommerce 2.3.6)
198
+ * Translations: Missing text domain on several strings
199
+ * Translations: Updated POT & Dutch
200
+
201
+ = 1.5.5 =
202
+ * Fix: Check for incomplete line tax data (Subscriptions compatibility)
203
+ * Fix: More precise template path instructions
204
+ * Fix: duplicate stylesheet filter
205
+ * Fix: Always prefer original order's billing address for refunds (WooCommerce EU VAT Number compatibility)
206
+ * Translations: Updated German (MwSt. instead of formal Ust.)
207
+ * Translations: Updated Dutch
208
+
209
+ = 1.5.4 =
210
+ * Tweak: include plugin version in style/script includes
211
+ * Tweak: upload code cleanup
212
+ * Fix: Parent invoice number (for Credit Notes in professional extension)
213
+
214
+ = 1.5.3 =
215
+ * Feature: add original order date value to order date filter
216
+ * Feature: Work with line_tax_data when available
217
+ * Feature: pass item_id to items
218
+ * Tweak: later check for woocommerce active
219
+ * Fix: do not try to validate empty settings (Status page settings)
220
+ * Translations: Fixed Dutch typo
221
+
222
+ = 1.5.2 =
223
+ * Fix: fatal error when trying to activate with WooCommerce not installed yet.
224
+ * Tweak: indentation fix on the Simple template
225
+
226
+ = 1.5.1 =
227
+ * Fix: prevent errors when upgrading
228
+
229
+ = 1.5.0 =
230
+ * Feature: All temporary files are now stored centrally in the WP uploads folder.
231
+ * Feature: Debug settings in status panel (output errors & output to HTML)
232
+ * Feature: Compatibility filter for WooCommerce Subscriptions (prevents duplicate invoice numbers)
233
+ * Tweak: Pass order to totals filters
234
+ * Translations: Updated POT
235
+ * Translations: Updated Italian (Thanks Astrid!)
236
+ * Translations: Updated Dutch
237
+ * FAQ: instructions for placing a link on the thank you page
238
+
239
+ = 1.4.14 =
240
+ * Fix: fatal error when user registers at checkout (applies to credit notes only)
241
+ * Translations: Updated German (Thanks Dietmar!)
242
+ * Translations: Place your custom translations in wp-content/languages/woocommerce-pdf-invoices-packing-slips/wpo_wcpdf-LOCALE.mo to protect them from being overwritten by plugin updates.
243
+
244
+ = 1.4.13 =
245
+ * Feature: use separate file for all your template specific functions (template-functions.php)
246
+ * Translations: Added Slovenian (thanks gregy1403!)
247
+ * Translations: Updated Norwegian & Dutch.
248
+ * Translations: Added Japanese - needs custom font!
249
+ * FAQ: instructions on how to use custom fonts
250
+
251
+ = 1.4.12 =
252
+ * Fix: issues with post parent objects (WC2.1 and older)
253
+
254
+ = 1.4.11 =
255
+ * Small fix: bulk actions for specific i18n configurations
256
+ * Tweak: total row key used as class in Simple template
257
+
258
+ = 1.4.10 =
259
+ * Fix: Invoice not attaching
260
+ * Translations: Updated POT file
261
+ * Translations: Updated Dutch, Norwegian, Polish, Brazilian Portugese, Romanian, Russian, Slovak, Spanish & Ukrainian (Many thanks to all the translators!)
262
+ * Templates: added action hooks for easier customizations (`wpo_wcpdf_before_order_details`, `wpo_wcpdf_after_order_details`, `wpo_wcpdf_invoice_title` & `wpo_wcpdf_packing_slip_title`)
263
+
264
+ = 1.4.9 =
265
+ * Feature: Order number and date are now displayed by default in the Simple template (invoice number and date still optional)
266
+ * Feature: Display Customer/Order notes with a simple shorthand (see FAQ)
267
+ * Translations: Added Brazilian Portugese (thanks Victor Debone!)
268
+ * Tweak: Fail more gracefully when there are errors during PDF generation
269
+ * Tweak: added template type class to template output body
270
+ * Tweak: cleaned up Simple template style.css
271
+
272
+ = 1.4.8 =
273
+ * Translations: Added Finnish (Thanks Sami Mäkelä/Contrast.fi!)
274
+
275
+ = 1.4.7 =
276
+ * Fix: check if image file exists locally, fallback to url if not (CDN compatibility)
277
+ * Fix: make deleting invoice date possible
278
+ * Fix: correct tmp folder check on status page
279
+ * Translations: updated po/mo files
280
+ * Tweak: changed settings capability requirement to `manage_woocommerce` (was: `manage_options`)
281
+ * Tweak: better email attachment function
282
+ * Tweak: prevent footer overlap (Simple template)
283
+ * Tweak: fallback if `glob()` is not allowed on the server
284
+ * Tweak: better custom template instructions (reflects path to actual (child-)theme)
285
+
286
+ = 1.4.6 =
287
+ * HOTFIX: WooCommerce 2.2 compatibility fix
288
+ * Filter for PDF temp folder (wpo_wcpdf_tmp_path)
289
+
290
+ = 1.4.5 =
291
+ * Fix: Double date conversion for order date on invoice number filter (to avoid i18n date issues)
292
+ * Fix: Template selector reset after update
293
+ * Translations: added Norwegian (Thanks Aleksander!)
294
+
295
+ = 1.4.4 =
296
+ * Feature: Editable invoice date per order/invoice.
297
+ * Feature: HTML is now allowed in footer and other settings fields.
298
+ * Translations: Updated German (Thanks Nadine!)
299
+ * Fix: template paths are now saved relative to the site base path (ABSPATH) to prevent errors when moving to another server
300
+ * Tweak: Changed bulk action hook for better theme compatibility
301
+ * Tweak: Newlines in custom checkout fields
302
+
303
+ = 1.4.3 =
304
+ * Feature: Added function to call custom fields more easily (see FAQ)
305
+ * Feature: Change the my account button text via a filter (wpo_wcpdf_myaccount_button_text)
306
+ * Translations: Added Danish (Thanks Mads!)
307
+ * Tweak: only load PDF engine if it's not already loaded by another plugin
308
+
309
+ = 1.4.2 =
310
+ * Fix: Don't create invoice number when exporting packing slips
311
+ * Fix: Division by zero for 0 quantity items
312
+
313
+ = 1.4.1 =
314
+ * Translations: Added Polish (Thanks Mike!)
315
+ * Fix: Invoice number formatting notices in debug mode
316
+
317
+ = 1.4.0 =
318
+ * Feature: Invoice numbers can now be given a prefix, suffix or padding on the settings page!
319
+ * Filter: `wpo_wcpdf_email_allowed_statuses` to attach pdf to custom order status emails
320
+ * Tweak: Sequential Order Numbers Pro compatibility
321
+ * Tweak: Filenames are now automatically sanitized to prevent issues with illegal characters
322
+
323
+ = 1.3.2 =
324
+ * Fix: error on wpo_wcpdf_email_attachment filter when $pdf_path not set
325
+
326
+ = 1.3.1 =
327
+ * Fix: invoice number was cleared when Order Actions were being used when an invoice number was not set
328
+ * Translations: Updated Slovak (Thanks Jozef!)
329
+ * Translations: Added Czech (Thanks CubiQ!)
330
+
331
+ = 1.3.0 =
332
+ * Feature: Added 'status' panel for better problem diagnosis
333
+ * Tweak: split create & get invoice number calls to prevent slow database calls from causing number skipping
334
+ * Translations: Added Romanian (Thanks Leonardo!)
335
+ * Translations: Added Slovak (Thanks Oleg!)
336
+
337
+ = 1.2.13 =
338
+ * Feature: added filter for custom email attachment condition (wpo_wcpdf_custom_email_condition)
339
+ * Fix: warning for tax implode
340
+
341
+ = 1.2.12 =
342
+ * Fix: hyperlink underline (was more like a strikethrough)
343
+
344
+ = 1.2.11 =
345
+ * Translations: Fixed German spelling error
346
+ * Translations: Updated Swedish (Thanks Fredrik!)
347
+
348
+ = 1.2.10 =
349
+ * Translations: Added Swedish (Thanks Jonathan!)
350
+ * Fix: Line-height issue (on some systems, the space between lines was very high)
351
+
352
+ = 1.2.9 =
353
+ * Fix: bug where 'standard' tax class would not display in some cases
354
+ * Fix: bug that caused the totals to jump for some font sizes
355
+ * Fix: WC2.1 deprecated totals function
356
+ * Fix: If multiple taxes were set up with the same name, only one would display (Simple template was not affected)
357
+
358
+ = 1.2.8 =
359
+ * Template: Body line-height defined to prevent character jumping with italic texts
360
+ * Fix: Open Sans now included in plugin package (fixes font issues for servers with allow_url_fopen disabled)
361
+
362
+ = 1.2.7 =
363
+ * Translations: POT, DE & NL updated
364
+ * Fix: Removed stray span tag in totals table
365
+
366
+ = 1.2.6 =
367
+ * Translations: Spanish update (thanks prepu!)
368
+ * Fix: More advanced checks to determine if a customer can download the invoice (including a status filter)
369
+
370
+ = 1.2.5 =
371
+ * Feature: Optional Invoice Number column for the orders listing
372
+ * Feature: Better support for international characters
373
+ * Translations: Added Russian & Ukrainian translation (thanks Oleg!)
374
+ * Translations: Updated Spanish (Thanks Manuel!) and Dutch translations & POT file
375
+ * Tweak: Memory limit notice
376
+ * Tweak: Filename name now includes invoice number (when configured in the settings)
377
+
378
+ = 1.2.4 =
379
+ * Feature: Set which type of emails you want to attach the invoice to
380
+
381
+ = 1.2.3 =
382
+ * Feature: Manually edit invoice number on the edit order screen
383
+ * Feature: Set the first (/next) invoice number on the settings screen
384
+ * Fix: Bug where invoice number would be generated twice due to slow database calls
385
+ * Fix: php strict warnings
386
+
387
+ = 1.2.2 =
388
+ * Feature: Simple template now uses Open Sans to include more international special characters
389
+ * Feature: Implemented filters for paper size & orientation ([read here](http://wordpress.org/support/topic/select-a5-paper-size-for-packing-slips?replies=5#post-5211129))
390
+ * Tweak: PDF engine updated (dompdf 0.6.0)
391
+ * Tweak: Download PDF link on the my account page is now only shown when an invoice is already created by the admin or automatically, to prevent unwanted invoice created (creating problems with european laws).
392
+
393
+ = 1.2.1 =
394
+ * Fix: shipping & fees functions didn't output correctly with the tax set to 'incl'
395
+
396
+ = 1.2.0 =
397
+ * Feature: Sequential invoice numbers (set upon invoice creation).
398
+ * Feature: Invoice date (set upon invoice creation).
399
+
400
+ = 1.1.6 =
401
+ * Feature: Hungarian translations added - thanks Joseph!
402
+ * Tweak: Better debug code.
403
+ * Tweak: Error reporting when templates not found.
404
+ * Fix: tax rate calculation for free items.
405
+
406
+ = 1.1.5 =
407
+ * Feature: German translations added - thanks Christian!
408
+ * Fix: dompdf 0.6.0 proved to be less stable, so switching back to beta3 for now.
409
+
410
+ = 1.1.4 =
411
+ * Fix: Template paths on windows servers were not properly saved (stripslashes), resulting in an empty output.
412
+
413
+ = 1.1.3 =
414
+ * Feature: PDF engine (dompdf) updated to 0.6.0 for better stability and utf-8 support.
415
+ * Tweak: Local server path is used for header image for better compatibility with server settings.
416
+ * Fix: several small bugs.
417
+
418
+ = 1.1.2 =
419
+ * Feature: Totals can now be called with simpler template functions
420
+ * Feature: Italian translations - thanks max66max!
421
+ * Tweak: improved memory performance
422
+
423
+ = 1.1.1 =
424
+ * Feature: French translations - thanks Guillaume!
425
+
426
+ = 1.1.0 =
427
+ * Feature: Fees can now also be called ex. VAT
428
+ * Feature: Invoices can now be downloaded from the My Account page
429
+ * Feature: Spanish translation & POT file included
430
+ * Fix: ternary statements that caused an error
431
+
432
+ = 1.0.1 =
433
+ * Tweak: Packing slip now displays shipping address instead of billing address
434
+ * Tweak: Variation data is now displayed by default
435
+
436
+ = 1.0.0 =
437
+ * First release
includes/class-wcpdf-admin.php CHANGED
@@ -1,351 +1,351 @@
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\\Admin' ) ) :
13
-
14
- class Admin {
15
-
16
- function __construct() {
17
- add_action( 'woocommerce_admin_order_actions_end', array( $this, 'add_listing_actions' ) );
18
- add_filter( 'manage_edit-shop_order_columns', array( $this, 'add_invoice_number_column' ), 999 );
19
- add_action( 'manage_shop_order_posts_custom_column', array( $this, 'invoice_number_column_data' ), 2 );
20
- add_action( 'add_meta_boxes_shop_order', array( $this, 'add_meta_boxes' ) );
21
- add_action( 'admin_footer', array( $this, 'bulk_actions' ) );
22
- add_filter( 'woocommerce_shop_order_search_fields', array( $this, 'search_fields' ) );
23
-
24
- add_action( 'save_post', array( $this,'save_invoice_number_date' ) );
25
-
26
- add_action( 'admin_notices', array( $this, 'review_plugin_notice' ) );
27
- // add_action( 'wpo_wcpdf_after_pdf', array( $this,'update_pdf_counter' ), 10, 2 );
28
- }
29
-
30
- // display review admin notice after 100 pdf downloads
31
- public function review_plugin_notice() {
32
- if ( $this->is_order_page() === false && !( isset( $_GET['page'] ) && $_GET['page'] == 'wpo_wcpdf_options_page' ) ) {
33
- return;
34
- }
35
-
36
- if ( get_option( 'wpo_wcpdf_review_notice_dismissed' ) !== false ) {
37
- return;
38
- } else {
39
- if ( isset( $_GET['wpo_wcpdf_dismis_review'] ) ) {
40
- update_option( 'wpo_wcpdf_review_notice_dismissed', true );
41
- return;
42
- }
43
-
44
- $invoice_count = $this->get_invoice_count();
45
- if ( $invoice_count > 100 ) {
46
- $rounded_count = (int) substr( (string) $invoice_count, 0, 1 ) * pow( 10, strlen( (string) $invoice_count ) - 1);
47
- ?>
48
- <div class="notice notice-info is-dismissible wpo-wcpdf-review-notice">
49
- <h3><?php printf( __( 'Wow, you have created more than %d invoices with our plugin!', 'woocommerce-pdf-invoices-packing-slips' ), $rounded_count ); ?></h3>
50
- <p><?php _e( 'It would mean a lot to us if you would quickly give our plugin a 5-star rating. Help us spread the word and boost our motivation!', 'woocommerce-pdf-invoices-packing-slips' ); ?></p>
51
- <ul>
52
- <li><a href="https://wordpress.org/support/plugin/woocommerce-pdf-invoices-packing-slips/reviews/?rate=5#new-post" class="button"><?php _e( 'Yes you deserve it!', 'woocommerce-pdf-invoices-packing-slips' ); ?></span></a></li>
53
- <li><a href="<?php echo esc_url( add_query_arg( 'wpo_wcpdf_dismis_review', true ) ); ?>" class="wpo-wcpdf-dismiss"><?php _e( 'Already did!', 'woocommerce-pdf-invoices-packing-slips' ); ?></a></li>
54
- <li><a href="mailto:support@wpovernight.com?Subject=Here%20is%20how%20I%20think%20you%20can%20do%20better"><?php _e( 'Actually, I have a complaint...', 'woocommerce-pdf-invoices-packing-slips' ); ?></a></li>
55
- </ul>
56
- </div>
57
- <!-- Hide extensions ad if this is shown -->
58
- <style>.wcpdf-extensions-ad { display: none; }</style>
59
- <?php
60
- }
61
- }
62
- }
63
-
64
- public function get_invoice_count() {
65
- global $wpdb;
66
- $invoice_count = $wpdb->get_var( $wpdb->prepare( "SELECT count(*) FROM {$wpdb->postmeta} WHERE meta_key = %s", '_wcpdf_invoice_number' ) );
67
- return (int) $invoice_count;
68
- }
69
-
70
- public function update_pdf_counter( $document_type, $document ) {
71
- if ( in_array( $document_type, array('invoice','packing-slip') ) ) {
72
- $pdf_count = (int) get_option( 'wpo_wcpdf_count_'.$document_type, 0 );
73
- update_option( 'wpo_wcpdf_count_'.$document_type, $pdf_count + 1 );
74
- }
75
- }
76
-
77
- /**
78
- * Add PDF actions to the orders listing
79
- */
80
- public function add_listing_actions( $order ) {
81
- // do not show buttons for trashed orders
82
- if ( $order->get_status() == 'trash' ) {
83
- return;
84
- }
85
-
86
- $listing_actions = array();
87
- $documents = WPO_WCPDF()->documents->get_documents();
88
- foreach ($documents as $document) {
89
- $listing_actions[$document->get_type()] = array(
90
- 'url' => wp_nonce_url( admin_url( "admin-ajax.php?action=generate_wpo_wcpdf&document_type={$document->get_type()}&order_ids=" . WCX_Order::get_id( $order ) ), 'generate_wpo_wcpdf' ),
91
- 'img' => !empty($document->icon) ? $document->icon : WPO_WCPDF()->plugin_url() . "/assets/images/generic_document.png",
92
- 'alt' => "PDF " . $document->get_title(),
93
- );
94
- }
95
-
96
- $listing_actions = apply_filters( 'wpo_wcpdf_listing_actions', $listing_actions, $order );
97
-
98
- foreach ($listing_actions as $action => $data) {
99
- ?>
100
- <a href="<?php echo $data['url']; ?>" class="button tips wpo_wcpdf <?php echo $action; ?>" target="_blank" alt="<?php echo $data['alt']; ?>" data-tip="<?php echo $data['alt']; ?>">
101
- <img src="<?php echo $data['img']; ?>" alt="<?php echo $data['alt']; ?>" width="16">
102
- </a>
103
- <?php
104
- }
105
- }
106
-
107
- /**
108
- * Create additional Shop Order column for Invoice Numbers
109
- * @param array $columns shop order columns
110
- */
111
- public function add_invoice_number_column( $columns ) {
112
- // get invoice settings
113
- $invoice = wcpdf_get_invoice( null );
114
- $invoice_settings = $invoice->get_settings();
115
- if ( !isset( $invoice_settings['invoice_number_column'] ) ) {
116
- return $columns;
117
- }
118
-
119
- // put the column after the Status column
120
- $new_columns = array_slice($columns, 0, 2, true) +
121
- array( 'pdf_invoice_number' => __( 'Invoice Number', 'woocommerce-pdf-invoices-packing-slips' ) ) +
122
- array_slice($columns, 2, count($columns) - 1, true) ;
123
- return $new_columns;
124
- }
125
-
126
- /**
127
- * Display Invoice Number in Shop Order column (if available)
128
- * @param string $column column slug
129
- */
130
- public function invoice_number_column_data( $column ) {
131
- global $post, $the_order;
132
-
133
- if ( $column == 'pdf_invoice_number' ) {
134
- if ( empty( $the_order ) || WCX_Order::get_id( $the_order ) != $post->ID ) {
135
- $order = WCX::get_order( $post->ID );
136
- if ( $invoice = wcpdf_get_invoice( $order ) ) {
137
- echo $invoice->get_number();
138
- }
139
- do_action( 'wcpdf_invoice_number_column_end', $order );
140
- } else {
141
- if ( $invoice = wcpdf_get_invoice( $the_order ) ) {
142
- echo $invoice->get_number();
143
- }
144
- do_action( 'wcpdf_invoice_number_column_end', $the_order );
145
- }
146
- }
147
- }
148
-
149
- /**
150
- * Add the meta box on the single order page
151
- */
152
- public function add_meta_boxes() {
153
- // create PDF buttons
154
- add_meta_box(
155
- 'wpo_wcpdf-box',
156
- __( 'Create PDF', 'woocommerce-pdf-invoices-packing-slips' ),
157
- array( $this, 'sidebar_box_content' ),
158
- 'shop_order',
159
- 'side',
160
- 'default'
161
- );
162
-
163
- // Invoice number & date
164
- add_meta_box(
165
- 'wpo_wcpdf-data-input-box',
166
- __( 'PDF Invoice data', 'woocommerce-pdf-invoices-packing-slips' ),
167
- array( $this, 'data_input_box_content' ),
168
- 'shop_order',
169
- 'normal',
170
- 'default'
171
- );
172
- }
173
-
174
- /**
175
- * Create the meta box content on the single order page
176
- */
177
- public function sidebar_box_content( $post ) {
178
- global $post_id;
179
-
180
- $meta_box_actions = array();
181
- $documents = WPO_WCPDF()->documents->get_documents();
182
- foreach ($documents as $document) {
183
- $meta_box_actions[$document->get_type()] = array(
184
- 'url' => wp_nonce_url( admin_url( "admin-ajax.php?action=generate_wpo_wcpdf&document_type={$document->get_type()}&order_ids=" . $post_id ), 'generate_wpo_wcpdf' ),
185
- 'alt' => esc_attr( "PDF " . $document->get_title() ),
186
- 'title' => "PDF " . $document->get_title(),
187
- );
188
- }
189
-
190
- $meta_box_actions = apply_filters( 'wpo_wcpdf_meta_box_actions', $meta_box_actions, $post_id );
191
-
192
- ?>
193
- <ul class="wpo_wcpdf-actions">
194
- <?php
195
- foreach ($meta_box_actions as $document_type => $data) {
196
- printf('<li><a href="%1$s" class="button" target="_blank" alt="%2$s">%3$s</a></li>', $data['url'], $data['alt'],$data['title']);
197
- }
198
- ?>
199
- </ul>
200
- <?php
201
- }
202
-
203
- /**
204
- * Add metabox for invoice number & date
205
- */
206
- public function data_input_box_content ( $post ) {
207
- $order = WCX::get_order( $post->ID );
208
-
209
- do_action( 'wpo_wcpdf_meta_box_start', $post->ID );
210
-
211
- if ( $invoice = wcpdf_get_invoice( $order ) ) {
212
- $invoice_number = $invoice->get_number();
213
- $invoice_date = $invoice->get_date();
214
- ?>
215
- <div class="wcpdf-data-fields">
216
- <h4><?php _e( 'Invoice', 'woocommerce-pdf-invoices-packing-slips' ) ?><?php if ($invoice->exists()) : ?><span id="" class="wpo-wcpdf-edit-date-number dashicons dashicons-edit"></span><?php endif; ?></h4>
217
-
218
- <!-- Read only -->
219
- <div class="read-only">
220
- <?php if ($invoice->exists()) : ?>
221
- <div class="invoice-number">
222
- <p class="form-field _wcpdf_invoice_number_field ">
223
- <p>
224
- <span><strong><?php _e( 'Invoice Number', 'woocommerce-pdf-invoices-packing-slips' ); ?>:</strong></span>
225
- <span><?php if (!empty($invoice_number)) echo $invoice_number->get_formatted(); ?></span>
226
- </p>
227
- </p>
228
- </div>
229
-
230
- <div class="invoice-date">
231
- <p class="form-field form-field-wide">
232
- <p>
233
- <span><strong><?php _e( 'Invoice Date:', 'woocommerce-pdf-invoices-packing-slips' ); ?></strong></span>
234
- <span><?php if (!empty($invoice_date)) echo $invoice_date->date_i18n( wc_date_format().' @ '.wc_time_format() ); ?></span>
235
- </p>
236
- </p>
237
- </div>
238
- <?php else : ?>
239
- <span id="set-invoice-date-number" class="button"><?php _e( 'Set invoice number & date', 'woocommerce-pdf-invoices-packing-slips' ) ?></span>
240
- <?php endif; ?>
241
- </div>
242
-
243
- <!-- Editable -->
244
- <div class="editable">
245
- <p class="form-field _wcpdf_invoice_number_field ">
246
- <label for="_wcpdf_invoice_number"><?php _e( 'Invoice Number (unformatted!)', 'woocommerce-pdf-invoices-packing-slips' ); ?>:</label>
247
- <?php if ( $invoice->exists() && !empty($invoice_number) ) : ?>
248
- <input type="text" class="short" style="" name="_wcpdf_invoice_number" id="_wcpdf_invoice_number" value="<?php echo $invoice_number->get_plain(); ?>">
249
- <?php else : ?>
250
- <input type="text" class="short" style="" name="_wcpdf_invoice_number" id="_wcpdf_invoice_number" value="" disabled="disabled" >
251
- <?php endif; ?>
252
- </p>
253
- <p class="form-field form-field-wide">
254
- <label for="wcpdf_invoice_date"><?php _e( 'Invoice Date:', 'woocommerce-pdf-invoices-packing-slips' ); ?></label>
255
- <?php if ( $invoice->exists() && !empty($invoice_date) ) : ?>
256
- <input type="text" class="date-picker-field" name="wcpdf_invoice_date" id="wcpdf_invoice_date" maxlength="10" value="<?php echo $invoice_date->date_i18n( 'Y-m-d' ); ?>" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" />@<input type="number" class="hour" placeholder="<?php _e( 'h', 'woocommerce' ) ?>" name="wcpdf_invoice_date_hour" id="wcpdf_invoice_date_hour" min="0" max="23" size="2" value="<?php echo $invoice_date->date_i18n( 'H' ) ?>" pattern="([01]?[0-9]{1}|2[0-3]{1})" />:<input type="number" class="minute" placeholder="<?php _e( 'm', 'woocommerce' ) ?>" name="wcpdf_invoice_date_minute" id="wcpdf_invoice_date_minute" min="0" max="59" size="2" value="<?php echo $invoice_date->date_i18n( 'i' ); ?>" pattern="[0-5]{1}[0-9]{1}" />
257
- <?php else : ?>
258
- <input type="text" class="date-picker-field" name="wcpdf_invoice_date" id="wcpdf_invoice_date" maxlength="10" disabled="disabled" value="" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" />@<input type="number" class="hour" disabled="disabled" placeholder="<?php _e( 'h', 'woocommerce' ) ?>" name="wcpdf_invoice_date_hour" id="wcpdf_invoice_date_hour" min="0" max="23" size="2" value="" pattern="([01]?[0-9]{1}|2[0-3]{1})" />:<input type="number" class="minute" placeholder="<?php _e( 'm', 'woocommerce' ) ?>" name="wcpdf_invoice_date_minute" id="wcpdf_invoice_date_minute" min="0" max="59" size="2" value="" pattern="[0-5]{1}[0-9]{1}" disabled="disabled" />
259
- <?php endif; ?>
260
- </p>
261
- </div>
262
- </div>
263
- <?php
264
- }
265
-
266
- do_action( 'wpo_wcpdf_meta_box_end', $post->ID );
267
- }
268
-
269
- /**
270
- * Add actions to menu
271
- */
272
- public function bulk_actions() {
273
- if ( $this->is_order_page() ) {
274
- $bulk_actions = array();
275
- $documents = WPO_WCPDF()->documents->get_documents();
276
- foreach ($documents as $document) {
277
- $bulk_actions[$document->get_type()] = "PDF " . $document->get_title();
278
- }
279
-
280
- $bulk_actions = apply_filters( 'wpo_wcpdf_bulk_actions', $bulk_actions );
281
-
282
- ?>
283
- <script type="text/javascript">
284
- jQuery(document).ready(function() {
285
- <?php foreach ($bulk_actions as $action => $title) { ?>
286
- jQuery('<option>').val('<?php echo $action; ?>').html('<?php echo esc_attr( $title ); ?>').appendTo("select[name='action'], select[name='action2']");
287
- <?php } ?>
288
- });
289
- </script>
290
- <?php
291
- }
292
- }
293
-
294
- /**
295
- * Save invoice number
296
- */
297
- public function save_invoice_number_date($post_id) {
298
- $post_type = get_post_type( $post_id );
299
- if( $post_type == 'shop_order' ) {
300
- // bail if this is not an actual 'Save order' action
301
- if (!isset($_POST['action']) || $_POST['action'] != 'editpost') {
302
- return;
303
- }
304
-
305
- $order = WCX::get_order( $post_id );
306
- if ( $invoice = wcpdf_get_invoice( $order ) ) {
307
- if ( isset( $_POST['wcpdf_invoice_date'] ) ) {
308
- $date = $_POST['wcpdf_invoice_date'];
309
- $hour = !empty( $_POST['wcpdf_invoice_date_hour'] ) ? $_POST['wcpdf_invoice_date_hour'] : '00';
310
- $minute = !empty( $_POST['wcpdf_invoice_date_minute'] ) ? $_POST['wcpdf_invoice_date_minute'] : '00';
311
- $invoice_date = "{$date} {$hour}:{$minute}:00";
312
- $invoice->set_date( $invoice_date );
313
- } elseif ( empty( $_POST['wcpdf_invoice_date'] ) && !empty( $_POST['_wcpdf_invoice_number'] ) ) {
314
- $invoice->set_date( current_time( 'timestamp', true ) );
315
- }
316
-
317
- if ( isset( $_POST['_wcpdf_invoice_number'] ) ) {
318
- $invoice->set_number( $_POST['_wcpdf_invoice_number'] );
319
- }
320
-
321
- $invoice->save();
322
- }
323
- }
324
- }
325
-
326
- /**
327
- * Add invoice number to order search scope
328
- */
329
- public function search_fields ( $custom_fields ) {
330
- $custom_fields[] = '_wcpdf_invoice_number';
331
- $custom_fields[] = '_wcpdf_formatted_invoice_number';
332
- return $custom_fields;
333
- }
334
-
335
-
336
- /**
337
- * Check if this is a shop_order page (edit or list)
338
- */
339
- public function is_order_page() {
340
- global $post_type;
341
- if( $post_type == 'shop_order' ) {
342
- return true;
343
- } else {
344
- return false;
345
- }
346
- }
347
- }
348
-
349
- endif; // class_exists
350
-
351
  return new Admin();
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\\Admin' ) ) :
13
+
14
+ class Admin {
15
+
16
+ function __construct() {
17
+ add_action( 'woocommerce_admin_order_actions_end', array( $this, 'add_listing_actions' ) );
18
+ add_filter( 'manage_edit-shop_order_columns', array( $this, 'add_invoice_number_column' ), 999 );
19
+ add_action( 'manage_shop_order_posts_custom_column', array( $this, 'invoice_number_column_data' ), 2 );
20
+ add_action( 'add_meta_boxes_shop_order', array( $this, 'add_meta_boxes' ) );
21
+ add_action( 'admin_footer', array( $this, 'bulk_actions' ) );
22
+ add_filter( 'woocommerce_shop_order_search_fields', array( $this, 'search_fields' ) );
23
+
24
+ add_action( 'save_post', array( $this,'save_invoice_number_date' ) );
25
+
26
+ add_action( 'admin_notices', array( $this, 'review_plugin_notice' ) );
27
+ // add_action( 'wpo_wcpdf_after_pdf', array( $this,'update_pdf_counter' ), 10, 2 );
28
+ }
29
+
30
+ // display review admin notice after 100 pdf downloads
31
+ public function review_plugin_notice() {
32
+ if ( $this->is_order_page() === false && !( isset( $_GET['page'] ) && $_GET['page'] == 'wpo_wcpdf_options_page' ) ) {
33
+ return;
34
+ }
35
+
36
+ if ( get_option( 'wpo_wcpdf_review_notice_dismissed' ) !== false ) {
37
+ return;
38
+ } else {
39
+ if ( isset( $_GET['wpo_wcpdf_dismis_review'] ) ) {
40
+ update_option( 'wpo_wcpdf_review_notice_dismissed', true );
41
+ return;
42
+ }
43
+
44
+ $invoice_count = $this->get_invoice_count();
45
+ if ( $invoice_count > 100 ) {
46
+ $rounded_count = (int) substr( (string) $invoice_count, 0, 1 ) * pow( 10, strlen( (string) $invoice_count ) - 1);
47
+ ?>
48
+ <div class="notice notice-info is-dismissible wpo-wcpdf-review-notice">
49
+ <h3><?php printf( __( 'Wow, you have created more than %d invoices with our plugin!', 'woocommerce-pdf-invoices-packing-slips' ), $rounded_count ); ?></h3>
50
+ <p><?php _e( 'It would mean a lot to us if you would quickly give our plugin a 5-star rating. Help us spread the word and boost our motivation!', 'woocommerce-pdf-invoices-packing-slips' ); ?></p>
51
+ <ul>
52
+ <li><a href="https://wordpress.org/support/plugin/woocommerce-pdf-invoices-packing-slips/reviews/?rate=5#new-post" class="button"><?php _e( 'Yes you deserve it!', 'woocommerce-pdf-invoices-packing-slips' ); ?></span></a></li>
53
+ <li><a href="<?php echo esc_url( add_query_arg( 'wpo_wcpdf_dismis_review', true ) ); ?>" class="wpo-wcpdf-dismiss"><?php _e( 'Already did!', 'woocommerce-pdf-invoices-packing-slips' ); ?></a></li>
54
+ <li><a href="mailto:support@wpovernight.com?Subject=Here%20is%20how%20I%20think%20you%20can%20do%20better"><?php _e( 'Actually, I have a complaint...', 'woocommerce-pdf-invoices-packing-slips' ); ?></a></li>
55
+ </ul>
56
+ </div>
57
+ <!-- Hide extensions ad if this is shown -->
58
+ <style>.wcpdf-extensions-ad { display: none; }</style>
59
+ <?php
60
+ }
61
+ }
62
+ }
63
+
64
+ public function get_invoice_count() {
65
+ global $wpdb;
66
+ $invoice_count = $wpdb->get_var( $wpdb->prepare( "SELECT count(*) FROM {$wpdb->postmeta} WHERE meta_key = %s", '_wcpdf_invoice_number' ) );
67
+ return (int) $invoice_count;
68
+ }
69
+
70
+ public function update_pdf_counter( $document_type, $document ) {
71
+ if ( in_array( $document_type, array('invoice','packing-slip') ) ) {
72
+ $pdf_count = (int) get_option( 'wpo_wcpdf_count_'.$document_type, 0 );
73
+ update_option( 'wpo_wcpdf_count_'.$document_type, $pdf_count + 1 );
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Add PDF actions to the orders listing
79
+ */
80
+ public function add_listing_actions( $order ) {
81
+ // do not show buttons for trashed orders
82
+ if ( $order->get_status() == 'trash' ) {
83
+ return;
84
+ }
85
+
86
+ $listing_actions = array();
87
+ $documents = WPO_WCPDF()->documents->get_documents();
88
+ foreach ($documents as $document) {
89
+ $listing_actions[$document->get_type()] = array(
90
+ 'url' => wp_nonce_url( admin_url( "admin-ajax.php?action=generate_wpo_wcpdf&document_type={$document->get_type()}&order_ids=" . WCX_Order::get_id( $order ) ), 'generate_wpo_wcpdf' ),
91
+ 'img' => !empty($document->icon) ? $document->icon : WPO_WCPDF()->plugin_url() . "/assets/images/generic_document.png",
92
+ 'alt' => "PDF " . $document->get_title(),
93
+ );
94
+ }
95
+
96
+ $listing_actions = apply_filters( 'wpo_wcpdf_listing_actions', $listing_actions, $order );
97
+
98
+ foreach ($listing_actions as $action => $data) {
99
+ ?>
100
+ <a href="<?php echo $data['url']; ?>" class="button tips wpo_wcpdf <?php echo $action; ?>" target="_blank" alt="<?php echo $data['alt']; ?>" data-tip="<?php echo $data['alt']; ?>">
101
+ <img src="<?php echo $data['img']; ?>" alt="<?php echo $data['alt']; ?>" width="16">
102
+ </a>
103
+ <?php
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Create additional Shop Order column for Invoice Numbers
109
+ * @param array $columns shop order columns
110
+ */
111
+ public function add_invoice_number_column( $columns ) {
112
+ // get invoice settings
113
+ $invoice = wcpdf_get_invoice( null );
114
+ $invoice_settings = $invoice->get_settings();
115
+ if ( !isset( $invoice_settings['invoice_number_column'] ) ) {
116
+ return $columns;
117
+ }
118
+
119
+ // put the column after the Status column
120
+ $new_columns = array_slice($columns, 0, 2, true) +
121
+ array( 'pdf_invoice_number' => __( 'Invoice Number', 'woocommerce-pdf-invoices-packing-slips' ) ) +
122
+ array_slice($columns, 2, count($columns) - 1, true) ;
123
+ return $new_columns;
124
+ }
125
+
126
+ /**
127
+ * Display Invoice Number in Shop Order column (if available)
128
+ * @param string $column column slug
129
+ */
130
+ public function invoice_number_column_data( $column ) {
131
+ global $post, $the_order;
132
+
133
+ if ( $column == 'pdf_invoice_number' ) {
134
+ if ( empty( $the_order ) || WCX_Order::get_id( $the_order ) != $post->ID ) {
135
+ $order = WCX::get_order( $post->ID );
136
+ if ( $invoice = wcpdf_get_invoice( $order ) ) {
137
+ echo $invoice->get_number();
138
+ }
139
+ do_action( 'wcpdf_invoice_number_column_end', $order );
140
+ } else {
141
+ if ( $invoice = wcpdf_get_invoice( $the_order ) ) {
142
+ echo $invoice->get_number();
143
+ }
144
+ do_action( 'wcpdf_invoice_number_column_end', $the_order );
145
+ }
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Add the meta box on the single order page
151
+ */
152
+ public function add_meta_boxes() {
153
+ // create PDF buttons
154
+ add_meta_box(
155
+ 'wpo_wcpdf-box',
156
+ __( 'Create PDF', 'woocommerce-pdf-invoices-packing-slips' ),
157
+ array( $this, 'sidebar_box_content' ),
158
+ 'shop_order',
159
+ 'side',
160
+ 'default'
161
+ );
162
+
163
+ // Invoice number & date
164
+ add_meta_box(
165
+ 'wpo_wcpdf-data-input-box',
166
+ __( 'PDF Invoice data', 'woocommerce-pdf-invoices-packing-slips' ),
167
+ array( $this, 'data_input_box_content' ),
168
+ 'shop_order',
169
+ 'normal',
170
+ 'default'
171
+ );
172
+ }
173
+
174
+ /**
175
+ * Create the meta box content on the single order page
176
+ */
177
+ public function sidebar_box_content( $post ) {
178
+ global $post_id;
179
+
180
+ $meta_box_actions = array();
181
+ $documents = WPO_WCPDF()->documents->get_documents();
182
+ foreach ($documents as $document) {
183
+ $meta_box_actions[$document->get_type()] = array(
184
+ 'url' => wp_nonce_url( admin_url( "admin-ajax.php?action=generate_wpo_wcpdf&document_type={$document->get_type()}&order_ids=" . $post_id ), 'generate_wpo_wcpdf' ),
185
+ 'alt' => esc_attr( "PDF " . $document->get_title() ),
186
+ 'title' => "PDF " . $document->get_title(),
187
+ );
188
+ }
189
+
190
+ $meta_box_actions = apply_filters( 'wpo_wcpdf_meta_box_actions', $meta_box_actions, $post_id );
191
+
192
+ ?>
193
+ <ul class="wpo_wcpdf-actions">
194
+ <?php
195
+ foreach ($meta_box_actions as $document_type => $data) {
196
+ printf('<li><a href="%1$s" class="button" target="_blank" alt="%2$s">%3$s</a></li>', $data['url'], $data['alt'],$data['title']);
197
+ }
198
+ ?>
199
+ </ul>
200
+ <?php
201
+ }
202
+
203
+ /**
204
+ * Add metabox for invoice number & date
205
+ */
206
+ public function data_input_box_content ( $post ) {
207
+ $order = WCX::get_order( $post->ID );
208
+
209
+ do_action( 'wpo_wcpdf_meta_box_start', $post->ID );
210
+
211
+ if ( $invoice = wcpdf_get_invoice( $order ) ) {
212
+ $invoice_number = $invoice->get_number();
213
+ $invoice_date = $invoice->get_date();
214
+ ?>
215
+ <div class="wcpdf-data-fields">
216
+ <h4><?php _e( 'Invoice', 'woocommerce-pdf-invoices-packing-slips' ) ?><?php if ($invoice->exists()) : ?><span id="" class="wpo-wcpdf-edit-date-number dashicons dashicons-edit"></span><?php endif; ?></h4>
217
+
218
+ <!-- Read only -->
219
+ <div class="read-only">
220
+ <?php if ($invoice->exists()) : ?>
221
+ <div class="invoice-number">
222
+ <p class="form-field _wcpdf_invoice_number_field ">
223
+ <p>
224
+ <span><strong><?php _e( 'Invoice Number', 'woocommerce-pdf-invoices-packing-slips' ); ?>:</strong></span>
225
+ <span><?php if (!empty($invoice_number)) echo $invoice_number->get_formatted(); ?></span>
226
+ </p>
227
+ </p>
228
+ </div>
229
+
230
+ <div class="invoice-date">
231
+ <p class="form-field form-field-wide">
232
+ <p>
233
+ <span><strong><?php _e( 'Invoice Date:', 'woocommerce-pdf-invoices-packing-slips' ); ?></strong></span>
234
+ <span><?php if (!empty($invoice_date)) echo $invoice_date->date_i18n( wc_date_format().' @ '.wc_time_format() ); ?></span>
235
+ </p>
236
+ </p>
237
+ </div>
238
+ <?php else : ?>
239
+ <span class="wpo-wcpdf-set-date-number button"><?php _e( 'Set invoice number & date', 'woocommerce-pdf-invoices-packing-slips' ) ?></span>
240
+ <?php endif; ?>
241
+ </div>
242
+
243
+ <!-- Editable -->
244
+ <div class="editable">
245
+ <p class="form-field _wcpdf_invoice_number_field ">
246
+ <label for="_wcpdf_invoice_number"><?php _e( 'Invoice Number (unformatted!)', 'woocommerce-pdf-invoices-packing-slips' ); ?>:</label>
247
+ <?php if ( $invoice->exists() && !empty($invoice_number) ) : ?>
248
+ <input type="text" class="short" style="" name="_wcpdf_invoice_number" id="_wcpdf_invoice_number" value="<?php echo $invoice_number->get_plain(); ?>">
249
+ <?php else : ?>
250
+ <input type="text" class="short" style="" name="_wcpdf_invoice_number" id="_wcpdf_invoice_number" value="" disabled="disabled" >
251
+ <?php endif; ?>
252
+ </p>
253
+ <p class="form-field form-field-wide">
254
+ <label for="wcpdf_invoice_date"><?php _e( 'Invoice Date:', 'woocommerce-pdf-invoices-packing-slips' ); ?></label>
255
+ <?php if ( $invoice->exists() && !empty($invoice_date) ) : ?>
256
+ <input type="text" class="date-picker-field" name="wcpdf_invoice_date" id="wcpdf_invoice_date" maxlength="10" value="<?php echo $invoice_date->date_i18n( 'Y-m-d' ); ?>" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" />@<input type="number" class="hour" placeholder="<?php _e( 'h', 'woocommerce' ) ?>" name="wcpdf_invoice_date_hour" id="wcpdf_invoice_date_hour" min="0" max="23" size="2" value="<?php echo $invoice_date->date_i18n( 'H' ) ?>" pattern="([01]?[0-9]{1}|2[0-3]{1})" />:<input type="number" class="minute" placeholder="<?php _e( 'm', 'woocommerce' ) ?>" name="wcpdf_invoice_date_minute" id="wcpdf_invoice_date_minute" min="0" max="59" size="2" value="<?php echo $invoice_date->date_i18n( 'i' ); ?>" pattern="[0-5]{1}[0-9]{1}" />
257
+ <?php else : ?>
258
+ <input type="text" class="date-picker-field" name="wcpdf_invoice_date" id="wcpdf_invoice_date" maxlength="10" disabled="disabled" value="" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" />@<input type="number" class="hour" disabled="disabled" placeholder="<?php _e( 'h', 'woocommerce' ) ?>" name="wcpdf_invoice_date_hour" id="wcpdf_invoice_date_hour" min="0" max="23" size="2" value="" pattern="([01]?[0-9]{1}|2[0-3]{1})" />:<input type="number" class="minute" placeholder="<?php _e( 'm', 'woocommerce' ) ?>" name="wcpdf_invoice_date_minute" id="wcpdf_invoice_date_minute" min="0" max="59" size="2" value="" pattern="[0-5]{1}[0-9]{1}" disabled="disabled" />
259
+ <?php endif; ?>
260
+ </p>
261
+ </div>
262
+ </div>
263
+ <?php
264
+ }
265
+
266
+ do_action( 'wpo_wcpdf_meta_box_end', $post->ID );
267
+ }
268
+
269
+ /**
270
+ * Add actions to menu
271
+ */
272
+ public function bulk_actions() {
273
+ if ( $this->is_order_page() ) {
274
+ $bulk_actions = array();
275
+ $documents = WPO_WCPDF()->documents->get_documents();
276
+ foreach ($documents as $document) {
277
+ $bulk_actions[$document->get_type()] = "PDF " . $document->get_title();
278
+ }
279
+
280
+ $bulk_actions = apply_filters( 'wpo_wcpdf_bulk_actions', $bulk_actions );
281
+
282
+ ?>
283
+ <script type="text/javascript">
284
+ jQuery(document).ready(function() {
285
+ <?php foreach ($bulk_actions as $action => $title) { ?>
286
+ jQuery('<option>').val('<?php echo $action; ?>').html('<?php echo esc_attr( $title ); ?>').appendTo("select[name='action'], select[name='action2']");
287
+ <?php } ?>
288
+ });
289
+ </script>
290
+ <?php
291
+ }
292
+ }
293
+
294
+ /**
295
+ * Save invoice number
296
+ */
297
+ public function save_invoice_number_date($post_id) {
298
+ $post_type = get_post_type( $post_id );
299
+ if( $post_type == 'shop_order' ) {
300
+ // bail if this is not an actual 'Save order' action
301
+ if (!isset($_POST['action']) || $_POST['action'] != 'editpost') {
302
+ return;
303
+ }
304
+
305
+ $order = WCX::get_order( $post_id );
306
+ if ( $invoice = wcpdf_get_invoice( $order ) ) {
307
+ if ( isset( $_POST['wcpdf_invoice_date'] ) ) {
308
+ $date = $_POST['wcpdf_invoice_date'];
309
+ $hour = !empty( $_POST['wcpdf_invoice_date_hour'] ) ? $_POST['wcpdf_invoice_date_hour'] : '00';
310
+ $minute = !empty( $_POST['wcpdf_invoice_date_minute'] ) ? $_POST['wcpdf_invoice_date_minute'] : '00';
311
+ $invoice_date = "{$date} {$hour}:{$minute}:00";
312
+ $invoice->set_date( $invoice_date );
313
+ } elseif ( empty( $_POST['wcpdf_invoice_date'] ) && !empty( $_POST['_wcpdf_invoice_number'] ) ) {
314
+ $invoice->set_date( current_time( 'timestamp', true ) );
315
+ }
316
+
317
+ if ( isset( $_POST['_wcpdf_invoice_number'] ) ) {
318
+ $invoice->set_number( $_POST['_wcpdf_invoice_number'] );
319
+ }
320
+
321
+ $invoice->save();
322
+ }
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Add invoice number to order search scope
328
+ */
329
+ public function search_fields ( $custom_fields ) {
330
+ $custom_fields[] = '_wcpdf_invoice_number';
331
+ $custom_fields[] = '_wcpdf_formatted_invoice_number';
332
+ return $custom_fields;
333
+ }
334
+
335
+
336
+ /**
337
+ * Check if this is a shop_order page (edit or list)
338
+ */
339
+ public function is_order_page() {
340
+ global $post_type;
341
+ if( $post_type == 'shop_order' ) {
342
+ return true;
343
+ } else {
344
+ return false;
345
+ }
346
+ }
347
+ }
348
+
349
+ endif; // class_exists
350
+
351
  return new Admin();
includes/class-wcpdf-pdf-maker.php CHANGED
@@ -1,57 +1,58 @@
1
- <?php
2
- namespace WPO\WC\PDF_Invoices;
3
-
4
- use Dompdf\Dompdf;
5
- use Dompdf\Options;
6
-
7
- if ( ! defined( 'ABSPATH' ) ) {
8
- exit; // Exit if accessed directly
9
- }
10
-
11
- if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\PDF_Maker' ) ) :
12
-
13
- class PDF_Maker {
14
- public $html;
15
- public $settings;
16
-
17
- public function __construct( $html, $settings = array() ) {
18
- $this->html = $html;
19
-
20
- $default_settings = array(
21
- 'paper_size' => 'A4',
22
- 'paper_orientation' => 'portrait',
23
- 'font_subsetting' => false,
24
- );
25
- $this->settings = $settings + $default_settings;
26
- }
27
-
28
- public function output() {
29
- if ( empty( $this->html ) ) {
30
- return;
31
- }
32
-
33
- require WPO_WCPDF()->plugin_path() . '/vendor/autoload.php';
34
-
35
- // set options
36
- $options = new Options();
37
- $options->setdefaultFont( 'dejavu sans');
38
- $options->setTempDir( WPO_WCPDF()->main->get_tmp_path('dompdf') );
39
- $options->setLogOutputFile( WPO_WCPDF()->main->get_tmp_path('dompdf') . "/log.htm");
40
- $options->setFontDir( WPO_WCPDF()->main->get_tmp_path('fonts') );
41
- $options->setFontCache( WPO_WCPDF()->main->get_tmp_path('fonts') );
42
- $options->setIsRemoteEnabled( true );
43
- $options->setIsFontSubsettingEnabled( $this->settings['font_subsetting'] );
44
-
45
- // instantiate and use the dompdf class
46
- $dompdf = new Dompdf( $options );
47
- $dompdf->loadHtml( $this->html );
48
- $dompdf->setPaper( $this->settings['paper_size'], $this->settings['paper_orientation'] );
49
- $dompdf = apply_filters( 'wpo_wcpdf_before_dompdf_render', $dompdf, $this->html );
50
- $dompdf->render();
51
- $dompdf = apply_filters( 'wpo_wcpdf_after_dompdf_render', $dompdf, $this->html );
52
-
53
- return $dompdf->output();
54
- }
55
- }
56
-
57
- endif; // class_exists
 
1
+ <?php
2
+ namespace WPO\WC\PDF_Invoices;
3
+
4
+ use Dompdf\Dompdf;
5
+ use Dompdf\Options;
6
+
7
+ if ( ! defined( 'ABSPATH' ) ) {
8
+ exit; // Exit if accessed directly
9
+ }
10
+
11
+ if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\PDF_Maker' ) ) :
12
+
13
+ class PDF_Maker {
14
+ public $html;
15
+ public $settings;
16
+
17
+ public function __construct( $html, $settings = array() ) {
18
+ $this->html = $html;
19
+
20
+ $default_settings = array(
21
+ 'paper_size' => 'A4',
22
+ 'paper_orientation' => 'portrait',
23
+ 'font_subsetting' => false,
24
+ );
25
+ $this->settings = $settings + $default_settings;
26
+ }
27
+
28
+ public function output() {
29
+ if ( empty( $this->html ) ) {
30
+ return;
31
+ }
32
+
33
+ require WPO_WCPDF()->plugin_path() . '/vendor/autoload.php';
34
+
35
+ // set options
36
+ $options = new Options( apply_filters( 'wpo_wcpdf_dompdf_options', array(
37
+ 'defaultFont' => 'dejavu sans',
38
+ 'tempDir' => WPO_WCPDF()->main->get_tmp_path('dompdf'),
39
+ 'logOutputFile' => WPO_WCPDF()->main->get_tmp_path('dompdf') . "/log.htm",
40
+ 'fontDir' => WPO_WCPDF()->main->get_tmp_path('fonts'),
41
+ 'fontCache' => WPO_WCPDF()->main->get_tmp_path('fonts'),
42
+ 'isRemoteEnabled' => true,
43
+ 'isFontSubsettingEnabled' => $this->settings['font_subsetting'],
44
+ ) ) );
45
+
46
+ // instantiate and use the dompdf class
47
+ $dompdf = new Dompdf( $options );
48
+ $dompdf->loadHtml( $this->html );
49
+ $dompdf->setPaper( $this->settings['paper_size'], $this->settings['paper_orientation'] );
50
+ $dompdf = apply_filters( 'wpo_wcpdf_before_dompdf_render', $dompdf, $this->html );
51
+ $dompdf->render();
52
+ $dompdf = apply_filters( 'wpo_wcpdf_after_dompdf_render', $dompdf, $this->html );
53
+
54
+ return $dompdf->output();
55
+ }
56
+ }
57
+
58
+ endif; // class_exists
includes/class-wcpdf-settings-general.php CHANGED
@@ -1,275 +1,299 @@
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\\Settings_General' ) ) :
9
-
10
- class Settings_General {
11
-
12
- function __construct() {
13
- add_action( 'admin_init', array( $this, 'init_settings' ) );
14
- add_action( 'wpo_wcpdf_settings_output_general', array( $this, 'output' ), 10, 1 );
15
- }
16
-
17
- public function output( $section ) {
18
- settings_fields( "wpo_wcpdf_settings_general" );
19
- do_settings_sections( "wpo_wcpdf_settings_general" );
20
-
21
- submit_button();
22
- }
23
-
24
- public function init_settings() {
25
- $page = $option_group = $option_name = 'wpo_wcpdf_settings_general';
26
-
27
- $template_base_path = ( defined( 'WC_TEMPLATE_PATH' ) ? WC_TEMPLATE_PATH : $GLOBALS['woocommerce']->template_url );
28
- $theme_template_path = get_stylesheet_directory() . '/' . $template_base_path;
29
- $wp_content_dir = str_replace( ABSPATH, '', WP_CONTENT_DIR );
30
- $theme_template_path = substr($theme_template_path, strpos($theme_template_path, $wp_content_dir)) . 'pdf/yourtemplate';
31
- $plugin_template_path = "{$wp_content_dir}/plugins/woocommerce-pdf-invoices-packing-slips/templates/Simple";
32
-
33
- $settings_fields = array(
34
- array(
35
- 'type' => 'section',
36
- 'id' => 'general_settings',
37
- 'title' => __( 'General settings', 'woocommerce-pdf-invoices-packing-slips' ),
38
- 'callback' => 'section',
39
- ),
40
- array(
41
- 'type' => 'setting',
42
- 'id' => 'download_display',
43
- 'title' => __( 'How do you want to view the PDF?', 'woocommerce-pdf-invoices-packing-slips' ),
44
- 'callback' => 'select',
45
- 'section' => 'general_settings',
46
- 'args' => array(
47
- 'option_name' => $option_name,
48
- 'id' => 'download_display',
49
- 'options' => array(
50
- 'download' => __( 'Download the PDF' , 'woocommerce-pdf-invoices-packing-slips' ),
51
- 'display' => __( 'Open the PDF in a new browser tab/window' , 'woocommerce-pdf-invoices-packing-slips' ),
52
- ),
53
- )
54
- ),
55
- array(
56
- 'type' => 'setting',
57
- 'id' => 'template_path',
58
- 'title' => __( 'Choose a template', 'woocommerce-pdf-invoices-packing-slips' ),
59
- 'callback' => 'select',
60
- 'section' => 'general_settings',
61
- 'args' => array(
62
- 'option_name' => $option_name,
63
- 'id' => 'template_path',
64
- 'options' => $this->find_templates(),
65
- 'description' => sprintf( __( 'Want to use your own template? Copy all the files from <code>%s</code> to your (child) theme in <code>%s</code> to customize them' , 'woocommerce-pdf-invoices-packing-slips' ), $plugin_template_path, $theme_template_path),
66
- )
67
- ),
68
- array(
69
- 'type' => 'setting',
70
- 'id' => 'paper_size',
71
- 'title' => __( 'Paper size', 'woocommerce-pdf-invoices-packing-slips' ),
72
- 'callback' => 'select',
73
- 'section' => 'general_settings',
74
- 'args' => array(
75
- 'option_name' => $option_name,
76
- 'id' => 'paper_size',
77
- 'options' => apply_filters( 'wpo_wcpdf_template_settings_paper_size', array(
78
- 'a4' => __( 'A4' , 'woocommerce-pdf-invoices-packing-slips' ),
79
- 'letter' => __( 'Letter' , 'woocommerce-pdf-invoices-packing-slips' ),
80
- ) ),
81
- )
82
- ),
83
- array(
84
- 'type' => 'setting',
85
- 'id' => 'currency_font',
86
- 'title' => __( 'Extended currency symbol support', 'woocommerce-pdf-invoices-packing-slips' ),
87
- 'callback' => 'checkbox',
88
- 'section' => 'general_settings',
89
- 'args' => array(
90
- 'option_name' => $option_name,
91
- 'id' => 'currency_font',
92
- 'description' => __( 'Enable this if your currency symbol is not displaying properly' , 'woocommerce-pdf-invoices-packing-slips' ),
93
- )
94
- ),
95
- array(
96
- 'type' => 'setting',
97
- 'id' => 'font_subsetting',
98
- 'title' => __( 'Enable font subsetting', 'woocommerce-pdf-invoices-packing-slips' ),
99
- 'callback' => 'checkbox',
100
- 'section' => 'general_settings',
101
- 'args' => array(
102
- 'option_name' => $option_name,
103
- 'id' => 'font_subsetting',
104
- 'description' => __( "Font subsetting can reduce file size by only including the characters that are used in the PDF, but limits the ability to edit PDF files later. Recommended if you're using an Asian font." , 'woocommerce-pdf-invoices-packing-slips' ),
105
- )
106
- ),
107
- array(
108
- 'type' => 'setting',
109
- 'id' => 'header_logo',
110
- 'title' => __( 'Shop header/logo', 'woocommerce-pdf-invoices-packing-slips' ),
111
- 'callback' => 'media_upload',
112
- 'section' => 'general_settings',
113
- 'args' => array(
114
- 'option_name' => $option_name,
115
- 'id' => 'header_logo',
116
- 'uploader_title' => __( 'Select or upload your invoice header/logo', 'woocommerce-pdf-invoices-packing-slips' ),
117
- 'uploader_button_text' => __( 'Set image', 'woocommerce-pdf-invoices-packing-slips' ),
118
- 'remove_button_text' => __( 'Remove image', 'woocommerce-pdf-invoices-packing-slips' ),
119
- //'description' => __( '...', 'woocommerce-pdf-invoices-packing-slips' ),
120
- )
121
- ),
122
- array(
123
- 'type' => 'setting',
124
- 'id' => 'shop_name',
125
- 'title' => __( 'Shop Name', 'woocommerce-pdf-invoices-packing-slips' ),
126
- 'callback' => 'text_input',
127
- 'section' => 'general_settings',
128
- 'args' => array(
129
- 'option_name' => $option_name,
130
- 'id' => 'shop_name',
131
- 'size' => '72',
132
- 'translatable' => true,
133
- )
134
- ),
135
- array(
136
- 'type' => 'setting',
137
- 'id' => 'shop_address',
138
- 'title' => __( 'Shop Address', 'woocommerce-pdf-invoices-packing-slips' ),
139
- 'callback' => 'textarea',
140
- 'section' => 'general_settings',
141
- 'args' => array(
142
- 'option_name' => $option_name,
143
- 'id' => 'shop_address',
144
- 'width' => '72',
145
- 'height' => '8',
146
- 'translatable' => true,
147
- //'description' => __( '...', 'woocommerce-pdf-invoices-packing-slips' ),
148
- )
149
- ),
150
- array(
151
- 'type' => 'setting',
152
- 'id' => 'footer',
153
- 'title' => __( 'Footer: terms & conditions, policies, etc.', 'woocommerce-pdf-invoices-packing-slips' ),
154
- 'callback' => 'textarea',
155
- 'section' => 'general_settings',
156
- 'args' => array(
157
- 'option_name' => $option_name,
158
- 'id' => 'footer',
159
- 'width' => '72',
160
- 'height' => '4',
161
- 'translatable' => true,
162
- //'description' => __( '...', 'woocommerce-pdf-invoices-packing-slips' ),
163
- )
164
- ),
165
- array(
166
- 'type' => 'section',
167
- 'id' => 'extra_template_fields',
168
- 'title' => __( 'Extra template fields', 'woocommerce-pdf-invoices-packing-slips' ),
169
- 'callback' => 'custom_fields_section',
170
- ),
171
- array(
172
- 'type' => 'setting',
173
- 'id' => 'extra_1',
174
- 'title' => __( 'Extra field 1', 'woocommerce-pdf-invoices-packing-slips' ),
175
- 'callback' => 'textarea',
176
- 'section' => 'extra_template_fields',
177
- 'args' => array(
178
- 'option_name' => $option_name,
179
- 'id' => 'extra_1',
180
- 'width' => '72',
181
- 'height' => '8',
182
- 'description' => __( 'This is footer column 1 in the <i>Modern (Premium)</i> template', 'woocommerce-pdf-invoices-packing-slips' ),
183
- 'translatable' => true,
184
- )
185
- ),
186
- array(
187
- 'type' => 'setting',
188
- 'id' => 'extra_2',
189
- 'title' => __( 'Extra field 2', 'woocommerce-pdf-invoices-packing-slips' ),
190
- 'callback' => 'textarea',
191
- 'section' => 'extra_template_fields',
192
- 'args' => array(
193
- 'option_name' => $option_name,
194
- 'id' => 'extra_2',
195
- 'width' => '72',
196
- 'height' => '8',
197
- 'description' => __( 'This is footer column 2 in the <i>Modern (Premium)</i> template', 'woocommerce-pdf-invoices-packing-slips' ),
198
- 'translatable' => true,
199
- )
200
- ),
201
- array(
202
- 'type' => 'setting',
203
- 'id' => 'extra_3',
204
- 'title' => __( 'Extra field 3', 'woocommerce-pdf-invoices-packing-slips' ),
205
- 'callback' => 'textarea',
206
- 'section' => 'extra_template_fields',
207
- 'args' => array(
208
- 'option_name' => $option_name,
209
- 'id' => 'extra_3',
210
- 'width' => '72',
211
- 'height' => '8',
212
- 'description' => __( 'This is footer column 3 in the <i>Modern (Premium)</i> template', 'woocommerce-pdf-invoices-packing-slips' ),
213
- 'translatable' => true,
214
- )
215
- ),
216
- );
217
-
218
- // allow plugins to alter settings fields
219
- $settings_fields = apply_filters( 'wpo_wcpdf_settings_fields_general', $settings_fields, $page, $option_group, $option_name );
220
- WPO_WCPDF()->settings->add_settings_fields( $settings_fields, $page, $option_group, $option_name );
221
- return;
222
- }
223
-
224
- /**
225
- * List templates in plugin folder, theme folder & child theme folder
226
- * @return array template path => template name
227
- */
228
- public function find_templates() {
229
- $installed_templates = array();
230
-
231
- // get base paths
232
- $template_base_path = ( defined( 'WC_TEMPLATE_PATH' ) ? WC_TEMPLATE_PATH : $GLOBALS['woocommerce']->template_url );
233
- $template_base_path = untrailingslashit( $template_base_path );
234
- $template_paths = array (
235
- // note the order: child-theme before theme, so that array_unique filters out parent doubles
236
- 'default' => WPO_WCPDF()->plugin_path() . '/templates/',
237
- 'child-theme' => get_stylesheet_directory() . "/{$template_base_path}/pdf/",
238
- 'theme' => get_template_directory() . "/{$template_base_path}/pdf/",
239
- );
240
-
241
- $template_paths = apply_filters( 'wpo_wcpdf_template_paths', $template_paths );
242
-
243
- if ( defined('WP_CONTENT_DIR') && strpos( WP_CONTENT_DIR, ABSPATH ) !== false ) {
244
- $forwardslash_basepath = str_replace('\\','/', ABSPATH);
245
- } else {
246
- $forwardslash_basepath = str_replace('\\','/', WP_CONTENT_DIR);
247
- }
248
-
249
- foreach ($template_paths as $template_source => $template_path) {
250
- $dirs = (array) glob( $template_path . '*' , GLOB_ONLYDIR);
251
-
252
- foreach ($dirs as $dir) {
253
- // we're stripping abspath to make the plugin settings more portable
254
- $forwardslash_dir = str_replace('\\','/', $dir);
255
- $installed_templates[ str_replace( $forwardslash_basepath, '', $forwardslash_dir ) ] = basename($dir);
256
- }
257
- }
258
-
259
- // remove parent doubles
260
- $installed_templates = array_unique($installed_templates);
261
-
262
- if (empty($installed_templates)) {
263
- // fallback to Simple template for servers with glob() disabled
264
- $simple_template_path = str_replace( ABSPATH, '', $template_paths['default'] . 'Simple' );
265
- $installed_templates[$simple_template_path] = 'Simple';
266
- }
267
-
268
- return apply_filters( 'wpo_wcpdf_templates', $installed_templates );
269
- }
270
-
271
- }
272
-
273
- endif; // class_exists
274
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  return new Settings_General();
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\\Settings_General' ) ) :
9
+
10
+ class Settings_General {
11
+
12
+ function __construct() {
13
+ add_action( 'admin_init', array( $this, 'init_settings' ) );
14
+ add_action( 'wpo_wcpdf_settings_output_general', array( $this, 'output' ), 10, 1 );
15
+ add_action( 'wpo_wcpdf_before_settings', array( $this, 'attachment_settings_hint' ), 10, 2 );
16
+ }
17
+
18
+ public function output( $section ) {
19
+ settings_fields( "wpo_wcpdf_settings_general" );
20
+ do_settings_sections( "wpo_wcpdf_settings_general" );
21
+
22
+ submit_button();
23
+ }
24
+
25
+ public function init_settings() {
26
+ $page = $option_group = $option_name = 'wpo_wcpdf_settings_general';
27
+
28
+ $template_base_path = ( defined( 'WC_TEMPLATE_PATH' ) ? WC_TEMPLATE_PATH : $GLOBALS['woocommerce']->template_url );
29
+ $theme_template_path = get_stylesheet_directory() . '/' . $template_base_path;
30
+ $wp_content_dir = str_replace( ABSPATH, '', WP_CONTENT_DIR );
31
+ $theme_template_path = substr($theme_template_path, strpos($theme_template_path, $wp_content_dir)) . 'pdf/yourtemplate';
32
+ $plugin_template_path = "{$wp_content_dir}/plugins/woocommerce-pdf-invoices-packing-slips/templates/Simple";
33
+
34
+ $settings_fields = array(
35
+ array(
36
+ 'type' => 'section',
37
+ 'id' => 'general_settings',
38
+ 'title' => __( 'General settings', 'woocommerce-pdf-invoices-packing-slips' ),
39
+ 'callback' => 'section',
40
+ ),
41
+ array(
42
+ 'type' => 'setting',
43
+ 'id' => 'download_display',
44
+ 'title' => __( 'How do you want to view the PDF?', 'woocommerce-pdf-invoices-packing-slips' ),
45
+ 'callback' => 'select',
46
+ 'section' => 'general_settings',
47
+ 'args' => array(
48
+ 'option_name' => $option_name,
49
+ 'id' => 'download_display',
50
+ 'options' => array(
51
+ 'download' => __( 'Download the PDF' , 'woocommerce-pdf-invoices-packing-slips' ),
52
+ 'display' => __( 'Open the PDF in a new browser tab/window' , 'woocommerce-pdf-invoices-packing-slips' ),
53
+ ),
54
+ )
55
+ ),
56
+ array(
57
+ 'type' => 'setting',
58
+ 'id' => 'template_path',
59
+ 'title' => __( 'Choose a template', 'woocommerce-pdf-invoices-packing-slips' ),
60
+ 'callback' => 'select',
61
+ 'section' => 'general_settings',
62
+ 'args' => array(
63
+ 'option_name' => $option_name,
64
+ 'id' => 'template_path',
65
+ 'options' => $this->find_templates(),
66
+ 'description' => sprintf( __( 'Want to use your own template? Copy all the files from <code>%s</code> to your (child) theme in <code>%s</code> to customize them' , 'woocommerce-pdf-invoices-packing-slips' ), $plugin_template_path, $theme_template_path),
67
+ )
68
+ ),
69
+ array(
70
+ 'type' => 'setting',
71
+ 'id' => 'paper_size',
72
+ 'title' => __( 'Paper size', 'woocommerce-pdf-invoices-packing-slips' ),
73
+ 'callback' => 'select',
74
+ 'section' => 'general_settings',
75
+ 'args' => array(
76
+ 'option_name' => $option_name,
77
+ 'id' => 'paper_size',
78
+ 'options' => apply_filters( 'wpo_wcpdf_template_settings_paper_size', array(
79
+ 'a4' => __( 'A4' , 'woocommerce-pdf-invoices-packing-slips' ),
80
+ 'letter' => __( 'Letter' , 'woocommerce-pdf-invoices-packing-slips' ),
81
+ ) ),
82
+ )
83
+ ),
84
+ array(
85
+ 'type' => 'setting',
86
+ 'id' => 'currency_font',
87
+ 'title' => __( 'Extended currency symbol support', 'woocommerce-pdf-invoices-packing-slips' ),
88
+ 'callback' => 'checkbox',
89
+ 'section' => 'general_settings',
90
+ 'args' => array(
91
+ 'option_name' => $option_name,
92
+ 'id' => 'currency_font',
93
+ 'description' => __( 'Enable this if your currency symbol is not displaying properly' , 'woocommerce-pdf-invoices-packing-slips' ),
94
+ )
95
+ ),
96
+ array(
97
+ 'type' => 'setting',
98
+ 'id' => 'font_subsetting',
99
+ 'title' => __( 'Enable font subsetting', 'woocommerce-pdf-invoices-packing-slips' ),
100
+ 'callback' => 'checkbox',
101
+ 'section' => 'general_settings',
102
+ 'args' => array(
103
+ 'option_name' => $option_name,
104
+ 'id' => 'font_subsetting',
105
+ 'description' => __( "Font subsetting can reduce file size by only including the characters that are used in the PDF, but limits the ability to edit PDF files later. Recommended if you're using an Asian font." , 'woocommerce-pdf-invoices-packing-slips' ),
106
+ )
107
+ ),
108
+ array(
109
+ 'type' => 'setting',
110
+ 'id' => 'header_logo',
111
+ 'title' => __( 'Shop header/logo', 'woocommerce-pdf-invoices-packing-slips' ),
112
+ 'callback' => 'media_upload',
113
+ 'section' => 'general_settings',
114
+ 'args' => array(
115
+ 'option_name' => $option_name,
116
+ 'id' => 'header_logo',
117
+ 'uploader_title' => __( 'Select or upload your invoice header/logo', 'woocommerce-pdf-invoices-packing-slips' ),
118
+ 'uploader_button_text' => __( 'Set image', 'woocommerce-pdf-invoices-packing-slips' ),
119
+ 'remove_button_text' => __( 'Remove image', 'woocommerce-pdf-invoices-packing-slips' ),
120
+ //'description' => __( '...', 'woocommerce-pdf-invoices-packing-slips' ),
121
+ )
122
+ ),
123
+ array(
124
+ 'type' => 'setting',
125
+ 'id' => 'shop_name',
126
+ 'title' => __( 'Shop Name', 'woocommerce-pdf-invoices-packing-slips' ),
127
+ 'callback' => 'text_input',
128
+ 'section' => 'general_settings',
129
+ 'args' => array(
130
+ 'option_name' => $option_name,
131
+ 'id' => 'shop_name',
132
+ 'size' => '72',
133
+ 'translatable' => true,
134
+ )
135
+ ),
136
+ array(
137
+ 'type' => 'setting',
138
+ 'id' => 'shop_address',
139
+ 'title' => __( 'Shop Address', 'woocommerce-pdf-invoices-packing-slips' ),
140
+ 'callback' => 'textarea',
141
+ 'section' => 'general_settings',
142
+ 'args' => array(
143
+ 'option_name' => $option_name,
144
+ 'id' => 'shop_address',
145
+ 'width' => '72',
146
+ 'height' => '8',
147
+ 'translatable' => true,
148
+ //'description' => __( '...', 'woocommerce-pdf-invoices-packing-slips' ),
149
+ )
150
+ ),
151
+ array(
152
+ 'type' => 'setting',
153
+ 'id' => 'footer',
154
+ 'title' => __( 'Footer: terms & conditions, policies, etc.', 'woocommerce-pdf-invoices-packing-slips' ),
155
+ 'callback' => 'textarea',
156
+ 'section' => 'general_settings',
157
+ 'args' => array(
158
+ 'option_name' => $option_name,
159
+ 'id' => 'footer',
160
+ 'width' => '72',
161
+ 'height' => '4',
162
+ 'translatable' => true,
163
+ //'description' => __( '...', 'woocommerce-pdf-invoices-packing-slips' ),
164
+ )
165
+ ),
166
+ array(
167
+ 'type' => 'section',
168
+ 'id' => 'extra_template_fields',
169
+ 'title' => __( 'Extra template fields', 'woocommerce-pdf-invoices-packing-slips' ),
170
+ 'callback' => 'custom_fields_section',
171
+ ),
172
+ array(
173
+ 'type' => 'setting',
174
+ 'id' => 'extra_1',
175
+ 'title' => __( 'Extra field 1', 'woocommerce-pdf-invoices-packing-slips' ),
176
+ 'callback' => 'textarea',
177
+ 'section' => 'extra_template_fields',
178
+ 'args' => array(
179
+ 'option_name' => $option_name,
180
+ 'id' => 'extra_1',
181
+ 'width' => '72',
182
+ 'height' => '8',
183
+ 'description' => __( 'This is footer column 1 in the <i>Modern (Premium)</i> template', 'woocommerce-pdf-invoices-packing-slips' ),
184
+ 'translatable' => true,
185
+ )
186
+ ),
187
+ array(
188
+ 'type' => 'setting',
189
+ 'id' => 'extra_2',
190
+ 'title' => __( 'Extra field 2', 'woocommerce-pdf-invoices-packing-slips' ),
191
+ 'callback' => 'textarea',
192
+ 'section' => 'extra_template_fields',
193
+ 'args' => array(
194
+ 'option_name' => $option_name,
195
+ 'id' => 'extra_2',
196
+ 'width' => '72',
197
+ 'height' => '8',
198
+ 'description' => __( 'This is footer column 2 in the <i>Modern (Premium)</i> template', 'woocommerce-pdf-invoices-packing-slips' ),
199
+ 'translatable' => true,
200
+ )
201
+ ),
202
+ array(
203
+ 'type' => 'setting',
204
+ 'id' => 'extra_3',
205
+ 'title' => __( 'Extra field 3', 'woocommerce-pdf-invoices-packing-slips' ),
206
+ 'callback' => 'textarea',
207
+ 'section' => 'extra_template_fields',
208
+ 'args' => array(
209
+ 'option_name' => $option_name,
210
+ 'id' => 'extra_3',
211
+ 'width' => '72',
212
+ 'height' => '8',
213
+ 'description' => __( 'This is footer column 3 in the <i>Modern (Premium)</i> template', 'woocommerce-pdf-invoices-packing-slips' ),
214
+ 'translatable' => true,
215
+ )
216
+ ),
217
+ );
218
+
219
+ // allow plugins to alter settings fields
220
+ $settings_fields = apply_filters( 'wpo_wcpdf_settings_fields_general', $settings_fields, $page, $option_group, $option_name );
221
+ WPO_WCPDF()->settings->add_settings_fields( $settings_fields, $page, $option_group, $option_name );
222
+ return;
223
+ }
224
+
225
+ public function attachment_settings_hint( $active_tab, $active_section ) {
226
+ // save or check option to hide attachments settings hint
227
+ if ( isset( $_GET['wpo_wcpdf_hide_attachments_hint'] ) ) {
228
+ update_option( 'wpo_wcpdf_hide_attachments_hint', true );
229
+ $hide_hint = true;
230
+ } else {
231
+ $hide_hint = get_option( 'wpo_wcpdf_hide_attachments_hint' );
232
+ }
233
+
234
+ if ( $active_tab == 'general' && !$hide_hint ) {
235
+ $documents = WPO_WCPDF()->documents->get_documents();
236
+
237
+ foreach ($documents as $document) {
238
+ if ( $document->get_type() == 'invoice' ) {
239
+ $invoice_email_ids = $document->get_attach_to_email_ids();
240
+ if (empty($invoice_email_ids)) {
241
+ include_once( WPO_WCPDF()->plugin_path() . '/includes/views/attachment-settings-hint.php' );
242
+ }
243
+ }
244
+ }
245
+ }
246
+ }
247
+
248
+ /**
249
+ * List templates in plugin folder, theme folder & child theme folder
250
+ * @return array template path => template name
251
+ */
252
+ public function find_templates() {
253
+ $installed_templates = array();
254
+
255
+ // get base paths
256
+ $template_base_path = ( defined( 'WC_TEMPLATE_PATH' ) ? WC_TEMPLATE_PATH : $GLOBALS['woocommerce']->template_url );
257
+ $template_base_path = untrailingslashit( $template_base_path );
258
+ $template_paths = array (
259
+ // note the order: child-theme before theme, so that array_unique filters out parent doubles
260
+ 'default' => WPO_WCPDF()->plugin_path() . '/templates/',
261
+ 'child-theme' => get_stylesheet_directory() . "/{$template_base_path}/pdf/",
262
+ 'theme' => get_template_directory() . "/{$template_base_path}/pdf/",
263
+ );
264
+
265
+ $template_paths = apply_filters( 'wpo_wcpdf_template_paths', $template_paths );
266
+
267
+ if ( defined('WP_CONTENT_DIR') && strpos( WP_CONTENT_DIR, ABSPATH ) !== false ) {
268
+ $forwardslash_basepath = str_replace('\\','/', ABSPATH);
269
+ } else {
270
+ $forwardslash_basepath = str_replace('\\','/', WP_CONTENT_DIR);
271
+ }
272
+
273
+ foreach ($template_paths as $template_source => $template_path) {
274
+ $dirs = (array) glob( $template_path . '*' , GLOB_ONLYDIR);
275
+
276
+ foreach ($dirs as $dir) {
277
+ // we're stripping abspath to make the plugin settings more portable
278
+ $forwardslash_dir = str_replace('\\','/', $dir);
279
+ $installed_templates[ str_replace( $forwardslash_basepath, '', $forwardslash_dir ) ] = basename($dir);
280
+ }
281
+ }
282
+
283
+ // remove parent doubles
284
+ $installed_templates = array_unique($installed_templates);
285
+
286
+ if (empty($installed_templates)) {
287
+ // fallback to Simple template for servers with glob() disabled
288
+ $simple_template_path = str_replace( ABSPATH, '', $template_paths['default'] . 'Simple' );
289
+ $installed_templates[$simple_template_path] = 'Simple';
290
+ }
291
+
292
+ return apply_filters( 'wpo_wcpdf_templates', $installed_templates );
293
+ }
294
+
295
+ }
296
+
297
+ endif; // class_exists
298
+
299
  return new Settings_General();
includes/documents/abstract-wcpdf-order-document-methods.php CHANGED
@@ -1,1009 +1,1018 @@
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
- $address_comparison_fields = apply_filters( 'wpo_wcpdf_address_comparison_fields', array(
71
- 'first_name',
72
- 'last_name',
73
- 'company',
74
- 'address_1',
75
- 'address_2',
76
- 'city',
77
- 'state',
78
- 'postcode',
79
- 'country'
80
- ), $this );
81
-
82
- foreach ($address_comparison_fields as $address_field) {
83
- $billing_field = WCX_Order::get_prop( $order, "billing_{$address_field}", 'view');
84
- $shipping_field = WCX_Order::get_prop( $order, "shipping_{$address_field}", 'view');
85
- if ( $shipping_field != $billing_field ) {
86
- // this address field is different -> ships to different address!
87
- return true;
88
- }
89
- }
90
-
91
- //if we got here, it means the addresses are equal -> doesn't ship to different address!
92
- return apply_filters( 'wpo_wcpdf_ships_to_different_address', false, $order, $this );
93
- }
94
-
95
- /**
96
- * Return/Show billing address
97
- */
98
- public function get_billing_address() {
99
- // always prefer parent billing address for refunds
100
- if ( $this->is_refund( $this->order ) ) {
101
- // temporarily switch order to make all filters / order calls work correctly
102
- $refund = $this->order;
103
- $this->order = $this->get_refund_parent( $this->order );
104
- $address = apply_filters( 'wpo_wcpdf_billing_address', $this->order->get_formatted_billing_address(), $this );
105
- // switch back & unset
106
- $this->order = $refund;
107
- unset($refund);
108
- } elseif ( $address = $this->order->get_formatted_billing_address() ) {
109
- // regular shop_order
110
- $address = apply_filters( 'wpo_wcpdf_billing_address', $address, $this );
111
- } else {
112
- // no address
113
- $address = apply_filters( 'wpo_wcpdf_billing_address', __('N/A', 'woocommerce-pdf-invoices-packing-slips' ), $this );
114
- }
115
-
116
- return $address;
117
- }
118
- public function billing_address() {
119
- echo $this->get_billing_address();
120
- }
121
-
122
- /**
123
- * Return/Show billing email
124
- */
125
- public function get_billing_email() {
126
- $billing_email = WCX_Order::get_prop( $this->order, 'billing_email', 'view' );
127
-
128
- if ( !$billing_email && $this->is_refund( $this->order ) ) {
129
- // try parent
130
- $parent_order = $this->get_refund_parent( $this->order );
131
- $billing_email = WCX_Order::get_prop( $parent_order, 'billing_email', 'view' );
132
- }
133
-
134
- return apply_filters( 'wpo_wcpdf_billing_email', $billing_email, $this );
135
- }
136
- public function billing_email() {
137
- echo $this->get_billing_email();
138
- }
139
-
140
- /**
141
- * Return/Show billing phone
142
- */
143
- public function get_billing_phone() {
144
- $billing_phone = WCX_Order::get_prop( $this->order, 'billing_phone', 'view' );
145
-
146
- if ( !$billing_phone && $this->is_refund( $this->order ) ) {
147
- // try parent
148
- $parent_order = $this->get_refund_parent( $this->order );
149
- $billing_phone = WCX_Order::get_prop( $parent_order, 'billing_phone', 'view' );
150
- }
151
-
152
- return apply_filters( 'wpo_wcpdf_billing_phone', $billing_phone, $this );
153
- }
154
- public function billing_phone() {
155
- echo $this->get_billing_phone();
156
- }
157
-
158
- /**
159
- * Return/Show shipping address
160
- */
161
- public function get_shipping_address() {
162
- // always prefer parent shipping address for refunds
163
- if ( $this->is_refund( $this->order ) ) {
164
- // temporarily switch order to make all filters / order calls work correctly
165
- $refund = $this->order;
166
- $this->order = $this->get_refund_parent( $this->order );
167
- $address = apply_filters( 'wpo_wcpdf_shipping_address', $this->order->get_formatted_shipping_address(), $this );
168
- // switch back & unset
169
- $this->order = $refund;
170
- unset($refund);
171
- } elseif ( $address = $this->order->get_formatted_shipping_address() ) {
172
- // regular shop_order
173
- $address = apply_filters( 'wpo_wcpdf_shipping_address', $address, $this );
174
- } else {
175
- // no address
176
- $address = apply_filters( 'wpo_wcpdf_shipping_address', __('N/A', 'woocommerce-pdf-invoices-packing-slips' ), $this );
177
- }
178
-
179
- return $address;
180
- }
181
- public function shipping_address() {
182
- echo $this->get_shipping_address();
183
- }
184
-
185
- /**
186
- * Return/Show a custom field
187
- */
188
- public function get_custom_field( $field_name ) {
189
- $custom_field = WCX_Order::get_meta( $this->order, $field_name, true );
190
-
191
- // WC3.0 fallback to properties
192
- $property = str_replace('-', '_', sanitize_title( ltrim($field_name, '_') ) );
193
- if ( !$custom_field && is_callable( array( $this->order, "get_{$property}" ) ) ) {
194
- $custom_field = $this->order->{"get_{$property}"}( 'view' );
195
- }
196
-
197
- // fallback to parent for refunds
198
- if ( !$custom_field && $this->is_refund( $this->order ) ) {
199
- $parent_order = $this->get_refund_parent( $this->order );
200
- $custom_field = WCX_Order::get_meta( $parent_order, $field_name, true );
201
-
202
- // WC3.0 fallback to properties
203
- if ( !$custom_field && is_callable( array( $parent_order, "get_{$property}" ) ) ) {
204
- $custom_field = $parent_order->{"get_{$property}"}( 'view' );
205
- }
206
- }
207
-
208
- return apply_filters( 'wpo_wcpdf_billing_custom_field', $custom_field, $this );
209
- }
210
- public function custom_field( $field_name, $field_label = '', $display_empty = false ) {
211
- $custom_field = $this->get_custom_field( $field_name );
212
- if (!empty($field_label)){
213
- // add a a trailing space to the label
214
- $field_label .= ' ';
215
- }
216
-
217
- if (!empty($custom_field) || $display_empty) {
218
- echo $field_label . nl2br ($custom_field);
219
- }
220
- }
221
-
222
- /**
223
- * Return/show product attribute
224
- */
225
- public function get_product_attribute( $attribute_name, $product ) {
226
- // first, check the text attributes
227
- $attributes = $product->get_attributes();
228
- $attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
229
- if (array_key_exists( sanitize_title( $attribute_name ), $attributes) ) {
230
- $attribute = $product->get_attribute ( $attribute_name );
231
- } elseif (array_key_exists( sanitize_title( $attribute_key ), $attributes) ) {
232
- $attribute = $product->get_attribute ( $attribute_key );
233
- }
234
-
235
- if (empty($attribute)) {
236
- // not a text attribute, try attribute taxonomy
237
- $attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
238
- $product_id = WCX_Product::get_prop($product, 'id');
239
- $product_terms = @wc_get_product_terms( $product_id, $attribute_key, array( 'fields' => 'names' ) );
240
- // check if not empty, then display
241
- if ( !empty($product_terms) ) {
242
- $attribute = array_shift( $product_terms );
243
- }
244
- }
245
-
246
- // WC3.0+ fallback parent product for variations
247
- if ( empty($attribute) && version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) && $product->is_type( 'variation' ) ) {
248
- $product = wc_get_product( $product->get_parent_id() );
249
- $attribute = $this->get_product_attribute( $attribute_name, $product );
250
- }
251
-
252
- return isset($attribute) ? $attribute : false;
253
- }
254
- public function product_attribute( $attribute_name, $product ) {
255
- echo $this->get_product_attribute( $attribute_name, $product );
256
- }
257
-
258
- /**
259
- * Return/Show order notes
260
- * could use $order->get_customer_order_notes(), but that filters out private notes already
261
- */
262
- public function get_order_notes( $filter = 'customer' ) {
263
- if ( $this->is_refund( $this->order ) ) {
264
- $post_id = $this->get_refund_parent_id( $this->order );
265
- } else {
266
- $post_id = $this->order_id;
267
- }
268
-
269
- if ( empty( $post_id ) ) {
270
- return; // prevent order notes from all orders showing when document is not loaded properly
271
- }
272
-
273
- $args = array(
274
- 'post_id' => $post_id,
275
- 'approve' => 'approve',
276
- 'type' => 'order_note'
277
- );
278
-
279
- remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
280
-
281
- $notes = get_comments( $args );
282
-
283
- add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
284
-
285
- if ( $notes ) {
286
- foreach( $notes as $key => $note ) {
287
- if ( $filter == 'customer' && !get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
288
- unset($notes[$key]);
289
- }
290
- if ( $filter == 'private' && get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
291
- unset($notes[$key]);
292
- }
293
- }
294
- return $notes;
295
- }
296
- }
297
- public function order_notes( $filter = 'customer' ) {
298
- $notes = $this->get_order_notes( $filter );
299
- if ( $notes ) {
300
- foreach( $notes as $note ) {
301
- ?>
302
- <div class="note_content">
303
- <?php echo wpautop( wptexturize( wp_kses_post( $note->comment_content ) ) ); ?>
304
- </div>
305
- <?php
306
- }
307
- }
308
- }
309
-
310
- /**
311
- * Return/Show the current date
312
- */
313
- public function get_current_date() {
314
- return apply_filters( 'wpo_wcpdf_date', date_i18n( get_option( 'date_format' ) ) );
315
- }
316
- public function current_date() {
317
- echo $this->get_current_date();
318
- }
319
-
320
- /**
321
- * Return/Show payment method
322
- */
323
- public function get_payment_method() {
324
- $payment_method_label = __( 'Payment method', 'woocommerce-pdf-invoices-packing-slips' );
325
-
326
- if ( $this->is_refund( $this->order ) ) {
327
- $parent_order = $this->get_refund_parent( $this->order );
328
- $payment_method_title = WCX_Order::get_prop( $parent_order, 'payment_method_title', 'view' );
329
- } else {
330
- $payment_method_title = WCX_Order::get_prop( $this->order, 'payment_method_title', 'view' );
331
- }
332
-
333
- $payment_method = __( $payment_method_title, 'woocommerce' );
334
-
335
- return apply_filters( 'wpo_wcpdf_payment_method', $payment_method, $this );
336
- }
337
- public function payment_method() {
338
- echo $this->get_payment_method();
339
- }
340
-
341
- /**
342
- * Return/Show shipping method
343
- */
344
- public function get_shipping_method() {
345
- $shipping_method_label = __( 'Shipping method', 'woocommerce-pdf-invoices-packing-slips' );
346
- $shipping_method = __( $this->order->get_shipping_method(), 'woocommerce' );
347
- return apply_filters( 'wpo_wcpdf_shipping_method', $shipping_method, $this );
348
- }
349
- public function shipping_method() {
350
- echo $this->get_shipping_method();
351
- }
352
-
353
- /**
354
- * Return/Show order number
355
- */
356
- public function get_order_number() {
357
- // try parent first
358
- if ( $this->is_refund( $this->order ) ) {
359
- $parent_order = $this->get_refund_parent( $this->order );
360
- $order_number = $parent_order->get_order_number();
361
- } else {
362
- $order_number = $this->order->get_order_number();
363
- }
364
-
365
- // Trim the hash to have a clean number but still
366
- // support any filters that were applied before.
367
- $order_number = ltrim($order_number, '#');
368
- return apply_filters( 'wpo_wcpdf_order_number', $order_number, $this );
369
- }
370
- public function order_number() {
371
- echo $this->get_order_number();
372
- }
373
-
374
- /**
375
- * Return/Show the order date
376
- */
377
- public function get_order_date() {
378
- if ( $this->is_refund( $this->order ) ) {
379
- $parent_order = $this->get_refund_parent( $this->order );
380
- $order_date = WCX_Order::get_prop( $parent_order, 'date_created' );
381
- } else {
382
- $order_date = WCX_Order::get_prop( $this->order, 'date_created' );
383
- }
384
-
385
- $date = $order_date->date_i18n( get_option( 'date_format' ) );
386
- $mysql_date = $order_date->date( "Y-m-d H:i:s" );
387
- return apply_filters( 'wpo_wcpdf_order_date', $date, $mysql_date, $this );
388
- }
389
- public function order_date() {
390
- echo $this->get_order_date();
391
- }
392
-
393
- /**
394
- * Return the order items
395
- */
396
- public function get_order_items() {
397
- $items = $this->order->get_items();
398
- $data_list = array();
399
-
400
- if( sizeof( $items ) > 0 ) {
401
- foreach ( $items as $item_id => $item ) {
402
- // Array with data for the pdf template
403
- $data = array();
404
-
405
- // Set the item_id
406
- $data['item_id'] = $item_id;
407
-
408
- // Set the id
409
- $data['product_id'] = $item['product_id'];
410
- $data['variation_id'] = $item['variation_id'];
411
-
412
- // Set item name
413
- $data['name'] = $item['name'];
414
-
415
- // Set item quantity
416
- $data['quantity'] = $item['qty'];
417
-
418
- // Set the line total (=after discount)
419
- $data['line_total'] = $this->format_price( $item['line_total'] );
420
- $data['single_line_total'] = $this->format_price( $item['line_total'] / max( 1, abs( $item['qty'] ) ) );
421
- $data['line_tax'] = $this->format_price( $item['line_tax'] );
422
- $data['single_line_tax'] = $this->format_price( $item['line_tax'] / max( 1, abs( $item['qty'] ) ) );
423
-
424
- $line_tax_data = maybe_unserialize( isset( $item['line_tax_data'] ) ? $item['line_tax_data'] : '' );
425
- $data['tax_rates'] = $this->get_tax_rate( $item['tax_class'], $item['line_total'], $item['line_tax'], $line_tax_data );
426
-
427
- // Set the line subtotal (=before discount)
428
- $data['line_subtotal'] = $this->format_price( $item['line_subtotal'] );
429
- $data['line_subtotal_tax'] = $this->format_price( $item['line_subtotal_tax'] );
430
- $data['ex_price'] = $this->get_formatted_item_price( $item, 'total', 'excl' );
431
- $data['price'] = $this->get_formatted_item_price( $item, 'total' );
432
- $data['order_price'] = $this->order->get_formatted_line_subtotal( $item ); // formatted according to WC settings
433
-
434
- // Calculate the single price with the same rules as the formatted line subtotal (!)
435
- // = before discount
436
- $data['ex_single_price'] = $this->get_formatted_item_price( $item, 'single', 'excl' );
437
- $data['single_price'] = $this->get_formatted_item_price( $item, 'single' );
438
-
439
- // Pass complete item array
440
- $data['item'] = $item;
441
-
442
- // Get the product to add more info
443
- $product = $this->order->get_product_from_item( $item );
444
-
445
- // Checking fo existance, thanks to MDesigner0
446
- if( !empty( $product ) ) {
447
- // Thumbnail (full img tag)
448
- $data['thumbnail'] = $this->get_thumbnail( $product );
449
-
450
- // Set item SKU
451
- $data['sku'] = $product->get_sku();
452
-
453
- // Set item weight
454
- $data['weight'] = $product->get_weight();
455
-
456
- // Set item dimensions
457
- $data['dimensions'] = WCX_Product::get_dimensions( $product );
458
-
459
- // Pass complete product object
460
- $data['product'] = $product;
461
-
462
- } else {
463
- $data['product'] = null;
464
- }
465
-
466
- // Set item meta
467
- if (function_exists('wc_display_item_meta')) { // WC3.0+
468
- $data['meta'] = wc_display_item_meta( $item, array(
469
- 'echo' => false,
470
- ) );
471
- } else {
472
- if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '<' ) ) {
473
- $meta = new \WC_Order_Item_Meta( $item['item_meta'], $product );
474
- } else { // pass complete item for WC2.4+
475
- $meta = new \WC_Order_Item_Meta( $item, $product );
476
- }
477
- $data['meta'] = $meta->display( false, true );
478
- }
479
-
480
- $data_list[$item_id] = apply_filters( 'wpo_wcpdf_order_item_data', $data, $this->order, $this->get_type() );
481
- }
482
- }
483
-
484
- return apply_filters( 'wpo_wcpdf_order_items_data', $data_list, $this->order, $this->get_type() );
485
- }
486
-
487
- /**
488
- * Get the tax rates/percentages for a given tax class
489
- * @param string $tax_class tax class slug
490
- * @return string $tax_rates imploded list of tax rates
491
- */
492
- public function get_tax_rate( $tax_class, $line_total, $line_tax, $line_tax_data = '' ) {
493
- // first try the easy wc2.2+ way, using line_tax_data
494
- if ( !empty( $line_tax_data ) && isset($line_tax_data['total']) ) {
495
- $tax_rates = array();
496
-
497
- $line_taxes = $line_tax_data['subtotal'];
498
- foreach ( $line_taxes as $tax_id => $tax ) {
499
- if ( isset($tax) && $tax !== '' ) {
500
- $tax_rates[] = $this->get_tax_rate_by_id( $tax_id ) . ' %';
501
- }
502
- }
503
-
504
- $tax_rates = implode(' ,', $tax_rates );
505
- return $tax_rates;
506
- }
507
-
508
- if ( $line_tax == 0 ) {
509
- return '-'; // no need to determine tax rate...
510
- }
511
-
512
- if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 && !apply_filters( 'wpo_wcpdf_calculate_tax_rate', false ) ) {
513
- // WC 2.1 or newer is used
514
- $tax = new \WC_Tax();
515
- $taxes = $tax->get_rates( $tax_class );
516
-
517
- $tax_rates = array();
518
-
519
- foreach ($taxes as $tax) {
520
- $tax_rates[$tax['label']] = round( $tax['rate'], 2 ).' %';
521
- }
522
-
523
- if (empty($tax_rates)) {
524
- // one last try: manually calculate
525
- if ( $line_total != 0) {
526
- $tax_rates[] = round( ($line_tax / $line_total)*100, 1 ).' %';
527
- } else {
528
- $tax_rates[] = '-';
529
- }
530
- }
531
-
532
- $tax_rates = implode(' ,', $tax_rates );
533
- } else {
534
- // Backwards compatibility/fallback: calculate tax from line items
535
- if ( $line_total != 0) {
536
- $tax_rates = round( ($line_tax / $line_total)*100, 1 ).' %';
537
- } else {
538
- $tax_rates = '-';
539
- }
540
- }
541
-
542
- return $tax_rates;
543
- }
544
-
545
- /**
546
- * Returns the percentage rate (float) for a given tax rate ID.
547
- * @param int $rate_id woocommerce tax rate id
548
- * @return float $rate percentage rate
549
- */
550
- public function get_tax_rate_by_id( $rate_id ) {
551
- global $wpdb;
552
- $rate = $wpdb->get_var( $wpdb->prepare( "SELECT tax_rate FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id ) );
553
- return (float) $rate;
554
- }
555
-
556
- /**
557
- * Returns a an array with rate_id => tax rate data (array) of all tax rates in woocommerce
558
- * @return array $tax_rate_ids keyed by id
559
- */
560
- public function get_tax_rate_ids() {
561
- global $wpdb;
562
- $rates = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates" );
563
-
564
- $tax_rate_ids = array();
565
- foreach ($rates as $rate) {
566
- // var_dump($rate->tax_rate_id);
567
- // die($rate);
568
- $rate_id = $rate->tax_rate_id;
569
- unset($rate->tax_rate_id);
570
- $tax_rate_ids[$rate_id] = (array) $rate;
571
- }
572
-
573
- return $tax_rate_ids;
574
- }
575
-
576
- /**
577
- * Returns the main product image ID
578
- * Adapted from the WC_Product class
579
- * (does not support thumbnail sizes)
580
- *
581
- * @access public
582
- * @return string
583
- */
584
- public function get_thumbnail_id ( $product ) {
585
- global $woocommerce;
586
-
587
- $product_id = WCX_Product::get_id( $product );
588
-
589
- if ( has_post_thumbnail( $product_id ) ) {
590
- $thumbnail_id = get_post_thumbnail_id ( $product_id );
591
- } elseif ( ( $parent_id = wp_get_post_parent_id( $product_id ) ) && has_post_thumbnail( $parent_id ) ) {
592
- $thumbnail_id = get_post_thumbnail_id ( $parent_id );
593
- } else {
594
- $thumbnail_id = false;
595
- }
596
-
597
- return $thumbnail_id;
598
- }
599
-
600
- /**
601
- * Returns the thumbnail image tag
602
- *
603
- * uses the internal WooCommerce/WP functions and extracts the image url or path
604
- * rather than the thumbnail ID, to simplify the code and make it possible to
605
- * filter for different thumbnail sizes
606
- *
607
- * @access public
608
- * @return string
609
- */
610
- public function get_thumbnail ( $product ) {
611
- // Get default WooCommerce img tag (url/http)
612
- $size = apply_filters( 'wpo_wcpdf_thumbnail_size', 'shop_thumbnail' );
613
- $thumbnail_img_tag_url = $product->get_image( $size, array( 'title' => '' ) );
614
-
615
- // Extract the url from img
616
- preg_match('/<img(.*)src(.*)=(.*)"(.*)"/U', $thumbnail_img_tag_url, $thumbnail_url );
617
- // remove http/https from image tag url to avoid mixed origin conflicts
618
- $thumbnail_url = array_pop($thumbnail_url);
619
- $contextless_thumbnail_url = str_replace(array('http://','https://'), '', $thumbnail_url );
620
- $contextless_site_url = str_replace(array('http://','https://'), '', trailingslashit(get_site_url()));
621
-
622
- // convert url to path
623
- $thumbnail_path = str_replace( $contextless_site_url, ABSPATH, $contextless_thumbnail_url);
624
- // fallback if thumbnail file doesn't exist
625
- if (apply_filters('wpo_wcpdf_use_path', true) && !file_exists($thumbnail_path)) {
626
- if ($thumbnail_id = $this->get_thumbnail_id( $product ) ) {
627
- $thumbnail_path = get_attached_file( $thumbnail_id );
628
- }
629
- }
630
-
631
- // Thumbnail (full img tag)
632
- if (apply_filters('wpo_wcpdf_use_path', true) && file_exists($thumbnail_path)) {
633
- // load img with server path by default
634
- $thumbnail = sprintf('<img width="90" height="90" src="%s" class="attachment-shop_thumbnail wp-post-image">', $thumbnail_path );
635
- } else {
636
- // load img with http url when filtered
637
- $thumbnail = $thumbnail_img_tag_url;
638
- }
639
-
640
- // die($thumbnail);
641
- return $thumbnail;
642
- }
643
-
644
- /**
645
- * Return the order totals listing
646
- */
647
- public function get_woocommerce_totals() {
648
- // get totals and remove the semicolon
649
- $totals = apply_filters( 'wpo_wcpdf_raw_order_totals', $this->order->get_order_item_totals(), $this->order );
650
-
651
- // remove the colon for every label
652
- foreach ( $totals as $key => $total ) {
653
- $label = $total['label'];
654
- $colon = strrpos( $label, ':' );
655
- if( $colon !== false ) {
656
- $label = substr_replace( $label, '', $colon, 1 );
657
- }
658
- $totals[$key]['label'] = $label;
659
- }
660
-
661
- // WC2.4 fix order_total for refunded orders
662
- // not if this is the actual refund!
663
- if ( ! $this->is_refund( $this->order ) ) {
664
- if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '>=' ) && isset($totals['order_total']) ) {
665
- if ( version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) ) {
666
- $tax_display = get_option( 'woocommerce_tax_display_cart' );
667
- } else {
668
- $tax_display = WCX_Order::get_prop( $this->order, 'tax_display_cart' );
669
- }
670
-
671
- $totals['order_total']['value'] = wc_price( $this->order->get_total(), array( 'currency' => WCX_Order::get_prop( $this->order, 'currency' ) ) );
672
- $order_total = $this->order->get_total();
673
- $tax_string = '';
674
-
675
- // Tax for inclusive prices
676
- if ( wc_tax_enabled() && 'incl' == $tax_display ) {
677
- $tax_string_array = array();
678
- if ( 'itemized' == get_option( 'woocommerce_tax_total_display' ) ) {
679
- foreach ( $this->order->get_tax_totals() as $code => $tax ) {
680
- $tax_amount = $tax->formatted_amount;
681
- $tax_string_array[] = sprintf( '%s %s', $tax_amount, $tax->label );
682
- }
683
- } else {
684
- $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() );
685
- }
686
- if ( ! empty( $tax_string_array ) ) {
687
- if ( version_compare( WOOCOMMERCE_VERSION, '2.6', '>=' ) ) {
688
- $tax_string = ' ' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
689
- } else {
690
- // use old capitalized string
691
- $tax_string = ' ' . sprintf( __( '(Includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
692
- }
693
- }
694
- }
695
-
696
- $totals['order_total']['value'] .= $tax_string;
697
- }
698
-
699
- // remove refund lines (shouldn't be in invoice)
700
- foreach ( $totals as $key => $total ) {
701
- if ( strpos($key, 'refund_') !== false ) {
702
- unset( $totals[$key] );
703
- }
704
- }
705
-
706
- }
707
-
708
- return apply_filters( 'wpo_wcpdf_woocommerce_totals', $totals, $this->order, $this->get_type() );
709
- }
710
-
711
- /**
712
- * Return/show the order subtotal
713
- */
714
- public function get_order_subtotal( $tax = 'excl', $discount = 'incl' ) { // set $tax to 'incl' to include tax, same for $discount
715
- //$compound = ($discount == 'incl')?true:false;
716
- $subtotal = $this->order->get_subtotal_to_display( false, $tax );
717
-
718
- $subtotal = ($pos = strpos($subtotal, ' <small')) ? substr($subtotal, 0, $pos) : $subtotal; //removing the 'excluding tax' text
719
-
720
- $subtotal = array (
721
- 'label' => __('Subtotal', 'woocommerce-pdf-invoices-packing-slips' ),
722
- 'value' => $subtotal,
723
- );
724
-
725
- return apply_filters( 'wpo_wcpdf_order_subtotal', $subtotal, $tax, $discount, $this );
726
- }
727
- public function order_subtotal( $tax = 'excl', $discount = 'incl' ) {
728
- $subtotal = $this->get_order_subtotal( $tax, $discount );
729
- echo $subtotal['value'];
730
- }
731
-
732
- /**
733
- * Return/show the order shipping costs
734
- */
735
- public function get_order_shipping( $tax = 'excl' ) { // set $tax to 'incl' to include tax
736
- $shipping_cost = WCX_Order::get_prop( $this->order, 'shipping_total', 'view' );
737
- $shipping_tax = WCX_Order::get_prop( $this->order, 'shipping_tax', 'view' );
738
-
739
- if ($tax == 'excl' ) {
740
- $formatted_shipping_cost = $this->format_price( $shipping_cost );
741
- } else {
742
- $formatted_shipping_cost = $this->format_price( $shipping_cost + $shipping_tax );
743
- }
744
-
745
- $shipping = array (
746
- 'label' => __('Shipping', 'woocommerce-pdf-invoices-packing-slips' ),
747
- 'value' => $formatted_shipping_cost,
748
- 'tax' => $this->format_price( $shipping_tax ),
749
- );
750
- return apply_filters( 'wpo_wcpdf_order_shipping', $shipping, $tax, $this );
751
- }
752
- public function order_shipping( $tax = 'excl' ) {
753
- $shipping = $this->get_order_shipping( $tax );
754
- echo $shipping['value'];
755
- }
756
-
757
- /**
758
- * Return/show the total discount
759
- */
760
- public function get_order_discount( $type = 'total', $tax = 'incl' ) {
761
- if ( $tax == 'incl' ) {
762
- switch ($type) {
763
- case 'cart':
764
- // Cart Discount - pre-tax discounts. (deprecated in WC2.3)
765
- $discount_value = $this->order->get_cart_discount();
766
- break;
767
- case 'order':
768
- // Order Discount - post-tax discounts. (deprecated in WC2.3)
769
- $discount_value = $this->order->get_order_discount();
770
- break;
771
- case 'total':
772
- // Total Discount
773
- if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
774
- $discount_value = $this->order->get_total_discount( false ); // $ex_tax = false
775
- } else {
776
- // WC2.2 and older: recalculate to include tax
777
- $discount_value = 0;
778
- $items = $this->order->get_items();;
779
- if( sizeof( $items ) > 0 ) {
780
- foreach( $items as $item ) {
781
- $discount_value += ($item['line_subtotal'] + $item['line_subtotal_tax']) - ($item['line_total'] + $item['line_tax']);
782
- }
783
- }
784
- }
785
-
786
- break;
787
- default:
788
- // Total Discount - Cart & Order Discounts combined
789
- $discount_value = $this->order->get_total_discount();
790
- break;
791
- }
792
- } else { // calculate discount excluding tax
793
- if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
794
- $discount_value = $this->order->get_total_discount( true ); // $ex_tax = true
795
- } else {
796
- // WC2.2 and older: recalculate to exclude tax
797
- $discount_value = 0;
798
-
799
- $items = $this->order->get_items();;
800
- if( sizeof( $items ) > 0 ) {
801
- foreach( $items as $item ) {
802
- $discount_value += ($item['line_subtotal'] - $item['line_total']);
803
- }
804
- }
805
- }
806
- }
807
-
808
- $discount = array (
809
- 'label' => __('Discount', 'woocommerce-pdf-invoices-packing-slips' ),
810
- 'value' => $this->format_price( $discount_value ),
811
- 'raw_value' => $discount_value,
812
- );
813
-
814
- if ( round( $discount_value, 3 ) != 0 ) {
815
- return apply_filters( 'wpo_wcpdf_order_discount', $discount, $type, $tax, $this );
816
- }
817
- }
818
- public function order_discount( $type = 'total', $tax = 'incl' ) {
819
- $discount = $this->get_order_discount( $type, $tax );
820
- echo $discount['value'];
821
- }
822
-
823
- /**
824
- * Return the order fees
825
- */
826
- public function get_order_fees( $tax = 'excl' ) {
827
- if ( $_fees = $this->order->get_fees() ) {
828
- foreach( $_fees as $id => $fee ) {
829
- if ($tax == 'excl' ) {
830
- $fee_price = $this->format_price( $fee['line_total'] );
831
- } else {
832
- $fee_price = $this->format_price( $fee['line_total'] + $fee['line_tax'] );
833
- }
834
-
835
- $fees[ $id ] = array(
836
- 'label' => $fee['name'],
837
- 'value' => $fee_price,
838
- 'line_total' => $this->format_price( $fee['line_total'] ),
839
- 'line_tax' => $this->format_price( $fee['line_tax'] )
840
- );
841
- }
842
- return $fees;
843
- }
844
- }
845
-
846
- /**
847
- * Return the order taxes
848
- */
849
- public function get_order_taxes() {
850
- $tax_label = __( 'VAT', 'woocommerce-pdf-invoices-packing-slips' ); // register alternate label translation
851
- $tax_label = __( 'Tax rate', 'woocommerce-pdf-invoices-packing-slips' );
852
- $tax_rate_ids = $this->get_tax_rate_ids();
853
- if ( $order_taxes = $this->order->get_taxes() ) {
854
- foreach ( $order_taxes as $key => $tax ) {
855
- if ( WCX::is_wc_version_gte_3_0() ) {
856
- $taxes[ $key ] = array(
857
- 'label' => $tax->get_label(),
858
- 'value' => $this->format_price( $tax->get_tax_total() + $tax->get_shipping_tax_total() ),
859
- 'rate_id' => $tax->get_rate_id(),
860
- 'tax_amount' => $tax->get_tax_total(),
861
- 'shipping_tax_amount' => $tax->get_shipping_tax_total(),
862
- 'rate' => isset( $tax_rate_ids[ $tax->get_rate_id() ] ) ? ( (float) $tax_rate_ids[$tax->get_rate_id()]['tax_rate'] ) . ' %': '',
863
- );
864
- } else {
865
- $taxes[ $key ] = array(
866
- 'label' => isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ],
867
- 'value' => $this->format_price( ( $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ] ) ),
868
- 'rate_id' => $tax['rate_id'],
869
- 'tax_amount' => $tax['tax_amount'],
870
- 'shipping_tax_amount' => $tax['shipping_tax_amount'],
871
- 'rate' => isset( $tax_rate_ids[ $tax['rate_id'] ] ) ? ( (float) $tax_rate_ids[$tax['rate_id']]['tax_rate'] ) . ' %': '',
872
- );
873
- }
874
-
875
- }
876
-
877
- return apply_filters( 'wpo_wcpdf_order_taxes', $taxes, $this );
878
- }
879
- }
880
-
881
- /**
882
- * Return/show the order grand total
883
- */
884
- public function get_order_grand_total( $tax = 'incl' ) {
885
- if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 ) {
886
- // WC 2.1 or newer is used
887
- $total_unformatted = $this->order->get_total();
888
- } else {
889
- // Backwards compatibility
890
- $total_unformatted = $this->order->get_order_total();
891
- }
892
-
893
- if ($tax == 'excl' ) {
894
- $total = $this->format_price( $total_unformatted - $this->order->get_total_tax() );
895
- $label = __( 'Total ex. VAT', 'woocommerce-pdf-invoices-packing-slips' );
896
- } else {
897
- $total = $this->format_price( ( $total_unformatted ) );
898
- $label = __( 'Total', 'woocommerce-pdf-invoices-packing-slips' );
899
- }
900
-
901
- $grand_total = array(
902
- 'label' => $label,
903
- 'value' => $total,
904
- );
905
-
906
- return apply_filters( 'wpo_wcpdf_order_grand_total', $grand_total, $tax, $this );
907
- }
908
- public function order_grand_total( $tax = 'incl' ) {
909
- $grand_total = $this->get_order_grand_total( $tax );
910
- echo $grand_total['value'];
911
- }
912
-
913
-
914
- /**
915
- * Return/Show shipping notes
916
- */
917
- public function get_shipping_notes() {
918
- if ( $this->is_refund( $this->order ) ) {
919
- // return reason for refund if order is a refund
920
- if ( version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) ) {
921
- $shipping_notes = $this->order->get_reason();
922
- } elseif ( method_exists($this->order, 'get_refund_reason') ) {
923
- $shipping_notes = $this->order->get_refund_reason();
924
- } else {
925
- $shipping_notes = wpautop( wptexturize( WCX_Order::get_prop( $this->order, 'customer_note', 'view' ) ) );
926
- }
927
- } else {
928
- $shipping_notes = wpautop( wptexturize( WCX_Order::get_prop( $this->order, 'customer_note', 'view' ) ) );
929
- }
930
- return apply_filters( 'wpo_wcpdf_shipping_notes', $shipping_notes, $this );
931
- }
932
- public function shipping_notes() {
933
- echo $this->get_shipping_notes();
934
- }
935
-
936
- /**
937
- * wrapper for wc_price, ensuring currency is always passed
938
- */
939
- public function format_price( $price, $args = array() ) {
940
- if ( function_exists( 'wc_price' ) ) { // WC 2.1+
941
- $args['currency'] = WCX_Order::get_prop( $this->order, 'currency' );
942
- $formatted_price = wc_price( $price, $args );
943
- } else {
944
- $formatted_price = woocommerce_price( $price );
945
- }
946
-
947
- return $formatted_price;
948
- }
949
- public function wc_price( $price, $args = array() ) {
950
- return $this->format_price( $price, $args );
951
- }
952
-
953
- /**
954
- * Gets price - formatted for display.
955
- *
956
- * @access public
957
- * @param mixed $item
958
- * @return string
959
- */
960
- public function get_formatted_item_price ( $item, $type, $tax_display = '' ) {
961
- if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) ) {
962
- return;
963
- }
964
-
965
- $divide_by = ($type == 'single' && $item['qty'] != 0 )?abs($item['qty']):1; //divide by 1 if $type is not 'single' (thus 'total')
966
- if ( $tax_display == 'excl' ) {
967
- $item_price = $this->format_price( ($this->order->get_line_subtotal( $item )) / $divide_by );
968
- } else {
969
- $item_price = $this->format_price( ($this->order->get_line_subtotal( $item, true )) / $divide_by );
970
- }
971
-
972
- return $item_price;
973
- }
974
-
975
- public function get_invoice_number() {
976
- // Call the woocommerce_invoice_number filter and let third-party plugins set a number.
977
- // Default is null, so we can detect whether a plugin has set the invoice number
978
- $third_party_invoice_number = apply_filters( 'woocommerce_invoice_number', null, $this->order_id );
979
- if ($third_party_invoice_number !== null) {
980
- return $third_party_invoice_number;
981
- }
982
-
983
- if ( $invoice_number = $this->get_number('invoice') ) {
984
- return $formatted_invoice_number = $invoice_number->get_formatted();
985
- } else {
986
- return '';
987
- }
988
- }
989
-
990
- public function invoice_number() {
991
- echo $this->get_invoice_number();
992
- }
993
-
994
- public function get_invoice_date() {
995
- if ( $invoice_date = $this->get_date('invoice') ) {
996
- return $invoice_date->date_i18n( apply_filters( 'wpo_wcpdf_date_format', wc_date_format(), $this ) );
997
- } else {
998
- return '';
999
- }
1000
- }
1001
-
1002
- public function invoice_date() {
1003
- echo $this->get_invoice_date();
1004
- }
1005
-
1006
-
1007
- }
1008
-
 
 
 
 
 
 
 
 
 
1009
  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
+ $address_comparison_fields = apply_filters( 'wpo_wcpdf_address_comparison_fields', array(
71
+ 'first_name',
72
+ 'last_name',
73
+ 'company',
74
+ 'address_1',
75
+ 'address_2',
76
+ 'city',
77
+ 'state',
78
+ 'postcode',
79
+ 'country'
80
+ ), $this );
81
+
82
+ foreach ($address_comparison_fields as $address_field) {
83
+ $billing_field = WCX_Order::get_prop( $order, "billing_{$address_field}", 'view');
84
+ $shipping_field = WCX_Order::get_prop( $order, "shipping_{$address_field}", 'view');
85
+ if ( $shipping_field != $billing_field ) {
86
+ // this address field is different -> ships to different address!
87
+ return true;
88
+ }
89
+ }
90
+
91
+ //if we got here, it means the addresses are equal -> doesn't ship to different address!
92
+ return apply_filters( 'wpo_wcpdf_ships_to_different_address', false, $order, $this );
93
+ }
94
+
95
+ /**
96
+ * Return/Show billing address
97
+ */
98
+ public function get_billing_address() {
99
+ // always prefer parent billing address for refunds
100
+ if ( $this->is_refund( $this->order ) ) {
101
+ // temporarily switch order to make all filters / order calls work correctly
102
+ $refund = $this->order;
103
+ $this->order = $this->get_refund_parent( $this->order );
104
+ $address = apply_filters( 'wpo_wcpdf_billing_address', $this->order->get_formatted_billing_address(), $this );
105
+ // switch back & unset
106
+ $this->order = $refund;
107
+ unset($refund);
108
+ } elseif ( $address = $this->order->get_formatted_billing_address() ) {
109
+ // regular shop_order
110
+ $address = apply_filters( 'wpo_wcpdf_billing_address', $address, $this );
111
+ } else {
112
+ // no address
113
+ $address = apply_filters( 'wpo_wcpdf_billing_address', __('N/A', 'woocommerce-pdf-invoices-packing-slips' ), $this );
114
+ }
115
+
116
+ return $address;
117
+ }
118
+ public function billing_address() {
119
+ echo $this->get_billing_address();
120
+ }
121
+
122
+ /**
123
+ * Return/Show billing email
124
+ */
125
+ public function get_billing_email() {
126
+ $billing_email = WCX_Order::get_prop( $this->order, 'billing_email', 'view' );
127
+
128
+ if ( !$billing_email && $this->is_refund( $this->order ) ) {
129
+ // try parent
130
+ $parent_order = $this->get_refund_parent( $this->order );
131
+ $billing_email = WCX_Order::get_prop( $parent_order, 'billing_email', 'view' );
132
+ }
133
+
134
+ return apply_filters( 'wpo_wcpdf_billing_email', $billing_email, $this );
135
+ }
136
+ public function billing_email() {
137
+ echo $this->get_billing_email();
138
+ }
139
+
140
+ /**
141
+ * Return/Show billing phone
142
+ */
143
+ public function get_billing_phone() {
144
+ $billing_phone = WCX_Order::get_prop( $this->order, 'billing_phone', 'view' );
145
+
146
+ if ( !$billing_phone && $this->is_refund( $this->order ) ) {
147
+ // try parent
148
+ $parent_order = $this->get_refund_parent( $this->order );
149
+ $billing_phone = WCX_Order::get_prop( $parent_order, 'billing_phone', 'view' );
150
+ }
151
+
152
+ return apply_filters( 'wpo_wcpdf_billing_phone', $billing_phone, $this );
153
+ }
154
+ public function billing_phone() {
155
+ echo $this->get_billing_phone();
156
+ }
157
+
158
+ /**
159
+ * Return/Show shipping address
160
+ */
161
+ public function get_shipping_address() {
162
+ // always prefer parent shipping address for refunds
163
+ if ( $this->is_refund( $this->order ) ) {
164
+ // temporarily switch order to make all filters / order calls work correctly
165
+ $refund = $this->order;
166
+ $this->order = $this->get_refund_parent( $this->order );
167
+ $address = apply_filters( 'wpo_wcpdf_shipping_address', $this->order->get_formatted_shipping_address(), $this );
168
+ // switch back & unset
169
+ $this->order = $refund;
170
+ unset($refund);
171
+ } elseif ( $address = $this->order->get_formatted_shipping_address() ) {
172
+ // regular shop_order
173
+ $address = apply_filters( 'wpo_wcpdf_shipping_address', $address, $this );
174
+ } else {
175
+ // no address
176
+ $address = apply_filters( 'wpo_wcpdf_shipping_address', __('N/A', 'woocommerce-pdf-invoices-packing-slips' ), $this );
177
+ }
178
+
179
+ return $address;
180
+ }
181
+ public function shipping_address() {
182
+ echo $this->get_shipping_address();
183
+ }
184
+
185
+ /**
186
+ * Return/Show a custom field
187
+ */
188
+ public function get_custom_field( $field_name ) {
189
+ $custom_field = WCX_Order::get_meta( $this->order, $field_name, true );
190
+
191
+ // WC3.0 fallback to properties
192
+ $property = str_replace('-', '_', sanitize_title( ltrim($field_name, '_') ) );
193
+ if ( !$custom_field && is_callable( array( $this->order, "get_{$property}" ) ) ) {
194
+ $custom_field = $this->order->{"get_{$property}"}( 'view' );
195
+ }
196
+
197
+ // fallback to parent for refunds
198
+ if ( !$custom_field && $this->is_refund( $this->order ) ) {
199
+ $parent_order = $this->get_refund_parent( $this->order );
200
+ $custom_field = WCX_Order::get_meta( $parent_order, $field_name, true );
201
+
202
+ // WC3.0 fallback to properties
203
+ if ( !$custom_field && is_callable( array( $parent_order, "get_{$property}" ) ) ) {
204
+ $custom_field = $parent_order->{"get_{$property}"}( 'view' );
205
+ }
206
+ }
207
+
208
+ return apply_filters( 'wpo_wcpdf_billing_custom_field', $custom_field, $this );
209
+ }
210
+ public function custom_field( $field_name, $field_label = '', $display_empty = false ) {
211
+ $custom_field = $this->get_custom_field( $field_name );
212
+ if (!empty($field_label)){
213
+ // add a a trailing space to the label
214
+ $field_label .= ' ';
215
+ }
216
+
217
+ if (!empty($custom_field) || $display_empty) {
218
+ echo $field_label . nl2br ($custom_field);
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Return/show product attribute
224
+ */
225
+ public function get_product_attribute( $attribute_name, $product ) {
226
+ // first, check the text attributes
227
+ $attributes = $product->get_attributes();
228
+ $attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
229
+ if (array_key_exists( sanitize_title( $attribute_name ), $attributes) ) {
230
+ $attribute = $product->get_attribute ( $attribute_name );
231
+ } elseif (array_key_exists( sanitize_title( $attribute_key ), $attributes) ) {
232
+ $attribute = $product->get_attribute ( $attribute_key );
233
+ }
234
+
235
+ if (empty($attribute)) {
236
+ // not a text attribute, try attribute taxonomy
237
+ $attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
238
+ $product_id = WCX_Product::get_prop($product, 'id');
239
+ $product_terms = @wc_get_product_terms( $product_id, $attribute_key, array( 'fields' => 'names' ) );
240
+ // check if not empty, then display
241
+ if ( !empty($product_terms) ) {
242
+ $attribute = array_shift( $product_terms );
243
+ }
244
+ }
245
+
246
+ // WC3.0+ fallback parent product for variations
247
+ if ( empty($attribute) && version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) && $product->is_type( 'variation' ) ) {
248
+ $product = wc_get_product( $product->get_parent_id() );
249
+ $attribute = $this->get_product_attribute( $attribute_name, $product );
250
+ }
251
+
252
+ return isset($attribute) ? $attribute : false;
253
+ }
254
+ public function product_attribute( $attribute_name, $product ) {
255
+ echo $this->get_product_attribute( $attribute_name, $product );
256
+ }
257
+
258
+ /**
259
+ * Return/Show order notes
260
+ * could use $order->get_customer_order_notes(), but that filters out private notes already
261
+ */
262
+ public function get_order_notes( $filter = 'customer' ) {
263
+ if ( $this->is_refund( $this->order ) ) {
264
+ $post_id = $this->get_refund_parent_id( $this->order );
265
+ } else {
266
+ $post_id = $this->order_id;
267
+ }
268
+
269
+ if ( empty( $post_id ) ) {
270
+ return; // prevent order notes from all orders showing when document is not loaded properly
271
+ }
272
+
273
+ $args = array(
274
+ 'post_id' => $post_id,
275
+ 'approve' => 'approve',
276
+ 'type' => 'order_note'
277
+ );
278
+
279
+ remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
280
+
281
+ $notes = get_comments( $args );
282
+
283
+ add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
284
+
285
+ if ( $notes ) {
286
+ foreach( $notes as $key => $note ) {
287
+ if ( $filter == 'customer' && !get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
288
+ unset($notes[$key]);
289
+ }
290
+ if ( $filter == 'private' && get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
291
+ unset($notes[$key]);
292
+ }
293
+ }
294
+ return $notes;
295
+ }
296
+ }
297
+ public function order_notes( $filter = 'customer' ) {
298
+ $notes = $this->get_order_notes( $filter );
299
+ if ( $notes ) {
300
+ foreach( $notes as $note ) {
301
+ ?>
302
+ <div class="note_content">
303
+ <?php echo wpautop( wptexturize( wp_kses_post( $note->comment_content ) ) ); ?>
304
+ </div>
305
+ <?php
306
+ }
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Return/Show the current date
312
+ */
313
+ public function get_current_date() {
314
+ return apply_filters( 'wpo_wcpdf_date', date_i18n( get_option( 'date_format' ) ) );
315
+ }
316
+ public function current_date() {
317
+ echo $this->get_current_date();
318
+ }
319
+
320
+ /**
321
+ * Return/Show payment method
322
+ */
323
+ public function get_payment_method() {
324
+ $payment_method_label = __( 'Payment method', 'woocommerce-pdf-invoices-packing-slips' );
325
+
326
+ if ( $this->is_refund( $this->order ) ) {
327
+ $parent_order = $this->get_refund_parent( $this->order );
328
+ $payment_method_title = WCX_Order::get_prop( $parent_order, 'payment_method_title', 'view' );
329
+ } else {
330
+ $payment_method_title = WCX_Order::get_prop( $this->order, 'payment_method_title', 'view' );
331
+ }
332
+
333
+ $payment_method = __( $payment_method_title, 'woocommerce' );
334
+
335
+ return apply_filters( 'wpo_wcpdf_payment_method', $payment_method, $this );
336
+ }
337
+ public function payment_method() {
338
+ echo $this->get_payment_method();
339
+ }
340
+
341
+ /**
342
+ * Return/Show shipping method
343
+ */
344
+ public function get_shipping_method() {
345
+ $shipping_method_label = __( 'Shipping method', 'woocommerce-pdf-invoices-packing-slips' );
346
+ $shipping_method = __( $this->order->get_shipping_method(), 'woocommerce' );
347
+ return apply_filters( 'wpo_wcpdf_shipping_method', $shipping_method, $this );
348
+ }
349
+ public function shipping_method() {
350
+ echo $this->get_shipping_method();
351
+ }
352
+
353
+ /**
354
+ * Return/Show order number
355
+ */
356
+ public function get_order_number() {
357
+ // try parent first
358
+ if ( $this->is_refund( $this->order ) ) {
359
+ $parent_order = $this->get_refund_parent( $this->order );
360
+ $order_number = $parent_order->get_order_number();
361
+ } else {
362
+ $order_number = $this->order->get_order_number();
363
+ }
364
+
365
+ // Trim the hash to have a clean number but still
366
+ // support any filters that were applied before.
367
+ $order_number = ltrim($order_number, '#');
368
+ return apply_filters( 'wpo_wcpdf_order_number', $order_number, $this );
369
+ }
370
+ public function order_number() {
371
+ echo $this->get_order_number();
372
+ }
373
+
374
+ /**
375
+ * Return/Show the order date
376
+ */
377
+ public function get_order_date() {
378
+ if ( $this->is_refund( $this->order ) ) {
379
+ $parent_order = $this->get_refund_parent( $this->order );
380
+ $order_date = WCX_Order::get_prop( $parent_order, 'date_created' );
381
+ } else {
382
+ $order_date = WCX_Order::get_prop( $this->order, 'date_created' );
383
+ }
384
+
385
+ $date = $order_date->date_i18n( get_option( 'date_format' ) );
386
+ $mysql_date = $order_date->date( "Y-m-d H:i:s" );
387
+ return apply_filters( 'wpo_wcpdf_order_date', $date, $mysql_date, $this );
388
+ }
389
+ public function order_date() {
390
+ echo $this->get_order_date();
391
+ }
392
+
393
+ /**
394
+ * Return the order items
395
+ */
396
+ public function get_order_items() {
397
+ $items = $this->order->get_items();
398
+ $data_list = array();
399
+
400
+ if( sizeof( $items ) > 0 ) {
401
+ foreach ( $items as $item_id => $item ) {
402
+ // Array with data for the pdf template
403
+ $data = array();
404
+
405
+ // Set the item_id
406
+ $data['item_id'] = $item_id;
407
+
408
+ // Set the id
409
+ $data['product_id'] = $item['product_id'];
410
+ $data['variation_id'] = $item['variation_id'];
411
+
412
+ // Set item name
413
+ $data['name'] = $item['name'];
414
+
415
+ // Set item quantity
416
+ $data['quantity'] = $item['qty'];
417
+
418
+ // Set the line total (=after discount)
419
+ $data['line_total'] = $this->format_price( $item['line_total'] );
420
+ $data['single_line_total'] = $this->format_price( $item['line_total'] / max( 1, abs( $item['qty'] ) ) );
421
+ $data['line_tax'] = $this->format_price( $item['line_tax'] );
422
+ $data['single_line_tax'] = $this->format_price( $item['line_tax'] / max( 1, abs( $item['qty'] ) ) );
423
+
424
+ $line_tax_data = maybe_unserialize( isset( $item['line_tax_data'] ) ? $item['line_tax_data'] : '' );
425
+ $data['tax_rates'] = $this->get_tax_rate( $item['tax_class'], $item['line_total'], $item['line_tax'], $line_tax_data );
426
+
427
+ // Set the line subtotal (=before discount)
428
+ $data['line_subtotal'] = $this->format_price( $item['line_subtotal'] );
429
+ $data['line_subtotal_tax'] = $this->format_price( $item['line_subtotal_tax'] );
430
+ $data['ex_price'] = $this->get_formatted_item_price( $item, 'total', 'excl' );
431
+ $data['price'] = $this->get_formatted_item_price( $item, 'total' );
432
+ $data['order_price'] = $this->order->get_formatted_line_subtotal( $item ); // formatted according to WC settings
433
+
434
+ // Calculate the single price with the same rules as the formatted line subtotal (!)
435
+ // = before discount
436
+ $data['ex_single_price'] = $this->get_formatted_item_price( $item, 'single', 'excl' );
437
+ $data['single_price'] = $this->get_formatted_item_price( $item, 'single' );
438
+
439
+ // Pass complete item array
440
+ $data['item'] = $item;
441
+
442
+ // Get the product to add more info
443
+ $product = $this->order->get_product_from_item( $item );
444
+
445
+ // Checking fo existance, thanks to MDesigner0
446
+ if( !empty( $product ) ) {
447
+ // Thumbnail (full img tag)
448
+ $data['thumbnail'] = $this->get_thumbnail( $product );
449
+
450
+ // Set item SKU
451
+ $data['sku'] = $product->get_sku();
452
+
453
+ // Set item weight
454
+ $data['weight'] = $product->get_weight();
455
+
456
+ // Set item dimensions
457
+ $data['dimensions'] = WCX_Product::get_dimensions( $product );
458
+
459
+ // Pass complete product object
460
+ $data['product'] = $product;
461
+
462
+ } else {
463
+ $data['product'] = null;
464
+ }
465
+
466
+ // Set item meta
467
+ if (function_exists('wc_display_item_meta')) { // WC3.0+
468
+ $data['meta'] = wc_display_item_meta( $item, array(
469
+ 'echo' => false,
470
+ ) );
471
+ } else {
472
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '<' ) ) {
473
+ $meta = new \WC_Order_Item_Meta( $item['item_meta'], $product );
474
+ } else { // pass complete item for WC2.4+
475
+ $meta = new \WC_Order_Item_Meta( $item, $product );
476
+ }
477
+ $data['meta'] = $meta->display( false, true );
478
+ }
479
+
480
+ $data_list[$item_id] = apply_filters( 'wpo_wcpdf_order_item_data', $data, $this->order, $this->get_type() );
481
+ }
482
+ }
483
+
484
+ return apply_filters( 'wpo_wcpdf_order_items_data', $data_list, $this->order, $this->get_type() );
485
+ }
486
+
487
+ /**
488
+ * Get the tax rates/percentages for a given tax class
489
+ * @param string $tax_class tax class slug
490
+ * @return string $tax_rates imploded list of tax rates
491
+ */
492
+ public function get_tax_rate( $tax_class, $line_total, $line_tax, $line_tax_data = '' ) {
493
+ // first try the easy wc2.2+ way, using line_tax_data
494
+ if ( !empty( $line_tax_data ) && isset($line_tax_data['total']) ) {
495
+ $tax_rates = array();
496
+
497
+ $line_taxes = $line_tax_data['subtotal'];
498
+ foreach ( $line_taxes as $tax_id => $tax ) {
499
+ if ( isset($tax) && $tax !== '' ) {
500
+ $tax_rates[] = $this->get_tax_rate_by_id( $tax_id ) . ' %';
501
+ }
502
+ }
503
+
504
+ $tax_rates = implode(' ,', $tax_rates );
505
+ return $tax_rates;
506
+ }
507
+
508
+ if ( $line_tax == 0 ) {
509
+ return '-'; // no need to determine tax rate...
510
+ }
511
+
512
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 && !apply_filters( 'wpo_wcpdf_calculate_tax_rate', false ) ) {
513
+ // WC 2.1 or newer is used
514
+ $tax = new \WC_Tax();
515
+ $taxes = $tax->get_rates( $tax_class );
516
+
517
+ $tax_rates = array();
518
+
519
+ foreach ($taxes as $tax) {
520
+ $tax_rates[$tax['label']] = round( $tax['rate'], 2 ).' %';
521
+ }
522
+
523
+ if (empty($tax_rates)) {
524
+ // one last try: manually calculate
525
+ if ( $line_total != 0) {
526
+ $tax_rates[] = round( ($line_tax / $line_total)*100, 1 ).' %';
527
+ } else {
528
+ $tax_rates[] = '-';
529
+ }
530
+ }
531
+
532
+ $tax_rates = implode(' ,', $tax_rates );
533
+ } else {
534
+ // Backwards compatibility/fallback: calculate tax from line items
535
+ if ( $line_total != 0) {
536
+ $tax_rates = round( ($line_tax / $line_total)*100, 1 ).' %';
537
+ } else {
538
+ $tax_rates = '-';
539
+ }
540
+ }
541
+
542
+ return $tax_rates;
543
+ }
544
+
545
+ /**
546
+ * Returns the percentage rate (float) for a given tax rate ID.
547
+ * @param int $rate_id woocommerce tax rate id
548
+ * @return float $rate percentage rate
549
+ */
550
+ public function get_tax_rate_by_id( $rate_id ) {
551
+ global $wpdb;
552
+ $rate = $wpdb->get_var( $wpdb->prepare( "SELECT tax_rate FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id ) );
553
+ return (float) $rate;
554
+ }
555
+
556
+ /**
557
+ * Returns a an array with rate_id => tax rate data (array) of all tax rates in woocommerce
558
+ * @return array $tax_rate_ids keyed by id
559
+ */
560
+ public function get_tax_rate_ids() {
561
+ global $wpdb;
562
+ $rates = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates" );
563
+
564
+ $tax_rate_ids = array();
565
+ foreach ($rates as $rate) {
566
+ // var_dump($rate->tax_rate_id);
567
+ // die($rate);
568
+ $rate_id = $rate->tax_rate_id;
569
+ unset($rate->tax_rate_id);
570
+ $tax_rate_ids[$rate_id] = (array) $rate;
571
+ }
572
+
573
+ return $tax_rate_ids;
574
+ }
575
+
576
+ /**
577
+ * Returns the main product image ID
578
+ * Adapted from the WC_Product class
579
+ * (does not support thumbnail sizes)
580
+ *
581
+ * @access public
582
+ * @return string
583
+ */
584
+ public function get_thumbnail_id ( $product ) {
585
+ global $woocommerce;
586
+
587
+ $product_id = WCX_Product::get_id( $product );
588
+
589
+ if ( has_post_thumbnail( $product_id ) ) {
590
+ $thumbnail_id = get_post_thumbnail_id ( $product_id );
591
+ } elseif ( ( $parent_id = wp_get_post_parent_id( $product_id ) ) && has_post_thumbnail( $parent_id ) ) {
592
+ $thumbnail_id = get_post_thumbnail_id ( $parent_id );
593
+ } else {
594
+ $thumbnail_id = false;
595
+ }
596
+
597
+ return $thumbnail_id;
598
+ }
599
+
600
+ /**
601
+ * Returns the thumbnail image tag
602
+ *
603
+ * uses the internal WooCommerce/WP functions and extracts the image url or path
604
+ * rather than the thumbnail ID, to simplify the code and make it possible to
605
+ * filter for different thumbnail sizes
606
+ *
607
+ * @access public
608
+ * @return string
609
+ */
610
+ public function get_thumbnail ( $product ) {
611
+ // Get default WooCommerce img tag (url/http)
612
+ $size = apply_filters( 'wpo_wcpdf_thumbnail_size', 'shop_thumbnail' );
613
+ $thumbnail_img_tag_url = $product->get_image( $size, array( 'title' => '' ) );
614
+
615
+ // Extract the url from img
616
+ preg_match('/<img(.*)src(.*)=(.*)"(.*)"/U', $thumbnail_img_tag_url, $thumbnail_url );
617
+ $thumbnail_url = array_pop($thumbnail_url);
618
+ // remove http/https from image tag url to avoid mixed origin conflicts
619
+ $contextless_thumbnail_url = ltrim( str_replace(array('http://','https://'), '', $thumbnail_url ), '/' );
620
+
621
+ // convert url to path
622
+ if ( defined('WP_CONTENT_DIR') && strpos( WP_CONTENT_DIR, ABSPATH ) !== false ) {
623
+ $forwardslash_basepath = str_replace('\\','/', ABSPATH);
624
+ $contextless_site_url = str_replace(array('http://','https://'), '', trailingslashit(get_site_url()));
625
+ } else {
626
+ // bedrock e.a
627
+ $forwardslash_basepath = str_replace('\\','/', WP_CONTENT_DIR);
628
+ $contextless_site_url = str_replace(array('http://','https://'), '', trailingslashit(WP_CONTENT_URL));
629
+ }
630
+ $thumbnail_path = str_replace( $contextless_site_url, trailingslashit( $forwardslash_basepath ), $contextless_thumbnail_url);
631
+
632
+ // fallback if thumbnail file doesn't exist
633
+ if (apply_filters('wpo_wcpdf_use_path', true) && !file_exists($thumbnail_path)) {
634
+ if ($thumbnail_id = $this->get_thumbnail_id( $product ) ) {
635
+ $thumbnail_path = get_attached_file( $thumbnail_id );
636
+ }
637
+ }
638
+
639
+ // Thumbnail (full img tag)
640
+ if (apply_filters('wpo_wcpdf_use_path', true) && file_exists($thumbnail_path)) {
641
+ // load img with server path by default
642
+ $thumbnail = sprintf('<img width="90" height="90" src="%s" class="attachment-shop_thumbnail wp-post-image">', $thumbnail_path );
643
+ } else {
644
+ // load img with http url when filtered
645
+ $thumbnail = $thumbnail_img_tag_url;
646
+ }
647
+
648
+ // die($thumbnail);
649
+ return $thumbnail;
650
+ }
651
+
652
+ /**
653
+ * Return the order totals listing
654
+ */
655
+ public function get_woocommerce_totals() {
656
+ // get totals and remove the semicolon
657
+ $totals = apply_filters( 'wpo_wcpdf_raw_order_totals', $this->order->get_order_item_totals(), $this->order );
658
+
659
+ // remove the colon for every label
660
+ foreach ( $totals as $key => $total ) {
661
+ $label = $total['label'];
662
+ $colon = strrpos( $label, ':' );
663
+ if( $colon !== false ) {
664
+ $label = substr_replace( $label, '', $colon, 1 );
665
+ }
666
+ $totals[$key]['label'] = $label;
667
+ }
668
+
669
+ // WC2.4 fix order_total for refunded orders
670
+ // not if this is the actual refund!
671
+ if ( ! $this->is_refund( $this->order ) ) {
672
+ $total_refunded = method_exists($this->order, 'get_total_refunded') ? $this->order->get_total_refunded() : 0;
673
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '>=' ) && isset($totals['order_total']) && $total_refunded ) {
674
+ if ( version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) ) {
675
+ $tax_display = get_option( 'woocommerce_tax_display_cart' );
676
+ } else {
677
+ $tax_display = WCX_Order::get_prop( $this->order, 'tax_display_cart' );
678
+ }
679
+
680
+ $totals['order_total']['value'] = wc_price( $this->order->get_total(), array( 'currency' => WCX_Order::get_prop( $this->order, 'currency' ) ) );
681
+ $order_total = $this->order->get_total();
682
+ $tax_string = '';
683
+
684
+ // Tax for inclusive prices
685
+ if ( wc_tax_enabled() && 'incl' == $tax_display ) {
686
+ $tax_string_array = array();
687
+ if ( 'itemized' == get_option( 'woocommerce_tax_total_display' ) ) {
688
+ foreach ( $this->order->get_tax_totals() as $code => $tax ) {
689
+ $tax_amount = $tax->formatted_amount;
690
+ $tax_string_array[] = sprintf( '%s %s', $tax_amount, $tax->label );
691
+ }
692
+ } else {
693
+ $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() );
694
+ }
695
+ if ( ! empty( $tax_string_array ) ) {
696
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.6', '>=' ) ) {
697
+ $tax_string = ' ' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
698
+ } else {
699
+ // use old capitalized string
700
+ $tax_string = ' ' . sprintf( __( '(Includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
701
+ }
702
+ }
703
+ }
704
+
705
+ $totals['order_total']['value'] .= $tax_string;
706
+ }
707
+
708
+ // remove refund lines (shouldn't be in invoice)
709
+ foreach ( $totals as $key => $total ) {
710
+ if ( strpos($key, 'refund_') !== false ) {
711
+ unset( $totals[$key] );
712
+ }
713
+ }
714
+
715
+ }
716
+
717
+ return apply_filters( 'wpo_wcpdf_woocommerce_totals', $totals, $this->order, $this->get_type() );
718
+ }
719
+
720
+ /**
721
+ * Return/show the order subtotal
722
+ */
723
+ public function get_order_subtotal( $tax = 'excl', $discount = 'incl' ) { // set $tax to 'incl' to include tax, same for $discount
724
+ //$compound = ($discount == 'incl')?true:false;
725
+ $subtotal = $this->order->get_subtotal_to_display( false, $tax );
726
+
727
+ $subtotal = ($pos = strpos($subtotal, ' <small')) ? substr($subtotal, 0, $pos) : $subtotal; //removing the 'excluding tax' text
728
+
729
+ $subtotal = array (
730
+ 'label' => __('Subtotal', 'woocommerce-pdf-invoices-packing-slips' ),
731
+ 'value' => $subtotal,
732
+ );
733
+
734
+ return apply_filters( 'wpo_wcpdf_order_subtotal', $subtotal, $tax, $discount, $this );
735
+ }
736
+ public function order_subtotal( $tax = 'excl', $discount = 'incl' ) {
737
+ $subtotal = $this->get_order_subtotal( $tax, $discount );
738
+ echo $subtotal['value'];
739
+ }
740
+
741
+ /**
742
+ * Return/show the order shipping costs
743
+ */
744
+ public function get_order_shipping( $tax = 'excl' ) { // set $tax to 'incl' to include tax
745
+ $shipping_cost = WCX_Order::get_prop( $this->order, 'shipping_total', 'view' );
746
+ $shipping_tax = WCX_Order::get_prop( $this->order, 'shipping_tax', 'view' );
747
+
748
+ if ($tax == 'excl' ) {
749
+ $formatted_shipping_cost = $this->format_price( $shipping_cost );
750
+ } else {
751
+ $formatted_shipping_cost = $this->format_price( $shipping_cost + $shipping_tax );
752
+ }
753
+
754
+ $shipping = array (
755
+ 'label' => __('Shipping', 'woocommerce-pdf-invoices-packing-slips' ),
756
+ 'value' => $formatted_shipping_cost,
757
+ 'tax' => $this->format_price( $shipping_tax ),
758
+ );
759
+ return apply_filters( 'wpo_wcpdf_order_shipping', $shipping, $tax, $this );
760
+ }
761
+ public function order_shipping( $tax = 'excl' ) {
762
+ $shipping = $this->get_order_shipping( $tax );
763
+ echo $shipping['value'];
764
+ }
765
+
766
+ /**
767
+ * Return/show the total discount
768
+ */
769
+ public function get_order_discount( $type = 'total', $tax = 'incl' ) {
770
+ if ( $tax == 'incl' ) {
771
+ switch ($type) {
772
+ case 'cart':
773
+ // Cart Discount - pre-tax discounts. (deprecated in WC2.3)
774
+ $discount_value = $this->order->get_cart_discount();
775
+ break;
776
+ case 'order':
777
+ // Order Discount - post-tax discounts. (deprecated in WC2.3)
778
+ $discount_value = $this->order->get_order_discount();
779
+ break;
780
+ case 'total':
781
+ // Total Discount
782
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
783
+ $discount_value = $this->order->get_total_discount( false ); // $ex_tax = false
784
+ } else {
785
+ // WC2.2 and older: recalculate to include tax
786
+ $discount_value = 0;
787
+ $items = $this->order->get_items();;
788
+ if( sizeof( $items ) > 0 ) {
789
+ foreach( $items as $item ) {
790
+ $discount_value += ($item['line_subtotal'] + $item['line_subtotal_tax']) - ($item['line_total'] + $item['line_tax']);
791
+ }
792
+ }
793
+ }
794
+
795
+ break;
796
+ default:
797
+ // Total Discount - Cart & Order Discounts combined
798
+ $discount_value = $this->order->get_total_discount();
799
+ break;
800
+ }
801
+ } else { // calculate discount excluding tax
802
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
803
+ $discount_value = $this->order->get_total_discount( true ); // $ex_tax = true
804
+ } else {
805
+ // WC2.2 and older: recalculate to exclude tax
806
+ $discount_value = 0;
807
+
808
+ $items = $this->order->get_items();;
809
+ if( sizeof( $items ) > 0 ) {
810
+ foreach( $items as $item ) {
811
+ $discount_value += ($item['line_subtotal'] - $item['line_total']);
812
+ }
813
+ }
814
+ }
815
+ }
816
+
817
+ $discount = array (
818
+ 'label' => __('Discount', 'woocommerce-pdf-invoices-packing-slips' ),
819
+ 'value' => $this->format_price( $discount_value ),
820
+ 'raw_value' => $discount_value,
821
+ );
822
+
823
+ if ( round( $discount_value, 3 ) != 0 ) {
824
+ return apply_filters( 'wpo_wcpdf_order_discount', $discount, $type, $tax, $this );
825
+ }
826
+ }
827
+ public function order_discount( $type = 'total', $tax = 'incl' ) {
828
+ $discount = $this->get_order_discount( $type, $tax );
829
+ echo $discount['value'];
830
+ }
831
+
832
+ /**
833
+ * Return the order fees
834
+ */
835
+ public function get_order_fees( $tax = 'excl' ) {
836
+ if ( $_fees = $this->order->get_fees() ) {
837
+ foreach( $_fees as $id => $fee ) {
838
+ if ($tax == 'excl' ) {
839
+ $fee_price = $this->format_price( $fee['line_total'] );
840
+ } else {
841
+ $fee_price = $this->format_price( $fee['line_total'] + $fee['line_tax'] );
842
+ }
843
+
844
+ $fees[ $id ] = array(
845
+ 'label' => $fee['name'],
846
+ 'value' => $fee_price,
847
+ 'line_total' => $this->format_price( $fee['line_total'] ),
848
+ 'line_tax' => $this->format_price( $fee['line_tax'] )
849
+ );
850
+ }
851
+ return $fees;
852
+ }
853
+ }
854
+
855
+ /**
856
+ * Return the order taxes
857
+ */
858
+ public function get_order_taxes() {
859
+ $tax_label = __( 'VAT', 'woocommerce-pdf-invoices-packing-slips' ); // register alternate label translation
860
+ $tax_label = __( 'Tax rate', 'woocommerce-pdf-invoices-packing-slips' );
861
+ $tax_rate_ids = $this->get_tax_rate_ids();
862
+ if ( $order_taxes = $this->order->get_taxes() ) {
863
+ foreach ( $order_taxes as $key => $tax ) {
864
+ if ( WCX::is_wc_version_gte_3_0() ) {
865
+ $taxes[ $key ] = array(
866
+ 'label' => $tax->get_label(),
867
+ 'value' => $this->format_price( $tax->get_tax_total() + $tax->get_shipping_tax_total() ),
868
+ 'rate_id' => $tax->get_rate_id(),
869
+ 'tax_amount' => $tax->get_tax_total(),
870
+ 'shipping_tax_amount' => $tax->get_shipping_tax_total(),
871
+ 'rate' => isset( $tax_rate_ids[ $tax->get_rate_id() ] ) ? ( (float) $tax_rate_ids[$tax->get_rate_id()]['tax_rate'] ) . ' %': '',
872
+ );
873
+ } else {
874
+ $taxes[ $key ] = array(
875
+ 'label' => isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ],
876
+ 'value' => $this->format_price( ( $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ] ) ),
877
+ 'rate_id' => $tax['rate_id'],
878
+ 'tax_amount' => $tax['tax_amount'],
879
+ 'shipping_tax_amount' => $tax['shipping_tax_amount'],
880
+ 'rate' => isset( $tax_rate_ids[ $tax['rate_id'] ] ) ? ( (float) $tax_rate_ids[$tax['rate_id']]['tax_rate'] ) . ' %': '',
881
+ );
882
+ }
883
+
884
+ }
885
+
886
+ return apply_filters( 'wpo_wcpdf_order_taxes', $taxes, $this );
887
+ }
888
+ }
889
+
890
+ /**
891
+ * Return/show the order grand total
892
+ */
893
+ public function get_order_grand_total( $tax = 'incl' ) {
894
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 ) {
895
+ // WC 2.1 or newer is used
896
+ $total_unformatted = $this->order->get_total();
897
+ } else {
898
+ // Backwards compatibility
899
+ $total_unformatted = $this->order->get_order_total();
900
+ }
901
+
902
+ if ($tax == 'excl' ) {
903
+ $total = $this->format_price( $total_unformatted - $this->order->get_total_tax() );
904
+ $label = __( 'Total ex. VAT', 'woocommerce-pdf-invoices-packing-slips' );
905
+ } else {
906
+ $total = $this->format_price( ( $total_unformatted ) );
907
+ $label = __( 'Total', 'woocommerce-pdf-invoices-packing-slips' );
908
+ }
909
+
910
+ $grand_total = array(
911
+ 'label' => $label,
912
+ 'value' => $total,
913
+ );
914
+
915
+ return apply_filters( 'wpo_wcpdf_order_grand_total', $grand_total, $tax, $this );
916
+ }
917
+ public function order_grand_total( $tax = 'incl' ) {
918
+ $grand_total = $this->get_order_grand_total( $tax );
919
+ echo $grand_total['value'];
920
+ }
921
+
922
+
923
+ /**
924
+ * Return/Show shipping notes
925
+ */
926
+ public function get_shipping_notes() {
927
+ if ( $this->is_refund( $this->order ) ) {
928
+ // return reason for refund if order is a refund
929
+ if ( version_compare( WOOCOMMERCE_VERSION, '3.0', '>=' ) ) {
930
+ $shipping_notes = $this->order->get_reason();
931
+ } elseif ( method_exists($this->order, 'get_refund_reason') ) {
932
+ $shipping_notes = $this->order->get_refund_reason();
933
+ } else {
934
+ $shipping_notes = wpautop( wptexturize( WCX_Order::get_prop( $this->order, 'customer_note', 'view' ) ) );
935
+ }
936
+ } else {
937
+ $shipping_notes = wpautop( wptexturize( WCX_Order::get_prop( $this->order, 'customer_note', 'view' ) ) );
938
+ }
939
+ return apply_filters( 'wpo_wcpdf_shipping_notes', $shipping_notes, $this );
940
+ }
941
+ public function shipping_notes() {
942
+ echo $this->get_shipping_notes();
943
+ }
944
+
945
+ /**
946
+ * wrapper for wc_price, ensuring currency is always passed
947
+ */
948
+ public function format_price( $price, $args = array() ) {
949
+ if ( function_exists( 'wc_price' ) ) { // WC 2.1+
950
+ $args['currency'] = WCX_Order::get_prop( $this->order, 'currency' );
951
+ $formatted_price = wc_price( $price, $args );
952
+ } else {
953
+ $formatted_price = woocommerce_price( $price );
954
+ }
955
+
956
+ return $formatted_price;
957
+ }
958
+ public function wc_price( $price, $args = array() ) {
959
+ return $this->format_price( $price, $args );
960
+ }
961
+
962
+ /**
963
+ * Gets price - formatted for display.
964
+ *
965
+ * @access public
966
+ * @param mixed $item
967
+ * @return string
968
+ */
969
+ public function get_formatted_item_price ( $item, $type, $tax_display = '' ) {
970
+ if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) ) {
971
+ return;
972
+ }
973
+
974
+ $divide_by = ($type == 'single' && $item['qty'] != 0 )?abs($item['qty']):1; //divide by 1 if $type is not 'single' (thus 'total')
975
+ if ( $tax_display == 'excl' ) {
976
+ $item_price = $this->format_price( ($this->order->get_line_subtotal( $item )) / $divide_by );
977
+ } else {
978
+ $item_price = $this->format_price( ($this->order->get_line_subtotal( $item, true )) / $divide_by );
979
+ }
980
+
981
+ return $item_price;
982
+ }
983
+
984
+ public function get_invoice_number() {
985
+ // Call the woocommerce_invoice_number filter and let third-party plugins set a number.
986
+ // Default is null, so we can detect whether a plugin has set the invoice number
987
+ $third_party_invoice_number = apply_filters( 'woocommerce_invoice_number', null, $this->order_id );
988
+ if ($third_party_invoice_number !== null) {
989
+ return $third_party_invoice_number;
990
+ }
991
+
992
+ if ( $invoice_number = $this->get_number('invoice') ) {
993
+ return $formatted_invoice_number = $invoice_number->get_formatted();
994
+ } else {
995
+ return '';
996
+ }
997
+ }
998
+
999
+ public function invoice_number() {
1000
+ echo $this->get_invoice_number();
1001
+ }
1002
+
1003
+ public function get_invoice_date() {
1004
+ if ( $invoice_date = $this->get_date('invoice') ) {
1005
+ return $invoice_date->date_i18n( apply_filters( 'wpo_wcpdf_date_format', wc_date_format(), $this ) );
1006
+ } else {
1007
+ return '';
1008
+ }
1009
+ }
1010
+
1011
+ public function invoice_date() {
1012
+ echo $this->get_invoice_date();
1013
+ }
1014
+
1015
+
1016
+ }
1017
+
1018
  endif; // class_exists
includes/views/attachment-settings-hint.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $invoice_settings_url = add_query_arg( array(
3
+ 'tab' => 'documents',
4
+ 'section' => 'invoice',
5
+ ) );
6
+ ?>
7
+ <style>
8
+ .wcpdf-attachment-settings-hint {
9
+ display: inline-block;
10
+ background: #fff;
11
+ border-left: 4px solid #cc99c2 !important;
12
+ -webkit-box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
13
+ box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
14
+ padding: 15px;
15
+ margin-top: 15px;
16
+ font-size: 120%;
17
+ }
18
+ </style>
19
+ <!-- <div id="message" class="updated woocommerce-message"> -->
20
+ <div class="wcpdf-attachment-settings-hint">
21
+ <?php printf(__( "It looks like you haven't setup any email attachments yet, check the settings under <b>%sDocuments > Invoice%s</b>", 'woocommerce-pdf-invoices-packing-slips' ), '<a href="'.$invoice_settings_url.'">', '</a>'); ?><br>
22
+ <?php printf('<a href="%s" style="font">%s</a>', add_query_arg( 'wpo_wcpdf_hide_attachments_hint', 'true' ), __( 'Hide this message', 'woocommerce-pdf-invoices-packing-slips' ) ); ?>
23
+ </div>
includes/views/wcpdf-extensions.php CHANGED
@@ -1,149 +1,131 @@
1
- <script type="text/javascript">
2
- jQuery(document).ready(function() {
3
- jQuery('.extensions .more').hide();
4
-
5
- jQuery('.extensions > li').click(function() {
6
- jQuery(this).toggleClass('expanded');
7
- jQuery(this).find('.more').slideToggle();
8
- });
9
- });
10
- </script>
11
-
12
- <div class="wcpdf-extensions-ad">
13
- <?php $no_pro = !class_exists('WooCommerce_PDF_IPS_Pro') && !class_exists('WooCommerce_PDF_IPS_Dropbox') && !class_exists('WooCommerce_PDF_IPS_Templates'); ?>
14
- <img src="<?php echo WPO_WCPDF()->plugin_url() . '/assets/images/wpo-helper.png'; ?>" class="wpo-helper">
15
- <h3><?php _e( 'Check out these premium extensions!', 'woocommerce-pdf-invoices-packing-slips' ); ?></h3>
16
- <i>(<?php _e( 'click items to read more', 'woocommerce-pdf-invoices-packing-slips' ); ?>)</i>
17
- <ul class="extensions">
18
- <?php if ( $no_pro ): ?>
19
- <!-- No Pro extensions: Ad for PDF bundle -->
20
- <li>
21
- <?php _e('Premium PDF Invoice bundle: Everything you need for a perfect invoicing system', 'woocommerce-pdf-invoices-packing-slips' )?>
22
- <div class="more" style="display:none;">
23
- <h4><?php _e( 'Supercharge WooCommerce PDF Invoices & Packing Slips with the all our premium extensions:', 'woocommerce-pdf-invoices-packing-slips' ); ?></h4>
24
- <?php _e( 'Professional features:', 'woocommerce-pdf-invoices-packing-slips' ); ?>
25
- <ul>
26
- <li><?php _e( 'Email/print/download <b>PDF Credit Notes & Proforma invoices</b>', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
27
- <li><?php _e( 'Send out a separate <b>notification email</b> with (or without) PDF invoices/packing slips, for example to a drop-shipper or a supplier.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
28
- <li><?php _e( 'Attach <b>up to 3 static files</b> (for example a terms & conditions document) to the WooCommerce emails of your choice.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
29
- <li><?php _e( 'Use <b>separate numbering systems</b> and/or format for proforma invoices and credit notes or utilize the main invoice numbering system', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
30
- <li><?php _e( '<b>Customize</b> the <b>shipping & billing address</b> format to include additional custom fields, font sizes etc. without the need to create a custom template.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
31
- <li><?php _e( 'Use the plugin in multilingual <b>WPML</b> setups', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
32
- </ul>
33
- <?php _e('Advanced, customizable templates', 'woocommerce-pdf-invoices-packing-slips' )?>
34
- <ul>
35
- <li><?php _e( 'Completely customize the invoice contents (prices, taxes, thumbnails) to your needs with a drag & drop customizer', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
36
- <li><?php _e( 'Two extra stylish premade templates (Modern & Business)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
37
- </ul>
38
- <?php _e('Upload automatically to dropbox', 'woocommerce-pdf-invoices-packing-slips' )?>
39
- <ul>
40
- <li><?php _e( 'This extension conveniently uploads all the invoices (and other pdf documents from the professional extension) that are emailed to your customers to Dropbox. The best way to keep your invoice administration up to date!', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
41
- </ul>
42
- <br>
43
- <a href="https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-bundle/" target="_blank"><?php _e("Get WooCommerce PDF Invoices & Packing Slips Bundle", 'woocommerce-pdf-invoices-packing-slips' ); ?></a>
44
- </div>
45
- </li>
46
- <?php endif; ?>
47
- <?php
48
- // NO BUNDLE: separate ads
49
- if (!class_exists('WooCommerce_PDF_IPS_Pro') && !$no_pro) {
50
- ?>
51
- <li>
52
- <?php _e('Go Pro: Proforma invoices, credit notes (=refunds) & more!', 'woocommerce-pdf-invoices-packing-slips' )?>
53
- <div class="more" style="display:none;">
54
- <?php _e( 'Supercharge WooCommerce PDF Invoices & Packing Slips with the following features:', 'woocommerce-pdf-invoices-packing-slips' ); ?>
55
- <ul>
56
- <li><?php _e( 'Email/print/download <b>PDF Credit Notes & Proforma invoices</b>', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
57
- <li><?php _e( 'Send out a separate <b>notification email</b> with (or without) PDF invoices/packing slips, for example to a drop-shipper or a supplier.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
58
- <li><?php _e( 'Attach <b>up to 3 static files</b> (for example a terms & conditions document) to the WooCommerce emails of your choice.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
59
- <li><?php _e( 'Use <b>separate numbering systems</b> and/or format for proforma invoices and credit notes or utilize the main invoice numbering system', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
60
- <li><?php _e( '<b>Customize</b> the <b>shipping & billing address</b> format to include additional custom fields, font sizes etc. without the need to create a custom template.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
61
- <li><?php _e( 'Use the plugin in multilingual <b>WPML</b> setups', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
62
- </ul>
63
- <a href="https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-professional/" target="_blank"><?php _e("Get WooCommerce PDF Invoices & Packing Slips Professional!", 'woocommerce-pdf-invoices-packing-slips' ); ?></a>
64
- </li>
65
- <?php } ?>
66
-
67
- <?php
68
- if (!class_exists('WPO_WC_Smart_Reminder_Emails')) {
69
- ?>
70
- <li>
71
- <?php _e('Automatically send payment reminders to your customers', 'woocommerce-pdf-invoices-packing-slips' )?>
72
- <div class="more" style="display:none;">
73
- <?php _e('WooCommerce Smart Reminder emails', 'woocommerce-pdf-invoices-packing-slips' )?>
74
- <ul>
75
- <li><?php _e( '<b>Completely automatic</b> scheduled emails', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
76
- <li><?php _e( '<b>Rich text editor</b> for the email text, including placeholders for data from the order (name, order total, etc)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
77
- <li><?php _e( 'Configure the exact requirements for sending an email (time after order, order status, payment method)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
78
- <li><?php _e( 'Fully <b>WPML Compatible</b> – emails will be automatically sent in the order language.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
79
- <li><?php _e( '<b>Super versatile!</b> Can be used for any kind of reminder email (review reminders, repeat purchases)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
80
- <li><b><?php _e( 'Integrates seamlessly with the PDF Invoices & Packing Slips plugin', 'woocommerce-pdf-invoices-packing-slips' ); ?></b></li>
81
- </ul>
82
- <a href="https://wpovernight.com/downloads/woocommerce-reminder-emails-payment-reminders/" target="_blank"><?php _e("Get WooCommerce Smart Reminder Emails", 'woocommerce-pdf-invoices-packing-slips' ); ?></a>
83
- </div>
84
- </li>
85
- <?php } ?>
86
-
87
- <?php
88
- if (!class_exists('WooCommerce_PDF_IPS_Dropbox') && !$no_pro) {
89
- ?>
90
- <li>
91
- <?php _e('Upload all invoices automatically to your dropbox', 'woocommerce-pdf-invoices-packing-slips' )?>
92
- <div class="more" style="display:none;">
93
- <table>
94
- <tr>
95
- <td><img src="<?php echo WPO_WCPDF()->plugin_url() . '/assets/images/dropbox_logo.png'; ?>" class="dropbox-logo"></td>
96
- <td>
97
- <?php _e( 'This extension conveniently uploads all the invoices (and other pdf documents from the professional extension) that are emailed to your customers to Dropbox. The best way to keep your invoice administration up to date!', 'woocommerce-pdf-invoices-packing-slips' ); ?><br/>
98
- <a href="https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-dropbox/" target="_blank"><?php _e("Get WooCommerce PDF Invoices & Packing Slips to dropbox!", 'woocommerce-pdf-invoices-packing-slips' ); ?></a>
99
- </td>
100
- </tr>
101
- </table>
102
- </div>
103
- </li>
104
- <?php } ?>
105
-
106
- <?php
107
- if (!class_exists('WooCommerce_Ext_PrintOrders')) {
108
- ?>
109
- <li>
110
- <?php _e('Automatically send new orders or packing slips to your printer, as soon as the customer orders!', 'woocommerce-pdf-invoices-packing-slips' )?>
111
- <div class="more" style="display:none;">
112
- <table>
113
- <tr>
114
- <td><img src="<?php echo WPO_WCPDF()->plugin_url() . '/assets/images/cloud-print.png'; ?>" class="cloud-logo"></td>
115
- <td>
116
- <?php _e( 'Check out the WooCommerce Automatic Order Printing extension from our partners at Simba Hosting', 'woocommerce-pdf-invoices-packing-slips' ); ?><br/>
117
- <a href="https://www.simbahosting.co.uk/s3/product/woocommerce-automatic-order-printing/?affiliates=2" target="_blank"><?php _e("WooCommerce Automatic Order Printing", 'woocommerce-pdf-invoices-packing-slips' ); ?></a>
118
- </td>
119
- </tr>
120
- </table>
121
- </div>
122
- </li>
123
- <?php } ?>
124
-
125
- <?php
126
- if (!class_exists('WooCommerce_PDF_IPS_Templates') && !$no_pro) {
127
- $template_link = '<a href="https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/" target="_blank">wpovernight.com</a>';
128
- $email_link = '<a href="mailto:support@wpovernight.com">support@wpovernight.com</a>'
129
- ?>
130
- <li>
131
- <?php _e('Advanced, customizable templates', 'woocommerce-pdf-invoices-packing-slips' )?>
132
- <div class="more" style="display:none;">
133
- <ul>
134
- <li><?php _e( 'Completely customize the invoice contents (prices, taxes, thumbnails) to your needs with a drag & drop customizer', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
135
- <li><?php _e( 'Two extra stylish premade templates (Modern & Business)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
136
- <li><?php printf( __("Check out the Premium PDF Invoice & Packing Slips templates at %s.", 'woocommerce-pdf-invoices-packing-slips' ), $template_link );?></li>
137
- <li><?php printf( __("For custom templates, contact us at %s.", 'woocommerce-pdf-invoices-packing-slips' ), $email_link );?></li>
138
- </ul>
139
- </div>
140
- </li>
141
- <?php } ?>
142
- </ul>
143
- <?php
144
- // link to hide message when one of the premium extensions is installed
145
- if ( class_exists('WooCommerce_PDF_IPS_Pro') || class_exists('WooCommerce_PDF_IPS_Dropbox') || class_exists('WooCommerce_PDF_IPS_Templates') || class_exists('WooCommerce_Ext_PrintOrders') || class_exists('WPO_WC_Smart_Reminder_Emails') ) {
146
- printf('<a href="%s" style="display:inline-block; margin-top: 10px;">%s</a>', add_query_arg( 'wpo_wcpdf_hide_extensions_ad', 'true' ), __( 'Hide this message', 'woocommerce-pdf-invoices-packing-slips' ) );
147
- }
148
- ?>
149
  </div>
1
+ <script type="text/javascript">
2
+ jQuery(document).ready(function() {
3
+ jQuery('.extensions .more').hide();
4
+
5
+ jQuery('.extensions > li').click(function() {
6
+ jQuery(this).toggleClass('expanded');
7
+ jQuery(this).find('.more').slideToggle();
8
+ });
9
+ });
10
+ </script>
11
+
12
+ <div class="wcpdf-extensions-ad">
13
+ <?php $no_pro = !class_exists('WooCommerce_PDF_IPS_Pro') && !class_exists('WooCommerce_PDF_IPS_Dropbox') && !class_exists('WooCommerce_PDF_IPS_Templates'); ?>
14
+ <img src="<?php echo WPO_WCPDF()->plugin_url() . '/assets/images/wpo-helper.png'; ?>" class="wpo-helper">
15
+ <h3><?php _e( 'Check out these premium extensions!', 'woocommerce-pdf-invoices-packing-slips' ); ?></h3>
16
+ <i>(<?php _e( 'click items to read more', 'woocommerce-pdf-invoices-packing-slips' ); ?>)</i>
17
+ <ul class="extensions">
18
+ <?php if ( $no_pro ): ?>
19
+ <!-- No Pro extensions: Ad for PDF bundle -->
20
+ <li>
21
+ <?php _e('Premium PDF Invoice bundle: Everything you need for a perfect invoicing system', 'woocommerce-pdf-invoices-packing-slips' )?>
22
+ <div class="more" style="display:none;">
23
+ <h4><?php _e( 'Supercharge WooCommerce PDF Invoices & Packing Slips with the all our premium extensions:', 'woocommerce-pdf-invoices-packing-slips' ); ?></h4>
24
+ <?php _e( 'Professional features:', 'woocommerce-pdf-invoices-packing-slips' ); ?>
25
+ <ul>
26
+ <li><?php _e( 'Email/print/download <b>PDF Credit Notes & Proforma invoices</b>', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
27
+ <li><?php _e( 'Send out a separate <b>notification email</b> with (or without) PDF invoices/packing slips, for example to a drop-shipper or a supplier.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
28
+ <li><?php _e( 'Attach <b>up to 3 static files</b> (for example a terms & conditions document) to the WooCommerce emails of your choice.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
29
+ <li><?php _e( 'Use <b>separate numbering systems</b> and/or format for proforma invoices and credit notes or utilize the main invoice numbering system', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
30
+ <li><?php _e( '<b>Customize</b> the <b>shipping & billing address</b> format to include additional custom fields, font sizes etc. without the need to create a custom template.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
31
+ <li><?php _e( 'Use the plugin in multilingual <b>WPML</b> setups', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
32
+ </ul>
33
+ <?php _e('Advanced, customizable templates', 'woocommerce-pdf-invoices-packing-slips' )?>
34
+ <ul>
35
+ <li><?php _e( 'Completely customize the invoice contents (prices, taxes, thumbnails) to your needs with a drag & drop customizer', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
36
+ <li><?php _e( 'Two extra stylish premade templates (Modern & Business)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
37
+ </ul>
38
+ <?php _e('Upload automatically to dropbox', 'woocommerce-pdf-invoices-packing-slips' )?>
39
+ <ul>
40
+ <li><?php _e( 'This extension conveniently uploads all the invoices (and other pdf documents from the professional extension) that are emailed to your customers to Dropbox. The best way to keep your invoice administration up to date!', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
41
+ </ul>
42
+ <br>
43
+ <a href="https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-bundle/" target="_blank"><?php _e("Get WooCommerce PDF Invoices & Packing Slips Bundle", 'woocommerce-pdf-invoices-packing-slips' ); ?></a>
44
+ </div>
45
+ </li>
46
+ <?php endif; ?>
47
+ <?php
48
+ // NO BUNDLE: separate ads
49
+ if (!class_exists('WooCommerce_PDF_IPS_Pro') && !$no_pro) {
50
+ ?>
51
+ <li>
52
+ <?php _e('Go Pro: Proforma invoices, credit notes (=refunds) & more!', 'woocommerce-pdf-invoices-packing-slips' )?>
53
+ <div class="more" style="display:none;">
54
+ <?php _e( 'Supercharge WooCommerce PDF Invoices & Packing Slips with the following features:', 'woocommerce-pdf-invoices-packing-slips' ); ?>
55
+ <ul>
56
+ <li><?php _e( 'Email/print/download <b>PDF Credit Notes & Proforma invoices</b>', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
57
+ <li><?php _e( 'Send out a separate <b>notification email</b> with (or without) PDF invoices/packing slips, for example to a drop-shipper or a supplier.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
58
+ <li><?php _e( 'Attach <b>up to 3 static files</b> (for example a terms & conditions document) to the WooCommerce emails of your choice.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
59
+ <li><?php _e( 'Use <b>separate numbering systems</b> and/or format for proforma invoices and credit notes or utilize the main invoice numbering system', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
60
+ <li><?php _e( '<b>Customize</b> the <b>shipping & billing address</b> format to include additional custom fields, font sizes etc. without the need to create a custom template.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
61
+ <li><?php _e( 'Use the plugin in multilingual <b>WPML</b> setups', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
62
+ <li><?php _e( 'Upload automatically to dropbox', 'woocommerce-pdf-invoices-packing-slips' )?></li>
63
+ </ul>
64
+ <a href="https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-professional/" target="_blank"><?php _e("Get WooCommerce PDF Invoices & Packing Slips Professional!", 'woocommerce-pdf-invoices-packing-slips' ); ?></a>
65
+ </li>
66
+ <?php } ?>
67
+
68
+ <?php
69
+ if (!class_exists('WPO_WC_Smart_Reminder_Emails')) {
70
+ ?>
71
+ <li>
72
+ <?php _e('Automatically send payment reminders to your customers', 'woocommerce-pdf-invoices-packing-slips' )?>
73
+ <div class="more" style="display:none;">
74
+ <?php _e('WooCommerce Smart Reminder emails', 'woocommerce-pdf-invoices-packing-slips' )?>
75
+ <ul>
76
+ <li><?php _e( '<b>Completely automatic</b> scheduled emails', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
77
+ <li><?php _e( '<b>Rich text editor</b> for the email text, including placeholders for data from the order (name, order total, etc)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
78
+ <li><?php _e( 'Configure the exact requirements for sending an email (time after order, order status, payment method)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
79
+ <li><?php _e( 'Fully <b>WPML Compatible</b> – emails will be automatically sent in the order language.', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
80
+ <li><?php _e( '<b>Super versatile!</b> Can be used for any kind of reminder email (review reminders, repeat purchases)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
81
+ <li><b><?php _e( 'Integrates seamlessly with the PDF Invoices & Packing Slips plugin', 'woocommerce-pdf-invoices-packing-slips' ); ?></b></li>
82
+ </ul>
83
+ <a href="https://wpovernight.com/downloads/woocommerce-reminder-emails-payment-reminders/" target="_blank"><?php _e("Get WooCommerce Smart Reminder Emails", 'woocommerce-pdf-invoices-packing-slips' ); ?></a>
84
+ </div>
85
+ </li>
86
+ <?php } ?>
87
+
88
+ <?php
89
+ if (!class_exists('WooCommerce_Ext_PrintOrders')) {
90
+ ?>
91
+ <li>
92
+ <?php _e('Automatically send new orders or packing slips to your printer, as soon as the customer orders!', 'woocommerce-pdf-invoices-packing-slips' )?>
93
+ <div class="more" style="display:none;">
94
+ <table>
95
+ <tr>
96
+ <td><img src="<?php echo WPO_WCPDF()->plugin_url() . '/assets/images/cloud-print.png'; ?>" class="cloud-logo"></td>
97
+ <td>
98
+ <?php _e( 'Check out the WooCommerce Automatic Order Printing extension from our partners at Simba Hosting', 'woocommerce-pdf-invoices-packing-slips' ); ?><br/>
99
+ <a href="https://www.simbahosting.co.uk/s3/product/woocommerce-automatic-order-printing/?affiliates=2" target="_blank"><?php _e("WooCommerce Automatic Order Printing", 'woocommerce-pdf-invoices-packing-slips' ); ?></a>
100
+ </td>
101
+ </tr>
102
+ </table>
103
+ </div>
104
+ </li>
105
+ <?php } ?>
106
+
107
+ <?php
108
+ if (!class_exists('WooCommerce_PDF_IPS_Templates') && !$no_pro) {
109
+ $template_link = '<a href="https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/" target="_blank">wpovernight.com</a>';
110
+ $email_link = '<a href="mailto:support@wpovernight.com">support@wpovernight.com</a>'
111
+ ?>
112
+ <li>
113
+ <?php _e('Advanced, customizable templates', 'woocommerce-pdf-invoices-packing-slips' )?>
114
+ <div class="more" style="display:none;">
115
+ <ul>
116
+ <li><?php _e( 'Completely customize the invoice contents (prices, taxes, thumbnails) to your needs with a drag & drop customizer', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
117
+ <li><?php _e( 'Two extra stylish premade templates (Modern & Business)', 'woocommerce-pdf-invoices-packing-slips' ); ?></li>
118
+ <li><?php printf( __("Check out the Premium PDF Invoice & Packing Slips templates at %s.", 'woocommerce-pdf-invoices-packing-slips' ), $template_link );?></li>
119
+ <li><?php printf( __("For custom templates, contact us at %s.", 'woocommerce-pdf-invoices-packing-slips' ), $email_link );?></li>
120
+ </ul>
121
+ </div>
122
+ </li>
123
+ <?php } ?>
124
+ </ul>
125
+ <?php
126
+ // link to hide message when one of the premium extensions is installed
127
+ if ( class_exists('WooCommerce_PDF_IPS_Pro') || class_exists('WooCommerce_PDF_IPS_Dropbox') || class_exists('WooCommerce_PDF_IPS_Templates') || class_exists('WooCommerce_Ext_PrintOrders') || class_exists('WPO_WC_Smart_Reminder_Emails') ) {
128
+ printf('<a href="%s" style="display:inline-block; margin-top: 10px;">%s</a>', add_query_arg( 'wpo_wcpdf_hide_extensions_ad', 'true' ), __( 'Hide this message', 'woocommerce-pdf-invoices-packing-slips' ) );
129
+ }
130
+ ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  </div>
readme.txt CHANGED
@@ -1,621 +1,188 @@
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: 4.8
7
- Stable tag: 2.0.9
8
- License: GPLv2 or later
9
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
-
11
- Create, print & automatically email PDF invoices & packing slips for WooCommerce orders.
12
-
13
- == Description ==
14
-
15
- 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.
16
-
17
- = Main features =
18
- * Automatically attach invoice PDF to WooCommerce emails of your choice
19
- * Download the PDF invoice / packing slip from the order admin page
20
- * Generate PDF invoices / packings slips in bulk
21
- * **Fully customizable** HTML/CSS invoice templates
22
- * Download invoices from the My Account page
23
- * Sequential invoice numbers - with custom formatting
24
- * **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**
25
-
26
- In addition to this, we offer several premium extensions:
27
-
28
- * 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/)
29
- * Upload all invoices automatically to Dropbox with [WooCommerce PDF Invoices & Packing Slips to Dropbox](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-dropbox/)
30
- * 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)
31
- * More advanced & stylish templates with [WooCommerce PDF Invoices & Packing Slips Premium Templates](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/)
32
-
33
- = Fully customizable =
34
- 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.
35
-
36
- * Insert customer header image/logo
37
- * Modify shop data / footer / disclaimer etc. on the invoices & packing slips
38
- * Select paper size (Letter or A4)
39
- * Translation ready
40
-
41
- == Installation ==
42
-
43
- = Minimum Requirements =
44
-
45
- * WooCommerce 2.0 or later
46
- * WordPress 3.5 or later
47
-
48
- = Automatic installation =
49
- 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.
50
-
51
- 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.
52
-
53
- = Manual installation via the WordPress interface =
54
- 1. Download the plugin zip file to your computer
55
- 2. Go to the WordPress admin panel menu Plugins > Add New
56
- 3. Choose upload
57
- 4. Upload the plugin zip file, the plugin will now be installed
58
- 5. After installation has finished, click the 'activate plugin' link
59
-
60
- = Manual installation via FTP =
61
- 1. Download the plugin file to your computer and unzip it
62
- 2. Using an FTP program, or your hosting control panel, upload the unzipped plugin folder to your WordPress installation's wp-content/plugins/ directory.
63
- 3. Activate the plugin from the Plugins menu within the WordPress admin.
64
-
65
- == Frequently Asked Questions ==
66
-
67
- = Where can I find the documentation? =
68
-
69
- [WooCommerce PDF Invoices & Packing Slips documentation](http://docs.wpovernight.com/woocommerce-pdf-invoices-packing-slips/)
70
-
71
- = It's not working! =
72
-
73
- Check out our step by step diagnostic instructions here: https://wordpress.org/support/topic/read-this-first-9/
74
-
75
-
76
-
77
-
78
-
79
- = Where can I find more templates? =
80
-
81
- 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.
82
-
83
- = Can I create/send a proforma invoice or a credit note? =
84
- 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/)
85
-
86
- = Can I contribute to the code? =
87
- You're more than welcome! This plugin is hosted on github, where you can post issues or make pull requests.
88
- https://github.com/wpovernight/woocommerce-pdf-invoices-packing-slips
89
-
90
- = How can I display the HTML/CSS source for debugging/developing templates? =
91
- 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!
92
-
93
-
94
- == Screenshots ==
95
-
96
- 1. Simple invoice PDF
97
- 2. Simple packing slip PDF
98
- 3. Quickly print individual invoices or packing slips from the order list
99
- 4. Print invoices or packing slips in bulk
100
- 5. Attach invoices to any WooCommerce email
101
- 6. Set shop name, address, header logo, etc.
102
-
103
- == Changelog ==
104
-
105
- **2.0 is a BIG update! Make a full site backup before upgrading**
106
-
107
- = 2.0.9 =
108
- * Feature: use `[invoice_date="ymd"]` in invoice number prefix or suffix to include a specific date format in the invoice number
109
- * Fix: Postmeta table prefix for invoice counter
110
- * Fix: 0% tax rates
111
-
112
- = 2.0.8 =
113
- * Feature: Add support for Bedrock / alternative folder structures
114
- * Dev: Filter for merged documents
115
- * Fix: Better attributes fallback for product variations
116
-
117
- = 2.0.7 =
118
- * Feature: Added button to delete legacy settings
119
- * Feature: Option to enable font subsetting
120
- * Fix: Invoice number sequence for databases with alternative auto_increment_increment settings
121
- * Fix: Fallback function for MB String (mb_stripos)
122
-
123
- = 2.0.6 =
124
- * Feature: Improved third party invoice number filters (`wpo_wcpdf_external_invoice_number_enabled` & `wpo_wcpdf_external_invoice_number`)
125
- * Fix: Underline position for Open Sans font
126
- * Fix: Invoice number auto_increment for servers that restarted frequently
127
- * Fix: Dompdf log file location (preventing open base_dir notices breaking PDF header)
128
- * Fix: 1.6.6 Settings migration duplicates merging
129
- * Tweak: Clear fonts folder when manually reinstalling fonts
130
-
131
- = 2.0.5 =
132
- * Feature: Remove temporary files (Status tab)
133
- * Fix: Page number replacement
134
- * Tweak: Fallback functions for MB String extension
135
- * Tweak: Improved wpo_wcpdf_check_privs usability for my account privileges
136
- * Legacy support: added wc_price alias for format_price method in document
137
-
138
- = 2.0.4 =
139
- * Fix: Apply filters for custom invoice number formatting in document too
140
- * Fix: Parent fallback for missing dates from refunds
141
-
142
- = 2.0.3 =
143
- * Fix: Better support for legacy invoice number filter (`wpo_wcpdf_invoice_number` - replaced by `wpo_wcpdf_formatted_document_number`)
144
- * Fix: Document number formatting fallback to order date if no document date available
145
- * Fix: Updated classmap: PSR loading didn't work on some installations
146
- * Fix: Prevent order notes from all orders showing when document is not loaded properly in filter
147
- * Tweak: Disable deprecation notices during email sending
148
- * Tweak: ignore outdated language packs
149
-
150
- = 2.0.2 =
151
- * Fix: order notes using correct order_id
152
- * Fix: WC3.0 deprecation notice for currency
153
- * Fix: Avoid crashing on PHP5.2 and older
154
- * Fix: Only use PHP MB String when present
155
- * Fix: Remote images
156
- * Fix: Download option
157
-
158
- = 2.0.1 =
159
- * Fix: PHP 5.4 issue
160
-
161
- = 2.0.0 =
162
- * New: Better structured & more advanced settings for documents
163
- * New: Option to enable & disable Packing Slips or Invoices
164
- * New: Invoice number sequence stored separately for improved speed & performance
165
- * New: Completely rewritten codebase for more flexibility & better reliability
166
- * New: Updated PDF library to DOMPDF 0.8
167
- * New: PDF Library made pluggable (by using the `wpo_wcpdf_pdf_maker` filter)
168
- * New: lots of new functions & filters to allow developers to hook into the plugin
169
- * Changed: **$wpo_wcpdf variable is now deprecated** (legacy mode available & automatically enabled on update)
170
- * Fix: Improved PHP 7 & 7.1 support
171
- * Fix: Positive prices for refunds
172
- * Fix: Use parent for attributes retrieved for product variations
173
- * Fix: Set content type to PDF for download
174
-
175
- = 1.6.6 =
176
- * Feature: Facilitate downgrading from 2.0 (re-installing fonts & resetting version)
177
- * Fix: Update currencies font (added Georgian Lari)
178
- * Translations: Added Indonesian
179
-
180
- = 1.6.5 =
181
- * Fix: Duplicate invoice numbers when bulk completing orders (WC3.0)
182
- * Fix: Hidden Invoice date when order refunded
183
-
184
- = 1.6.4 =
185
- * Fix: My account invoice button visibility
186
-
187
- = 1.6.3 =
188
- * Fix: Empty date handling
189
- * Fix: Shipping notes on refunds (reason for refund)
190
-
191
- = 1.6.2 =
192
- * Fix: TM Extra Product Options compatibility (in WC3.0)
193
- * Fix: Tax display in WC3.0
194
-
195
- = 1.6.1 =
196
- * Fix: Error with totals in credit notes
197
- * Fix: Always set invoice date when invoice is create (even display is disabled in the settings)
198
-
199
- = 1.6.0.2 =
200
- * Fix: Don't crash with PHP 5.2 or older (5.3 or higher required, 5.6 or higher recommended)
201
-
202
- = 1.6.0 =
203
- * WooCommerce 3.0 Compatible
204
- * **Requires PHP version 5.3 or higher**
205
- * Fix: Invoice number display in mobile view
206
- * Fix: Update formatted invoice number in order meta when number is altered
207
- * Fix: global plugin object loading in wrapped cron methods
208
- * Tweak: Avoid PHP7 scan false positives in DomPDF
209
-
210
- = 1.5.39 =
211
- * Feature: new template action hooks `wpo_wcpdf_before_document` & `wpo_wcpdf_after_document`
212
- * Tweak: In totals, emphasize order total rather than last item
213
- * Fix: User deprecation notices
214
- * Translations: Updated Slovenian
215
-
216
- = 1.5.38 =
217
- * Fix: Thumbnail path fallback
218
- * Fix: Edge/IE hour & minute pattern
219
- * Fix: Skip over non-order objects
220
- * Tweak: Let shop manager view My Account links
221
- * Dev: added `wpo_wcpdf_before_attachment_creation` action
222
- * Translations: Updated POT, Swedish, Dutch & Norwegian
223
-
224
- = 1.5.37 =
225
- * Feature: Added support for third party invoice numbers
226
- * Feature: Enable pre-invoice number click-to-edit
227
- * Fix: Review link for custom admins
228
- * Fix: PHP7 compatibility
229
- * Fix: Invoice date hour/minute pattern
230
- * Tweak: Multisite WooCommerce check optimization
231
-
232
- = 1.5.36 =
233
- * Translations: Fixed Romanian (incorrect "Factură Proforma" translation for "Invoice")
234
-
235
- = 1.5.35 =
236
- * Translations: Fixed "Includes %s" string for WC2.6+
237
-
238
- = 1.5.34 =
239
- * Fix: Document check that was introduced in 1.5.33 for disable free setting
240
-
241
- = 1.5.33 =
242
- * Tweak: Don't apply 'disable free' setting to packing slip attachment
243
- * Translations: Updated Romanian
244
-
245
- = 1.5.32 =
246
- * Fix: Updated currency font with Indian Rupee symbol
247
- * Translations: added Formal German (currently a copy of informal German)
248
-
249
- = 1.5.31 =
250
- * Feature: [invoice_day] or [order_day] in invoice number format
251
- * Fix: Link to hide all ads when premium extensions active
252
-
253
- = 1.5.30 =
254
- * Feature: Enable currency font for extended currency support
255
- * Fix: Font sync on plugin update
256
-
257
- = 1.5.29 =
258
- * Translations: Added Croation (Thanks Neven/Spine ICT!), updated French (Thanks Sabra!)
259
- * Tweak: filter shop address before checking if it's empty
260
- * Dev: added $order to `wpo_wcpdf_template_file` filter
261
-
262
- = 1.5.28 =
263
- * Tweak: the 'Next invoice number' is now stored separately in the database for faster and more reliable retrieval. Circumventing any caching, this should prevent duplicate invoice numbers.
264
- * Fix: Bulk actions plugin conflicts
265
- * Experimental: page numbers (use {{PAGE_NUM}} / {{PAGE_COUNT}} in your template)
266
-
267
- = 1.5.27 =
268
- * Feature: Use [invoice_year] and [invoice_month] placeholders in invoice number prefix/suffix
269
- * Feature: WooCommerce Order Status & Actions Manager emails compatibility
270
- * Feature: Add invoice number to WC REST API
271
- * Fix: Allow positive 'discounts' (price corrections)
272
- * Fix: Discounts rounding
273
- * Translations: Updated Finnish & Portugese & POT
274
-
275
- = 1.5.26 =
276
- * Feature: Automatically list all emails registered in WooCommerce
277
- * Feature: Reset invoice number yearly
278
- * Feature: WooCommerce Chained Products compatibility
279
- * Feature: WooCommerce Product Bundles visibility settings taken into account in invoice
280
- * Fix: Disable PDF creation from trashed order_ids
281
- * Tweak: Alert when no orders selected for bulk export (Props to Dartui!)
282
- * Tweak: PDF invoice settings always under WooCommerce menu (also for premium users)
283
- * Tweak: extra $item_id passed in row class filter
284
- * Translations: Updated Slovenian, Spanish, Dutch & POT file
285
-
286
- = 1.5.24 =
287
- * Hotfix: Subscriptions renewal filter arguments
288
-
289
- = 1.5.23 =
290
- * Fix: WooCommerce Subscriptons 2.0 deprecation notice.
291
- * Tweak: better qTranslate-X support
292
- * Tweak: filter for user privileges check (wpo_wcpdf_check_privs)
293
- * Translations: French translations fix
294
-
295
- = 1.5.22 =
296
- * Fix: Workaround for bug in WPML (which cleared all settings)
297
- * Translation: fixed Polish translation for invoice
298
-
299
- = 1.5.21 =
300
- * Translations: Added Estionan (thanks Tanel!)
301
- * Tweak: WC2.4 compatibility
302
-
303
- = 1.5.20 =
304
- * Feature: Option to 'never' display My Account invoice link
305
- * Fix: Order total for refunds in WC2.4
306
- * Fix: notice when no custom statuses selected for My Account display
307
- * Tweak: Product bundles styles
308
-
309
- = 1.5.19 =
310
- * Fix: Invoice number search (broke other custom searches)
311
-
312
- = 1.5.18 =
313
- * Fix: wpo_wcpdf_item_row_class packing slip filter arguments
314
-
315
- = 1.5.17 =
316
- * Feature: WooCommerce Product Bundles compatibility styles
317
- * Tweak: wpo_wcpdf_item_row_class as filter instead of action
318
-
319
- = 1.5.16 =
320
- * Feature: Search orders by invoice number (note: search on formatted invoice number only works for new orders)
321
- * Feature: Formatted invoice number stored in order
322
- * Tweak: Function parameters added to some of the filters
323
- * Tweak: WooCommerce 2.4 compatibility
324
- * Dev feature: action to add class to items table row (wpo_wcpdf_item_row_class)
325
- * Translations: Swedish updated (thanks Conney!)
326
- * Translations: Norwegian updated
327
-
328
- = 1.5.15 =
329
- * Fix: invoice number padding didn't work for values lower than 3
330
- * Tweak: WPML compatibility filter
331
- * Translations: Updated French (Thanks Nicolas!)
332
-
333
- = 1.5.14 =
334
- * Tweak: Invoice number & date edit fields moved to separate box on order edit page
335
- * Translations: Updated POT & Dutch
336
-
337
- = 1.5.13 =
338
- * Fix: Better address comparison to determine when to display alternate address
339
- * Tweak: Filter N/A addresses
340
- * Tweak: Use WooCommerce function for 2.3 discounts
341
- * Translations: Czech Updated (Thanks Ivo!)
342
- * Translations: French (minor fixes)
343
-
344
- = 1.5.12 =
345
- * Translations: added Danish, Updated POT & Italian
346
-
347
- = 1.5.11 =
348
- * Fix: Product text attributes (now checks key too)
349
- * Fix: Status page upload explanation typos
350
-
351
- = 1.5.10 =
352
- * Fix: Double check to make sure plugin doesn't attach to user emails
353
-
354
- = 1.5.9 =
355
- * Feature: Shorthand function to display product attributes: `$wpo_wcpdf->get_product_attribute( $attribute_name, $product )`
356
-
357
- = 1.5.8 =
358
- * Feature: disable invoice for free orders
359
- * Feature: action to insert data before & after item meta
360
- * Tweak: Added classes to sku & weight
361
- * Tweak: Hide payment method from totals (already shown in template)
362
- * Translations: Updated POT & Dutch
363
-
364
- = 1.5.7 =
365
- * Feature: Setting to show email address & phone number on invoice or packing slip (does not work on custom templates based on previous versions!)
366
-
367
- = 1.5.6 =
368
- * Feature: Setting to show shipping address on invoice (does not work on custom templates based on previous versions!)
369
- * Feature: My Account invoice download setting
370
- * Feature: several new template actions
371
- * Tweak: WooCommerce Bookings compatibility
372
- * Tweak: Gerenal stylesheet cleanup
373
- * Fix: temp path check/error on settings page
374
- * Fix: Document titles for credit notes and proforma (Pro)
375
- * Fix: Discount including tax
376
- * Fix: Special characters on item meta (requires WooCommerce 2.3.6)
377
- * Translations: Missing text domain on several strings
378
- * Translations: Updated POT & Dutch
379
-
380
- = 1.5.5 =
381
- * Fix: Check for incomplete line tax data (Subscriptions compatibility)
382
- * Fix: More precise template path instructions
383
- * Fix: duplicate stylesheet filter
384
- * Fix: Always prefer original order's billing address for refunds (WooCommerce EU VAT Number compatibility)
385
- * Translations: Updated German (MwSt. instead of formal Ust.)
386
- * Translations: Updated Dutch
387
-
388
- = 1.5.4 =
389
- * Tweak: include plugin version in style/script includes
390
- * Tweak: upload code cleanup
391
- * Fix: Parent invoice number (for Credit Notes in professional extension)
392
-
393
- = 1.5.3 =
394
- * Feature: add original order date value to order date filter
395
- * Feature: Work with line_tax_data when available
396
- * Feature: pass item_id to items
397
- * Tweak: later check for woocommerce active
398
- * Fix: do not try to validate empty settings (Status page settings)
399
- * Translations: Fixed Dutch typo
400
-
401
- = 1.5.2 =
402
- * Fix: fatal error when trying to activate with WooCommerce not installed yet.
403
- * Tweak: indentation fix on the Simple template
404
-
405
- = 1.5.1 =
406
- * Fix: prevent errors when upgrading
407
-
408
- = 1.5.0 =
409
- * Feature: All temporary files are now stored centrally in the WP uploads folder.
410
- * Feature: Debug settings in status panel (output errors & output to HTML)
411
- * Feature: Compatibility filter for WooCommerce Subscriptions (prevents duplicate invoice numbers)
412
- * Tweak: Pass order to totals filters
413
- * Translations: Updated POT
414
- * Translations: Updated Italian (Thanks Astrid!)
415
- * Translations: Updated Dutch
416
- * FAQ: instructions for placing a link on the thank you page
417
-
418
- = 1.4.14 =
419
- * Fix: fatal error when user registers at checkout (applies to credit notes only)
420
- * Translations: Updated German (Thanks Dietmar!)
421
- * Translations: Place your custom translations in wp-content/languages/woocommerce-pdf-invoices-packing-slips/wpo_wcpdf-LOCALE.mo to protect them from being overwritten by plugin updates.
422
-
423
- = 1.4.13 =
424
- * Feature: use separate file for all your template specific functions (template-functions.php)
425
- * Translations: Added Slovenian (thanks gregy1403!)
426
- * Translations: Updated Norwegian & Dutch.
427
- * Translations: Added Japanese - needs custom font!
428
- * FAQ: instructions on how to use custom fonts
429
-
430
- = 1.4.12 =
431
- * Fix: issues with post parent objects (WC2.1 and older)
432
-
433
- = 1.4.11 =
434
- * Small fix: bulk actions for specific i18n configurations
435
- * Tweak: total row key used as class in Simple template
436
-
437
- = 1.4.10 =
438
- * Fix: Invoice not attaching
439
- * Translations: Updated POT file
440
- * Translations: Updated Dutch, Norwegian, Polish, Brazilian Portugese, Romanian, Russian, Slovak, Spanish & Ukrainian (Many thanks to all the translators!)
441
- * Templates: added action hooks for easier customizations (`wpo_wcpdf_before_order_details`, `wpo_wcpdf_after_order_details`, `wpo_wcpdf_invoice_title` & `wpo_wcpdf_packing_slip_title`)
442
-
443
- = 1.4.9 =
444
- * Feature: Order number and date are now displayed by default in the Simple template (invoice number and date still optional)
445
- * Feature: Display Customer/Order notes with a simple shorthand (see FAQ)
446
- * Translations: Added Brazilian Portugese (thanks Victor Debone!)
447
- * Tweak: Fail more gracefully when there are errors during PDF generation
448
- * Tweak: added template type class to template output body
449
- * Tweak: cleaned up Simple template style.css
450
-
451
- = 1.4.8 =
452
- * Translations: Added Finnish (Thanks Sami Mäkelä/Contrast.fi!)
453
-
454
- = 1.4.7 =
455
- * Fix: check if image file exists locally, fallback to url if not (CDN compatibility)
456
- * Fix: make deleting invoice date possible
457
- * Fix: correct tmp folder check on status page
458
- * Translations: updated po/mo files
459
- * Tweak: changed settings capability requirement to `manage_woocommerce` (was: `manage_options`)
460
- * Tweak: better email attachment function
461
- * Tweak: prevent footer overlap (Simple template)
462
- * Tweak: fallback if `glob()` is not allowed on the server
463
- * Tweak: better custom template instructions (reflects path to actual (child-)theme)
464
-
465
- = 1.4.6 =
466
- * HOTFIX: WooCommerce 2.2 compatibility fix
467
- * Filter for PDF temp folder (wpo_wcpdf_tmp_path)
468
-
469
- = 1.4.5 =
470
- * Fix: Double date conversion for order date on invoice number filter (to avoid i18n date issues)
471
- * Fix: Template selector reset after update
472
- * Translations: added Norwegian (Thanks Aleksander!)
473
-
474
- = 1.4.4 =
475
- * Feature: Editable invoice date per order/invoice.
476
- * Feature: HTML is now allowed in footer and other settings fields.
477
- * Translations: Updated German (Thanks Nadine!)
478
- * Fix: template paths are now saved relative to the site base path (ABSPATH) to prevent errors when moving to another server
479
- * Tweak: Changed bulk action hook for better theme compatibility
480
- * Tweak: Newlines in custom checkout fields
481
-
482
- = 1.4.3 =
483
- * Feature: Added function to call custom fields more easily (see FAQ)
484
- * Feature: Change the my account button text via a filter (wpo_wcpdf_myaccount_button_text)
485
- * Translations: Added Danish (Thanks Mads!)
486
- * Tweak: only load PDF engine if it's not already loaded by another plugin
487
-
488
- = 1.4.2 =
489
- * Fix: Don't create invoice number when exporting packing slips
490
- * Fix: Division by zero for 0 quantity items
491
-
492
- = 1.4.1 =
493
- * Translations: Added Polish (Thanks Mike!)
494
- * Fix: Invoice number formatting notices in debug mode
495
-
496
- = 1.4.0 =
497
- * Feature: Invoice numbers can now be given a prefix, suffix or padding on the settings page!
498
- * Filter: `wpo_wcpdf_email_allowed_statuses` to attach pdf to custom order status emails
499
- * Tweak: Sequential Order Numbers Pro compatibility
500
- * Tweak: Filenames are now automatically sanitized to prevent issues with illegal characters
501
-
502
- = 1.3.2 =
503
- * Fix: error on wpo_wcpdf_email_attachment filter when $pdf_path not set
504
-
505
- = 1.3.1 =
506
- * Fix: invoice number was cleared when Order Actions were being used when an invoice number was not set
507
- * Translations: Updated Slovak (Thanks Jozef!)
508
- * Translations: Added Czech (Thanks CubiQ!)
509
-
510
- = 1.3.0 =
511
- * Feature: Added 'status' panel for better problem diagnosis
512
- * Tweak: split create & get invoice number calls to prevent slow database calls from causing number skipping
513
- * Translations: Added Romanian (Thanks Leonardo!)
514
- * Translations: Added Slovak (Thanks Oleg!)
515
-
516
- = 1.2.13 =
517
- * Feature: added filter for custom email attachment condition (wpo_wcpdf_custom_email_condition)
518
- * Fix: warning for tax implode
519
-
520
- = 1.2.12 =
521
- * Fix: hyperlink underline (was more like a strikethrough)
522
-
523
- = 1.2.11 =
524
- * Translations: Fixed German spelling error
525
- * Translations: Updated Swedish (Thanks Fredrik!)
526
-
527
- = 1.2.10 =
528
- * Translations: Added Swedish (Thanks Jonathan!)
529
- * Fix: Line-height issue (on some systems, the space between lines was very high)
530
-
531
- = 1.2.9 =
532
- * Fix: bug where 'standard' tax class would not display in some cases
533
- * Fix: bug that caused the totals to jump for some font sizes
534
- * Fix: WC2.1 deprecated totals function
535
- * Fix: If multiple taxes were set up with the same name, only one would display (Simple template was not affected)
536
-
537
- = 1.2.8 =
538
- * Template: Body line-height defined to prevent character jumping with italic texts
539
- * Fix: Open Sans now included in plugin package (fixes font issues for servers with allow_url_fopen disabled)
540
-
541
- = 1.2.7 =
542
- * Translations: POT, DE & NL updated
543
- * Fix: Removed stray span tag in totals table
544
-
545
- = 1.2.6 =
546
- * Translations: Spanish update (thanks prepu!)
547
- * Fix: More advanced checks to determine if a customer can download the invoice (including a status filter)
548
-
549
- = 1.2.5 =
550
- * Feature: Optional Invoice Number column for the orders listing
551
- * Feature: Better support for international characters
552
- * Translations: Added Russian & Ukrainian translation (thanks Oleg!)
553
- * Translations: Updated Spanish (Thanks Manuel!) and Dutch translations & POT file
554
- * Tweak: Memory limit notice
555
- * Tweak: Filename name now includes invoice number (when configured in the settings)
556
-
557
- = 1.2.4 =
558
- * Feature: Set which type of emails you want to attach the invoice to
559
-
560
- = 1.2.3 =
561
- * Feature: Manually edit invoice number on the edit order screen
562
- * Feature: Set the first (/next) invoice number on the settings screen
563
- * Fix: Bug where invoice number would be generated twice due to slow database calls
564
- * Fix: php strict warnings
565
-
566
- = 1.2.2 =
567
- * Feature: Simple template now uses Open Sans to include more international special characters
568
- * Feature: Implemented filters for paper size & orientation ([read here](http://wordpress.org/support/topic/select-a5-paper-size-for-packing-slips?replies=5#post-5211129))
569
- * Tweak: PDF engine updated (dompdf 0.6.0)
570
- * Tweak: Download PDF link on the my account page is now only shown when an invoice is already created by the admin or automatically, to prevent unwanted invoice created (creating problems with european laws).
571
-
572
- = 1.2.1 =
573
- * Fix: shipping & fees functions didn't output correctly with the tax set to 'incl'
574
-
575
- = 1.2.0 =
576
- * Feature: Sequential invoice numbers (set upon invoice creation).
577
- * Feature: Invoice date (set upon invoice creation).
578
-
579
- = 1.1.6 =
580
- * Feature: Hungarian translations added - thanks Joseph!
581
- * Tweak: Better debug code.
582
- * Tweak: Error reporting when templates not found.
583
- * Fix: tax rate calculation for free items.
584
-
585
- = 1.1.5 =
586
- * Feature: German translations added - thanks Christian!
587
- * Fix: dompdf 0.6.0 proved to be less stable, so switching back to beta3 for now.
588
-
589
- = 1.1.4 =
590
- * Fix: Template paths on windows servers were not properly saved (stripslashes), resulting in an empty output.
591
-
592
- = 1.1.3 =
593
- * Feature: PDF engine (dompdf) updated to 0.6.0 for better stability and utf-8 support.
594
- * Tweak: Local server path is used for header image for better compatibility with server settings.
595
- * Fix: several small bugs.
596
-
597
- = 1.1.2 =
598
- * Feature: Totals can now be called with simpler template functions
599
- * Feature: Italian translations - thanks max66max!
600
- * Tweak: improved memory performance
601
-
602
- = 1.1.1 =
603
- * Feature: French translations - thanks Guillaume!
604
-
605
- = 1.1.0 =
606
- * Feature: Fees can now also be called ex. VAT
607
- * Feature: Invoices can now be downloaded from the My Account page
608
- * Feature: Spanish translation & POT file included
609
- * Fix: ternary statements that caused an error
610
-
611
- = 1.0.1 =
612
- * Tweak: Packing slip now displays shipping address instead of billing address
613
- * Tweak: Variation data is now displayed by default
614
-
615
- = 1.0.0 =
616
- * First release
617
-
618
- == Upgrade Notice ==
619
-
620
- = 2.0.9 =
621
  **2.0 is a BIG update! Make a full site backup before upgrading!**
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: 4.8
7
+ Stable tag: 2.0.10
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Create, print & automatically email PDF invoices & packing slips for WooCommerce orders.
12
+
13
+ == Description ==
14
+
15
+ 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.
16
+
17
+ = Main features =
18
+ * Automatically attach invoice PDF to WooCommerce emails of your choice
19
+ * Download the PDF invoice / packing slip from the order admin page
20
+ * Generate PDF invoices / packings slips in bulk
21
+ * **Fully customizable** HTML/CSS invoice templates
22
+ * Download invoices from the My Account page
23
+ * Sequential invoice numbers - with custom formatting
24
+ * **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**
25
+
26
+ In addition to this, we offer several premium extensions:
27
+
28
+ * 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/)
29
+ * Upload all invoices automatically to Dropbox with [WooCommerce PDF Invoices & Packing Slips to Dropbox](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-dropbox/)
30
+ * 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)
31
+ * More advanced & stylish templates with [WooCommerce PDF Invoices & Packing Slips Premium Templates](https://wpovernight.com/downloads/woocommerce-pdf-invoices-packing-slips-premium-templates/)
32
+
33
+ = Fully customizable =
34
+ 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.
35
+
36
+ * Insert customer header image/logo
37
+ * Modify shop data / footer / disclaimer etc. on the invoices & packing slips
38
+ * Select paper size (Letter or A4)
39
+ * Translation ready
40
+
41
+ == Installation ==
42
+
43
+ = Minimum Requirements =
44
+
45
+ * WooCommerce 2.0 or later
46
+ * WordPress 3.5 or later
47
+
48
+ = Automatic installation =
49
+ 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.
50
+
51
+ 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.
52
+
53
+ = Manual installation via the WordPress interface =
54
+ 1. Download the plugin zip file to your computer
55
+ 2. Go to the WordPress admin panel menu Plugins > Add New
56
+ 3. Choose upload
57
+ 4. Upload the plugin zip file, the plugin will now be installed
58
+ 5. After installation has finished, click the 'activate plugin' link
59
+
60
+ = Manual installation via FTP =
61
+ 1. Download the plugin file to your computer and unzip it
62
+ 2. Using an FTP program, or your hosting control panel, upload the unzipped plugin folder to your WordPress installation's wp-content/plugins/ directory.
63
+ 3. Activate the plugin from the Plugins menu within the WordPress admin.
64
+
65
+ == Frequently Asked Questions ==
66
+
67
+ = Where can I find the documentation? =
68
+
69
+ [WooCommerce PDF Invoices & Packing Slips documentation](http://docs.wpovernight.com/woocommerce-pdf-invoices-packing-slips/)
70
+
71
+ = It's not working! =
72
+
73
+ Check out our step by step diagnostic instructions here: https://wordpress.org/support/topic/read-this-first-9/
74
+
75
+
76
+
77
+
78
+
79
+ = Where can I find more templates? =
80
+
81
+ 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.
82
+
83
+ = Can I create/send a proforma invoice or a credit note? =
84
+ 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/)
85
+
86
+ = Can I contribute to the code? =
87
+ You're more than welcome! This plugin is hosted on github, where you can post issues or make pull requests.
88
+ https://github.com/wpovernight/woocommerce-pdf-invoices-packing-slips
89
+
90
+ = How can I display the HTML/CSS source for debugging/developing templates? =
91
+ 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!
92
+
93
+
94
+ == Screenshots ==
95
+
96
+ 1. Simple invoice PDF
97
+ 2. Simple packing slip PDF
98
+ 3. Quickly print individual invoices or packing slips from the order list
99
+ 4. Print invoices or packing slips in bulk
100
+ 5. Attach invoices to any WooCommerce email
101
+ 6. Set shop name, address, header logo, etc.
102
+
103
+ == Changelog ==
104
+
105
+ **2.0 is a BIG update! Make a full site backup before upgrading**
106
+
107
+ = 2.0.10 =
108
+ * Fix: Set invoice number backend button
109
+ * Fix: Thumbail paths
110
+ * Tweak: Make dompdf options filterable
111
+
112
+ = 2.0.9 =
113
+ * Feature: use `[invoice_date="ymd"]` in invoice number prefix or suffix to include a specific date format in the invoice number
114
+ * Fix: Postmeta table prefix for invoice counter
115
+ * Fix: 0% tax rates
116
+
117
+ = 2.0.8 =
118
+ * Feature: Add support for Bedrock / alternative folder structures
119
+ * Dev: Filter for merged documents
120
+ * Fix: Better attributes fallback for product variations
121
+
122
+ = 2.0.7 =
123
+ * Feature: Added button to delete legacy settings
124
+ * Feature: Option to enable font subsetting
125
+ * Fix: Invoice number sequence for databases with alternative auto_increment_increment settings
126
+ * Fix: Fallback function for MB String (mb_stripos)
127
+
128
+ = 2.0.6 =
129
+ * Feature: Improved third party invoice number filters (`wpo_wcpdf_external_invoice_number_enabled` & `wpo_wcpdf_external_invoice_number`)
130
+ * Fix: Underline position for Open Sans font
131
+ * Fix: Invoice number auto_increment for servers that restarted frequently
132
+ * Fix: Dompdf log file location (preventing open base_dir notices breaking PDF header)
133
+ * Fix: 1.6.6 Settings migration duplicates merging
134
+ * Tweak: Clear fonts folder when manually reinstalling fonts
135
+
136
+ = 2.0.5 =
137
+ * Feature: Remove temporary files (Status tab)
138
+ * Fix: Page number replacement
139
+ * Tweak: Fallback functions for MB String extension
140
+ * Tweak: Improved wpo_wcpdf_check_privs usability for my account privileges
141
+ * Legacy support: added wc_price alias for format_price method in document
142
+
143
+ = 2.0.4 =
144
+ * Fix: Apply filters for custom invoice number formatting in document too
145
+ * Fix: Parent fallback for missing dates from refunds
146
+
147
+ = 2.0.3 =
148
+ * Fix: Better support for legacy invoice number filter (`wpo_wcpdf_invoice_number` - replaced by `wpo_wcpdf_formatted_document_number`)
149
+ * Fix: Document number formatting fallback to order date if no document date available
150
+ * Fix: Updated classmap: PSR loading didn't work on some installations
151
+ * Fix: Prevent order notes from all orders showing when document is not loaded properly in filter
152
+ * Tweak: Disable deprecation notices during email sending
153
+ * Tweak: ignore outdated language packs
154
+
155
+ = 2.0.2 =
156
+ * Fix: order notes using correct order_id
157
+ * Fix: WC3.0 deprecation notice for currency
158
+ * Fix: Avoid crashing on PHP5.2 and older
159
+ * Fix: Only use PHP MB String when present
160
+ * Fix: Remote images
161
+ * Fix: Download option
162
+
163
+ = 2.0.1 =
164
+ * Fix: PHP 5.4 issue
165
+
166
+ = 2.0.0 =
167
+ * New: Better structured & more advanced settings for documents
168
+ * New: Option to enable & disable Packing Slips or Invoices
169
+ * New: Invoice number sequence stored separately for improved speed & performance
170
+ * New: Completely rewritten codebase for more flexibility & better reliability
171
+ * New: Updated PDF library to DOMPDF 0.8
172
+ * New: PDF Library made pluggable (by using the `wpo_wcpdf_pdf_maker` filter)
173
+ * New: lots of new functions & filters to allow developers to hook into the plugin
174
+ * Changed: **$wpo_wcpdf variable is now deprecated** (legacy mode available & automatically enabled on update)
175
+ * Fix: Improved PHP 7 & 7.1 support
176
+ * Fix: Positive prices for refunds
177
+ * Fix: Use parent for attributes retrieved for product variations
178
+ * Fix: Set content type to PDF for download
179
+
180
+ = 1.6.6 =
181
+ * Feature: Facilitate downgrading from 2.0 (re-installing fonts & resetting version)
182
+ * Fix: Update currencies font (added Georgian Lari)
183
+ * Translations: Added Indonesian
184
+
185
+ == Upgrade Notice ==
186
+
187
+ = 2.0.10 =
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  **2.0 is a BIG update! Make a full site backup before upgrading!**
woocommerce-pdf-invoices-packingslips.php CHANGED
@@ -1,355 +1,355 @@
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.0.9
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
- */
13
-
14
- if ( ! defined( 'ABSPATH' ) ) {
15
- exit; // Exit if accessed directly
16
- }
17
-
18
- if ( !class_exists( 'WPO_WCPDF' ) ) :
19
-
20
- class WPO_WCPDF {
21
-
22
- public $version = '2.0.9';
23
- public $plugin_basename;
24
- public $legacy_mode;
25
-
26
- protected static $_instance = null;
27
-
28
- /**
29
- * Main Plugin Instance
30
- *
31
- * Ensures only one instance of plugin is loaded or can be loaded.
32
- */
33
- public static function instance() {
34
- if ( is_null( self::$_instance ) ) {
35
- self::$_instance = new self();
36
- }
37
- return self::$_instance;
38
- }
39
-
40
- /**
41
- * Constructor
42
- */
43
- public function __construct() {
44
- $this->plugin_basename = plugin_basename(__FILE__);
45
-
46
- $this->define( 'WPO_WCPDF_VERSION', $this->version );
47
-
48
- // load the localisation & classes
49
- add_action( 'plugins_loaded', array( $this, 'translations' ) );
50
- add_filter( 'load_textdomain_mofile', array( $this, 'textdomain_fallback' ), 10, 2 );
51
- add_action( 'plugins_loaded', array( $this, 'load_classes' ), 9 );
52
- add_action( 'in_plugin_update_message-'.$this->plugin_basename, array( $this, 'in_plugin_update_message' ) );
53
- }
54
-
55
- /**
56
- * Define constant if not already set
57
- * @param string $name
58
- * @param string|bool $value
59
- */
60
- private function define( $name, $value ) {
61
- if ( ! defined( $name ) ) {
62
- define( $name, $value );
63
- }
64
- }
65
-
66
-
67
- /**
68
- * Load the translation / textdomain files
69
- *
70
- * Note: the first-loaded translation file overrides any following ones if the same translation is present
71
- */
72
- public function translations() {
73
- $locale = apply_filters( 'plugin_locale', get_locale(), 'woocommerce-pdf-invoices-packing-slips' );
74
- $dir = trailingslashit( WP_LANG_DIR );
75
-
76
- $textdomains = array( 'woocommerce-pdf-invoices-packing-slips' );
77
- if ( $this->legacy_mode_enabled() === true ) {
78
- $textdomains[] = 'wpo_wcpdf';
79
- }
80
-
81
- /**
82
- * Frontend/global Locale. Looks in:
83
- *
84
- * - WP_LANG_DIR/woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
85
- * - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
86
- * - woocommerce-pdf-invoices-packing-slips-pro/languages/woocommerce-pdf-invoices-packing-slips-LOCALE.mo (which if not found falls back to:)
87
- * - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
88
- */
89
- foreach ($textdomains as $textdomain) {
90
- load_textdomain( $textdomain, $dir . 'woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' );
91
- load_textdomain( $textdomain, $dir . 'plugins/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' );
92
- load_plugin_textdomain( $textdomain, false, dirname( plugin_basename(__FILE__) ) . '/languages' );
93
- }
94
- }
95
-
96
- /**
97
- * Maintain backwards compatibility with old translation files
98
- * Uses old .mo file if it exists in any of the override locations
99
- */
100
- public function textdomain_fallback( $mofile, $textdomain ) {
101
- $plugin_domain = 'woocommerce-pdf-invoices-packing-slips';
102
- $old_domain = 'wpo_wcpdf';
103
-
104
- if ($textdomain == $old_domain) {
105
- $textdomain = $plugin_domain;
106
- $mofile = str_replace( "{$old_domain}-", "{$textdomain}-", $mofile ); // with trailing dash to target file and not folder
107
- }
108
-
109
- if ( $textdomain === $plugin_domain ) {
110
- $old_mofile = str_replace( "{$textdomain}-", "{$old_domain}-", $mofile ); // with trailing dash to target file and not folder
111
- if ( file_exists( $old_mofile ) ) {
112
- // we have an old override - use it
113
- return $old_mofile;
114
- }
115
-
116
- // prevent loading outdated language packs
117
- $pofile = str_replace('.mo', '.po', $mofile);
118
- if ( file_exists( $pofile ) ) {
119
- // load po file
120
- $podata = file_get_contents($pofile);
121
- // set revision date threshold
122
- $block_before = strtotime( '2017-05-15' );
123
- // read revision date
124
- preg_match('~PO-Revision-Date: (.*?)\\\n~s',$podata,$matches);
125
- if (isset($matches[1])) {
126
- $revision_date = $matches[1];
127
- if ( $revision_timestamp = strtotime($revision_date) ) {
128
- // check if revision is before threshold date
129
- if ( $revision_timestamp < $block_before ) {
130
- // try bundled
131
- $bundled_file = $this->plugin_path() . '/languages/'. basename( $mofile );
132
- if (file_exists($bundled_file)) {
133
- return $bundled_file;
134
- } else {
135
- return '';
136
- }
137
- // delete po & mo file if possible
138
- // @unlink($pofile);
139
- // @unlink($mofile);
140
- }
141
- }
142
- }
143
- }
144
- }
145
-
146
- return $mofile;
147
- }
148
-
149
- /**
150
- * Load the main plugin classes and functions
151
- */
152
- public function includes() {
153
- // WooCommerce compatibility classes
154
- include_once( $this->plugin_path() . '/includes/compatibility/abstract-wc-data-compatibility.php' );
155
- include_once( $this->plugin_path() . '/includes/compatibility/class-wc-date-compatibility.php' );
156
- include_once( $this->plugin_path() . '/includes/compatibility/class-wc-core-compatibility.php' );
157
- include_once( $this->plugin_path() . '/includes/compatibility/class-wc-order-compatibility.php' );
158
- include_once( $this->plugin_path() . '/includes/compatibility/class-wc-product-compatibility.php' );
159
- include_once( $this->plugin_path() . '/includes/compatibility/wc-datetime-functions-compatibility.php' );
160
-
161
- // Third party compatibility
162
- include_once( $this->plugin_path() . '/includes/compatibility/class-wcpdf-compatibility-third-party-plugins.php' );
163
-
164
- // Plugin classes
165
- include_once( $this->plugin_path() . '/includes/wcpdf-functions.php' );
166
- $this->settings = include_once( $this->plugin_path() . '/includes/class-wcpdf-settings.php' );
167
- $this->documents = include_once( $this->plugin_path() . '/includes/class-wcpdf-documents.php' );
168
- $this->main = include_once( $this->plugin_path() . '/includes/class-wcpdf-main.php' );
169
- include_once( $this->plugin_path() . '/includes/class-wcpdf-assets.php' );
170
- include_once( $this->plugin_path() . '/includes/class-wcpdf-admin.php' );
171
- include_once( $this->plugin_path() . '/includes/class-wcpdf-frontend.php' );
172
- include_once( $this->plugin_path() . '/includes/class-wcpdf-install.php' );
173
-
174
- // Backwards compatibility with self
175
- include_once( $this->plugin_path() . '/includes/legacy/class-wcpdf-legacy.php' );
176
- include_once( $this->plugin_path() . '/includes/legacy/class-wcpdf-legacy-deprecated-hooks.php' );
177
-
178
- // PHP MB String fallback functions
179
- include_once( $this->plugin_path() . '/includes/compatibility/mb-string-compatibility.php' );
180
- }
181
-
182
-
183
- /**
184
- * Instantiate classes when woocommerce is activated
185
- */
186
- public function load_classes() {
187
- if ( $this->is_woocommerce_activated() === false ) {
188
- add_action( 'admin_notices', array ( $this, 'need_woocommerce' ) );
189
- return;
190
- }
191
-
192
- if ( version_compare( PHP_VERSION, '5.3', '<' ) ) {
193
- add_action( 'admin_notices', array ( $this, 'required_php_version' ) );
194
- return;
195
- }
196
-
197
- // all systems ready - GO!
198
- $this->includes();
199
- }
200
-
201
- /**
202
- * Check if legacy mode is enabled
203
- */
204
- public function legacy_mode_enabled() {
205
- if (!isset($this->legacy_mode)) {
206
- $debug_settings = get_option( 'wpo_wcpdf_settings_debug' );
207
- $this->legacy_mode = isset($debug_settings['legacy_mode']);
208
- }
209
- return $this->legacy_mode;
210
- }
211
-
212
-
213
- /**
214
- * Check if woocommerce is activated
215
- */
216
- public function is_woocommerce_activated() {
217
- $blog_plugins = get_option( 'active_plugins', array() );
218
- $site_plugins = is_multisite() ? (array) maybe_unserialize( get_site_option('active_sitewide_plugins' ) ) : array();
219
-
220
- if ( in_array( 'woocommerce/woocommerce.php', $blog_plugins ) || isset( $site_plugins['woocommerce/woocommerce.php'] ) ) {
221
- return true;
222
- } else {
223
- return false;
224
- }
225
- }
226
-
227
- /**
228
- * WooCommerce not active notice.
229
- *
230
- * @return string Fallack notice.
231
- */
232
-
233
- public function need_woocommerce() {
234
- $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>' );
235
-
236
- $message = '<div class="error"><p>' . $error . '</p></div>';
237
-
238
- echo $message;
239
- }
240
-
241
- /**
242
- * PHP version requirement notice
243
- */
244
-
245
- public function required_php_version() {
246
- $error = __( 'WooCommerce PDF Invoices & Packing Slips requires PHP 5.3 or higher (5.6 or higher recommended).', 'woocommerce-pdf-invoices-packing-slips' );
247
- $how_to_update = __( 'How to update your PHP version', 'woocommerce-pdf-invoices-packing-slips' );
248
- $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);
249
-
250
- echo $message;
251
- }
252
-
253
- /**
254
- * Show plugin changes. Code adapted from W3 Total Cache.
255
- */
256
- public function in_plugin_update_message( $args ) {
257
- $transient_name = 'wpo_wcpdf_upgrade_notice_' . $args['Version'];
258
-
259
- if ( false === ( $upgrade_notice = get_transient( $transient_name ) ) ) {
260
- $response = wp_safe_remote_get( 'https://plugins.svn.wordpress.org/woocommerce-pdf-invoices-packing-slips/trunk/readme.txt' );
261
-
262
- if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) {
263
- $upgrade_notice = self::parse_update_notice( $response['body'], $args['new_version'] );
264
- set_transient( $transient_name, $upgrade_notice, DAY_IN_SECONDS );
265
- }
266
- }
267
-
268
- echo wp_kses_post( $upgrade_notice );
269
- }
270
-
271
- /**
272
- * Parse update notice from readme file.
273
- *
274
- * @param string $content
275
- * @param string $new_version
276
- * @return string
277
- */
278
- private function parse_update_notice( $content, $new_version ) {
279
- // Output Upgrade Notice.
280
- $matches = null;
281
- $regexp = '~==\s*Upgrade Notice\s*==\s*=\s*(.*)\s*=(.*)(=\s*' . preg_quote( $new_version ) . '\s*=|$)~Uis';
282
- $upgrade_notice = '';
283
-
284
-
285
- if ( preg_match( $regexp, $content, $matches ) ) {
286
- $notices = (array) preg_split( '~[\r\n]+~', trim( $matches[2] ) );
287
-
288
- // Convert the full version strings to minor versions.
289
- $notice_version_parts = explode( '.', trim( $matches[1] ) );
290
- $current_version_parts = explode( '.', $this->version );
291
-
292
- if ( 3 !== sizeof( $notice_version_parts ) ) {
293
- return;
294
- }
295
-
296
- $notice_version = $notice_version_parts[0] . '.' . $notice_version_parts[1];
297
- $current_version = $current_version_parts[0] . '.' . $current_version_parts[1];
298
-
299
- // Check the latest stable version and ignore trunk.
300
- if ( version_compare( $current_version, $notice_version, '<' ) ) {
301
-
302
- $upgrade_notice .= '</p><p class="wpo_wcpdf_upgrade_notice">';
303
-
304
- foreach ( $notices as $index => $line ) {
305
- $upgrade_notice .= preg_replace( '~\[([^\]]*)\]\(([^\)]*)\)~', '<a href="${2}">${1}</a>', $line );
306
- }
307
- }
308
- }
309
-
310
- return wp_kses_post( $upgrade_notice );
311
- }
312
-
313
- /**
314
- * Get the plugin url.
315
- * @return string
316
- */
317
- public function plugin_url() {
318
- return untrailingslashit( plugins_url( '/', __FILE__ ) );
319
- }
320
-
321
- /**
322
- * Get the plugin path.
323
- * @return string
324
- */
325
- public function plugin_path() {
326
- return untrailingslashit( plugin_dir_path( __FILE__ ) );
327
- }
328
-
329
- } // class WPO_WCPDF
330
-
331
- endif; // class_exists
332
-
333
- /**
334
- * Returns the main instance of WooCommerce PDF Invoices & Packing Slips to prevent the need to use globals.
335
- *
336
- * @since 1.6
337
- * @return WPO_WCPDF
338
- */
339
- function WPO_WCPDF() {
340
- return WPO_WCPDF::instance();
341
- }
342
-
343
- WPO_WCPDF(); // load plugin
344
-
345
- // legacy class for plugin detecting
346
- if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
347
- class WooCommerce_PDF_Invoices{
348
- public static $version;
349
-
350
- public function __construct() {
351
- self::$version = WPO_WCPDF()->version;
352
- }
353
- }
354
- new WooCommerce_PDF_Invoices();
355
- }
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.0.10
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
+ */
13
+
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit; // Exit if accessed directly
16
+ }
17
+
18
+ if ( !class_exists( 'WPO_WCPDF' ) ) :
19
+
20
+ class WPO_WCPDF {
21
+
22
+ public $version = '2.0.10';
23
+ public $plugin_basename;
24
+ public $legacy_mode;
25
+
26
+ protected static $_instance = null;
27
+
28
+ /**
29
+ * Main Plugin Instance
30
+ *
31
+ * Ensures only one instance of plugin is loaded or can be loaded.
32
+ */
33
+ public static function instance() {
34
+ if ( is_null( self::$_instance ) ) {
35
+ self::$_instance = new self();
36
+ }
37
+ return self::$_instance;
38
+ }
39
+
40
+ /**
41
+ * Constructor
42
+ */
43
+ public function __construct() {
44
+ $this->plugin_basename = plugin_basename(__FILE__);
45
+
46
+ $this->define( 'WPO_WCPDF_VERSION', $this->version );
47
+
48
+ // load the localisation & classes
49
+ add_action( 'plugins_loaded', array( $this, 'translations' ) );
50
+ add_filter( 'load_textdomain_mofile', array( $this, 'textdomain_fallback' ), 10, 2 );
51
+ add_action( 'plugins_loaded', array( $this, 'load_classes' ), 9 );
52
+ add_action( 'in_plugin_update_message-'.$this->plugin_basename, array( $this, 'in_plugin_update_message' ) );
53
+ }
54
+
55
+ /**
56
+ * Define constant if not already set
57
+ * @param string $name
58
+ * @param string|bool $value
59
+ */
60
+ private function define( $name, $value ) {
61
+ if ( ! defined( $name ) ) {
62
+ define( $name, $value );
63
+ }
64
+ }
65
+
66
+
67
+ /**
68
+ * Load the translation / textdomain files
69
+ *
70
+ * Note: the first-loaded translation file overrides any following ones if the same translation is present
71
+ */
72
+ public function translations() {
73
+ $locale = apply_filters( 'plugin_locale', get_locale(), 'woocommerce-pdf-invoices-packing-slips' );
74
+ $dir = trailingslashit( WP_LANG_DIR );
75
+
76
+ $textdomains = array( 'woocommerce-pdf-invoices-packing-slips' );
77
+ if ( $this->legacy_mode_enabled() === true ) {
78
+ $textdomains[] = 'wpo_wcpdf';
79
+ }
80
+
81
+ /**
82
+ * Frontend/global Locale. Looks in:
83
+ *
84
+ * - WP_LANG_DIR/woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
85
+ * - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
86
+ * - woocommerce-pdf-invoices-packing-slips-pro/languages/woocommerce-pdf-invoices-packing-slips-LOCALE.mo (which if not found falls back to:)
87
+ * - WP_LANG_DIR/plugins/woocommerce-pdf-invoices-packing-slips-LOCALE.mo
88
+ */
89
+ foreach ($textdomains as $textdomain) {
90
+ load_textdomain( $textdomain, $dir . 'woocommerce-pdf-invoices-packing-slips/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' );
91
+ load_textdomain( $textdomain, $dir . 'plugins/woocommerce-pdf-invoices-packing-slips-' . $locale . '.mo' );
92
+ load_plugin_textdomain( $textdomain, false, dirname( plugin_basename(__FILE__) ) . '/languages' );
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Maintain backwards compatibility with old translation files
98
+ * Uses old .mo file if it exists in any of the override locations
99
+ */
100
+ public function textdomain_fallback( $mofile, $textdomain ) {
101
+ $plugin_domain = 'woocommerce-pdf-invoices-packing-slips';
102
+ $old_domain = 'wpo_wcpdf';
103
+
104
+ if ($textdomain == $old_domain) {
105
+ $textdomain = $plugin_domain;
106
+ $mofile = str_replace( "{$old_domain}-", "{$textdomain}-", $mofile ); // with trailing dash to target file and not folder
107
+ }
108
+
109
+ if ( $textdomain === $plugin_domain ) {
110
+ $old_mofile = str_replace( "{$textdomain}-", "{$old_domain}-", $mofile ); // with trailing dash to target file and not folder
111
+ if ( file_exists( $old_mofile ) ) {
112
+ // we have an old override - use it
113
+ return $old_mofile;
114
+ }
115
+
116
+ // prevent loading outdated language packs
117
+ $pofile = str_replace('.mo', '.po', $mofile);
118
+ if ( file_exists( $pofile ) ) {
119
+ // load po file
120
+ $podata = file_get_contents($pofile);
121
+ // set revision date threshold
122
+ $block_before = strtotime( '2017-05-15' );
123
+ // read revision date
124
+ preg_match('~PO-Revision-Date: (.*?)\\\n~s',$podata,$matches);
125
+ if (isset($matches[1])) {
126
+ $revision_date = $matches[1];
127
+ if ( $revision_timestamp = strtotime($revision_date) ) {
128
+ // check if revision is before threshold date
129
+ if ( $revision_timestamp < $block_before ) {
130
+ // try bundled
131
+ $bundled_file = $this->plugin_path() . '/languages/'. basename( $mofile );
132
+ if (file_exists($bundled_file)) {
133
+ return $bundled_file;
134
+ } else {
135
+ return '';
136
+ }
137
+ // delete po & mo file if possible
138
+ // @unlink($pofile);
139
+ // @unlink($mofile);
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+
146
+ return $mofile;
147
+ }
148
+
149
+ /**
150
+ * Load the main plugin classes and functions
151
+ */
152
+ public function includes() {
153
+ // WooCommerce compatibility classes
154
+ include_once( $this->plugin_path() . '/includes/compatibility/abstract-wc-data-compatibility.php' );
155
+ include_once( $this->plugin_path() . '/includes/compatibility/class-wc-date-compatibility.php' );
156
+ include_once( $this->plugin_path() . '/includes/compatibility/class-wc-core-compatibility.php' );
157
+ include_once( $this->plugin_path() . '/includes/compatibility/class-wc-order-compatibility.php' );
158
+ include_once( $this->plugin_path() . '/includes/compatibility/class-wc-product-compatibility.php' );
159
+ include_once( $this->plugin_path() . '/includes/compatibility/wc-datetime-functions-compatibility.php' );
160
+
161
+ // Third party compatibility
162
+ include_once( $this->plugin_path() . '/includes/compatibility/class-wcpdf-compatibility-third-party-plugins.php' );
163
+
164
+ // Plugin classes
165
+ include_once( $this->plugin_path() . '/includes/wcpdf-functions.php' );
166
+ $this->settings = include_once( $this->plugin_path() . '/includes/class-wcpdf-settings.php' );
167
+ $this->documents = include_once( $this->plugin_path() . '/includes/class-wcpdf-documents.php' );
168
+ $this->main = include_once( $this->plugin_path() . '/includes/class-wcpdf-main.php' );
169
+ include_once( $this->plugin_path() . '/includes/class-wcpdf-assets.php' );
170
+ include_once( $this->plugin_path() . '/includes/class-wcpdf-admin.php' );
171
+ include_once( $this->plugin_path() . '/includes/class-wcpdf-frontend.php' );
172
+ include_once( $this->plugin_path() . '/includes/class-wcpdf-install.php' );
173
+
174
+ // Backwards compatibility with self
175
+ include_once( $this->plugin_path() . '/includes/legacy/class-wcpdf-legacy.php' );
176
+ include_once( $this->plugin_path() . '/includes/legacy/class-wcpdf-legacy-deprecated-hooks.php' );
177
+
178
+ // PHP MB String fallback functions
179
+ include_once( $this->plugin_path() . '/includes/compatibility/mb-string-compatibility.php' );
180
+ }
181
+
182
+
183
+ /**
184
+ * Instantiate classes when woocommerce is activated
185
+ */
186
+ public function load_classes() {
187
+ if ( $this->is_woocommerce_activated() === false ) {
188
+ add_action( 'admin_notices', array ( $this, 'need_woocommerce' ) );
189
+ return;
190
+ }
191
+
192
+ if ( version_compare( PHP_VERSION, '5.3', '<' ) ) {
193
+ add_action( 'admin_notices', array ( $this, 'required_php_version' ) );
194
+ return;
195
+ }
196
+
197
+ // all systems ready - GO!
198
+ $this->includes();
199
+ }
200
+
201
+ /**
202
+ * Check if legacy mode is enabled
203
+ */
204
+ public function legacy_mode_enabled() {
205
+ if (!isset($this->legacy_mode)) {
206
+ $debug_settings = get_option( 'wpo_wcpdf_settings_debug' );
207
+ $this->legacy_mode = isset($debug_settings['legacy_mode']);
208
+ }
209
+ return $this->legacy_mode;
210
+ }
211
+
212
+
213
+ /**
214
+ * Check if woocommerce is activated
215
+ */
216
+ public function is_woocommerce_activated() {
217
+ $blog_plugins = get_option( 'active_plugins', array() );
218
+ $site_plugins = is_multisite() ? (array) maybe_unserialize( get_site_option('active_sitewide_plugins' ) ) : array();
219
+
220
+ if ( in_array( 'woocommerce/woocommerce.php', $blog_plugins ) || isset( $site_plugins['woocommerce/woocommerce.php'] ) ) {
221
+ return true;
222
+ } else {
223
+ return false;
224
+ }
225
+ }
226
+
227
+ /**
228
+ * WooCommerce not active notice.
229
+ *
230
+ * @return string Fallack notice.
231
+ */
232
+
233
+ public function need_woocommerce() {
234
+ $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>' );
235
+
236
+ $message = '<div class="error"><p>' . $error . '</p></div>';
237
+
238
+ echo $message;
239
+ }
240
+
241
+ /**
242
+ * PHP version requirement notice
243
+ */
244
+
245
+ public function required_php_version() {
246
+ $error = __( 'WooCommerce PDF Invoices & Packing Slips requires PHP 5.3 or higher (5.6 or higher recommended).', 'woocommerce-pdf-invoices-packing-slips' );
247
+ $how_to_update = __( 'How to update your PHP version', 'woocommerce-pdf-invoices-packing-slips' );
248
+ $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);
249
+
250
+ echo $message;
251
+ }
252
+
253
+ /**
254
+ * Show plugin changes. Code adapted from W3 Total Cache.
255
+ */
256
+ public function in_plugin_update_message( $args ) {
257
+ $transient_name = 'wpo_wcpdf_upgrade_notice_' . $args['Version'];
258
+
259
+ if ( false === ( $upgrade_notice = get_transient( $transient_name ) ) ) {
260
+ $response = wp_safe_remote_get( 'https://plugins.svn.wordpress.org/woocommerce-pdf-invoices-packing-slips/trunk/readme.txt' );
261
+
262
+ if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) {
263
+ $upgrade_notice = self::parse_update_notice( $response['body'], $args['new_version'] );
264
+ set_transient( $transient_name, $upgrade_notice, DAY_IN_SECONDS );
265
+ }
266
+ }
267
+
268
+ echo wp_kses_post( $upgrade_notice );
269
+ }
270
+
271
+ /**
272
+ * Parse update notice from readme file.
273
+ *
274
+ * @param string $content
275
+ * @param string $new_version
276
+ * @return string
277
+ */
278
+ private function parse_update_notice( $content, $new_version ) {
279
+ // Output Upgrade Notice.
280
+ $matches = null;
281
+ $regexp = '~==\s*Upgrade Notice\s*==\s*=\s*(.*)\s*=(.*)(=\s*' . preg_quote( $new_version ) . '\s*=|$)~Uis';
282
+ $upgrade_notice = '';
283
+
284
+
285
+ if ( preg_match( $regexp, $content, $matches ) ) {
286
+ $notices = (array) preg_split( '~[\r\n]+~', trim( $matches[2] ) );
287
+
288
+ // Convert the full version strings to minor versions.
289
+ $notice_version_parts = explode( '.', trim( $matches[1] ) );
290
+ $current_version_parts = explode( '.', $this->version );
291
+
292
+ if ( 3 !== sizeof( $notice_version_parts ) ) {
293
+ return;
294
+ }
295
+
296
+ $notice_version = $notice_version_parts[0] . '.' . $notice_version_parts[1];
297
+ $current_version = $current_version_parts[0] . '.' . $current_version_parts[1];
298
+
299
+ // Check the latest stable version and ignore trunk.
300
+ if ( version_compare( $current_version, $notice_version, '<' ) ) {
301
+
302
+ $upgrade_notice .= '</p><p class="wpo_wcpdf_upgrade_notice">';
303
+
304
+ foreach ( $notices as $index => $line ) {
305
+ $upgrade_notice .= preg_replace( '~\[([^\]]*)\]\(([^\)]*)\)~', '<a href="${2}">${1}</a>', $line );
306
+ }
307
+ }
308
+ }
309
+
310
+ return wp_kses_post( $upgrade_notice );
311
+ }
312
+
313
+ /**
314
+ * Get the plugin url.
315
+ * @return string
316
+ */
317
+ public function plugin_url() {
318
+ return untrailingslashit( plugins_url( '/', __FILE__ ) );
319
+ }
320
+
321
+ /**
322
+ * Get the plugin path.
323
+ * @return string
324
+ */
325
+ public function plugin_path() {
326
+ return untrailingslashit( plugin_dir_path( __FILE__ ) );
327
+ }
328
+
329
+ } // class WPO_WCPDF
330
+
331
+ endif; // class_exists
332
+
333
+ /**
334
+ * Returns the main instance of WooCommerce PDF Invoices & Packing Slips to prevent the need to use globals.
335
+ *
336
+ * @since 1.6
337
+ * @return WPO_WCPDF
338
+ */
339
+ function WPO_WCPDF() {
340
+ return WPO_WCPDF::instance();
341
+ }
342
+
343
+ WPO_WCPDF(); // load plugin
344
+
345
+ // legacy class for plugin detecting
346
+ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
347
+ class WooCommerce_PDF_Invoices{
348
+ public static $version;
349
+
350
+ public function __construct() {
351
+ self::$version = WPO_WCPDF()->version;
352
+ }
353
+ }
354
+ new WooCommerce_PDF_Invoices();
355
+ }