Gravity PDF - Version 5.1.0-RC1

Version Description

Download this release

Release Info

Developer Blue Liquid Designs
Plugin Icon 128x128 Gravity PDF
Version 5.1.0-RC1
Comparing to
See all releases

Code changes from version 5.0.2 to 5.1.0-RC1

Files changed (180) hide show
  1. README.txt +22 -1
  2. dist/assets/js/gfpdf-settings.min.js +1 -1
  3. pdf.php +2 -2
  4. src/assets/languages/gravity-forms-pdf-extended.pot +107 -103
  5. src/bootstrap.php +16 -1
  6. src/controller/Controller_Debug.php +155 -0
  7. src/controller/Controller_Install.php +2 -1
  8. src/controller/Controller_PDF.php +1 -0
  9. src/controller/Controller_Shortcodes.php +1 -75
  10. src/helper/Helper_Data.php +1 -0
  11. src/helper/Helper_Options_Fields.php +12 -12
  12. src/helper/Helper_PDF.php +1 -15
  13. src/helper/Helper_Sha256_Url_Signer.php +66 -0
  14. src/helper/Helper_Templates.php +32 -1
  15. src/helper/abstract/Helper_Abstract_Addon.php +4 -4
  16. src/helper/fields/Field_Checkbox.php +1 -1
  17. src/helper/fields/Field_Consent.php +137 -0
  18. src/helper/fields/Field_Form.php +160 -0
  19. src/helper/fields/Field_Html.php +2 -4
  20. src/helper/fields/Field_Multiselect.php +1 -1
  21. src/helper/fields/Field_Option.php +3 -1
  22. src/helper/fields/Field_Products.php +7 -5
  23. src/helper/fields/Field_Radio.php +3 -4
  24. src/helper/fields/Field_Repeater.php +241 -0
  25. src/helper/fields/Field_Select.php +3 -4
  26. src/helper/licensing/EDD_SL_Plugin_Updater.php +96 -38
  27. src/model/Model_Install.php +33 -1
  28. src/model/Model_PDF.php +107 -41
  29. src/model/Model_Settings.php +20 -8
  30. src/model/Model_Shortcodes.php +75 -25
  31. src/model/Model_Templates.php +4 -1
  32. src/view/View_PDF.php +7 -3
  33. src/view/html/Actions/core_font.php +1 -1
  34. src/view/html/PDF/core_template_styles.php +28 -0
  35. vendor/composer/autoload_classmap.php +58 -0
  36. vendor/composer/autoload_files.php +1 -0
  37. vendor/composer/autoload_psr4.php +4 -0
  38. vendor/composer/autoload_static.php +88 -0
  39. vendor/composer/installed.json +246 -22
  40. vendor/league/url/CHANGELOG.md +135 -0
  41. vendor/league/url/CONTRIBUTING.md +32 -0
  42. vendor/league/url/LICENSE +20 -0
  43. vendor/league/url/README.md +63 -0
  44. vendor/league/url/composer.json +43 -0
  45. vendor/league/url/src/AbstractUrl.php +466 -0
  46. vendor/league/url/src/Components/AbstractArray.php +156 -0
  47. vendor/league/url/src/Components/AbstractComponent.php +117 -0
  48. vendor/league/url/src/Components/AbstractSegment.php +302 -0
  49. vendor/league/url/src/Components/ComponentArrayInterface.php +36 -0
  50. vendor/league/url/src/Components/ComponentInterface.php +62 -0
  51. vendor/league/url/src/Components/Fragment.php +60 -0
  52. vendor/league/url/src/Components/Host.php +181 -0
  53. vendor/league/url/src/Components/HostInterface.php +36 -0
  54. vendor/league/url/src/Components/Pass.php +35 -0
  55. vendor/league/url/src/Components/Path.php +107 -0
  56. vendor/league/url/src/Components/PathInterface.php +32 -0
  57. vendor/league/url/src/Components/Port.php +58 -0
  58. vendor/league/url/src/Components/Query.php +143 -0
  59. vendor/league/url/src/Components/QueryInterface.php +31 -0
  60. vendor/league/url/src/Components/Scheme.php +59 -0
  61. vendor/league/url/src/Components/SegmentInterface.php +53 -0
  62. vendor/league/url/src/Components/User.php +23 -0
  63. vendor/league/url/src/Url.php +197 -0
  64. vendor/league/url/src/UrlConstants.php +24 -0
  65. vendor/league/url/src/UrlImmutable.php +220 -0
  66. vendor/league/url/src/UrlInterface.php +201 -0
  67. vendor/masterminds/html5/.travis.yml +1 -1
  68. vendor/masterminds/html5/README.md +3 -3
  69. vendor/masterminds/html5/RELEASE.md +6 -0
  70. vendor/masterminds/html5/src/HTML5/Elements.php +1 -1
  71. vendor/masterminds/html5/src/HTML5/Parser/DOMTreeBuilder.php +12 -1
  72. vendor/masterminds/html5/src/HTML5/Parser/Tokenizer.php +2 -5
  73. vendor/masterminds/html5/test/HTML5/ElementsTest.php +0 -1
  74. vendor/masterminds/html5/test/HTML5/Parser/DOMTreeBuilderTest.php +62 -0
  75. vendor/masterminds/html5/test/HTML5/Parser/TokenizerTest.php +4 -3
  76. vendor/monolog/monolog/CHANGELOG.md +28 -0
  77. vendor/monolog/monolog/README.md +0 -1
  78. vendor/monolog/monolog/doc/02-handlers-formatters-processors.md +1 -0
  79. vendor/monolog/monolog/doc/03-utilities.md +2 -0
  80. vendor/monolog/monolog/src/Monolog/ErrorHandler.php +11 -2
  81. vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php +1 -0
  82. vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php +1 -1
  83. vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php +12 -6
  84. vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php +5 -3
  85. vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php +4 -2
  86. vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php +24 -7
  87. vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php +2 -2
  88. vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php +18 -8
  89. vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php +2 -0
  90. vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php +3 -3
  91. vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php +33 -23
  92. vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php +14 -2
  93. vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php +5 -5
  94. vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php +1 -1
  95. vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php +4 -4
  96. vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php +4 -4
  97. vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php +2 -2
  98. vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php +1 -1
  99. vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php +30 -16
  100. vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php +1 -1
  101. vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php +0 -8
  102. vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php +14 -2
  103. vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php +2 -2
  104. vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php +9 -1
  105. vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php +15 -0
  106. vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php +4 -4
  107. vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php +62 -0
  108. vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php +2 -2
  109. vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php +1 -1
  110. vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php +3 -1
  111. vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php +1 -1
  112. vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php +3 -3
  113. vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php +6 -6
  114. vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php +12 -0
  115. vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php +15 -3
  116. vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php +5 -5
  117. vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php +5 -0
  118. vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php +5 -0
  119. vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php +43 -4
  120. vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php +3 -3
  121. vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php +14 -2
  122. vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php +5 -5
  123. vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php +6 -6
  124. vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php +13 -3
  125. vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php +10 -0
  126. vendor/monolog/monolog/src/Monolog/Logger.php +165 -74
  127. vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php +1 -1
  128. vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php +1 -1
  129. vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php +3 -3
  130. vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php +1 -1
  131. vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php +1 -1
  132. vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php +25 -0
  133. vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php +4 -2
  134. vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php +1 -1
  135. vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php +15 -2
  136. vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php +1 -1
  137. vendor/monolog/monolog/src/Monolog/ResettableInterface.php +31 -0
  138. vendor/monolog/monolog/src/Monolog/SignalHandler.php +115 -0
  139. vendor/monolog/monolog/src/Monolog/Utils.php +25 -0
  140. vendor/monolog/monolog/tests/Monolog/Formatter/FluentdFormatterTest.php +2 -2
  141. vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php +36 -0
  142. vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php +59 -1
  143. vendor/monolog/monolog/tests/Monolog/Handler/BrowserConsoleHandlerTest.php +1 -1
  144. vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php +2 -2
  145. vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php +2 -2
  146. vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php +2 -2
  147. vendor/monolog/monolog/tests/Monolog/Handler/InsightOpsHandlerTest.php +80 -0
  148. vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php +34 -0
  149. vendor/monolog/monolog/tests/Monolog/Handler/Slack/SlackRecordTest.php +12 -4
  150. vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php +26 -0
  151. vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php +46 -0
  152. vendor/monolog/monolog/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php +23 -0
  153. vendor/monolog/monolog/tests/Monolog/LoggerTest.php +142 -0
  154. vendor/monolog/monolog/tests/Monolog/SignalHandlerTest.php +287 -0
  155. vendor/mpdf/mpdf/composer.json +1 -1
  156. vendor/mpdf/mpdf/src/CssManager.php +28 -9
  157. vendor/mpdf/mpdf/src/Form.php +292 -231
  158. vendor/mpdf/mpdf/src/Gradient.php +11 -3
  159. vendor/mpdf/mpdf/src/Image/ImageProcessor.php +383 -331
  160. vendor/mpdf/mpdf/src/Image/ImageTypeGuesser.php +5 -0
  161. vendor/mpdf/mpdf/src/Image/Svg.php +35 -32
  162. vendor/mpdf/mpdf/src/Mpdf.php +3204 -5983
  163. vendor/mpdf/mpdf/src/Otl.php +9 -4
  164. vendor/mpdf/mpdf/src/RemoteContentFetcher.php +116 -0
  165. vendor/mpdf/mpdf/src/ServiceFactory.php +177 -0
  166. vendor/mpdf/mpdf/src/Strict.php +67 -0
  167. vendor/mpdf/mpdf/src/TTFontFile.php +2 -0
  168. vendor/mpdf/mpdf/src/Tag.php +4 -0
  169. vendor/mpdf/mpdf/src/Tag/BlockTag.php +1 -0
  170. vendor/mpdf/mpdf/src/Tag/Table.php +50 -19
  171. vendor/mpdf/mpdf/src/Tag/Tag.php +5 -0
  172. vendor/mpdf/mpdf/src/Writer/BackgroundWriter.php +415 -0
  173. vendor/mpdf/mpdf/src/Writer/BaseWriter.php +250 -0
  174. vendor/mpdf/mpdf/src/Writer/BookmarkWriter.php +138 -0
  175. vendor/mpdf/mpdf/src/Writer/ColorWriter.php +46 -0
  176. vendor/mpdf/mpdf/src/Writer/FontWriter.php +686 -0
  177. vendor/mpdf/mpdf/src/Writer/FormWriter.php +149 -0
  178. vendor/mpdf/mpdf/src/Writer/ImageWriter.php +119 -0
  179. vendor/mpdf/mpdf/src/Writer/JavaScriptWriter.php +46 -0
  180. vendor/mpdf/mpdf/src/Writer/MetadataWriter.php +796 -0
README.txt CHANGED
@@ -5,7 +5,7 @@ Donate link: https://gravitypdf.com/donate-to-plugin/
5
  Tags: gravity, forms, pdf, automation, attachment, email
6
  Requires at least: 4.8
7
  Tested up to: 4.9
8
- Stable tag: 5.0.2
9
  Requires PHP: 5.6
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl.txt
@@ -90,6 +90,27 @@ Also, if you enjoy using the software [we'd love it if you could give us a revie
90
 
91
  == Changelog ==
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  = 5.0.2 =
94
  * Bug: Resolve fatal error on WP Engine due to security in place that prevented mPDF font cache from being saved.
95
 
5
  Tags: gravity, forms, pdf, automation, attachment, email
6
  Requires at least: 4.8
7
  Tested up to: 4.9
8
+ Stable tag: 5.1.0-RC1
9
  Requires PHP: 5.6
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl.txt
90
 
91
  == Changelog ==
92
 
93
+ = 5.1.0 =
94
+ * Feature: Add support for Gravity Forms Repeater Fields in PDFs [GH#833]
95
+ * Feature: Add support for Gravity Wiz's Nested Forms Perk in PDFs
96
+ * Feature: Add support for Gravity Forms Consent Field in PDFs [GH#832]
97
+ * Feature: Add signed-URL authentication to [gravitypdf] shortcode using new "signed" and "expires" attributes [GH#841]
98
+ * Feature: Add new "raw" attribute to the [gravitypdf] shortcode which will display the raw PDF URL [GH#841]
99
+ * Feature: Added "Debug Mode" Global PDF Setting which replaces "Shortcode Debug Message", WP_DEBUG settings, and caches the template headers [GH#823]
100
+
101
+ * Dev Feature: Add `gfpdf_disable_global_addon_data` filter to disable aggrigate Survey / Poll / Quiz data in $form_data array (for performance)
102
+ * Dev Feature: Add `gfpdf_disable_product_table` filter to disable Product table in PDF [GH#827]
103
+ * Dev Feature: Pass additional parameters to the `gfpdf_show_field_value` filter
104
+ * Dev Feature: Trigger `gfpdf_template_loaded` JS event after loading new PDF Template settings dynamically
105
+ * Dev Feature: Add `gfpdf_field_product_value` filter to change Product table HTML mark-up in PDF
106
+
107
+ * Bug: Enable Image Watermarks in PDF
108
+ * Bug: Prevent HTML fields getting passed through `wpautop()` [GH#834]
109
+ * Bug: Test for writability in the mPDF tmp directory and fallback to the Gravity PDF tmp directory if failed [GH#837]
110
+ * Bug: Fix scheduled licensing status check and display better error if license deactivation fails [GH#838]
111
+ * Bug: Correctly display the values for multiple Option fields assigned to a single Product when Product Table is ungrouped in PDF [GH#839]
112
+ * Bug: Disable IP-based authentication when the entry IP matches the server IP [GH#840]
113
+
114
  = 5.0.2 =
115
  * Bug: Resolve fatal error on WP Engine due to security in place that prevented mPDF font cache from being saved.
116
 
dist/assets/js/gfpdf-settings.min.js CHANGED
@@ -1 +1 @@
1
- !function(t){t(function(){(new function(){var e=this;this.init=function(){this.initCommon(),this.isSettings()&&this.processSettings(),this.isFormSettings()&&this.processFormSettings()},this.initCommon=function(){this.setupGravityForms(),this.doUploadListener(),this.doColorPicker(),this.setupSelectBoxes(),this.showTooltips(),this.setupCustomPaperSize(),this.setupToggledFields(),this.setupDynamicTemplateFields(),this.setupLicenseDeactivation()},this.setupGravityForms=function(){"undefined"!=typeof gf_vars&&(gf_vars.thisFormButton=GFPDF.conditionalText,gf_vars.show=GFPDF.enable,gf_vars.hide=GFPDF.disable)},this.isSettings=function(){return t("#tab_PDF").length},this.isFormSettings=function(){return t("#tab_pdf").length},this.isFormSettingsList=function(){return t("#gfpdf_list_form").length},this.isFormSettingsEdit=function(){return t("#gfpdf_pdf_form").length},this.getCurrentSettingsPage=function(){return this.isSettings()?t(".nav-tab-wrapper a.nav-tab-active:first").data("id"):""},this.processSettings=function(){switch(this.cleanupGFNavigation(),this.runPDFAccessCheck(),this.getCurrentSettingsPage()){case"general":this.generalSettings();break;case"tools":this.toolsSettings()}},this.processFormSettings=function(){this.isFormSettingsList()&&this.doFormSettingsListPage(),this.isFormSettingsEdit()&&this.doFormSettingsEditPage()},this.doFormSettingsEditPage=function(){this.setupRequiredFields(t("#gfpdf_pdf_form")),this.setupPdfTabs(),this.handleSecurityConditionals(),this.handlePDFConditionalLogic(),this.handleOwnerRestriction(),this.toggleFontAppearance(t("#gfpdf_settings\\[template\\]").data("template_group")),this.toggleAppearanceTab(),t("#gfpdf_pdf_form").submit(function(){try{tinyMCE.triggerSave()}catch(t){}}),t("#gfpdf_pdf_form").submit(function(){t("#gfpdf_settings\\[conditionalLogic\\]").val(jQuery.toJSON(window.gfpdf_current_pdf.conditionalLogic))})},this.handleSecurityConditionals=function(){var i=t("#pdf-general-advanced"),e=i.find('input[name="gfpdf_settings[security]"]'),n=i.find('input[name="gfpdf_settings[format]"]');e.change(function(){if(t(this).is(":checked")){var e=n.filter(":checked").val();t(this).val()===GFPDF.no||e!==GFPDF.standard?i.find("tr:nth-child(3),tr:nth-child(4),tr:nth-child(5):not(.gfpdf-hidden)").hide():i.find("tr:nth-child(3),tr:nth-child(4),tr:nth-child(5):not(.gfpdf-hidden)").show(),e!==GFPDF.standard?i.find("tr:nth-child(2)").hide():i.find("tr:nth-child(2)").show()}}).trigger("change"),n.change(function(){t(this).is(":checked")&&e.trigger("change")}).trigger("change")},this.handlePDFConditionalLogic=function(){gform.addFilter("gform_conditional_object",function(t,i){return"gfpdf"===i?window.gfpdf_current_pdf:t}),t("#gfpdf_conditional_logic").change(function(){void 0===window.gfpdf_current_pdf.conditionalLogic&&t(this).prop("checked")?window.gfpdf_current_pdf.conditionalLogic=new ConditionalLogic:t(this).prop("checked")||(window.gfpdf_current_pdf.conditionalLogic=null),ToggleConditionalLogic(!1,"gfpdf")}).trigger("change")},this.handleOwnerRestriction=function(){var i=t("#gfpdf-advanced-pdf-options");i.find('input[name="gfpdf_settings[public_access]"]').change(function(){t(this).is(":checked")&&("Yes"===t(this).val()?i.find("tr:nth-child(9)").hide():i.find("tr:nth-child(9)").show())}).trigger("change")},this.doFormSettingsListPage=function(){this.setupAJAXListDeleteListener(),this.setupAJAXListDuplicateListener(),this.setupAJAXListStateListener()},this.setupAJAXListStateListener=function(){t("#gfpdf_list_form").on("click",".check-column img",function(){var i=this;if(String(t(this).data("id")).length>0){i.src.indexOf("active1.png")>=0?(i.src=i.src.replace("active1.png","active0.png"),t(i).attr("title",GFPDF.inactive).attr("alt",GFPDF.inactive)):(i.src=i.src.replace("active0.png","active1.png"),t(i).attr("title",GFPDF.active).attr("alt",GFPDF.active));var n={action:"gfpdf_change_state",nonce:t(this).data("nonce"),fid:t(this).data("fid"),pid:t(this).data("id")};e.ajax(n,function(t){})}})},this.setupAJAXListDuplicateListener=function(){t("#gfpdf_list_form").on("click","a.submitduplicate",function(){var i=String(t(this).data("id")),n=this,a=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner gfpdf-spinner-small" />');if(t(this).after(a).parent().parent().attr("style","position:static; visibility: visible;"),i.length>0){var s={action:"gfpdf_list_duplicate",nonce:t(this).data("nonce"),fid:t(this).data("fid"),pid:t(this).data("id")};e.ajax(s,function(a){if(a.msg){t(n).parent().parent().attr("style","").find(".gfpdf-spinner").remove(),e.show_message(a.msg);var s=t(n).parents("tr"),o=s.clone().css("background","#baffb8");o.find(".column-name > a, .edit a").each(function(){var i=t(this).attr("href");i=e.updateURLParameter(i,"pid",a.pid),t(this).attr("href",i)}),o.find(".column-name > a").html(a.name);var d=o.find(".duplicate a"),r=o.find(".delete a"),c=o.find(".check-column img"),l=o.find(".column-shortcode input");d.data("id",a.pid),d.data("nonce",a.dup_nonce),r.data("id",a.pid),r.data("nonce",a.del_nonce),c.data("id",a.pid),c.data("nonce",a.state_nonce);var f=l.val();f=f.replace(i,a.pid),l.val(f);var p="";s.hasClass("alternate")?(o.removeClass("alternate"),p="#FFF"):(o.addClass("alternate"),p="#f9f9f9");var h=c.attr("src");c.attr("title",GFPDF.inactive).attr("alt",GFPDF.inactive).attr("src",h.replace("active1.png","active0.png")),o.hide().insertAfter(s).fadeIn().animate({backgroundColor:p})}})}})},this.maybeShowEmptyRow=function(){var i=t("#gfpdf_list_form tbody");if(0===i.find("tr").length){var e=t("<tr>").addClass("no-items"),n=t("<td>").attr("colspan","5").addClass("colspanchange"),a=t("<a>").attr("href",t("#add-new-pdf").attr("href")).append(GFPDF.letsGoCreateOne+".");n.append(GFPDF.thisFormHasNoPdfs).append(" ").append(a),e.append(n),i.append(e)}},this.setupAJAXListDeleteListener=function(){var i=t("#delete-confirm"),n=[{text:GFPDF.delete,click:function(){i.wpdialog("close"),$elm=t(i.data("elm"));var n=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner gfpdf-spinner-small" />');$elm.append(n).parent().parent().attr("style","position:static; visibility: visible;");var a={action:"gfpdf_list_delete",nonce:$elm.data("nonce"),fid:$elm.data("fid"),pid:$elm.data("id")};e.ajax(a,function(t){t.msg&&($elm.parent().parent().attr("style","").find(".gfpdf-spinner").remove(),e.show_message(t.msg),$elm.parents("tr").css("background","#ffb8b8").fadeOut(400,function(){this.remove(),e.maybeShowEmptyRow()})),i.data("elm",null)})}},{text:GFPDF.cancel,click:function(){i.wpdialog("close").data("elm",null)}}];this.wp_dialog(i,n,300,175),t("#gfpdf_list_form").on("click","a.submitdelete",function(){String(t(this).data("id")).length>0&&!i.data("elm")&&(e.resizeDialogIfNeeded(i,300,175),i.wpdialog("open").data("elm",this))})},this.setupPdfTabs=function(){t(".gfpdf-tab-container").not(":eq(0)").hide(),t(".gfpdf-tab-wrapper a").click(function(){return t(this).parents("ul").find("a").removeClass("current"),t(this).addClass("current").blur(),t(".gfpdf-tab-container").hide(),t(t(this).attr("href")).show(),!1})},this.setupToggledFields=function(){t("form").off("change",".gfpdf-input-toggle").on("change",".gfpdf-input-toggle",function(){var i=t(this).parent().next();t(this).prop("checked")?i.slideDown("slow"):(i.slideUp("slow"),i.find(".wp-editor-area").each(function(){var i=tinyMCE.get(t(this).attr("id"));null!==i&&i.setContent("")}),i.find("textarea").each(function(){t(this).val("")}))})},this.setupDynamicTemplateFields=function(){t("#gfpdf_settings\\[template\\]").off("change").change(function(){var i=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner" />');t(this).next().after(i);var n={action:"gfpdf_get_template_fields",nonce:GFPDF.ajaxNonce,template:t(this).val(),type:t(this).attr("id"),id:t("#gform_id").val(),gform_pdf_id:t("#gform_pdf_id").val()};e.ajax(n,function(n){i.remove(),t('input[name="gfpdf_settings[advanced_template]"][value="No"]').prop("checked",!0).trigger("change"),n.fields?(t.each(n.editors,function(t,i){var e=tinyMCE.get(i);if(null!==e)try{tinyMCE.remove(e)}catch(t){}}),t("#pdf-custom-appearance").hide().html(n.fields).fadeIn(),t("#gfpdf-custom-appearance-nav").show(),e.loadTinyMCEEditor(n.editors,n.editor_init),e.initCommon(),e.doMergetags()):(t("#gfpdf-custom-appearance-nav").hide(),t("#pdf-custom-appearance").html("")),n.template_type&&e.toggleFontAppearance(n.template_type)})})},this.setupLicenseDeactivation=function(){t(".gfpdf-deactivate-license").click(function(){var i=t(this).parent();i.find(".gf_settings_description label").html("");var n=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner" />');t(this).append(n);var a=t(this).data("addon-name"),s={action:"gfpdf_deactivate_license",addon_name:a,license:t(this).data("license"),nonce:t(this).data("nonce")};return e.ajax(s,function(e){n.remove(),e.success?(t("#gfpdf_settings\\[license_"+a+"\\]").val(""),t("#gfpdf_settings\\[license_"+a+"_message\\]").val(""),t("#gfpdf_settings\\[license_"+a+"_status\\]").val(""),i.find("i").remove(),i.find("a").remove(),i.find(".gf_settings_description label").html(e.success)):i.find(".gf_settings_description label").html(e.error)}),!1})},this.toggleFontAppearance=function(i){var e=t("#pdf-general-appearance").find("tr.gfpdf_font_type, tr.gfpdf_font_size, tr.gfpdf_font_colour");"legacy"==i?e.hide():e.show()},this.toggleAppearanceTab=function(){t('input[name="gfpdf_settings[advanced_template]"]').change(function(){"Yes"==t(this).val()?t("#gfpdf-appearance-nav").hide():t("#gfpdf-appearance-nav").show()}),t('input[name="gfpdf_settings[advanced_template]"]:checked').trigger("change")},this.loadTinyMCEEditor=function(i,e){null!=e&&(e.body_class="id post-type-post post-status-publish post-format-standard",e.formats={alignleft:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"left"}},{selector:"img,table,dl.wp-caption",classes:"alignleft"}],aligncenter:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"center"}},{selector:"img,table,dl.wp-caption",classes:"aligncenter"}],alignright:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"right"}},{selector:"img,table,dl.wp-caption",classes:"alignright"}],strikethrough:{inline:"del"}},e.content_style='body#tinymce { max-width: 100%; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;}'),t.each(i,function(t,i){e.selector="#"+i,tinyMCE.init(e),tinyMCE.execCommand("mceAddEditor",!1,i),"function"==typeof QTags&&(QTags({id:i}),QTags._buttonsInit(),"function"==typeof switchEditors.switchto&&switchEditors.switchto(jQuery("#wp-"+i+"-wrap").find(".wp-switch-editor.switch-"+("html"==getUserSetting("editor")?"html":"tmce"))[0]))})},this.doUploadListener=function(){var i;window.formfield="",t("body").off("click",".gfpdf_settings_upload_button").on("click",".gfpdf_settings_upload_button",function(e){e.preventDefault();var n=t(this);window.formfield=t(this).parent().prev(),i?i.open():((i=wp.media.frames.file_frame=wp.media({title:n.data("uploader-title"),button:{text:n.data("uploader-button-text")},multiple:!1})).on("select",function(){i.state().get("selection").each(function(t,i){t=t.toJSON(),window.formfield.val(t.url).change()})}),i.open())})},this.doColorPicker=function(){t(".gfpdf-color-picker").each(function(){t(this).wpColorPicker()})},this.doMergetags=function(){window.gfMergeTags&&"undefined"!=typeof form&&t(".merge-tag-support").length>=0&&t(".merge-tag-support").each(function(){new gfMergeTagsObj(form,t(this))})},this.setupCustomPaperSize=function(){t(".gfpdf_paper_size").each(function(){var i=t(this).nextAll(".gfpdf_paper_size_other").first();t(this).find("select").off("change").change(function(){"CUSTOM"===t(this).val()?i.fadeIn():i.fadeOut()}).trigger("change")})},this.cleanupGFNavigation=function(){t("#gform_tabs a").each(function(){var i=t(this).attr("href"),e=new RegExp("&tab=[^&;]*","g");t(this).attr("href",i.replace(e,""))})},this.runPDFAccessCheck=function(){var i=t("#gfpdf-direct-pdf-protection-check");if(i.length>0){var e=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner" />');i.append(e);var n={action:"gfpdf_has_pdf_protection",nonce:i.data("nonce")};this.ajax(n,function(t){e.remove(),!0===t?i.find("#gfpdf-direct-pdf-check-protected").show():i.find("#gfpdf-direct-pdf-check-unprotected").show()})}},this.setupRequiredFields=function(i){i.attr("novalidate","novalidate"),i.find('tr input[type="submit"]').click(function(){i.addClass("formSubmitted")}),i.find("tr").each(function(){t(this).find(':input[required=""]:first, :input[required]:first').parents("tr").find("th").append('<span class="gfield_required">*</span>')})},this.showTooltips=function(){"function"==typeof gform_initialize_tooltips&&(t(".gf_hidden_tooltip").each(function(){t(this).parent().siblings("th:first").append(" ").append(e.get_tooltip(t(this).html())),t(this).remove()}),gform_initialize_tooltips())},this.setupSelectBoxes=function(){var i=t(".gfpdf-chosen"),e={disable_search_threshold:5,width:"100%"};t("body").hasClass("rtl")&&(i.addClass("chosen-rtl"),e.rtl=!0),i.each(function(){t(this).chosen(e)})},this.setup_advanced_options=function(){var i=t(".gfpdf-advanced-options"),e=i.prev();i.find("a").click(function(){var i=this;return e.slideToggle(600,function(){var e=t(i).text();t(i).text(e==GFPDF.showAdvancedOptions?GFPDF.hideAdvancedOptions:GFPDF.showAdvancedOptions)}),!1}),t(".gfpdf-advanced-options").prev().find(".gfield_error").length&&e.show()},this.generalSettings=function(){this.setupRequiredFields(t("#pdfextended-settings > form"));var i=t("#pdf-general-security");i.find('input[name="gfpdf_settings[default_restrict_owner]"]').change(function(){t(this).is(":checked")&&("Yes"===t(this).val()?i.find("tr:nth-child(3)").hide():i.find("tr:nth-child(3)").show())}).trigger("change"),this.setup_advanced_options()},this.toolsSettings=function(){this.setupToolsTemplateInstallerDialog(),this.setupToolsFontsDialog(),this.setupToolsUninstallDialog()},this.setupToolsTemplateInstallerDialog=function(){var i=t("#gfpdf_settings\\[setup_templates\\]"),n=t("#setup-templates-confirm"),a=[{text:GFPDF.continue,click:function(){i.unbind().click()}},{text:GFPDF.cancel,click:function(){n.wpdialog("close")}}];n.length&&(this.wp_dialog(n,a,500,350),i.click(function(){return e.resizeDialogIfNeeded(n,500,350),n.wpdialog("open"),!1}))},this.setupToolsFontsDialog=function(){var i=t("#gfpdf_settings\\[manage_fonts\\]"),n=t("#manage-font-files");this.wp_dialog(n,[],500,500),i.click(function(){return e.resizeDialogIfNeeded(n,500,500),n.wpdialog("open"),!1}),window.location.hash&&"#manage_fonts"==window.location.hash&&i.click()},this.setupToolsUninstallDialog=function(){var i=t("#gfpdf-uninstall"),n=t("#uninstall-confirm"),a=[{text:GFPDF.uninstall,click:function(){i.parents("form").submit()}},{text:GFPDF.cancel,click:function(){n.wpdialog("close")}}];this.wp_dialog(n,a,500,175),i.click(function(){return e.resizeDialogIfNeeded(n,500,175),n.wpdialog("open"),!1})},this.resizeDialogIfNeeded=function(i,e,n){var a=t(window).width(),s=t(window).height(),o=a<500?a-20:e,d=s<500?s-50:n;i.wpdialog("option","width",o),i.wpdialog("option","height",d)},this.wp_dialog=function(i,e,n,a){i.wpdialog({autoOpen:!1,resizable:!1,draggable:!1,width:n,height:a,modal:!0,dialogClass:"wp-dialog",zIndex:3e5,buttons:e,open:function(){t(this).siblings(".ui-dialog-buttonpane").find("button:eq(1)").focus(),t(".ui-widget-overlay").bind("click",function(){i.wpdialog("close")})}})},this.get_tooltip=function(i){var e=t("<a>"),n=t('<i class="fa fa-question-circle">');return e.append(n),e.addClass("gf_tooltip tooltip"),e.click(function(){return!1}),e.attr("title",i),e},this.ajax=function(i,e){t.ajax({type:"post",dataType:"json",url:GFPDF.ajaxUrl,data:i,success:e,error:this.ajax_error})},this.ajax_error=function(t,i,e){console.log(i),console.log(e)},this.show_message=function(i,e,n){e=void 0!==e?e:4500,n=void 0!==n&&n;var a=t('<div id="message">').html("<p>"+i+"</p>");!0===n?a.addClass("error"):a.addClass("updated"),t(".wrap > h2").after(a),setTimeout(function(){a.slideUp()},e)},this.updateURLParameter=function(t,e,n){var a="",s=t.split("?"),o=s[0],d=s[1],r="";if(d)for(s=d.split("&"),i=0;i<s.length;i++)s[i].split("=")[0]!=e&&(a+=r+s[i],r="&");return o+"?"+a+r+e+"="+n}}).init()})}(jQuery);
1
+ !function(t){t(function(){(new function(){var e=this;this.init=function(){this.initCommon(),this.isSettings()&&this.processSettings(),this.isFormSettings()&&this.processFormSettings()},this.initCommon=function(){this.setupGravityForms(),this.doUploadListener(),this.doColorPicker(),this.setupSelectBoxes(),this.showTooltips(),this.setupCustomPaperSize(),this.setupToggledFields(),this.setupDynamicTemplateFields(),this.setupLicenseDeactivation()},this.setupGravityForms=function(){"undefined"!=typeof gf_vars&&(gf_vars.thisFormButton=GFPDF.conditionalText,gf_vars.show=GFPDF.enable,gf_vars.hide=GFPDF.disable)},this.isSettings=function(){return t("#tab_PDF").length},this.isFormSettings=function(){return t("#tab_pdf").length},this.isFormSettingsList=function(){return t("#gfpdf_list_form").length},this.isFormSettingsEdit=function(){return t("#gfpdf_pdf_form").length},this.getCurrentSettingsPage=function(){return this.isSettings()?t(".nav-tab-wrapper a.nav-tab-active:first").data("id"):""},this.processSettings=function(){switch(this.cleanupGFNavigation(),this.runPDFAccessCheck(),this.getCurrentSettingsPage()){case"general":this.generalSettings();break;case"tools":this.toolsSettings()}},this.processFormSettings=function(){this.isFormSettingsList()&&this.doFormSettingsListPage(),this.isFormSettingsEdit()&&this.doFormSettingsEditPage()},this.doFormSettingsEditPage=function(){this.setupRequiredFields(t("#gfpdf_pdf_form")),this.setupPdfTabs(),this.handleSecurityConditionals(),this.handlePDFConditionalLogic(),this.handleOwnerRestriction(),this.toggleFontAppearance(t("#gfpdf_settings\\[template\\]").data("template_group")),this.toggleAppearanceTab(),t("#gfpdf_pdf_form").submit(function(){try{tinyMCE.triggerSave()}catch(t){}}),t("#gfpdf_pdf_form").submit(function(){t("#gfpdf_settings\\[conditionalLogic\\]").val(jQuery.toJSON(window.gfpdf_current_pdf.conditionalLogic))})},this.handleSecurityConditionals=function(){var e=t("#pdf-general-advanced"),i=e.find('input[name="gfpdf_settings[security]"]'),n=e.find('input[name="gfpdf_settings[format]"]');i.change(function(){if(t(this).is(":checked")){var i=n.filter(":checked").val();t(this).val()===GFPDF.no||i!==GFPDF.standard?e.find("tr:nth-child(3),tr:nth-child(4),tr:nth-child(5):not(.gfpdf-hidden)").hide():e.find("tr:nth-child(3),tr:nth-child(4),tr:nth-child(5):not(.gfpdf-hidden)").show(),i!==GFPDF.standard?e.find("tr:nth-child(2)").hide():e.find("tr:nth-child(2)").show()}}).trigger("change"),n.change(function(){t(this).is(":checked")&&i.trigger("change")}).trigger("change")},this.handlePDFConditionalLogic=function(){gform.addFilter("gform_conditional_object",function(t,e){return"gfpdf"===e?window.gfpdf_current_pdf:t}),t("#gfpdf_conditional_logic").change(function(){void 0===window.gfpdf_current_pdf.conditionalLogic&&t(this).prop("checked")?window.gfpdf_current_pdf.conditionalLogic=new ConditionalLogic:t(this).prop("checked")||(window.gfpdf_current_pdf.conditionalLogic=null),ToggleConditionalLogic(!1,"gfpdf")}).trigger("change")},this.handleOwnerRestriction=function(){var e=t("#gfpdf-advanced-pdf-options");e.find('input[name="gfpdf_settings[public_access]"]').change(function(){t(this).is(":checked")&&("Yes"===t(this).val()?e.find("tr:nth-child(9)").hide():e.find("tr:nth-child(9)").show())}).trigger("change")},this.doFormSettingsListPage=function(){this.setupAJAXListDeleteListener(),this.setupAJAXListDuplicateListener(),this.setupAJAXListStateListener()},this.setupAJAXListStateListener=function(){t("#gfpdf_list_form").on("click",".check-column img",function(){var i=this;if(String(t(this).data("id")).length>0){i.src.indexOf("active1.png")>=0?(i.src=i.src.replace("active1.png","active0.png"),t(i).attr("title",GFPDF.inactive).attr("alt",GFPDF.inactive)):(i.src=i.src.replace("active0.png","active1.png"),t(i).attr("title",GFPDF.active).attr("alt",GFPDF.active));var n={action:"gfpdf_change_state",nonce:t(this).data("nonce"),fid:t(this).data("fid"),pid:t(this).data("id")};e.ajax(n,function(t){})}})},this.setupAJAXListDuplicateListener=function(){t("#gfpdf_list_form").on("click","a.submitduplicate",function(){var i=String(t(this).data("id")),n=this,a=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner gfpdf-spinner-small" />');if(t(this).after(a).parent().parent().attr("style","position:static; visibility: visible;"),i.length>0){var s={action:"gfpdf_list_duplicate",nonce:t(this).data("nonce"),fid:t(this).data("fid"),pid:t(this).data("id")};e.ajax(s,function(a){if(a.msg){t(n).parent().parent().attr("style","").find(".gfpdf-spinner").remove(),e.show_message(a.msg);var s=t(n).parents("tr"),o=s.clone().css("background","#baffb8");o.find(".column-name > a, .edit a").each(function(){var i=t(this).attr("href");i=e.updateURLParameter(i,"pid",a.pid),t(this).attr("href",i)}),o.find(".column-name > a").html(a.name);var d=o.find(".duplicate a"),r=o.find(".delete a"),c=o.find(".check-column img"),l=o.find(".column-shortcode input");d.data("id",a.pid),d.data("nonce",a.dup_nonce),r.data("id",a.pid),r.data("nonce",a.del_nonce),c.data("id",a.pid),c.data("nonce",a.state_nonce);var f=l.val();f=f.replace(i,a.pid),l.val(f);var p="";s.hasClass("alternate")?(o.removeClass("alternate"),p="#FFF"):(o.addClass("alternate"),p="#f9f9f9");var h=c.attr("src");c.attr("title",GFPDF.inactive).attr("alt",GFPDF.inactive).attr("src",h.replace("active1.png","active0.png")),o.hide().insertAfter(s).fadeIn().animate({backgroundColor:p})}})}})},this.maybeShowEmptyRow=function(){var e=t("#gfpdf_list_form tbody");if(0===e.find("tr").length){var i=t("<tr>").addClass("no-items"),n=t("<td>").attr("colspan","5").addClass("colspanchange"),a=t("<a>").attr("href",t("#add-new-pdf").attr("href")).append(GFPDF.letsGoCreateOne+".");n.append(GFPDF.thisFormHasNoPdfs).append(" ").append(a),i.append(n),e.append(i)}},this.setupAJAXListDeleteListener=function(){var i=t("#delete-confirm"),n=[{text:GFPDF.delete,click:function(){i.wpdialog("close"),$elm=t(i.data("elm"));var n=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner gfpdf-spinner-small" />');$elm.append(n).parent().parent().attr("style","position:static; visibility: visible;");var a={action:"gfpdf_list_delete",nonce:$elm.data("nonce"),fid:$elm.data("fid"),pid:$elm.data("id")};e.ajax(a,function(t){t.msg&&($elm.parent().parent().attr("style","").find(".gfpdf-spinner").remove(),e.show_message(t.msg),$elm.parents("tr").css("background","#ffb8b8").fadeOut(400,function(){this.remove(),e.maybeShowEmptyRow()})),i.data("elm",null)})}},{text:GFPDF.cancel,click:function(){i.wpdialog("close").data("elm",null)}}];this.wp_dialog(i,n,300,175),t("#gfpdf_list_form").on("click","a.submitdelete",function(){String(t(this).data("id")).length>0&&!i.data("elm")&&(e.resizeDialogIfNeeded(i,300,175),i.wpdialog("open").data("elm",this))})},this.setupPdfTabs=function(){t(".gfpdf-tab-container").not(":eq(0)").hide(),t(".gfpdf-tab-wrapper a").click(function(){return t(this).parents("ul").find("a").removeClass("current"),t(this).addClass("current").blur(),t(".gfpdf-tab-container").hide(),t(t(this).attr("href")).show(),!1})},this.setupToggledFields=function(){t("form").off("change",".gfpdf-input-toggle").on("change",".gfpdf-input-toggle",function(){var e=t(this).parent().next();t(this).prop("checked")?e.slideDown("slow"):(e.slideUp("slow"),e.find(".wp-editor-area").each(function(){var e=tinyMCE.get(t(this).attr("id"));null!==e&&e.setContent("")}),e.find("textarea").each(function(){t(this).val("")}))})},this.setupDynamicTemplateFields=function(){t("#gfpdf_settings\\[template\\]").off("change").change(function(){var i=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner" />');t(this).next().after(i);var n={action:"gfpdf_get_template_fields",nonce:GFPDF.ajaxNonce,template:t(this).val(),type:t(this).attr("id"),id:t("#gform_id").val(),gform_pdf_id:t("#gform_pdf_id").val()};e.ajax(n,function(n){i.remove(),t('input[name="gfpdf_settings[advanced_template]"][value="No"]').prop("checked",!0).trigger("change"),n.fields?(t.each(n.editors,function(t,e){var i=tinyMCE.get(e);if(null!==i)try{tinyMCE.remove(i)}catch(t){}}),t("#pdf-custom-appearance").hide().html(n.fields).fadeIn(),t("#gfpdf-custom-appearance-nav").show(),e.loadTinyMCEEditor(n.editors,n.editor_init),e.initCommon(),e.doMergetags()):(t("#gfpdf-custom-appearance-nav").hide(),t("#pdf-custom-appearance").html("")),n.template_type&&e.toggleFontAppearance(n.template_type),t(document).trigger("gfpdf_template_loaded",[n])})})},this.setupLicenseDeactivation=function(){t(".gfpdf-deactivate-license").click(function(){var i=t(this).parent();i.find(".gf_settings_description label").html("");var n=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner" />');t(this).append(n);var a=t(this).data("addon-name"),s={action:"gfpdf_deactivate_license",addon_name:a,license:t(this).data("license"),nonce:t(this).data("nonce")};return e.ajax(s,function(e){n.remove(),e.success?(t("#gfpdf_settings\\[license_"+a+"\\]").val(""),t("#gfpdf_settings\\[license_"+a+"_message\\]").val(""),t("#gfpdf_settings\\[license_"+a+"_status\\]").val(""),i.find("i").remove(),i.find("a").remove(),i.find(".gf_settings_description label").html(e.success)):i.find(".gf_settings_description label").html(e.error)}),!1})},this.toggleFontAppearance=function(e){var i=t("#pdf-general-appearance").find("tr.gfpdf_font_type, tr.gfpdf_font_size, tr.gfpdf_font_colour");"legacy"==e?i.hide():i.show()},this.toggleAppearanceTab=function(){t('input[name="gfpdf_settings[advanced_template]"]').change(function(){"Yes"==t(this).val()?t("#gfpdf-appearance-nav").hide():t("#gfpdf-appearance-nav").show()}),t('input[name="gfpdf_settings[advanced_template]"]:checked').trigger("change")},this.loadTinyMCEEditor=function(e,i){null!=i&&(i.body_class="id post-type-post post-status-publish post-format-standard",i.formats={alignleft:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"left"}},{selector:"img,table,dl.wp-caption",classes:"alignleft"}],aligncenter:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"center"}},{selector:"img,table,dl.wp-caption",classes:"aligncenter"}],alignright:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"right"}},{selector:"img,table,dl.wp-caption",classes:"alignright"}],strikethrough:{inline:"del"}},i.content_style='body#tinymce { max-width: 100%; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;}'),t.each(e,function(t,e){i.selector="#"+e,tinyMCE.init(i),tinyMCE.execCommand("mceAddEditor",!1,e),"function"==typeof QTags&&(QTags({id:e}),QTags._buttonsInit(),"function"==typeof switchEditors.switchto&&switchEditors.switchto(jQuery("#wp-"+e+"-wrap").find(".wp-switch-editor.switch-"+("html"==getUserSetting("editor")?"html":"tmce"))[0]))})},this.doUploadListener=function(){var e;window.formfield="",t("body").off("click",".gfpdf_settings_upload_button").on("click",".gfpdf_settings_upload_button",function(i){i.preventDefault();var n=t(this);window.formfield=t(this).parent().prev(),e?e.open():((e=wp.media.frames.file_frame=wp.media({title:n.data("uploader-title"),button:{text:n.data("uploader-button-text")},multiple:!1})).on("select",function(){e.state().get("selection").each(function(t,e){t=t.toJSON(),window.formfield.val(t.url).change()})}),e.open())})},this.doColorPicker=function(){t(".gfpdf-color-picker").each(function(){t(this).wpColorPicker()})},this.doMergetags=function(){window.gfMergeTags&&"undefined"!=typeof form&&t(".merge-tag-support").length>=0&&t(".merge-tag-support").each(function(){new gfMergeTagsObj(form,t(this))})},this.setupCustomPaperSize=function(){t(".gfpdf_paper_size").each(function(){var e=t(this).nextAll(".gfpdf_paper_size_other").first();t(this).find("select").off("change").change(function(){"CUSTOM"===t(this).val()?e.fadeIn():e.fadeOut()}).trigger("change")})},this.cleanupGFNavigation=function(){t("#gform_tabs a").each(function(){var e=t(this).attr("href"),i=new RegExp("&tab=[^&;]*","g");t(this).attr("href",e.replace(i,""))})},this.runPDFAccessCheck=function(){var e=t("#gfpdf-direct-pdf-protection-check");if(e.length>0){var i=t('<img alt="'+GFPDF.spinnerAlt+'" src="'+GFPDF.spinnerUrl+'" class="gfpdf-spinner" />');e.append(i);var n={action:"gfpdf_has_pdf_protection",nonce:e.data("nonce")};this.ajax(n,function(t){i.remove(),!0===t?e.find("#gfpdf-direct-pdf-check-protected").show():e.find("#gfpdf-direct-pdf-check-unprotected").show()})}},this.setupRequiredFields=function(e){e.attr("novalidate","novalidate"),e.find('tr input[type="submit"]').click(function(){e.addClass("formSubmitted")}),e.find("tr").each(function(){t(this).find(':input[required=""]:first, :input[required]:first').parents("tr").find("th").append('<span class="gfield_required">*</span>')})},this.showTooltips=function(){"function"==typeof gform_initialize_tooltips&&(t(".gf_hidden_tooltip").each(function(){t(this).parent().siblings("th:first").append(" ").append(e.get_tooltip(t(this).html())),t(this).remove()}),gform_initialize_tooltips())},this.setupSelectBoxes=function(){var e=t(".gfpdf-chosen"),i={disable_search_threshold:5,width:"100%"};t("body").hasClass("rtl")&&(e.addClass("chosen-rtl"),i.rtl=!0),e.each(function(){t(this).chosen(i)})},this.setup_advanced_options=function(){var e=t(".gfpdf-advanced-options"),i=e.prev();e.find("a").click(function(){var e=this;return i.slideToggle(600,function(){var i=t(e).text();t(e).text(i==GFPDF.showAdvancedOptions?GFPDF.hideAdvancedOptions:GFPDF.showAdvancedOptions)}),!1}),t(".gfpdf-advanced-options").prev().find(".gfield_error").length&&i.show()},this.generalSettings=function(){this.setupRequiredFields(t("#pdfextended-settings > form"));var e=t("#pdf-general-security");e.find('input[name="gfpdf_settings[default_restrict_owner]"]').change(function(){t(this).is(":checked")&&("Yes"===t(this).val()?e.find("tr:nth-child(3)").hide():e.find("tr:nth-child(3)").show())}).trigger("change"),this.setup_advanced_options()},this.toolsSettings=function(){this.setupToolsTemplateInstallerDialog(),this.setupToolsFontsDialog(),this.setupToolsUninstallDialog()},this.setupToolsTemplateInstallerDialog=function(){var i=t("#gfpdf_settings\\[setup_templates\\]"),n=t("#setup-templates-confirm"),a=[{text:GFPDF.continue,click:function(){i.unbind().click()}},{text:GFPDF.cancel,click:function(){n.wpdialog("close")}}];n.length&&(this.wp_dialog(n,a,500,350),i.click(function(){return e.resizeDialogIfNeeded(n,500,350),n.wpdialog("open"),!1}))},this.setupToolsFontsDialog=function(){var i=t("#gfpdf_settings\\[manage_fonts\\]"),n=t("#manage-font-files");this.wp_dialog(n,[],500,500),i.click(function(){return e.resizeDialogIfNeeded(n,500,500),n.wpdialog("open"),!1}),window.location.hash&&"#manage_fonts"==window.location.hash&&i.click()},this.setupToolsUninstallDialog=function(){var i=t("#gfpdf-uninstall"),n=t("#uninstall-confirm"),a=[{text:GFPDF.uninstall,click:function(){i.parents("form").submit()}},{text:GFPDF.cancel,click:function(){n.wpdialog("close")}}];this.wp_dialog(n,a,500,175),i.click(function(){return e.resizeDialogIfNeeded(n,500,175),n.wpdialog("open"),!1})},this.resizeDialogIfNeeded=function(e,i,n){var a=t(window).width(),s=t(window).height(),o=a<500?a-20:i,d=s<500?s-50:n;e.wpdialog("option","width",o),e.wpdialog("option","height",d)},this.wp_dialog=function(e,i,n,a){e.wpdialog({autoOpen:!1,resizable:!1,draggable:!1,width:n,height:a,modal:!0,dialogClass:"wp-dialog",zIndex:3e5,buttons:i,open:function(){t(this).siblings(".ui-dialog-buttonpane").find("button:eq(1)").focus(),t(".ui-widget-overlay").bind("click",function(){e.wpdialog("close")})}})},this.get_tooltip=function(e){var i=t("<a>"),n=t('<i class="fa fa-question-circle">');return i.append(n),i.addClass("gf_tooltip tooltip"),i.click(function(){return!1}),i.attr("title",e),i},this.ajax=function(e,i){t.ajax({type:"post",dataType:"json",url:GFPDF.ajaxUrl,data:e,success:i,error:this.ajax_error})},this.ajax_error=function(t,e,i){console.log(e),console.log(i)},this.show_message=function(e,i,n){i=void 0!==i?i:4500,n=void 0!==n&&n;var a=t('<div id="message">').html("<p>"+e+"</p>");!0===n?a.addClass("error"):a.addClass("updated"),t(".wrap > h2").after(a),setTimeout(function(){a.slideUp()},i)},this.updateURLParameter=function(t,e,n){var a="",s=t.split("?"),o=s[0],d=s[1],r="";if(d)for(s=d.split("&"),i=0;i<s.length;i++)s[i].split("=")[0]!=e&&(a+=r+s[i],r="&");return o+"?"+a+r+e+"="+n}}).init()})}(jQuery);
pdf.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  Plugin Name: Gravity PDF
4
- Version: 5.0.2
5
  Description: Automatically generate highly-customisable PDF documents using Gravity Forms.
6
  Author: Gravity PDF
7
  Author URI: https://gravitypdf.com
@@ -37,7 +37,7 @@ if ( ! defined( 'ABSPATH' ) ) {
37
  /*
38
  * Set base constants we'll use throughout the plugin
39
  */
40
- define( 'PDF_EXTENDED_VERSION', '5.0.2' ); /* the current plugin version */
41
  define( 'PDF_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); /* plugin directory path */
42
  define( 'PDF_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); /* plugin directory url */
43
  define( 'PDF_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); /* the plugin basename */
1
  <?php
2
  /*
3
  Plugin Name: Gravity PDF
4
+ Version: 5.1.0-RC1
5
  Description: Automatically generate highly-customisable PDF documents using Gravity Forms.
6
  Author: Gravity PDF
7
  Author URI: https://gravitypdf.com
37
  /*
38
  * Set base constants we'll use throughout the plugin
39
  */
40
+ define( 'PDF_EXTENDED_VERSION', '5.1.0-RC1' ); /* the current plugin version */
41
  define( 'PDF_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); /* plugin directory path */
42
  define( 'PDF_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); /* plugin directory url */
43
  define( 'PDF_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); /* the plugin basename */
src/assets/languages/gravity-forms-pdf-extended.pot CHANGED
@@ -69,51 +69,51 @@ msgstr ""
69
  msgid "\"%s\" has been deprecated as of Gravity PDF 4.0"
70
  msgstr ""
71
 
72
- #: src/bootstrap.php:313
73
  msgid "Get started with Gravity PDF"
74
  msgstr ""
75
 
76
- #: src/bootstrap.php:313, src/view/html/Settings/help.php:77
77
  msgid "Getting Started"
78
  msgstr ""
79
 
80
- #: src/bootstrap.php:314
81
  msgid "View Gravity PDF Settings"
82
  msgstr ""
83
 
84
- #: src/bootstrap.php:314
85
  msgid "Settings"
86
  msgstr ""
87
 
88
- #: src/bootstrap.php:334
89
  msgid "View Gravity PDF Documentation"
90
  msgstr ""
91
 
92
- #: src/bootstrap.php:334, src/helper/abstract/Helper_Abstract_Addon.php:645
93
  msgid "Docs"
94
  msgstr ""
95
 
96
- #: src/bootstrap.php:335, src/helper/abstract/Helper_Abstract_Addon.php:648
97
  msgid "Get Help and Support"
98
  msgstr ""
99
 
100
- #: src/bootstrap.php:335, src/helper/abstract/Helper_Abstract_Addon.php:648
101
  msgid "Support"
102
  msgstr ""
103
 
104
- #: src/bootstrap.php:336
105
  msgid "View Gravity PDF Extensions Shop"
106
  msgstr ""
107
 
108
- #: src/bootstrap.php:336, src/view/View_Settings.php:215
109
  msgid "Extensions"
110
  msgstr ""
111
 
112
- #: src/bootstrap.php:337
113
  msgid "View Gravity PDF Template Shop"
114
  msgstr ""
115
 
116
- #: src/bootstrap.php:337, src/helper/Helper_Options_Fields.php:117, src/helper/Helper_Options_Fields.php:317
117
  msgid "Templates"
118
  msgstr ""
119
 
@@ -137,11 +137,11 @@ msgstr ""
137
  msgid "There was a problem processing the action. Please try again."
138
  msgstr ""
139
 
140
- #: src/controller/Controller_Install.php:235
141
  msgid "There was a problem uninstalling Gravity PDF. Please try again."
142
  msgstr ""
143
 
144
- #: src/controller/Controller_PDF.php:316, src/view/View_PDF.php:272
145
  msgid "There was a problem generating your PDF"
146
  msgstr ""
147
 
@@ -149,259 +149,259 @@ msgstr ""
149
  msgid "There was a problem installing the PDF templates. Please try again."
150
  msgstr ""
151
 
152
- #: src/controller/Controller_Shortcodes.php:149, src/helper/Helper_Data.php:169
153
- msgid "Gravity PDF"
154
  msgstr ""
155
 
156
- #: src/helper/Helper_Data.php:168, src/model/Model_Mergetags.php:140
157
- msgid "PDF"
158
  msgstr ""
159
 
160
- #: src/helper/Helper_Data.php:196
161
  msgid "Your license key expired on %s."
162
  msgstr ""
163
 
164
- #: src/helper/Helper_Data.php:197
165
  msgid "Your license key has been disabled"
166
  msgstr ""
167
 
168
- #: src/helper/Helper_Data.php:198
169
  msgid "Invalid license key provided"
170
  msgstr ""
171
 
172
- #: src/helper/Helper_Data.php:199, src/helper/Helper_Data.php:200
173
  msgid "Your license is not active for this URL"
174
  msgstr ""
175
 
176
- #: src/helper/Helper_Data.php:201
177
  msgid "This appears to be an invalid license key for %s"
178
  msgstr ""
179
 
180
- #: src/helper/Helper_Data.php:202
181
  msgid "Your license key has reached its activation limit"
182
  msgstr ""
183
 
184
- #: src/helper/Helper_Data.php:203
185
  msgid "An error occurred, please try again"
186
  msgstr ""
187
 
188
- #: src/helper/Helper_Data.php:204
189
  msgid "An error occurred during activation, please try again"
190
  msgstr ""
191
 
192
- #: src/helper/Helper_Data.php:232
193
  msgid "Loading..."
194
  msgstr ""
195
 
196
- #: src/helper/Helper_Data.php:233
197
  msgid "Continue"
198
  msgstr ""
199
 
200
- #: src/helper/Helper_Data.php:234
201
  msgid "Uninstall"
202
  msgstr ""
203
 
204
- #: src/helper/Helper_Data.php:235
205
  msgid "Cancel"
206
  msgstr ""
207
 
208
- #: src/helper/Helper_Data.php:236, src/helper/Helper_PDF_List_Table.php:338
209
  msgid "Delete"
210
  msgstr ""
211
 
212
- #: src/helper/Helper_Data.php:237, src/helper/Helper_PDF_List_Table.php:247, src/helper/Helper_PDF_List_Table.php:248, src/model/Model_Form_Settings.php:881
213
  msgid "Active"
214
  msgstr ""
215
 
216
- #: src/helper/Helper_Data.php:238, src/helper/Helper_PDF_List_Table.php:247, src/helper/Helper_PDF_List_Table.php:248, src/model/Model_Form_Settings.php:881
217
  msgid "Inactive"
218
  msgstr ""
219
 
220
- #: src/helper/Helper_Data.php:239
221
  msgid "this PDF if"
222
  msgstr ""
223
 
224
- #: src/helper/Helper_Data.php:240, src/helper/Helper_Options_Fields.php:181, src/helper/Helper_Options_Fields.php:193, src/helper/Helper_Options_Fields.php:227
225
  msgid "Enable"
226
  msgstr ""
227
 
228
- #: src/helper/Helper_Data.php:241, src/helper/Helper_Options_Fields.php:182, src/helper/Helper_Options_Fields.php:194, src/helper/Helper_Options_Fields.php:228
229
  msgid "Disable"
230
  msgstr ""
231
 
232
- #: src/helper/Helper_Data.php:242
233
  msgid "Successfully Updated"
234
  msgstr ""
235
 
236
- #: src/helper/Helper_Data.php:243
237
  msgid "Successfully Deleted"
238
  msgstr ""
239
 
240
- #: src/helper/Helper_Data.php:244, src/helper/Helper_Options_Fields.php:156, src/helper/Helper_Options_Fields.php:444, src/helper/Helper_Options_Fields.php:492, src/helper/Helper_Options_Fields.php:550, src/helper/Helper_Options_Fields.php:563, src/helper/Helper_Options_Fields.php:576, src/helper/Helper_Options_Fields.php:617, src/helper/Helper_Options_Fields.php:674, src/helper/Helper_Options_Fields.php:695, src/helper/Helper_Options_Fields.php:716, src/helper/Helper_Options_Fields.php:737, src/helper/Helper_Options_Fields.php:758, src/helper/Helper_Options_Fields.php:780
241
  msgid "No"
242
  msgstr ""
243
 
244
- #: src/helper/Helper_Data.php:245, src/helper/Helper_Options_Fields.php:155, src/helper/Helper_Options_Fields.php:443, src/helper/Helper_Options_Fields.php:491, src/helper/Helper_Options_Fields.php:549, src/helper/Helper_Options_Fields.php:562, src/helper/Helper_Options_Fields.php:575, src/helper/Helper_Options_Fields.php:616, src/helper/Helper_Options_Fields.php:673, src/helper/Helper_Options_Fields.php:694, src/helper/Helper_Options_Fields.php:715, src/helper/Helper_Options_Fields.php:736, src/helper/Helper_Options_Fields.php:757, src/helper/Helper_Options_Fields.php:779
245
  msgid "Yes"
246
  msgstr ""
247
 
248
- #: src/helper/Helper_Data.php:246
249
  msgid "Standard"
250
  msgstr ""
251
 
252
- #: src/helper/Helper_Data.php:247
253
  msgid "Advanced"
254
  msgstr ""
255
 
256
- #: src/helper/Helper_Data.php:248
257
  msgid "Select"
258
  msgstr ""
259
 
260
- #: src/helper/Helper_Data.php:249
261
  msgid "Version"
262
  msgstr ""
263
 
264
- #: src/helper/Helper_Data.php:250
265
  msgid "Group"
266
  msgstr ""
267
 
268
- #: src/helper/Helper_Data.php:251
269
  msgid "Tags"
270
  msgstr ""
271
 
272
- #: src/helper/Helper_Data.php:253
273
  msgid "Migrating site #%s"
274
  msgstr ""
275
 
276
- #: src/helper/Helper_Data.php:254
277
  msgid "Site #%s migration complete."
278
  msgstr ""
279
 
280
- #: src/helper/Helper_Data.php:255
281
  msgid "Migration Error"
282
  msgstr ""
283
 
284
- #: src/helper/Helper_Data.php:256
285
  msgid "Site #%s migration errors."
286
  msgstr ""
287
 
288
- #: src/helper/Helper_Data.php:258
289
  msgid "Add New Template"
290
  msgstr ""
291
 
292
- #: src/helper/Helper_Data.php:259, src/view/html/Settings/general.php:70
293
  msgid "Show Advanced Options..."
294
  msgstr ""
295
 
296
- #: src/helper/Helper_Data.php:260
297
  msgid "Hide Advanced Options..."
298
  msgstr ""
299
 
300
- #: src/helper/Helper_Data.php:261
301
  msgid "This form doesn't have any PDFs."
302
  msgstr ""
303
 
304
- #: src/helper/Helper_Data.php:262
305
  msgid "Let's go create one"
306
  msgstr ""
307
 
308
- #: src/helper/Helper_Data.php:263
309
  msgid "Installed PDFs"
310
  msgstr ""
311
 
312
- #: src/helper/Helper_Data.php:265
313
  msgid "Search the Gravity PDF Knowledgebase..."
314
  msgstr ""
315
 
316
- #: src/helper/Helper_Data.php:267
317
  msgid "Requires Gravity PDF v%s"
318
  msgstr ""
319
 
320
- #: src/helper/Helper_Data.php:268
321
  msgid "This PDF template is not compatible with your version of Gravity PDF. This template required Gravity PDF v%s."
322
  msgstr ""
323
 
324
- #: src/helper/Helper_Data.php:269
325
  msgid "Template Details"
326
  msgstr ""
327
 
328
- #: src/helper/Helper_Data.php:270
329
  msgid "Current Template"
330
  msgstr ""
331
 
332
- #: src/helper/Helper_Data.php:271
333
  msgid "Show previous template"
334
  msgstr ""
335
 
336
- #: src/helper/Helper_Data.php:272
337
  msgid "Show next template"
338
  msgstr ""
339
 
340
- #: src/helper/Helper_Data.php:273
341
  msgid "Upload is not a valid template. Upload a .zip file."
342
  msgstr ""
343
 
344
- #: src/helper/Helper_Data.php:274
345
  msgid "Upload exceeds the 10MB limit."
346
  msgstr ""
347
 
348
- #: src/helper/Helper_Data.php:275
349
  msgid "Template successfully installed"
350
  msgstr ""
351
 
352
- #: src/helper/Helper_Data.php:276
353
  msgid "Template successfully updated"
354
  msgstr ""
355
 
356
- #: src/helper/Helper_Data.php:277
357
  msgid "PDF Template(s) Successfully Installed / Updated"
358
  msgstr ""
359
 
360
- #: src/helper/Helper_Data.php:278
361
  msgid "There was a problem with the upload. Reload the page and try again."
362
  msgstr ""
363
 
364
- #: src/helper/Helper_Data.php:279
365
  msgid "Do you really want to delete this PDF template?%sClick 'Cancel' to go back, 'OK' to confirm the delete."
366
  msgstr ""
367
 
368
- #: src/helper/Helper_Data.php:280
369
  msgid "Could not delete template."
370
  msgstr ""
371
 
372
- #: src/helper/Helper_Data.php:281
373
  msgid "If you have a PDF template in .zip format you may install it here. You can also update an existing PDF template (this will override any changes you have made)."
374
  msgstr ""
375
 
376
- #: src/helper/Helper_Data.php:284
377
  msgid "ALL CORE FONTS SUCCESSFULLY INSTALLED"
378
  msgstr ""
379
 
380
- #: src/helper/Helper_Data.php:285
381
  msgid "%s CORE FONT(S) DID NOT INSTALL CORRECTLY"
382
  msgstr ""
383
 
384
- #: src/helper/Helper_Data.php:286
385
  msgid "Could not download Core Font list. Try again."
386
  msgstr ""
387
 
388
- #: src/helper/Helper_Data.php:287
389
  msgid "Downloading %s..."
390
  msgstr ""
391
 
392
- #: src/helper/Helper_Data.php:288
393
  msgid "Completed installation of %s"
394
  msgstr ""
395
 
396
- #: src/helper/Helper_Data.php:289
397
  msgid "Failed installation of %s"
398
  msgstr ""
399
 
400
- #: src/helper/Helper_Data.php:290
401
  msgid "Fonts remaining:"
402
  msgstr ""
403
 
404
- #: src/helper/Helper_Data.php:291
405
  msgid "Retry Failed Downloads?"
406
  msgstr ""
407
 
@@ -518,7 +518,7 @@ msgid "When enabled, reduce wait time during form submission as PDF generation i
518
  msgstr ""
519
 
520
  #: src/helper/Helper_Options_Fields.php:190, src/helper/Helper_Options_Fields.php:198
521
- msgid "Shortcode Debug Message"
522
  msgstr ""
523
 
524
  #: src/helper/Helper_Options_Fields.php:208, src/helper/Helper_Options_Fields.php:218
@@ -778,7 +778,7 @@ msgid "Enable Public Access"
778
  msgstr ""
779
 
780
  #: src/helper/Helper_Options_Fields.php:559
781
- msgid "Allow %sanyone%s with a direct link to access the PDF. %sThis disables all %ssecurity protocols%s for this PDF.%s "
782
  msgstr ""
783
 
784
  #: src/helper/Helper_Options_Fields.php:566
@@ -786,7 +786,7 @@ msgid "Public Access"
786
  msgstr ""
787
 
788
  #: src/helper/Helper_Options_Fields.php:566
789
- msgid "When public access is on all security protocols are disabled and anyone worldwide can view the PDF document for ALL your form's entries. For most users the standard security measures will be adequate and public access should remain disabled."
790
  msgstr ""
791
 
792
  #: src/helper/Helper_Options_Fields.php:572
@@ -794,7 +794,7 @@ msgid "When enabled, the original entry owner will NOT be able to view the PDFs.
794
  msgstr ""
795
 
796
  #: src/helper/Helper_Options_Fields.php:579
797
- msgid "Enable this setting if your PDFs should not be viewable by the end user."
798
  msgstr ""
799
 
800
  #: src/helper/Helper_Options_Fields.php:612
@@ -929,7 +929,7 @@ msgstr ""
929
  msgid "For the best results, use a JPG or non-interlaced 8-Bit PNG that has the same dimensions as the paper size."
930
  msgstr ""
931
 
932
- #: src/helper/Helper_PDF.php:403
933
  msgid "The PDF Template %s requires Gravity PDF version %s. Upgrade to the latest version."
934
  msgstr ""
935
 
@@ -973,7 +973,7 @@ msgstr ""
973
  msgid "Requires Gravity PDF"
974
  msgstr ""
975
 
976
- #: src/helper/Helper_Templates.php:332, src/helper/Helper_Templates.php:392, src/view/View_PDF.php:593
977
  msgid "Legacy"
978
  msgstr ""
979
 
@@ -1013,43 +1013,43 @@ msgstr ""
1013
  msgid "PDF successfully duplicated."
1014
  msgstr ""
1015
 
1016
- #: src/model/Model_Install.php:314
1017
  msgid "There was a problem creating the %s directory. Ensure you have write permissions to your uploads folder."
1018
  msgstr ""
1019
 
1020
- #: src/model/Model_Install.php:323
1021
  msgid "Gravity PDF does not have write permission to the %s directory. Contact your web hosting provider to fix the issue."
1022
  msgstr ""
1023
 
1024
- #: src/model/Model_Install.php:482
1025
  msgid "There was a problem removing the Gravity Form \"%s\" PDF configuration. Try delete manually."
1026
  msgstr ""
1027
 
1028
- #: src/model/Model_Install.php:514
1029
  msgid "There was a problem removing the %s directory. Clean up manually via (S)FTP."
1030
  msgstr ""
1031
 
1032
- #: src/model/Model_PDF.php:335
1033
  msgid "The PDF configuration is not currently active."
1034
  msgstr ""
1035
 
1036
- #: src/model/Model_PDF.php:357
1037
  msgid "PDF conditional logic requirements have not been met."
1038
  msgstr ""
1039
 
1040
- #: src/model/Model_PDF.php:459
1041
  msgid "Your PDF is no longer accessible."
1042
  msgstr ""
1043
 
1044
- #: src/model/Model_PDF.php:513, src/model/Model_PDF.php:553
1045
  msgid "You do not have access to view this PDF."
1046
  msgstr ""
1047
 
1048
- #: src/model/Model_PDF.php:937
1049
  msgid "The PDF could not be saved."
1050
  msgstr ""
1051
 
1052
- #: src/model/Model_PDF.php:1821
1053
  msgid "Could not find PDF configuration requested"
1054
  msgstr ""
1055
 
@@ -1085,19 +1085,19 @@ msgstr ""
1085
  msgid "A font with the same name already exists. Try a different name."
1086
  msgstr ""
1087
 
1088
- #: src/model/Model_Settings.php:869
1089
  msgid "License deactivated."
1090
  msgstr ""
1091
 
1092
- #: src/model/Model_Settings.php:878
1093
  msgid "An error occurred during deactivation, please try again"
1094
  msgstr ""
1095
 
1096
- #: src/model/Model_Templates.php:374
1097
  msgid "No valid PDF template found in Zip archive."
1098
  msgstr ""
1099
 
1100
- #: src/model/Model_Templates.php:405
1101
  msgid "The PHP file %s is not a valid PDF Template."
1102
  msgstr ""
1103
 
@@ -1477,11 +1477,15 @@ msgstr ""
1477
  msgid "Cannot find file %s"
1478
  msgstr ""
1479
 
1480
- #: src/helper/fields/Field_Products.php:230
 
 
 
 
1481
  msgid "Subtotal"
1482
  msgstr ""
1483
 
1484
- #: src/helper/fields/Field_Products.php:235
1485
  msgid "Shipping (%s)"
1486
  msgstr ""
1487
 
@@ -1554,7 +1558,7 @@ msgid "Gravity PDF needs to download the Core PDF fonts."
1554
  msgstr ""
1555
 
1556
  #: src/view/html/Actions/core_font.php:45
1557
- msgid "Before you can generate a PDF using Gravity Forms the core fonts need to be saved to your server. This only needs to be done once."
1558
  msgstr ""
1559
 
1560
  #: src/view/html/Actions/migration.php:41
69
  msgid "\"%s\" has been deprecated as of Gravity PDF 4.0"
70
  msgstr ""
71
 
72
+ #: src/bootstrap.php:314
73
  msgid "Get started with Gravity PDF"
74
  msgstr ""
75
 
76
+ #: src/bootstrap.php:314, src/view/html/Settings/help.php:77
77
  msgid "Getting Started"
78
  msgstr ""
79
 
80
+ #: src/bootstrap.php:315
81
  msgid "View Gravity PDF Settings"
82
  msgstr ""
83
 
84
+ #: src/bootstrap.php:315
85
  msgid "Settings"
86
  msgstr ""
87
 
88
+ #: src/bootstrap.php:335
89
  msgid "View Gravity PDF Documentation"
90
  msgstr ""
91
 
92
+ #: src/bootstrap.php:335, src/helper/abstract/Helper_Abstract_Addon.php:645
93
  msgid "Docs"
94
  msgstr ""
95
 
96
+ #: src/bootstrap.php:336, src/helper/abstract/Helper_Abstract_Addon.php:648
97
  msgid "Get Help and Support"
98
  msgstr ""
99
 
100
+ #: src/bootstrap.php:336, src/helper/abstract/Helper_Abstract_Addon.php:648
101
  msgid "Support"
102
  msgstr ""
103
 
104
+ #: src/bootstrap.php:337
105
  msgid "View Gravity PDF Extensions Shop"
106
  msgstr ""
107
 
108
+ #: src/bootstrap.php:337, src/view/View_Settings.php:215
109
  msgid "Extensions"
110
  msgstr ""
111
 
112
+ #: src/bootstrap.php:338
113
  msgid "View Gravity PDF Template Shop"
114
  msgstr ""
115
 
116
+ #: src/bootstrap.php:338, src/helper/Helper_Options_Fields.php:117, src/helper/Helper_Options_Fields.php:317
117
  msgid "Templates"
118
  msgstr ""
119
 
137
  msgid "There was a problem processing the action. Please try again."
138
  msgstr ""
139
 
140
+ #: src/controller/Controller_Install.php:236
141
  msgid "There was a problem uninstalling Gravity PDF. Please try again."
142
  msgstr ""
143
 
144
+ #: src/controller/Controller_PDF.php:317, src/view/View_PDF.php:272
145
  msgid "There was a problem generating your PDF"
146
  msgstr ""
147
 
149
  msgid "There was a problem installing the PDF templates. Please try again."
150
  msgstr ""
151
 
152
+ #: src/helper/Helper_Data.php:169, src/model/Model_Mergetags.php:140
153
+ msgid "PDF"
154
  msgstr ""
155
 
156
+ #: src/helper/Helper_Data.php:170
157
+ msgid "Gravity PDF"
158
  msgstr ""
159
 
160
+ #: src/helper/Helper_Data.php:197
161
  msgid "Your license key expired on %s."
162
  msgstr ""
163
 
164
+ #: src/helper/Helper_Data.php:198
165
  msgid "Your license key has been disabled"
166
  msgstr ""
167
 
168
+ #: src/helper/Helper_Data.php:199
169
  msgid "Invalid license key provided"
170
  msgstr ""
171
 
172
+ #: src/helper/Helper_Data.php:200, src/helper/Helper_Data.php:201
173
  msgid "Your license is not active for this URL"
174
  msgstr ""
175
 
176
+ #: src/helper/Helper_Data.php:202
177
  msgid "This appears to be an invalid license key for %s"
178
  msgstr ""
179
 
180
+ #: src/helper/Helper_Data.php:203
181
  msgid "Your license key has reached its activation limit"
182
  msgstr ""
183
 
184
+ #: src/helper/Helper_Data.php:204
185
  msgid "An error occurred, please try again"
186
  msgstr ""
187
 
188
+ #: src/helper/Helper_Data.php:205
189
  msgid "An error occurred during activation, please try again"
190
  msgstr ""
191
 
192
+ #: src/helper/Helper_Data.php:233
193
  msgid "Loading..."
194
  msgstr ""
195
 
196
+ #: src/helper/Helper_Data.php:234
197
  msgid "Continue"
198
  msgstr ""
199
 
200
+ #: src/helper/Helper_Data.php:235
201
  msgid "Uninstall"
202
  msgstr ""
203
 
204
+ #: src/helper/Helper_Data.php:236
205
  msgid "Cancel"
206
  msgstr ""
207
 
208
+ #: src/helper/Helper_Data.php:237, src/helper/Helper_PDF_List_Table.php:338
209
  msgid "Delete"
210
  msgstr ""
211
 
212
+ #: src/helper/Helper_Data.php:238, src/helper/Helper_PDF_List_Table.php:247, src/helper/Helper_PDF_List_Table.php:248, src/model/Model_Form_Settings.php:881
213
  msgid "Active"
214
  msgstr ""
215
 
216
+ #: src/helper/Helper_Data.php:239, src/helper/Helper_PDF_List_Table.php:247, src/helper/Helper_PDF_List_Table.php:248, src/model/Model_Form_Settings.php:881
217
  msgid "Inactive"
218
  msgstr ""
219
 
220
+ #: src/helper/Helper_Data.php:240
221
  msgid "this PDF if"
222
  msgstr ""
223
 
224
+ #: src/helper/Helper_Data.php:241, src/helper/Helper_Options_Fields.php:227
225
  msgid "Enable"
226
  msgstr ""
227
 
228
+ #: src/helper/Helper_Data.php:242, src/helper/Helper_Options_Fields.php:228
229
  msgid "Disable"
230
  msgstr ""
231
 
232
+ #: src/helper/Helper_Data.php:243
233
  msgid "Successfully Updated"
234
  msgstr ""
235
 
236
+ #: src/helper/Helper_Data.php:244
237
  msgid "Successfully Deleted"
238
  msgstr ""
239
 
240
+ #: src/helper/Helper_Data.php:245, src/helper/Helper_Options_Fields.php:156, src/helper/Helper_Options_Fields.php:182, src/helper/Helper_Options_Fields.php:194, src/helper/Helper_Options_Fields.php:444, src/helper/Helper_Options_Fields.php:492, src/helper/Helper_Options_Fields.php:550, src/helper/Helper_Options_Fields.php:563, src/helper/Helper_Options_Fields.php:576, src/helper/Helper_Options_Fields.php:617, src/helper/Helper_Options_Fields.php:674, src/helper/Helper_Options_Fields.php:695, src/helper/Helper_Options_Fields.php:716, src/helper/Helper_Options_Fields.php:737, src/helper/Helper_Options_Fields.php:758, src/helper/Helper_Options_Fields.php:780
241
  msgid "No"
242
  msgstr ""
243
 
244
+ #: src/helper/Helper_Data.php:246, src/helper/Helper_Options_Fields.php:155, src/helper/Helper_Options_Fields.php:181, src/helper/Helper_Options_Fields.php:193, src/helper/Helper_Options_Fields.php:443, src/helper/Helper_Options_Fields.php:491, src/helper/Helper_Options_Fields.php:549, src/helper/Helper_Options_Fields.php:562, src/helper/Helper_Options_Fields.php:575, src/helper/Helper_Options_Fields.php:616, src/helper/Helper_Options_Fields.php:673, src/helper/Helper_Options_Fields.php:694, src/helper/Helper_Options_Fields.php:715, src/helper/Helper_Options_Fields.php:736, src/helper/Helper_Options_Fields.php:757, src/helper/Helper_Options_Fields.php:779
245
  msgid "Yes"
246
  msgstr ""
247
 
248
+ #: src/helper/Helper_Data.php:247
249
  msgid "Standard"
250
  msgstr ""
251
 
252
+ #: src/helper/Helper_Data.php:248
253
  msgid "Advanced"
254
  msgstr ""
255
 
256
+ #: src/helper/Helper_Data.php:249
257
  msgid "Select"
258
  msgstr ""
259
 
260
+ #: src/helper/Helper_Data.php:250
261
  msgid "Version"
262
  msgstr ""
263
 
264
+ #: src/helper/Helper_Data.php:251
265
  msgid "Group"
266
  msgstr ""
267
 
268
+ #: src/helper/Helper_Data.php:252
269
  msgid "Tags"
270
  msgstr ""
271
 
272
+ #: src/helper/Helper_Data.php:254
273
  msgid "Migrating site #%s"
274
  msgstr ""
275
 
276
+ #: src/helper/Helper_Data.php:255
277
  msgid "Site #%s migration complete."
278
  msgstr ""
279
 
280
+ #: src/helper/Helper_Data.php:256
281
  msgid "Migration Error"
282
  msgstr ""
283
 
284
+ #: src/helper/Helper_Data.php:257
285
  msgid "Site #%s migration errors."
286
  msgstr ""
287
 
288
+ #: src/helper/Helper_Data.php:259
289
  msgid "Add New Template"
290
  msgstr ""
291
 
292
+ #: src/helper/Helper_Data.php:260, src/view/html/Settings/general.php:70
293
  msgid "Show Advanced Options..."
294
  msgstr ""
295
 
296
+ #: src/helper/Helper_Data.php:261
297
  msgid "Hide Advanced Options..."
298
  msgstr ""
299
 
300
+ #: src/helper/Helper_Data.php:262
301
  msgid "This form doesn't have any PDFs."
302
  msgstr ""
303
 
304
+ #: src/helper/Helper_Data.php:263
305
  msgid "Let's go create one"
306
  msgstr ""
307
 
308
+ #: src/helper/Helper_Data.php:264
309
  msgid "Installed PDFs"
310
  msgstr ""
311
 
312
+ #: src/helper/Helper_Data.php:266
313
  msgid "Search the Gravity PDF Knowledgebase..."
314
  msgstr ""
315
 
316
+ #: src/helper/Helper_Data.php:268
317
  msgid "Requires Gravity PDF v%s"
318
  msgstr ""
319
 
320
+ #: src/helper/Helper_Data.php:269
321
  msgid "This PDF template is not compatible with your version of Gravity PDF. This template required Gravity PDF v%s."
322
  msgstr ""
323
 
324
+ #: src/helper/Helper_Data.php:270
325
  msgid "Template Details"
326
  msgstr ""
327
 
328
+ #: src/helper/Helper_Data.php:271
329
  msgid "Current Template"
330
  msgstr ""
331
 
332
+ #: src/helper/Helper_Data.php:272
333
  msgid "Show previous template"
334
  msgstr ""
335
 
336
+ #: src/helper/Helper_Data.php:273
337
  msgid "Show next template"
338
  msgstr ""
339
 
340
+ #: src/helper/Helper_Data.php:274
341
  msgid "Upload is not a valid template. Upload a .zip file."
342
  msgstr ""
343
 
344
+ #: src/helper/Helper_Data.php:275
345
  msgid "Upload exceeds the 10MB limit."
346
  msgstr ""
347
 
348
+ #: src/helper/Helper_Data.php:276
349
  msgid "Template successfully installed"
350
  msgstr ""
351
 
352
+ #: src/helper/Helper_Data.php:277
353
  msgid "Template successfully updated"
354
  msgstr ""
355
 
356
+ #: src/helper/Helper_Data.php:278
357
  msgid "PDF Template(s) Successfully Installed / Updated"
358
  msgstr ""
359
 
360
+ #: src/helper/Helper_Data.php:279
361
  msgid "There was a problem with the upload. Reload the page and try again."
362
  msgstr ""
363
 
364
+ #: src/helper/Helper_Data.php:280
365
  msgid "Do you really want to delete this PDF template?%sClick 'Cancel' to go back, 'OK' to confirm the delete."
366
  msgstr ""
367
 
368
+ #: src/helper/Helper_Data.php:281
369
  msgid "Could not delete template."
370
  msgstr ""
371
 
372
+ #: src/helper/Helper_Data.php:282
373
  msgid "If you have a PDF template in .zip format you may install it here. You can also update an existing PDF template (this will override any changes you have made)."
374
  msgstr ""
375
 
376
+ #: src/helper/Helper_Data.php:285
377
  msgid "ALL CORE FONTS SUCCESSFULLY INSTALLED"
378
  msgstr ""
379
 
380
+ #: src/helper/Helper_Data.php:286
381
  msgid "%s CORE FONT(S) DID NOT INSTALL CORRECTLY"
382
  msgstr ""
383
 
384
+ #: src/helper/Helper_Data.php:287
385
  msgid "Could not download Core Font list. Try again."
386
  msgstr ""
387
 
388
+ #: src/helper/Helper_Data.php:288
389
  msgid "Downloading %s..."
390
  msgstr ""
391
 
392
+ #: src/helper/Helper_Data.php:289
393
  msgid "Completed installation of %s"
394
  msgstr ""
395
 
396
+ #: src/helper/Helper_Data.php:290
397
  msgid "Failed installation of %s"
398
  msgstr ""
399
 
400
+ #: src/helper/Helper_Data.php:291
401
  msgid "Fonts remaining:"
402
  msgstr ""
403
 
404
+ #: src/helper/Helper_Data.php:292
405
  msgid "Retry Failed Downloads?"
406
  msgstr ""
407
 
518
  msgstr ""
519
 
520
  #: src/helper/Helper_Options_Fields.php:190, src/helper/Helper_Options_Fields.php:198
521
+ msgid "Debug Mode"
522
  msgstr ""
523
 
524
  #: src/helper/Helper_Options_Fields.php:208, src/helper/Helper_Options_Fields.php:218
778
  msgstr ""
779
 
780
  #: src/helper/Helper_Options_Fields.php:559
781
+ msgid "Disable all %ssecurity protocols%s and allow %sanyone%s to access the PDFs."
782
  msgstr ""
783
 
784
  #: src/helper/Helper_Options_Fields.php:566
786
  msgstr ""
787
 
788
  #: src/helper/Helper_Options_Fields.php:566
789
+ msgid "When public access is on all security protocols are disabled and anyone worldwide can view the PDF document for ALL your form's entries. For better security, %suse the signed PDF URLs feature instead%s."
790
  msgstr ""
791
 
792
  #: src/helper/Helper_Options_Fields.php:572
794
  msgstr ""
795
 
796
  #: src/helper/Helper_Options_Fields.php:579
797
+ msgid "Enable this setting if your PDFs should not be viewable by the end user. This setting is overridden %swhen using signed PDF URLs%s."
798
  msgstr ""
799
 
800
  #: src/helper/Helper_Options_Fields.php:612
929
  msgid "For the best results, use a JPG or non-interlaced 8-Bit PNG that has the same dimensions as the paper size."
930
  msgstr ""
931
 
932
+ #: src/helper/Helper_PDF.php:401
933
  msgid "The PDF Template %s requires Gravity PDF version %s. Upgrade to the latest version."
934
  msgstr ""
935
 
973
  msgid "Requires Gravity PDF"
974
  msgstr ""
975
 
976
+ #: src/helper/Helper_Templates.php:332, src/helper/Helper_Templates.php:406, src/view/View_PDF.php:597
977
  msgid "Legacy"
978
  msgstr ""
979
 
1013
  msgid "PDF successfully duplicated."
1014
  msgstr ""
1015
 
1016
+ #: src/model/Model_Install.php:315
1017
  msgid "There was a problem creating the %s directory. Ensure you have write permissions to your uploads folder."
1018
  msgstr ""
1019
 
1020
+ #: src/model/Model_Install.php:324
1021
  msgid "Gravity PDF does not have write permission to the %s directory. Contact your web hosting provider to fix the issue."
1022
  msgstr ""
1023
 
1024
+ #: src/model/Model_Install.php:514
1025
  msgid "There was a problem removing the Gravity Form \"%s\" PDF configuration. Try delete manually."
1026
  msgstr ""
1027
 
1028
+ #: src/model/Model_Install.php:546
1029
  msgid "There was a problem removing the %s directory. Clean up manually via (S)FTP."
1030
  msgstr ""
1031
 
1032
+ #: src/model/Model_PDF.php:373
1033
  msgid "The PDF configuration is not currently active."
1034
  msgstr ""
1035
 
1036
+ #: src/model/Model_PDF.php:395
1037
  msgid "PDF conditional logic requirements have not been met."
1038
  msgstr ""
1039
 
1040
+ #: src/model/Model_PDF.php:504
1041
  msgid "Your PDF is no longer accessible."
1042
  msgstr ""
1043
 
1044
+ #: src/model/Model_PDF.php:558, src/model/Model_PDF.php:598
1045
  msgid "You do not have access to view this PDF."
1046
  msgstr ""
1047
 
1048
+ #: src/model/Model_PDF.php:982
1049
  msgid "The PDF could not be saved."
1050
  msgstr ""
1051
 
1052
+ #: src/model/Model_PDF.php:1887
1053
  msgid "Could not find PDF configuration requested"
1054
  msgstr ""
1055
 
1085
  msgid "A font with the same name already exists. Try a different name."
1086
  msgstr ""
1087
 
1088
+ #: src/model/Model_Settings.php:871
1089
  msgid "License deactivated."
1090
  msgstr ""
1091
 
1092
+ #: src/model/Model_Settings.php:891
1093
  msgid "An error occurred during deactivation, please try again"
1094
  msgstr ""
1095
 
1096
+ #: src/model/Model_Templates.php:377
1097
  msgid "No valid PDF template found in Zip archive."
1098
  msgstr ""
1099
 
1100
+ #: src/model/Model_Templates.php:408
1101
  msgid "The PHP file %s is not a valid PDF Template."
1102
  msgstr ""
1103
 
1477
  msgid "Cannot find file %s"
1478
  msgstr ""
1479
 
1480
+ #: src/helper/fields/Field_Consent.php:93
1481
+ msgid "Consent not given."
1482
+ msgstr ""
1483
+
1484
+ #: src/helper/fields/Field_Products.php:231
1485
  msgid "Subtotal"
1486
  msgstr ""
1487
 
1488
+ #: src/helper/fields/Field_Products.php:236
1489
  msgid "Shipping (%s)"
1490
  msgstr ""
1491
 
1558
  msgstr ""
1559
 
1560
  #: src/view/html/Actions/core_font.php:45
1561
+ msgid "Before you can generate a PDF using Gravity Forms, the core fonts need to be saved to your server. This only needs to be done once."
1562
  msgstr ""
1563
 
1564
  #: src/view/html/Actions/migration.php:41
src/bootstrap.php CHANGED
@@ -231,6 +231,7 @@ class Router implements Helper\Helper_Interface_Actions, Helper\Helper_Interface
231
  $this->actions();
232
  $this->template_manager();
233
  $this->load_core_font_handler();
 
234
 
235
  /* Add localisation support */
236
  $this->add_localization_support();
@@ -449,7 +450,6 @@ class Router implements Helper\Helper_Interface_Actions, Helper\Helper_Interface
449
 
450
  /* add media uploader */
451
  wp_enqueue_media();
452
-
453
  wp_enqueue_script( 'gfpdf_js_entrypoint' );
454
 
455
  /* Load TinyMCE styles */
@@ -868,6 +868,21 @@ class Router implements Helper\Helper_Interface_Actions, Helper\Helper_Interface
868
  $this->singleton->add_class( $class );
869
  }
870
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
871
  /**
872
  * Initialise our background PDF processing handler
873
  *
231
  $this->actions();
232
  $this->template_manager();
233
  $this->load_core_font_handler();
234
+ $this->load_debug();
235
 
236
  /* Add localisation support */
237
  $this->add_localization_support();
450
 
451
  /* add media uploader */
452
  wp_enqueue_media();
 
453
  wp_enqueue_script( 'gfpdf_js_entrypoint' );
454
 
455
  /* Load TinyMCE styles */
868
  $this->singleton->add_class( $class );
869
  }
870
 
871
+ /**
872
+ * Initialise our debug code
873
+ *
874
+ * @since 5.1
875
+ *
876
+ * @return void
877
+ */
878
+ public function load_debug() {
879
+ $class = new Controller\Controller_Debug( $this->data, $this->options, $this->templates );
880
+
881
+ $class->init();
882
+
883
+ $this->singleton->add_class( $class );
884
+ }
885
+
886
  /**
887
  * Initialise our background PDF processing handler
888
  *
src/controller/Controller_Debug.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GFPDF\Controller;
4
+
5
+ use GFPDF\Helper\Helper_Abstract_Controller;
6
+ use GFPDF\Helper\Helper_Abstract_Options;
7
+ use GFPDF\Helper\Helper_Interface_Actions;
8
+ use GFPDF\Helper\Helper_Interface_Filters;
9
+ use GFPDF\Helper\Helper_Data;
10
+ use GFPDF\Helper\Helper_Templates;
11
+
12
+ /**
13
+ * Handle Debug Mode
14
+ *
15
+ * @package Gravity PDF
16
+ * @copyright Copyright (c) 2018, Blue Liquid Designs
17
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
18
+ * @since 5.1
19
+ */
20
+
21
+ /* Exit if accessed directly */
22
+ if ( ! defined( 'ABSPATH' ) ) {
23
+ exit;
24
+ }
25
+
26
+ /*
27
+ This file is part of Gravity PDF.
28
+
29
+ Gravity PDF – Copyright (C) 2018, Blue Liquid Designs
30
+
31
+ This program is free software; you can redistribute it and/or modify
32
+ it under the terms of the GNU General Public License as published by
33
+ the Free Software Foundation; either version 2 of the License, or
34
+ (at your option) any later version.
35
+
36
+ This program is distributed in the hope that it will be useful,
37
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
38
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39
+ GNU General Public License for more details.
40
+
41
+ You should have received a copy of the GNU General Public License
42
+ along with this program; if not, write to the Free Software
43
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44
+ */
45
+
46
+
47
+ /**
48
+ * Class Controller_Debug
49
+ *
50
+ * @package GFPDF\Controller
51
+ *
52
+ * @since 5.1
53
+ */
54
+ class Controller_Debug extends Helper_Abstract_Controller implements Helper_Interface_Actions, Helper_Interface_Filters {
55
+
56
+ /**
57
+ * Holds our Helper_Data object
58
+ * which we can autoload with any data needed
59
+ *
60
+ * @var \GFPDF\Helper\Helper_Data
61
+ *
62
+ * @since 5.1
63
+ */
64
+ protected $data;
65
+
66
+ /**
67
+ * Holds our Helper_Abstract_Options / Helper_Options_Fields object
68
+ * Makes it easy to access global PDF settings and individual form PDF settings
69
+ *
70
+ * @var \GFPDF\Helper\Helper_Abstract_Options
71
+ *
72
+ * @since 5.1
73
+ */
74
+ protected $options;
75
+
76
+ /**
77
+ * Holds our Helper_Templates object
78
+ * used to ease access to our PDF templates
79
+ *
80
+ * @var \GFPDF\Helper\Helper_Templates
81
+ *
82
+ * @since 5.1
83
+ */
84
+ protected $templates;
85
+
86
+ /**
87
+ * Controller_Debug constructor.
88
+ *
89
+ * @param Helper_Data $data
90
+ * @param Helper_Abstract_Options $options
91
+ * @param Helper_Templates $templates
92
+ */
93
+ public function __construct( Helper_Data $data, Helper_Abstract_Options $options, Helper_Templates $templates ) {
94
+ $this->data = $data;
95
+ $this->options = $options;
96
+ $this->templates = $templates;
97
+ }
98
+
99
+ /**
100
+ * Initialise our class defaults
101
+ *
102
+ * @since 5.1
103
+ */
104
+ public function init() {
105
+ $this->add_actions();
106
+ $this->add_filters();
107
+ }
108
+
109
+ /**
110
+ * @since 5.1
111
+ */
112
+ public function add_actions() {
113
+ add_action( 'update_option_gfpdf_settings', [ $this, 'maybe_flush_transient_cache' ], 10, 2 );
114
+ }
115
+
116
+ /**
117
+ * @since 5.1
118
+ */
119
+ public function add_filters() {
120
+ add_filter( 'gfpdf_mpdf_class', [ $this, 'maybe_add_pdf_stats' ] );
121
+ }
122
+
123
+ /**
124
+ * If Debug Mode is toggled on, flush the transient cache
125
+ *
126
+ * @param array $oldvalue
127
+ * @param array $value
128
+ *
129
+ * @since 5.1
130
+ */
131
+ public function maybe_flush_transient_cache( $oldvalue, $value ) {
132
+ if ( isset( $value['debug_mode'] ) && $value['debug_mode'] === 'Yes' && ( ! isset( $oldvalue['debug_mode'] ) || $oldvalue['debug_mode'] !== 'Yes' ) ) {
133
+ $this->templates->flush_template_transient_cache();
134
+ }
135
+ }
136
+
137
+ /**
138
+ * If debug mode enabled, enable PDF stats.
139
+ *
140
+ * @param Mpdf $mpdf
141
+ *
142
+ * @return Mpdf
143
+ *
144
+ * @since 5.1
145
+ */
146
+ public function maybe_add_pdf_stats( $mpdf ) {
147
+ if ( $this->options->get_option( 'debug_mode', 'No' ) === 'Yes' ) {
148
+ $mpdf->WriteHTML( '<div>Generated in ' . sprintf( '%.2F', ( microtime( true ) - $mpdf->time0 ) ) . ' seconds</div>' );
149
+ $mpdf->WriteHTML( '<div>Peak Memory usage ' . number_format( ( memory_get_peak_usage( true ) / ( 1024 * 1024 ) ), 2 ) . ' MB</div>' );
150
+ $mpdf->WriteHTML( '<div>Number of fonts ' . count( $mpdf->fonts ) . '</div>' );
151
+ }
152
+
153
+ return $mpdf;
154
+ }
155
+ }
src/controller/Controller_Install.php CHANGED
@@ -182,7 +182,8 @@ class Controller_Install extends Helper_Abstract_Controller implements Helper_In
182
  $this->data->working_folder = $this->model->get_working_directory();
183
  $this->data->settings_url = $this->model->get_settings_url();
184
 
185
- $this->data->memory_limit = ini_get( 'memory_limit' );
 
186
 
187
  $upload_details = $this->misc->get_upload_details();
188
  $this->data->upload_dir = $upload_details['path'];
182
  $this->data->working_folder = $this->model->get_working_directory();
183
  $this->data->settings_url = $this->model->get_settings_url();
184
 
185
+ $this->data->memory_limit = ini_get( 'memory_limit' );
186
+ $this->data->template_transient_cache = 'gfpdf_template_info';
187
 
188
  $upload_details = $this->misc->get_upload_details();
189
  $this->data->upload_dir = $upload_details['path'];
src/controller/Controller_PDF.php CHANGED
@@ -164,6 +164,7 @@ class Controller_PDF extends Helper_Abstract_Controller implements Helper_Interf
164
  public function add_filters() {
165
  /* PDF authentication middleware */
166
  add_filter( 'gfpdf_pdf_middleware', [ $this->model, 'middle_public_access' ], 10, 3 );
 
167
  add_filter( 'gfpdf_pdf_middleware', [ $this->model, 'middle_active' ], 20, 3 );
168
  add_filter( 'gfpdf_pdf_middleware', [ $this->model, 'middle_conditional' ], 30, 3 );
169
  add_filter( 'gfpdf_pdf_middleware', [ $this->model, 'middle_owner_restriction' ], 40, 3 );
164
  public function add_filters() {
165
  /* PDF authentication middleware */
166
  add_filter( 'gfpdf_pdf_middleware', [ $this->model, 'middle_public_access' ], 10, 3 );
167
+ add_filter( 'gfpdf_pdf_middleware', [ $this->model, 'middle_signed_url_access' ], 15, 3 );
168
  add_filter( 'gfpdf_pdf_middleware', [ $this->model, 'middle_active' ], 20, 3 );
169
  add_filter( 'gfpdf_pdf_middleware', [ $this->model, 'middle_conditional' ], 30, 3 );
170
  add_filter( 'gfpdf_pdf_middleware', [ $this->model, 'middle_owner_restriction' ], 40, 3 );
src/controller/Controller_Shortcodes.php CHANGED
@@ -89,14 +89,8 @@ class Controller_Shortcodes extends Helper_Abstract_Controller implements Helper
89
  * @return void
90
  */
91
  public function init() {
92
-
93
  $this->add_filters();
94
  $this->add_shortcodes();
95
-
96
- /* Add support for the new shortcake UI currently being considered for core integration */
97
- if ( is_admin() ) {
98
- $this->add_shortcake_support();
99
- }
100
  }
101
 
102
  /**
@@ -111,6 +105,7 @@ class Controller_Shortcodes extends Helper_Abstract_Controller implements Helper
111
  add_filter( 'gform_confirmation', [ $this->model, 'gravitypdf_confirmation' ], 100, 3 );
112
  add_filter( 'gform_notification', [ $this->model, 'gravitypdf_notification' ], 100, 3 );
113
  add_filter( 'gform_admin_pre_render', [ $this->model, 'gravitypdf_redirect_confirmation' ] );
 
114
 
115
  /* Basic GravityView Support */
116
  add_filter( 'gravityview/fields/custom/content_before', [ $this->model, 'gravitypdf_gravityview_custom' ], 10 );
@@ -127,73 +122,4 @@ class Controller_Shortcodes extends Helper_Abstract_Controller implements Helper
127
  public function add_shortcodes() {
128
  add_shortcode( 'gravitypdf', [ $this->model, 'gravitypdf' ] );
129
  }
130
-
131
-
132
- /**
133
- * Register our shortcake attributes
134
- * See https://github.com/fusioneng/Shortcake for more details
135
- *
136
- * @since 4.0
137
- *
138
- * @return void
139
- */
140
- public function add_shortcake_support() {
141
-
142
- /* Exist if the shortcake function doesn't exist */
143
- if ( ! function_exists( 'shortcode_ui_register_for_shortcode' ) ) {
144
- return null;
145
- }
146
-
147
- /* Enhance further */
148
- shortcode_ui_register_for_shortcode( 'gravitypdf', [
149
- 'label' => esc_html__( 'Gravity PDF', 'gravity-forms-pdf-extended' ),
150
-
151
- 'listItemImage' => 'dashicons-admin-site',
152
-
153
- 'attrs' => [
154
- [
155
- 'label' => 'ID',
156
- 'attr' => 'id',
157
- 'type' => 'text',
158
- ],
159
-
160
- [
161
- 'label' => 'Anchor Text',
162
- 'attr' => 'text',
163
- 'type' => 'text',
164
- ],
165
-
166
- [
167
- 'label' => 'View',
168
- 'attr' => 'type',
169
- 'type' => 'select',
170
- 'default' => 'download',
171
- 'options' => [
172
- 'download' => 'Download',
173
- 'view' => 'View',
174
- ],
175
- ],
176
-
177
- [
178
- 'label' => 'Anchor Class',
179
- 'attr' => 'class',
180
- 'type' => 'text',
181
- 'description' => 'Optional. Add any class name – separated by a space – you want to apply to the PDF link.',
182
- 'meta' => [
183
- 'placeholder' => '',
184
- ],
185
- ],
186
-
187
- [
188
- 'label' => 'Entry ID',
189
- 'attr' => 'entry',
190
- 'type' => 'text',
191
- 'description' => 'Optional. You can pass in a specific ID or let us auto select one.',
192
- 'meta' => [
193
- 'placeholder' => '',
194
- ],
195
- ],
196
- ],
197
- ] );
198
- }
199
  }
89
  * @return void
90
  */
91
  public function init() {
 
92
  $this->add_filters();
93
  $this->add_shortcodes();
 
 
 
 
 
94
  }
95
 
96
  /**
105
  add_filter( 'gform_confirmation', [ $this->model, 'gravitypdf_confirmation' ], 100, 3 );
106
  add_filter( 'gform_notification', [ $this->model, 'gravitypdf_notification' ], 100, 3 );
107
  add_filter( 'gform_admin_pre_render', [ $this->model, 'gravitypdf_redirect_confirmation' ] );
108
+ add_filter( 'gform_confirmation', [ $this->model, 'gravitypdf_redirect_confirmation_shortcode_processing'], 10, 3 );
109
 
110
  /* Basic GravityView Support */
111
  add_filter( 'gravityview/fields/custom/content_before', [ $this->model, 'gravitypdf_gravityview_custom' ], 10 );
122
  public function add_shortcodes() {
123
  add_shortcode( 'gravitypdf', [ $this->model, 'gravitypdf' ] );
124
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
src/helper/Helper_Data.php CHANGED
@@ -60,6 +60,7 @@ if ( ! defined( 'ABSPATH' ) ) {
60
  * @property string $mpdf_tmp_location The current path to the mPDF tmp directory (including fonts)
61
  * @property string $multisite_template_location The current path to the multisite PDF working directory
62
  * @property string $multisite_template_location_url The current URL to the multisite PDF working directory
 
63
  *
64
  */
65
  class Helper_Data {
60
  * @property string $mpdf_tmp_location The current path to the mPDF tmp directory (including fonts)
61
  * @property string $multisite_template_location The current path to the multisite PDF working directory
62
  * @property string $multisite_template_location_url The current URL to the multisite PDF working directory
63
+ * @property string $template_transient_cache The ID for the template header transient cache
64
  *
65
  */
66
  class Helper_Data {
src/helper/Helper_Options_Fields.php CHANGED
@@ -178,24 +178,24 @@ class Helper_Options_Fields extends Helper_Abstract_Options implements Helper_In
178
  'desc' => sprintf( esc_html__( 'When enable, form submission and resending notifications with PDFs are handled in a background task. %sRequires Background tasks to be enabled%s.', 'gravity-forms-pdf-extended' ), '<a href="https://gravitypdf.com/documentation/v5/background-processing/">', '</a>' ),
179
  'type' => 'radio',
180
  'options' => [
181
- 'Enable' => esc_html__( 'Enable', 'gravity-forms-pdf-extended' ),
182
- 'Disable' => esc_html__( 'Disable', 'gravity-forms-pdf-extended' ),
183
  ],
184
  'std' => 'Disable',
185
  'tooltip' => '<h6>' . esc_html__( 'Background Processing', 'gravity-forms-pdf-extended' ) . '</h6>' . esc_html__( 'When enabled, reduce wait time during form submission as PDF generation is off-loaded to a background process. It is important to ensure Background Tasks are enabled in the Gravity Forms System Status before enabling this feature.', 'gravity-forms-pdf-extended' ),
186
  ],
187
 
188
- 'shortcode_debug_messages' => [
189
- 'id' => 'shortcode_debug_messages',
190
- 'name' => esc_html__( 'Shortcode Debug Message', 'gravity-forms-pdf-extended' ),
191
  'type' => 'radio',
192
  'options' => [
193
- 'Yes' => esc_html__( 'Enable', 'gravity-forms-pdf-extended' ),
194
- 'No' => esc_html__( 'Disable', 'gravity-forms-pdf-extended' ),
195
  ],
196
  'std' => 'No',
197
- 'desc' => esc_html__( 'When enabled and an error occurs, admins will be shown an error message in place of the shortcode.' ),
198
- 'tooltip' => '<h6>' . esc_html__( 'Shortcode Debug Message', 'gravity-forms-pdf-extended' ) . '</h6>' . sprintf( esc_html__( 'Users with the %sgravityforms_view_entries%s capability (the Administrator Role by default) will be shown debug messages when the [gravitypdf] shortcode cannot be generated. When disabled, no content is shown with an error.' ), '<code>', '</code>' ),
199
  ],
200
  ]
201
  ),
@@ -556,14 +556,14 @@ class Helper_Options_Fields extends Helper_Abstract_Options implements Helper_In
556
  'public_access' => [
557
  'id' => 'public_access',
558
  'name' => esc_html__( 'Enable Public Access', 'gravity-forms-pdf-extended' ),
559
- 'desc' => sprintf( esc_html__( 'Allow %sanyone%s with a direct link to access the PDF. %sThis disables all %ssecurity protocols%s for this PDF.%s ', 'gravity-forms-pdf-extended' ), '<strong>', '</strong>', '<em>', '<a href="https://gravitypdf.com/documentation/v5/user-pdf-security/">', '</a>', '</em>' ),
560
  'type' => 'radio',
561
  'options' => [
562
  'Yes' => esc_html__( 'Yes', 'gravity-forms-pdf-extended' ),
563
  'No' => esc_html__( 'No', 'gravity-forms-pdf-extended' ),
564
  ],
565
  'std' => 'No',
566
- 'tooltip' => '<h6>' . esc_html__( 'Public Access', 'gravity-forms-pdf-extended' ) . '</h6>' . esc_html__( "When public access is on all security protocols are disabled and anyone worldwide can view the PDF document for ALL your form's entries. For most users the standard security measures will be adequate and public access should remain disabled.", 'gravity-forms-pdf-extended' ),
567
  ],
568
 
569
  'restrict_owner' => [
@@ -576,7 +576,7 @@ class Helper_Options_Fields extends Helper_Abstract_Options implements Helper_In
576
  'No' => esc_html__( 'No', 'gravity-forms-pdf-extended' ),
577
  ],
578
  'std' => $this->get_option( 'default_restrict_owner', 'No' ),
579
- 'tooltip' => '<h6>' . esc_html__( 'Restrict Owner', 'gravity-forms-pdf-extended' ) . '</h6>' . esc_html__( 'Enable this setting if your PDFs should not be viewable by the end user.', 'gravity-forms-pdf-extended' ),
580
  ],
581
  ]
582
  ),
178
  'desc' => sprintf( esc_html__( 'When enable, form submission and resending notifications with PDFs are handled in a background task. %sRequires Background tasks to be enabled%s.', 'gravity-forms-pdf-extended' ), '<a href="https://gravitypdf.com/documentation/v5/background-processing/">', '</a>' ),
179
  'type' => 'radio',
180
  'options' => [
181
+ 'Enable' => esc_html__( 'Yes', 'gravity-forms-pdf-extended' ),
182
+ 'Disable' => esc_html__( 'No', 'gravity-forms-pdf-extended' ),
183
  ],
184
  'std' => 'Disable',
185
  'tooltip' => '<h6>' . esc_html__( 'Background Processing', 'gravity-forms-pdf-extended' ) . '</h6>' . esc_html__( 'When enabled, reduce wait time during form submission as PDF generation is off-loaded to a background process. It is important to ensure Background Tasks are enabled in the Gravity Forms System Status before enabling this feature.', 'gravity-forms-pdf-extended' ),
186
  ],
187
 
188
+ 'debug_mode' => [
189
+ 'id' => 'debug_mode',
190
+ 'name' => esc_html__( 'Debug Mode', 'gravity-forms-pdf-extended' ),
191
  'type' => 'radio',
192
  'options' => [
193
+ 'Yes' => esc_html__( 'Yes', 'gravity-forms-pdf-extended' ),
194
+ 'No' => esc_html__( 'No', 'gravity-forms-pdf-extended' ),
195
  ],
196
  'std' => 'No',
197
+ 'desc' => esc_html__( 'When enabled, debug information will be displayed on-screen for core features.' ),
198
+ 'tooltip' => '<h6>' . esc_html__( 'Debug Mode', 'gravity-forms-pdf-extended' ) . '</h6>' . esc_html__( 'When enabled, template caching is turned off and flushed, shortcode errors will be displayed on-screen and generation statistics will be included in PDFs.' ),
199
  ],
200
  ]
201
  ),
556
  'public_access' => [
557
  'id' => 'public_access',
558
  'name' => esc_html__( 'Enable Public Access', 'gravity-forms-pdf-extended' ),
559
+ 'desc' => sprintf( esc_html__( 'Disable all %ssecurity protocols%s and allow %sanyone%s to access the PDFs.', 'gravity-forms-pdf-extended' ), '<a href="https://gravitypdf.com/documentation/v5/user-pdf-security/">', '</a>', '<strong>', '</strong>' ),
560
  'type' => 'radio',
561
  'options' => [
562
  'Yes' => esc_html__( 'Yes', 'gravity-forms-pdf-extended' ),
563
  'No' => esc_html__( 'No', 'gravity-forms-pdf-extended' ),
564
  ],
565
  'std' => 'No',
566
+ 'tooltip' => '<h6>' . esc_html__( 'Public Access', 'gravity-forms-pdf-extended' ) . '</h6>' . sprintf( esc_html__( "When public access is on all security protocols are disabled and anyone worldwide can view the PDF document for ALL your form's entries. For better security, %suse the signed PDF URLs feature instead%s.", 'gravity-forms-pdf-extended' ), '<a href="https://gravitypdf.com/documentation/v5/user-shortcodes/#signed-attribute">', '</a>' ),
567
  ],
568
 
569
  'restrict_owner' => [
576
  'No' => esc_html__( 'No', 'gravity-forms-pdf-extended' ),
577
  ],
578
  'std' => $this->get_option( 'default_restrict_owner', 'No' ),
579
+ 'tooltip' => '<h6>' . esc_html__( 'Restrict Owner', 'gravity-forms-pdf-extended' ) . '</h6>' . sprintf( esc_html__( 'Enable this setting if your PDFs should not be viewable by the end user. This setting is overridden %swhen using signed PDF URLs%s.', 'gravity-forms-pdf-extended' ), '<a href="https://gravitypdf.com/documentation/v5/user-shortcodes/#signed-attribute">', '</a>' ),
580
  ],
581
  ]
582
  ),
src/helper/Helper_PDF.php CHANGED
@@ -314,8 +314,6 @@ class Helper_PDF {
314
  $this->mpdf = apply_filters( 'gfpdfe_pre_render_pdf', $this->mpdf, $this->entry['form_id'], $this->entry['id'], $this->settings, '', $this->get_filename() );
315
  $this->mpdf = apply_filters( 'gfpdfe_mpdf_class', $this->mpdf, $this->entry['form_id'], $this->entry['id'], $this->settings, '', $this->get_filename() );
316
 
317
- $this->maybe_add_stats();
318
-
319
  /* If a developer decides to disable all security protocols we don't want the PDF indexed */
320
  if ( ! headers_sent() ) {
321
  header( 'X-Robots-Tag: noindex, nofollow', true );
@@ -655,6 +653,7 @@ class Helper_PDF {
655
  'keepColumns' => true,
656
  'biDirectional' => true,
657
  'showWatermarkText' => true,
 
658
 
659
  'format' => $this->paper_size,
660
  'orientation' => $this->orientation,
@@ -973,17 +972,4 @@ class Helper_PDF {
973
  define( 'DONOTCACHEPAGE', true );
974
  }
975
  }
976
-
977
- /**
978
- * Add PDF stats to end of document if WP_DEBUG_DISPLAY is set to `true`
979
- *
980
- * @since 5.0
981
- */
982
- protected function maybe_add_stats() {
983
- if ( defined( 'WP_DEBUG' ) && defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG && WP_DEBUG_DISPLAY ) {
984
- $this->mpdf->WriteHTML( '<div>Generated in ' . sprintf( '%.2F', ( microtime( true ) - $this->mpdf->time0 ) ) . ' seconds</div>' );
985
- $this->mpdf->WriteHTML( '<div>Peak Memory usage ' . number_format( ( memory_get_peak_usage( true ) / ( 1024 * 1024 ) ), 2 ) . ' MB</div>' );
986
- $this->mpdf->WriteHTML( '<div>Number of fonts ' . count( $this->mpdf->fonts ) . '</div>' );
987
- }
988
- }
989
  }
314
  $this->mpdf = apply_filters( 'gfpdfe_pre_render_pdf', $this->mpdf, $this->entry['form_id'], $this->entry['id'], $this->settings, '', $this->get_filename() );
315
  $this->mpdf = apply_filters( 'gfpdfe_mpdf_class', $this->mpdf, $this->entry['form_id'], $this->entry['id'], $this->settings, '', $this->get_filename() );
316
 
 
 
317
  /* If a developer decides to disable all security protocols we don't want the PDF indexed */
318
  if ( ! headers_sent() ) {
319
  header( 'X-Robots-Tag: noindex, nofollow', true );
653
  'keepColumns' => true,
654
  'biDirectional' => true,
655
  'showWatermarkText' => true,
656
+ 'showWatermarkImage' => true,
657
 
658
  'format' => $this->paper_size,
659
  'orientation' => $this->orientation,
972
  define( 'DONOTCACHEPAGE', true );
973
  }
974
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
975
  }
src/helper/Helper_Sha256_Url_Signer.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GFPDF\Helper;
4
+
5
+ use Spatie\UrlSigner\BaseUrlSigner;
6
+
7
+ /**
8
+ * Custom URL Signer used for auto-expiring PDF URLs
9
+ *
10
+ * @package Gravity PDF
11
+ * @copyright Copyright (c) 2018, Blue Liquid Designs
12
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
13
+ * @since 5.1
14
+ */
15
+
16
+ /* Exit if accessed directly */
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
+
21
+ /*
22
+ This file is part of Gravity PDF.
23
+
24
+ Gravity PDF – Copyright (C) 2018, Blue Liquid Designs
25
+
26
+ This program is free software; you can redistribute it and/or modify
27
+ it under the terms of the GNU General Public License as published by
28
+ the Free Software Foundation; either version 2 of the License, or
29
+ (at your option) any later version.
30
+
31
+ This program is distributed in the hope that it will be useful,
32
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
33
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
+ GNU General Public License for more details.
35
+
36
+ You should have received a copy of the GNU General Public License
37
+ along with this program; if not, write to the Free Software
38
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39
+ */
40
+
41
+ /**
42
+ * Class Helper_Sha256_Url_Signer
43
+ *
44
+ * @package GFPDF\Helper
45
+ */
46
+ class Helper_Sha256_Url_Signer extends BaseUrlSigner {
47
+
48
+ /**
49
+ * Generate a token to identify the secure action.
50
+ *
51
+ * @param \League\Url\UrlImmutable|string $url
52
+ * @param string $expiration
53
+ *
54
+ * @return string
55
+ */
56
+ protected function createSignature( $url, $expiration ) {
57
+ $token_data = [
58
+ 'expires' => $expiration,
59
+ 'url' => (string) $url,
60
+ ];
61
+
62
+ $token = rawurlencode( base64_encode( json_encode( $token_data ) ) );
63
+
64
+ return hash_hmac( 'sha256', $token, $this->signatureKey );
65
+ }
66
+ }
src/helper/Helper_Templates.php CHANGED
@@ -379,12 +379,26 @@ class Helper_Templates {
379
  * Gets the PDF template header information and returns it in a parsed format
380
  *
381
  * @param string $template_path The full path to the PDF template file
 
 
382
  *
383
  * @return array
384
  *
385
  * @since 4.1
386
  */
387
- public function get_template_info_by_path( $template_path ) {
 
 
 
 
 
 
 
 
 
 
 
 
388
  $info = get_file_data( $template_path, $this->get_template_header_details() );
389
 
390
  $info['id'] = basename( $template_path, '.php' );
@@ -399,9 +413,26 @@ class Helper_Templates {
399
  $info['screenshot'] = $this->get_template_image( $info['id'] );
400
  $info['required_pdf_version'] = ( strlen( 'required_pdf_version' ) > 0 ) ? $info['required_pdf_version'] : '4.0';
401
 
 
 
 
 
 
 
 
 
402
  return $info;
403
  }
404
 
 
 
 
 
 
 
 
 
 
405
  /**
406
  * The key / value parsing of the expected PDF template header in v4
407
  *
379
  * Gets the PDF template header information and returns it in a parsed format
380
  *
381
  * @param string $template_path The full path to the PDF template file
382
+ * @param string $cache_name The ID of the transient we should check first
383
+ * @param int $cache_time How long in microseconds until the transient expires (default 1 week)
384
  *
385
  * @return array
386
  *
387
  * @since 4.1
388
  */
389
+ public function get_template_info_by_path( $template_path, $cache_name = '', $cache_time = 604800 ) {
390
+ $options = \GPDFAPI::get_options_class();
391
+ $debug = $options->get_option( 'debug_mode', 'No' );
392
+
393
+ if ( $debug === 'No' ) {
394
+ $cache_name = ! empty( $cache_name ) ? $cache_name : $this->data->template_transient_cache;
395
+ $cache = get_transient( $cache_name );
396
+
397
+ if ( isset( $cache[ $template_path ] ) ) {
398
+ return $cache[ $template_path ];
399
+ }
400
+ }
401
+
402
  $info = get_file_data( $template_path, $this->get_template_header_details() );
403
 
404
  $info['id'] = basename( $template_path, '.php' );
413
  $info['screenshot'] = $this->get_template_image( $info['id'] );
414
  $info['required_pdf_version'] = ( strlen( 'required_pdf_version' ) > 0 ) ? $info['required_pdf_version'] : '4.0';
415
 
416
+ /* Save the results to a transient so we don't hit the disk every page load */
417
+ if ( $debug === 'No' ) {
418
+ $cache = is_array( $cache ) ? $cache : [];
419
+ $cache[ $template_path ] = $info;
420
+
421
+ set_transient( $cache_name, $cache, $cache_time );
422
+ }
423
+
424
  return $info;
425
  }
426
 
427
+ /**
428
+ * Flush the template transient cache, when required
429
+ *
430
+ * @since 5.1
431
+ */
432
+ public function flush_template_transient_cache() {
433
+ delete_transient( $this->data->template_transient_cache );
434
+ }
435
+
436
  /**
437
  * The key / value parsing of the expected PDF template header in v4
438
  *
src/helper/abstract/Helper_Abstract_Addon.php CHANGED
@@ -566,17 +566,17 @@ abstract class Helper_Abstract_Addon {
566
  $possible_responses = $this->data->addon_license_responses( $this->get_name() );
567
 
568
  /* Ensure we have a known error */
569
- if ( ! isset( $license_check->error ) || ! isset( $possible_responses[ $license_check->error ] ) ) {
570
  $this->log->error( 'Unknown license status returned from remote API' );
571
 
572
  return false;
573
  }
574
 
575
- $license_info['status'] = $license_check->error;
576
- $license_info['message'] = $possible_responses[ $license_check->error ];
577
 
578
  /* Include the expiry date if license expired */
579
- if ( $license_check->error === 'expired' ) {
580
  $license_info['message'] = sprintf( $license_info['message'], date_i18n( get_option( 'date_format' ), strtotime( $license_check->expires, current_time( 'timestamp' ) ) ) );
581
  }
582
 
566
  $possible_responses = $this->data->addon_license_responses( $this->get_name() );
567
 
568
  /* Ensure we have a known error */
569
+ if ( ! isset( $license_check->license ) || ! isset( $possible_responses[ $license_check->license ] ) ) {
570
  $this->log->error( 'Unknown license status returned from remote API' );
571
 
572
  return false;
573
  }
574
 
575
+ $license_info['status'] = $license_check->license;
576
+ $license_info['message'] = $possible_responses[ $license_check->license ];
577
 
578
  /* Include the expiry date if license expired */
579
+ if ( $license_check->license === 'expired' ) {
580
  $license_info['message'] = sprintf( $license_info['message'], date_i18n( get_option( 'date_format' ), strtotime( $license_check->expires, current_time( 'timestamp' ) ) ) );
581
  }
582
 
src/helper/fields/Field_Checkbox.php CHANGED
@@ -128,8 +128,8 @@ class Field_Checkbox extends Helper_Abstract_Fields {
128
  */
129
  public function html( $value = '', $label = true ) {
130
 
131
- $value = apply_filters( 'gfpdf_show_field_value', false ); /* Set to `true` to show a field's value instead of the label */
132
  $items = $this->value();
 
133
  $html = '';
134
 
135
  /* Generate our drop down list */
128
  */
129
  public function html( $value = '', $label = true ) {
130
 
 
131
  $items = $this->value();
132
+ $value = apply_filters( 'gfpdf_show_field_value', false, $this->field, $items ); /* Set to `true` to show a field's value instead of the label */
133
  $html = '';
134
 
135
  /* Generate our drop down list */
src/helper/fields/Field_Consent.php ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GFPDF\Helper\Fields;
4
+
5
+ use GFPDF\Helper\Helper_Abstract_Form;
6
+ use GFPDF\Helper\Helper_Misc;
7
+ use GFPDF\Helper\Helper_Abstract_Fields;
8
+
9
+ use GF_Field_Consent;
10
+
11
+ use Exception;
12
+
13
+ /**
14
+ * Gravity Forms Field
15
+ *
16
+ * @package Gravity PDF
17
+ * @copyright Copyright (c) 2018, Blue Liquid Designs
18
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
19
+ * @since 5.1
20
+ */
21
+
22
+ /* Exit if accessed directly */
23
+ if ( ! defined( 'ABSPATH' ) ) {
24
+ exit;
25
+ }
26
+
27
+ /*
28
+ This file is part of Gravity PDF.
29
+
30
+ Gravity PDF – Copyright (C) 2018, Blue Liquid Designs
31
+
32
+ This program is free software; you can redistribute it and/or modify
33
+ it under the terms of the GNU General Public License as published by
34
+ the Free Software Foundation; either version 2 of the License, or
35
+ (at your option) any later version.
36
+
37
+ This program is distributed in the hope that it will be useful,
38
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
39
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40
+ GNU General Public License for more details.
41
+
42
+ You should have received a copy of the GNU General Public License
43
+ along with this program; if not, write to the Free Software
44
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45
+ */
46
+
47
+ /**
48
+ * Controls the display and output of a Gravity Form field
49
+ *
50
+ * @since 5.1
51
+ */
52
+ class Field_Consent extends Helper_Abstract_Fields {
53
+
54
+ /**
55
+ * Check the appropriate variables are parsed in send to the parent construct
56
+ *
57
+ * @param object $field The GF_Field_* Object
58
+ * @param array $entry The Gravity Forms Entry
59
+ *
60
+ * @param \GFPDF\Helper\Helper_Abstract_Form $gform
61
+ * @param \GFPDF\Helper\Helper_Misc $misc
62
+ *
63
+ * @throws Exception
64
+ *
65
+ * @since 5.1
66
+ */
67
+ public function __construct( $field, $entry, Helper_Abstract_Form $gform, Helper_Misc $misc ) {
68
+
69
+ if ( ! is_object( $field ) || ! $field instanceof GF_Field_Consent ) {
70
+ throw new Exception( '$field needs to be in instance of GF_Field_Consent' );
71
+ }
72
+
73
+ /* call our parent method */
74
+ parent::__construct( $field, $entry, $gform, $misc );
75
+ }
76
+
77
+ /**
78
+ * Display the HTML version of this field
79
+ *
80
+ * @param string $value
81
+ * @param bool $label
82
+ *
83
+ * @return string
84
+ *
85
+ * @since 5.1
86
+ */
87
+ public function html( $value = '', $label = true ) {
88
+ $value = $this->value();
89
+
90
+ if ( empty( $value['value'] ) ) {
91
+ $html = sprintf(
92
+ '<span class="consent-tick consent-not-accepted" style="font-family:dejavusans;">&#10006;</span> <span class="consent-label consent-not-accepted-label">%s</span>',
93
+ __( 'Consent not given.', 'gravity-forms-pdf-extended' )
94
+ );
95
+ } else {
96
+ $html = sprintf(
97
+ '<span class="consent-tick consent-accepted" style="font-family:dejavusans;">&#10004;</span> <span class="consent-label consent-accepted-label">%s</span>',
98
+ $value['label']
99
+ );
100
+ }
101
+
102
+ if ( strlen( $value['description'] ) > 0 ) {
103
+ $html .= sprintf( '<div class="consent-text">%s</div>', $value['description'] );
104
+ }
105
+
106
+ return parent::html( $html );
107
+ }
108
+
109
+ /**
110
+ * Get the standard GF value of this field
111
+ *
112
+ * @return string|array
113
+ *
114
+ * @since 5.1
115
+ */
116
+ public function value() {
117
+ if ( $this->has_cache() ) {
118
+ return $this->cache();
119
+ }
120
+
121
+ $value = array_values( $this->get_value() );
122
+
123
+ $consent = [
124
+ 'value' => $value[0],
125
+ 'label' => esc_html( $value[1] ),
126
+ 'description' => wp_kses_post(
127
+ wpautop(
128
+ $this->gform->process_tags( $this->field->get_field_description_from_revision( $value[2] ), $this->form, $this->entry )
129
+ )
130
+ ),
131
+ ];
132
+
133
+ $this->cache( $consent );
134
+
135
+ return $this->cache();
136
+ }
137
+ }
src/helper/fields/Field_Form.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GFPDF\Helper\Fields;
4
+
5
+ use GFPDF\Helper\Helper_Abstract_Form;
6
+ use GFPDF\Helper\Helper_Field_Container;
7
+ use GFPDF\Helper\Helper_Misc;
8
+ use GFPDF\Helper\Helper_Abstract_Fields;
9
+
10
+ use GP_Field_Nested_Form;
11
+
12
+ use Exception;
13
+
14
+ /**
15
+ * Gravity Forms Field
16
+ *
17
+ * @package Gravity PDF
18
+ * @copyright Copyright (c) 2018, Blue Liquid Designs
19
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
20
+ * @since 5.1
21
+ */
22
+
23
+ /* Exit if accessed directly */
24
+ if ( ! defined( 'ABSPATH' ) ) {
25
+ exit;
26
+ }
27
+
28
+ /*
29
+ This file is part of Gravity PDF.
30
+
31
+ Gravity PDF – Copyright (C) 2018, Blue Liquid Designs
32
+
33
+ This program is free software; you can redistribute it and/or modify
34
+ it under the terms of the GNU General Public License as published by
35
+ the Free Software Foundation; either version 2 of the License, or
36
+ (at your option) any later version.
37
+
38
+ This program is distributed in the hope that it will be useful,
39
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
40
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
+ GNU General Public License for more details.
42
+
43
+ You should have received a copy of the GNU General Public License
44
+ along with this program; if not, write to the Free Software
45
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
46
+ */
47
+
48
+ /**
49
+ * Controls the display and output of a Gravity Form field
50
+ *
51
+ * @since 5.1
52
+ */
53
+ class Field_Form extends Helper_Abstract_Fields {
54
+
55
+ /**
56
+ * Check the appropriate variables are parsed in send to the parent construct
57
+ *
58
+ * @param object $field The GF_Field_* Object
59
+ * @param array $entry The Gravity Forms Entry
60
+ *
61
+ * @param \GFPDF\Helper\Helper_Abstract_Form $gform
62
+ * @param \GFPDF\Helper\Helper_Misc $misc
63
+ *
64
+ * @throws Exception
65
+ *
66
+ * @since 5.1
67
+ */
68
+ public function __construct( $field, $entry, Helper_Abstract_Form $gform, Helper_Misc $misc ) {
69
+
70
+ if ( ! is_object( $field ) || ! $field instanceof GP_Field_Nested_Form ) {
71
+ throw new Exception( '$field needs to be in instance of GP_Field_Nested_Form' );
72
+ }
73
+
74
+ /* call our parent method */
75
+ parent::__construct( $field, $entry, $gform, $misc );
76
+ }
77
+
78
+ /**
79
+ * Display the HTML version of this field
80
+ *
81
+ * @param string $value
82
+ * @param bool $label
83
+ *
84
+ * @return string
85
+ *
86
+ * @since 5.1
87
+ */
88
+ public function html( $value = '', $label = true ) {
89
+ /* Get the Nested Form */
90
+ $form = $this->gform->get_form( $this->field->gpnfForm );
91
+ if ( is_wp_error( $form ) ) {
92
+ return parent::html( '' );
93
+ }
94
+
95
+ $html = '';
96
+
97
+ /* Get the Nested Form Entries */
98
+ $value = explode( ',', $this->value() );
99
+ foreach ( $value as $id ) {
100
+ $entry = $this->gform->get_entry( (int) trim( $id ) );
101
+ if ( is_wp_error( $entry ) ) {
102
+ continue;
103
+ }
104
+
105
+ /* Output the entry HTML mark-up */
106
+ $html .= parent::html( $this->get_repeater_html( $form, $entry ) );
107
+ }
108
+
109
+ return $html;
110
+ }
111
+
112
+ /**
113
+ * Output a nested form entry
114
+ *
115
+ * @param array $form
116
+ * @param array $entry
117
+ *
118
+ * @return false|string
119
+ *
120
+ * @since 5.1
121
+ */
122
+ public function get_repeater_html( $form, $entry ) {
123
+ ob_start();
124
+
125
+ $container = new Helper_Field_Container( [ 'class_map' => [] ] );
126
+ $pdf_model = \GPDFAPI::get_mvc_class( 'Model_PDF' );
127
+ $products = new Field_Products( new \GF_Field(), $entry, $this->gform, $this->misc );
128
+
129
+ /* Loop through the Repeater fields */
130
+ foreach ( $form['fields'] as $field ) {
131
+ /* Output a field using the standard method if not empty */
132
+ $class = $pdf_model->get_field_class( $field, $form, $entry, $products );
133
+ if ( ! $class->is_empty() ) {
134
+ $field->cssClass = '';
135
+ $container->generate( $field );
136
+ echo $class->html();
137
+ $container->close( $field );
138
+ }
139
+ }
140
+
141
+ return ob_get_clean();
142
+ }
143
+
144
+ /**
145
+ * Get the standard GF value of this field
146
+ *
147
+ * @return string|array
148
+ *
149
+ * @since 5.1
150
+ */
151
+ public function value() {
152
+ if ( $this->has_cache() ) {
153
+ return $this->cache();
154
+ }
155
+
156
+ $this->cache( $this->get_value() );
157
+
158
+ return $this->cache();
159
+ }
160
+ }
src/helper/fields/Field_Html.php CHANGED
@@ -120,11 +120,9 @@ class Field_Html extends Helper_Abstract_Fields {
120
  return $this->cache();
121
  }
122
 
123
- $value = ( isset( $this->field->content ) ) ? wpautop(
124
- wp_kses_post(
125
  $this->gform->process_tags( $this->field->content, $this->form, $this->entry )
126
- )
127
- ) : '';
128
 
129
  $this->cache( $value );
130
 
120
  return $this->cache();
121
  }
122
 
123
+ $value = ( isset( $this->field->content ) ) ? wp_kses_post(
 
124
  $this->gform->process_tags( $this->field->content, $this->form, $this->entry )
125
+ ) : '';
 
126
 
127
  $this->cache( $value );
128
 
src/helper/fields/Field_Multiselect.php CHANGED
@@ -128,8 +128,8 @@ class Field_Multiselect extends Helper_Abstract_Fields {
128
  */
129
  public function html( $value = '', $label = true ) {
130
 
131
- $value = apply_filters( 'gfpdf_show_field_value', false ); /* Set to `true` to show a field's value instead of the label */
132
  $items = $this->value();
 
133
  $html = '';
134
 
135
  if ( sizeof( $items ) > 0 ) {
128
  */
129
  public function html( $value = '', $label = true ) {
130
 
 
131
  $items = $this->value();
132
+ $value = apply_filters( 'gfpdf_show_field_value', false, $this->field, $items ); /* Set to `true` to show a field's value instead of the label */
133
  $html = '';
134
 
135
  if ( sizeof( $items ) > 0 ) {
src/helper/fields/Field_Option.php CHANGED
@@ -162,7 +162,9 @@ class Field_Option extends Helper_Abstract_Field_Products {
162
 
163
  if ( isset( $data['products'][ $this->field->productField ]['options'] ) ) {
164
  $this->cache( [
165
- 'options' => $data['products'][ $this->field->productField ]['options'],
 
 
166
  ] );
167
  } else {
168
  $this->cache( [] );
162
 
163
  if ( isset( $data['products'][ $this->field->productField ]['options'] ) ) {
164
  $this->cache( [
165
+ 'options' => array_filter( $data['products'][ $this->field->productField ]['options'], function( $option ) {
166
+ return ! isset( $option['id'] ) || $option['id'] === $this->field->id;
167
+ }),
168
  ] );
169
  } else {
170
  $this->cache( [] );
src/helper/fields/Field_Products.php CHANGED
@@ -198,8 +198,9 @@ class Field_Products extends Helper_Abstract_Fields {
198
 
199
  <?php if ( class_exists( 'GP_Ecommerce_Fields' ) ):
200
  $gpecommerce = \GP_Ecommerce_Fields::get_instance( null );
201
- $use_value = (bool) apply_filters( 'gfpdf_show_field_value', false ); /* Set to `true` to show a field's value instead of the label */
202
- $order = GFCommon::get_product_fields( $this->form, $this->entry, ! $use_value );
 
203
  $order_summary = $gpecommerce->get_order_summary( $order, $this->form, $this->entry );
204
  ?>
205
  <?php foreach ( $order_summary as $index => $group ): ?>
@@ -256,7 +257,7 @@ class Field_Products extends Helper_Abstract_Fields {
256
 
257
  <?php
258
 
259
- return ob_get_clean();
260
  }
261
 
262
  /**
@@ -279,8 +280,9 @@ class Field_Products extends Helper_Abstract_Fields {
279
  $lead = $this->entry;
280
 
281
  /* Get all products for this field */
282
- $use_value = (bool) apply_filters( 'gfpdf_show_field_value', false ); /* Set to `true` to show a field's value instead of the label */
283
- $products = GFCommon::get_product_fields( $form, $lead, ! $use_value );
 
284
 
285
  /* Set up the appropriate varaibles needed for our product processing */
286
  $form_array = []; /* holds the actual product data */
198
 
199
  <?php if ( class_exists( 'GP_Ecommerce_Fields' ) ):
200
  $gpecommerce = \GP_Ecommerce_Fields::get_instance( null );
201
+ $use_value = (bool) apply_filters( 'gfpdf_show_field_value', false, $this->field, '' ); /* Set to `true` to show a field's value instead of the label */
202
+ $use_admin_label = (bool) apply_filters( 'gfpdf_use_admin_label', false, $this->field, '' ); /* Set to `true` to use the admin label */
203
+ $order = GFCommon::get_product_fields( $this->form, $this->entry, ! $use_value, $use_admin_label );
204
  $order_summary = $gpecommerce->get_order_summary( $order, $this->form, $this->entry );
205
  ?>
206
  <?php foreach ( $order_summary as $index => $group ): ?>
257
 
258
  <?php
259
 
260
+ return apply_filters( 'gfpdf_field_product_value', ob_get_clean(), $products, $this->field, $this->form, $this->entry, $this );
261
  }
262
 
263
  /**
280
  $lead = $this->entry;
281
 
282
  /* Get all products for this field */
283
+ $use_value = (bool) apply_filters( 'gfpdf_show_field_value', false, $this->field, '' ); /* Set to `true` to show a field's value instead of the label */
284
+ $use_admin_label = (bool) apply_filters( 'gfpdf_use_admin_label', false, $this->field, '' ); /* Set to `true` to use the admin label */
285
+ $products = GFCommon::get_product_fields( $form, $lead, ! $use_value, $use_admin_label );
286
 
287
  /* Set up the appropriate varaibles needed for our product processing */
288
  $form_array = []; /* holds the actual product data */
src/helper/fields/Field_Radio.php CHANGED
@@ -85,10 +85,9 @@ class Field_Radio extends Helper_Abstract_Fields {
85
  * @since 4.0
86
  */
87
  public function html( $value = '', $label = true ) {
88
- $data = $this->value();
89
-
90
- $value = apply_filters( 'gfpdf_show_field_value', false ); /* Set to `true` to show a field's value instead of the label */
91
- $output = ( $value ) ? $data['value'] : $data['label'];
92
 
93
  return parent::html( $output );
94
  }
85
  * @since 4.0
86
  */
87
  public function html( $value = '', $label = true ) {
88
+ $items = $this->value();
89
+ $value = apply_filters( 'gfpdf_show_field_value', false, $this->field, $items ); /* Set to `true` to show a field's value instead of the label */
90
+ $output = ( $value ) ? $items['value'] : $items['label'];
 
91
 
92
  return parent::html( $output );
93
  }
src/helper/fields/Field_Repeater.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GFPDF\Helper\Fields;
4
+
5
+ use GFPDF\Helper\Helper_Abstract_Form;
6
+ use GFPDF\Helper\Helper_Field_Container;
7
+ use GFPDF\Helper\Helper_Misc;
8
+ use GFPDF\Helper\Helper_Abstract_Fields;
9
+
10
+ use GF_Field_Repeater;
11
+
12
+ use Exception;
13
+
14
+ /**
15
+ * Gravity Forms Field
16
+ *
17
+ * @package Gravity PDF
18
+ * @copyright Copyright (c) 2018, Blue Liquid Designs
19
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
20
+ * @since 5.1
21
+ */
22
+
23
+ /* Exit if accessed directly */
24
+ if ( ! defined( 'ABSPATH' ) ) {
25
+ exit;
26
+ }
27
+
28
+ /*
29
+ This file is part of Gravity PDF.
30
+
31
+ Gravity PDF – Copyright (C) 2018, Blue Liquid Designs
32
+
33
+ This program is free software; you can redistribute it and/or modify
34
+ it under the terms of the GNU General Public License as published by
35
+ the Free Software Foundation; either version 2 of the License, or
36
+ (at your option) any later version.
37
+
38
+ This program is distributed in the hope that it will be useful,
39
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
40
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
+ GNU General Public License for more details.
42
+
43
+ You should have received a copy of the GNU General Public License
44
+ along with this program; if not, write to the Free Software
45
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
46
+ */
47
+
48
+ /**
49
+ * Controls the display and output of a Gravity Form field
50
+ *
51
+ * @since 5.1
52
+ */
53
+ class Field_Repeater extends Helper_Abstract_Fields {
54
+
55
+ /**
56
+ * Check the appropriate variables are parsed in send to the parent construct
57
+ *
58
+ * @param object $field The GF_Field_* Object
59
+ * @param array $entry The Gravity Forms Entry
60
+ *
61
+ * @param \GFPDF\Helper\Helper_Abstract_Form $gform
62
+ * @param \GFPDF\Helper\Helper_Misc $misc
63
+ *
64
+ * @throws Exception
65
+ *
66
+ * @since 5.1
67
+ */
68
+ public function __construct( $field, $entry, Helper_Abstract_Form $gform, Helper_Misc $misc ) {
69
+
70
+ if ( ! is_object( $field ) || ! $field instanceof GF_Field_Repeater ) {
71
+ throw new Exception( '$field needs to be in instance of GF_Field_Repeater' );
72
+ }
73
+
74
+ /* call our parent method */
75
+ parent::__construct( $field, $entry, $gform, $misc );
76
+ }
77
+
78
+ /**
79
+ * Return the form data
80
+ *
81
+ * @return array
82
+ *
83
+ * @since 5.1
84
+ */
85
+ public function form_data() {
86
+ $value = $this->get_repeater_form_data( [], $this->value(), $this->field );
87
+
88
+ /* Add our List HTML */
89
+ $label = $this->get_label();
90
+ $data['repeater'][ $this->field->id . '.' . $label ] = $value;
91
+ $data['repeater'][ $this->field->id ] = $value;
92
+ $data['repeater'][ $label ] = $value;
93
+
94
+ return $data;
95
+ }
96
+
97
+ /**
98
+ * Recursively get the form data array
99
+ *
100
+ * @param array $data
101
+ * @param array $value The current Repeater entry data
102
+ * @param array $field The current Repeater Field
103
+ *
104
+ * @return array
105
+ * @since 5.1
106
+ */
107
+ public function get_repeater_form_data( $data, $value, $field ) {
108
+ $pdf_model = \GPDFAPI::get_mvc_class( 'Model_PDF' );
109
+ $products = new Field_Products( new \GF_Field(), $this->entry, $this->gform, $this->misc );
110
+
111
+ foreach ( $value as $id => $item ) {
112
+ $item = $this->add_form_entry_ids( $item );
113
+
114
+ /* Loop through the Repeater fields */
115
+ foreach ( $field->fields as $sub_field ) {
116
+ if ( $sub_field instanceof GF_Field_Repeater ) {
117
+ if ( isset( $item[ $sub_field->id ] ) ) {
118
+ $data = array_replace_recursive( $data, [ $id => [ $sub_field->id => $this->get_repeater_form_data( [], $item[ $sub_field->id ], $sub_field ) ] ] );
119
+ }
120
+ continue;
121
+ }
122
+
123
+ $class = $pdf_model->get_field_class( $sub_field, $this->form, $item, $products );
124
+ $form_data = $class->form_data();
125
+ $data = array_replace_recursive( $data, [ $id => $form_data['field'] ] );
126
+ }
127
+ }
128
+
129
+ return $data;
130
+ }
131
+
132
+ /**
133
+ * Display the HTML version of this field
134
+ *
135
+ * @param string $value
136
+ * @param bool $label
137
+ *
138
+ * @return string
139
+ *
140
+ * @since 5.1
141
+ */
142
+ public function html( $value = '', $label = true ) {
143
+ $value = $this->value();
144
+
145
+ ob_start();
146
+ $this->get_repeater_html( $value, $this->field );
147
+ return ob_get_clean();
148
+ }
149
+
150
+ /**
151
+ * Output the Repeater HTML
152
+ *
153
+ * @param array $value The current Repeater entry data
154
+ * @param array $field The current Repeater Field
155
+ *
156
+ * @since 5.1
157
+ */
158
+ public function get_repeater_html( $value, $field ) {
159
+ $is_top_level = $field === $this->field;
160
+ $container = new Helper_Field_Container();
161
+ $pdf_model = \GPDFAPI::get_mvc_class( 'Model_PDF' );
162
+ $products = new Field_Products( new \GF_Field(), $this->entry, $this->gform, $this->misc );
163
+
164
+ /* Output the Repeater Label if a sub Repeater */
165
+ if ( ! $is_top_level ) {
166
+ echo sprintf( '<div class="gfpdf-section-title"><h3>%s</h3></div>', $field->label );
167
+ }
168
+
169
+ /* Loop through the entry data for the current repeater */
170
+ foreach ( $value as $item ) {
171
+ if ( $is_top_level ) {
172
+ ob_start();
173
+ }
174
+
175
+ $item = $this->add_form_entry_ids( $item );
176
+
177
+ /* Loop through the Repeater fields */
178
+ foreach ( $field->fields as $sub_field ) {
179
+ $sub_field = \GF_Fields::create($sub_field);
180
+
181
+ if ( $sub_field instanceof GF_Field_Repeater ) {
182
+
183
+ /* Only recursively output if a value exists */
184
+ if ( isset( $item[ $sub_field->id ] ) ) {
185
+ echo '<div class="repeater-container">';
186
+ $this->get_repeater_html( $item[ $sub_field->id ], $sub_field );
187
+ echo '</div>';
188
+ }
189
+
190
+ continue;
191
+ }
192
+
193
+ /* Output a field using the standard method if not empty */
194
+ $class = $pdf_model->get_field_class( $sub_field, $this->form, $item, $products );
195
+ if ( ! $class->is_empty() ) {
196
+ $field->cssClass = '';
197
+ $container->generate( $sub_field );
198
+ echo $class->html();
199
+ $container->close( $sub_field );
200
+ }
201
+ }
202
+
203
+ if ( $is_top_level ) {
204
+ echo parent::html( ob_get_clean() );
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Allow the Repeater fields to act as an entry by padding the entry ID and form ID
211
+ *
212
+ * @param array $item
213
+ *
214
+ * @return array
215
+ *
216
+ * @since 5.1
217
+ */
218
+ protected function add_form_entry_ids( $item ) {
219
+ $item['id'] = $this->entry['id'];
220
+ $item['form_id'] = $this->entry['form_id'];
221
+
222
+ return $item;
223
+ }
224
+
225
+ /**
226
+ * Get the standard GF value of this field
227
+ *
228
+ * @return string|array
229
+ *
230
+ * @since 5.1
231
+ */
232
+ public function value() {
233
+ if ( $this->has_cache() ) {
234
+ return $this->cache();
235
+ }
236
+
237
+ $this->cache( $this->get_value() );
238
+
239
+ return $this->cache();
240
+ }
241
+ }
src/helper/fields/Field_Select.php CHANGED
@@ -112,10 +112,9 @@ class Field_Select extends Helper_Abstract_Fields {
112
  * @since 4.0
113
  */
114
  public function html( $value = '', $label = true ) {
115
- $data = $this->value();
116
-
117
- $value = apply_filters( 'gfpdf_show_field_value', false ); /* Set to `true` to show a field's value instead of the label */
118
- $output = ( $value ) ? $data['value'] : $data['label'];
119
 
120
  return parent::html( $output );
121
  }
112
  * @since 4.0
113
  */
114
  public function html( $value = '', $label = true ) {
115
+ $items = $this->value();
116
+ $value = apply_filters( 'gfpdf_show_field_value', false, $this->field, $items ); /* Set to `true` to show a field's value instead of the label */
117
+ $output = ( $value ) ? $items['value'] : $items['label'];
 
118
 
119
  return parent::html( $output );
120
  }
src/helper/licensing/EDD_SL_Plugin_Updater.php CHANGED
@@ -38,7 +38,7 @@ if ( ! defined( 'ABSPATH' ) ) {
38
  * Allows plugins to use their own update API.
39
  *
40
  * @author Easy Digital Downloads
41
- * @version 1.6.14
42
  */
43
  class EDD_SL_Plugin_Updater {
44
 
@@ -50,6 +50,8 @@ class EDD_SL_Plugin_Updater {
50
  private $wp_override = false;
51
  private $cache_key = '';
52
 
 
 
53
  /**
54
  * Class constructor.
55
  *
@@ -71,10 +73,19 @@ class EDD_SL_Plugin_Updater {
71
  $this->version = $_api_data['version'];
72
  $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
73
  $this->beta = ! empty( $this->api_data['beta'] ) ? true : false;
74
- $this->cache_key = md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
75
 
76
  $edd_plugin_data[ $this->slug ] = $this->api_data;
77
 
 
 
 
 
 
 
 
 
 
78
  // Set up hooks.
79
  $this->init();
80
 
@@ -130,10 +141,7 @@ class EDD_SL_Plugin_Updater {
130
  $version_info = $this->get_cached_version_info();
131
 
132
  if ( false === $version_info ) {
133
- $version_info = $this->api_request( 'plugin_latest_version', [
134
- 'slug' => $this->slug,
135
- 'beta' => $this->beta,
136
- ] );
137
 
138
  $this->set_version_info_cache( $version_info );
139
 
@@ -147,7 +155,7 @@ class EDD_SL_Plugin_Updater {
147
 
148
  }
149
 
150
- $_transient_data->last_checked = current_time( 'timestamp' );
151
  $_transient_data->checked[ $this->name ] = $this->version;
152
 
153
  }
@@ -191,10 +199,20 @@ class EDD_SL_Plugin_Updater {
191
  $version_info = $this->get_cached_version_info();
192
 
193
  if ( false === $version_info ) {
194
- $version_info = $this->api_request( 'plugin_latest_version', [
195
- 'slug' => $this->slug,
196
- 'beta' => $this->beta,
197
- ] );
 
 
 
 
 
 
 
 
 
 
198
 
199
  $this->set_version_info_cache( $version_info );
200
  }
@@ -209,7 +227,7 @@ class EDD_SL_Plugin_Updater {
209
 
210
  }
211
 
212
- $update_cache->last_checked = current_time( 'timestamp' );
213
  $update_cache->checked[ $this->name ] = $this->version;
214
 
215
  set_site_transient( 'update_plugins', $update_cache );
@@ -291,6 +309,7 @@ class EDD_SL_Plugin_Updater {
291
  'fields' => [
292
  'banners' => [],
293
  'reviews' => false,
 
294
  ],
295
  ];
296
 
@@ -317,27 +336,43 @@ class EDD_SL_Plugin_Updater {
317
 
318
  // Convert sections into an associative array, since we're getting an object, but Core expects an array.
319
  if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
320
- $new_sections = [];
321
- foreach ( $_data->sections as $key => $value ) {
322
- $new_sections[ $key ] = $value;
323
- }
324
-
325
- $_data->sections = $new_sections;
326
  }
327
 
328
  // Convert banners into an associative array, since we're getting an object, but Core expects an array.
329
  if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
330
- $new_banners = [];
331
- foreach ( $_data->banners as $key => $value ) {
332
- $new_banners[ $key ] = $value;
333
- }
334
 
335
- $_data->banners = $new_banners;
 
 
336
  }
337
 
338
  return $_data;
339
  }
340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  /**
342
  * Disable SSL verification in order to prevent download update failures
343
  *
@@ -352,7 +387,6 @@ class EDD_SL_Plugin_Updater {
352
  if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
353
  $args['sslverify'] = $verify_ssl;
354
  }
355
-
356
  return $args;
357
 
358
  }
@@ -371,7 +405,29 @@ class EDD_SL_Plugin_Updater {
371
  */
372
  private function api_request( $_action, $_data ) {
373
 
374
- global $wp_version;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
 
376
  $data = array_merge( $this->api_data, $_data );
377
 
@@ -396,11 +452,7 @@ class EDD_SL_Plugin_Updater {
396
  ];
397
 
398
  $verify_ssl = $this->verify_ssl();
399
- $request = wp_remote_post( $this->api_url, [
400
- 'timeout' => 15,
401
- 'sslverify' => $verify_ssl,
402
- 'body' => $api_params,
403
- ] );
404
 
405
  if ( ! is_wp_error( $request ) ) {
406
  $request = json_decode( wp_remote_retrieve_body( $request ) );
@@ -416,6 +468,10 @@ class EDD_SL_Plugin_Updater {
416
  $request->banners = maybe_unserialize( $request->banners );
417
  }
418
 
 
 
 
 
419
  if ( ! empty( $request->sections ) ) {
420
  foreach ( $request->sections as $key => $section ) {
421
  $request->$key = (array) $section;
@@ -463,11 +519,7 @@ class EDD_SL_Plugin_Updater {
463
  ];
464
 
465
  $verify_ssl = $this->verify_ssl();
466
- $request = wp_remote_post( $this->api_url, [
467
- 'timeout' => 15,
468
- 'sslverify' => $verify_ssl,
469
- 'body' => $api_params,
470
- ] );
471
 
472
  if ( ! is_wp_error( $request ) ) {
473
  $version_info = json_decode( wp_remote_retrieve_body( $request ) );
@@ -505,11 +557,17 @@ class EDD_SL_Plugin_Updater {
505
 
506
  $cache = get_option( $cache_key );
507
 
508
- if ( empty( $cache['timeout'] ) || current_time( 'timestamp' ) > $cache['timeout'] ) {
509
  return false; // Cache is expired
510
  }
511
 
512
- return json_decode( $cache['value'] );
 
 
 
 
 
 
513
 
514
  }
515
 
@@ -520,7 +578,7 @@ class EDD_SL_Plugin_Updater {
520
  }
521
 
522
  $data = [
523
- 'timeout' => strtotime( '+3 hours', current_time( 'timestamp' ) ),
524
  'value' => json_encode( $value ),
525
  ];
526
 
38
  * Allows plugins to use their own update API.
39
  *
40
  * @author Easy Digital Downloads
41
+ * @version 1.6.17
42
  */
43
  class EDD_SL_Plugin_Updater {
44
 
50
  private $wp_override = false;
51
  private $cache_key = '';
52
 
53
+ private $health_check_timeout = 5;
54
+
55
  /**
56
  * Class constructor.
57
  *
73
  $this->version = $_api_data['version'];
74
  $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
75
  $this->beta = ! empty( $this->api_data['beta'] ) ? true : false;
76
+ $this->cache_key = 'edd_sl_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
77
 
78
  $edd_plugin_data[ $this->slug ] = $this->api_data;
79
 
80
+ /**
81
+ * Fires after the $edd_plugin_data is setup.
82
+ *
83
+ * @since x.x.x
84
+ *
85
+ * @param array $edd_plugin_data Array of EDD SL plugin data.
86
+ */
87
+ do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
88
+
89
  // Set up hooks.
90
  $this->init();
91
 
141
  $version_info = $this->get_cached_version_info();
142
 
143
  if ( false === $version_info ) {
144
+ $version_info = $this->api_request( 'plugin_latest_version', [ 'slug' => $this->slug, 'beta' => $this->beta ] );
 
 
 
145
 
146
  $this->set_version_info_cache( $version_info );
147
 
155
 
156
  }
157
 
158
+ $_transient_data->last_checked = time();
159
  $_transient_data->checked[ $this->name ] = $this->version;
160
 
161
  }
199
  $version_info = $this->get_cached_version_info();
200
 
201
  if ( false === $version_info ) {
202
+ $version_info = $this->api_request( 'plugin_latest_version', [ 'slug' => $this->slug, 'beta' => $this->beta ] );
203
+
204
+ // Since we disabled our filter for the transient, we aren't running our object conversion on banners, sections, or icons. Do this now:
205
+ if ( isset( $version_info->banners ) && ! is_array( $version_info->banners ) ) {
206
+ $version_info->banners = $this->convert_object_to_array( $version_info->banners );
207
+ }
208
+
209
+ if ( isset( $version_info->sections ) && ! is_array( $version_info->sections ) ) {
210
+ $version_info->sections = $this->convert_object_to_array( $version_info->sections );
211
+ }
212
+
213
+ if ( isset( $version_info->icons ) && ! is_array( $version_info->icons ) ) {
214
+ $version_info->icons = $this->convert_object_to_array( $version_info->icons );
215
+ }
216
 
217
  $this->set_version_info_cache( $version_info );
218
  }
227
 
228
  }
229
 
230
+ $update_cache->last_checked = time();
231
  $update_cache->checked[ $this->name ] = $this->version;
232
 
233
  set_site_transient( 'update_plugins', $update_cache );
309
  'fields' => [
310
  'banners' => [],
311
  'reviews' => false,
312
+ 'icons' => [],
313
  ],
314
  ];
315
 
336
 
337
  // Convert sections into an associative array, since we're getting an object, but Core expects an array.
338
  if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
339
+ $_data->sections = $this->convert_object_to_array( $_data->sections );
 
 
 
 
 
340
  }
341
 
342
  // Convert banners into an associative array, since we're getting an object, but Core expects an array.
343
  if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
344
+ $_data->banners = $this->convert_object_to_array( $_data->banners );
345
+ }
 
 
346
 
347
+ // Convert icons into an associative array, since we're getting an object, but Core expects an array.
348
+ if ( isset( $_data->icons ) && ! is_array( $_data->icons ) ) {
349
+ $_data->icons = $this->convert_object_to_array( $_data->icons );
350
  }
351
 
352
  return $_data;
353
  }
354
 
355
+ /**
356
+ * Convert some objects to arrays when injecting data into the update API
357
+ *
358
+ * Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
359
+ * decoding, they are objects. This method allows us to pass in the object and return an associative array.
360
+ *
361
+ * @since 3.6.5
362
+ *
363
+ * @param stdClass $data
364
+ *
365
+ * @return array
366
+ */
367
+ private function convert_object_to_array( $data ) {
368
+ $new_data = [];
369
+ foreach ( $data as $key => $value ) {
370
+ $new_data[ $key ] = $value;
371
+ }
372
+
373
+ return $new_data;
374
+ }
375
+
376
  /**
377
  * Disable SSL verification in order to prevent download update failures
378
  *
387
  if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
388
  $args['sslverify'] = $verify_ssl;
389
  }
 
390
  return $args;
391
 
392
  }
405
  */
406
  private function api_request( $_action, $_data ) {
407
 
408
+ global $wp_version, $edd_plugin_url_available;
409
+
410
+ // Do a quick status check on this domain if we haven't already checked it.
411
+ $store_hash = md5( $this->api_url );
412
+ if ( ! is_array( $edd_plugin_url_available ) || ! isset( $edd_plugin_url_available[ $store_hash ] ) ) {
413
+ $test_url_parts = parse_url( $this->api_url );
414
+
415
+ $scheme = ! empty( $test_url_parts['scheme'] ) ? $test_url_parts['scheme'] : 'http';
416
+ $host = ! empty( $test_url_parts['host'] ) ? $test_url_parts['host'] : '';
417
+ $port = ! empty( $test_url_parts['port'] ) ? ':' . $test_url_parts['port'] : '';
418
+
419
+ if ( empty( $host ) ) {
420
+ $edd_plugin_url_available[ $store_hash ] = false;
421
+ } else {
422
+ $test_url = $scheme . '://' . $host . $port;
423
+ $response = wp_remote_get( $test_url, [ 'timeout' => $this->health_check_timeout, 'sslverify' => true ] );
424
+ $edd_plugin_url_available[ $store_hash ] = is_wp_error( $response ) ? false : true;
425
+ }
426
+ }
427
+
428
+ if ( false === $edd_plugin_url_available[ $store_hash ] ) {
429
+ return;
430
+ }
431
 
432
  $data = array_merge( $this->api_data, $_data );
433
 
452
  ];
453
 
454
  $verify_ssl = $this->verify_ssl();
455
+ $request = wp_remote_post( $this->api_url, [ 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ] );
 
 
 
 
456
 
457
  if ( ! is_wp_error( $request ) ) {
458
  $request = json_decode( wp_remote_retrieve_body( $request ) );
468
  $request->banners = maybe_unserialize( $request->banners );
469
  }
470
 
471
+ if ( $request && isset( $request->icons ) ) {
472
+ $request->icons = maybe_unserialize( $request->icons );
473
+ }
474
+
475
  if ( ! empty( $request->sections ) ) {
476
  foreach ( $request->sections as $key => $section ) {
477
  $request->$key = (array) $section;
519
  ];
520
 
521
  $verify_ssl = $this->verify_ssl();
522
+ $request = wp_remote_post( $this->api_url, [ 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ] );
 
 
 
 
523
 
524
  if ( ! is_wp_error( $request ) ) {
525
  $version_info = json_decode( wp_remote_retrieve_body( $request ) );
557
 
558
  $cache = get_option( $cache_key );
559
 
560
+ if ( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
561
  return false; // Cache is expired
562
  }
563
 
564
+ // We need to turn the icons into an array, thanks to WP Core forcing these into an object at some point.
565
+ $cache['value'] = json_decode( $cache['value'] );
566
+ if ( ! empty( $cache['value']->icons ) ) {
567
+ $cache['value']->icons = (array) $cache['value']->icons;
568
+ }
569
+
570
+ return $cache['value'];
571
 
572
  }
573
 
578
  }
579
 
580
  $data = [
581
+ 'timeout' => strtotime( '+3 hours', time() ),
582
  'value' => json_encode( $value ),
583
  ];
584
 
src/model/Model_Install.php CHANGED
@@ -293,13 +293,14 @@ class Model_Install extends Helper_Abstract_Model {
293
  $this->data->template_location,
294
  $this->data->template_font_location,
295
  $this->data->template_tmp_location,
296
- $this->data->mpdf_tmp_location,
297
  ];
298
 
299
  if ( is_multisite() ) {
300
  $folders[] = $this->data->multisite_template_location;
301
  }
302
 
 
 
303
  /* allow other plugins to add their own folders which should be checked */
304
  $folders = apply_filters( 'gfpdf_installer_create_folders', $folders );
305
 
@@ -343,6 +344,37 @@ class Model_Install extends Helper_Abstract_Model {
343
  }
344
  }
345
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  /**
347
  * Register our PDF custom rewrite rules
348
  *
293
  $this->data->template_location,
294
  $this->data->template_font_location,
295
  $this->data->template_tmp_location,
 
296
  ];
297
 
298
  if ( is_multisite() ) {
299
  $folders[] = $this->data->multisite_template_location;
300
  }
301
 
302
+ $folders = $this->pre_test_mpdf_tmp_location($folders);
303
+
304
  /* allow other plugins to add their own folders which should be checked */
305
  $folders = apply_filters( 'gfpdf_installer_create_folders', $folders );
306
 
344
  }
345
  }
346
 
347
+ /**
348
+ * Test that the mPDF tmp directory is writable, otherwise fallback to standard tmp folder.
349
+ *
350
+ * @Internal Some hosts prevent writing PHP files to the PHP tmp directory, and this just adds a quick fallback
351
+ *
352
+ * @param array $folders
353
+ *
354
+ * @return array
355
+ *
356
+ * @since 5.1
357
+ */
358
+ public function pre_test_mpdf_tmp_location($folders) {
359
+ wp_mkdir_p( $this->data->mpdf_tmp_location );
360
+ $mpdf_tmp_test_file = $this->data->mpdf_tmp_location . '/tmp_directory_test.php';
361
+
362
+ if (
363
+ ! is_dir( $this->data->mpdf_tmp_location ) ||
364
+ file_put_contents( $mpdf_tmp_test_file, 'pass-if-read' ) === false ||
365
+ file_get_contents( $mpdf_tmp_test_file ) !== 'pass-if-read'
366
+ ) {
367
+ $this->data->mpdf_tmp_location = $this->data->template_tmp_location . 'mpdf';
368
+ $folders[] = $this->data->mpdf_tmp_location;
369
+ }
370
+
371
+ if ( is_file( $mpdf_tmp_test_file ) ) {
372
+ unlink( $mpdf_tmp_test_file );
373
+ }
374
+
375
+ return $folders;
376
+ }
377
+
378
  /**
379
  * Register our PDF custom rewrite rules
380
  *
src/model/Model_PDF.php CHANGED
@@ -15,8 +15,11 @@ use GFPDF\Helper\Helper_Abstract_Options;
15
  use GFPDF\Helper\Helper_Data;
16
  use GFPDF\Helper\Helper_Misc;
17
  use GFPDF\Helper\Helper_Notices;
 
18
  use GFPDF\Helper\Helper_Templates;
19
 
 
 
20
  use Psr\Log\LoggerInterface;
21
 
22
  use GFFormsModel;
@@ -317,6 +320,41 @@ class Model_PDF extends Helper_Abstract_Model {
317
  return $action;
318
  }
319
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  /**
321
  * Check if the current PDF trying to be viewed is active
322
  *
@@ -381,8 +419,15 @@ class Model_PDF extends Helper_Abstract_Model {
381
  }
382
 
383
  if ( $type === 'all' || $type === 'logged_out' ) {
384
- $user_ip = trim( GFFormsModel::get_ip() );
385
- if ( $entry['ip'] == $user_ip && $entry['ip'] !== '127.0.0.1' && strlen( $user_ip ) !== 0 ) { /* check if the user IP matches the entry IP */
 
 
 
 
 
 
 
386
  $owner = true;
387
  }
388
  }
@@ -1116,7 +1161,7 @@ class Model_PDF extends Helper_Abstract_Model {
1116
  );
1117
 
1118
  foreach ( $directory_list as $file ) {
1119
- if ( in_array( $file->getFilename(), [ '.htaccess', 'index.html' ] ) ) {
1120
  continue;
1121
  }
1122
 
@@ -1356,6 +1401,7 @@ class Model_PDF extends Helper_Abstract_Model {
1356
  'signature_details_id',
1357
  'products',
1358
  'products_totals',
 
1359
  'poll',
1360
  'survey',
1361
  'quiz',
@@ -1468,33 +1514,36 @@ class Model_PDF extends Helper_Abstract_Model {
1468
 
1469
  $results = $this->get_addon_global_data( $form, [], $fields );
1470
 
1471
- /* Loop through the global survey data and convert information correctly */
1472
- foreach ( $fields as $field ) {
1473
 
1474
- /* Check if we have a multifield likert and replace the row key */
1475
- if ( isset( $field['gsurveyLikertEnableMultipleRows'] ) && $field['gsurveyLikertEnableMultipleRows'] == 1 ) {
1476
 
1477
- foreach ( $field['gsurveyLikertRows'] as $row ) {
 
1478
 
1479
- $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], $row['value'], $row['text'] );
1480
 
1481
- if ( isset( $field->choices ) && is_array( $field->choices ) ) {
1482
- foreach ( $field->choices as $choice ) {
1483
- $results['field_data'][ $field->id ][ $row['text'] ] = $this->replace_key( $results['field_data'][ $field->id ][ $row['text'] ], $choice['value'], $choice['text'] );
 
 
 
1484
  }
1485
  }
1486
  }
1487
- }
1488
 
1489
- /* Replace the standard row data */
1490
- if ( isset( $field->choices ) && is_array( $field->choices ) ) {
1491
- foreach ( $field->choices as $choice ) {
1492
- $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], $choice['value'], $choice['text'] );
 
1493
  }
1494
  }
1495
- }
1496
 
1497
- $data['survey']['global'] = $results;
 
1498
  }
1499
 
1500
  return $data;
@@ -1558,19 +1607,22 @@ class Model_PDF extends Helper_Abstract_Model {
1558
  $fields = GFCommon::get_fields_by_type( $form, [ 'poll' ] );
1559
  $results = $this->get_addon_global_data( $form, [], $fields );
1560
 
1561
- /* Loop through our fields and update the results as needed */
1562
- foreach ( $fields as $field ) {
1563
 
1564
- /* Add the field name to a new 'misc' array key */
1565
- $results['field_data'][ $field->id ]['misc']['label'] = $field->label;
1566
 
1567
- /* Loop through the field choices */
1568
- foreach ( $field->choices as $choice ) {
1569
- $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], $choice['value'], $choice['text'] );
 
 
 
 
1570
  }
1571
- }
1572
 
1573
- $data['poll']['global'] = $results;
 
1574
  }
1575
 
1576
  return $data;
@@ -1603,23 +1655,25 @@ class Model_PDF extends Helper_Abstract_Model {
1603
 
1604
  $results = $this->get_addon_global_data( $form, $options, $fields );
1605
 
1606
- /* Loop through our fields and update our global results */
1607
- foreach ( $fields as $field ) {
 
1608
 
1609
- /* Replace ['totals'] key with ['misc'] key */
1610
- $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], 'totals', 'misc' );
1611
 
1612
- /* Add the field name to the ['misc'] key */
1613
- $results['field_data'][ $field->id ]['misc']['label'] = $field->label;
1614
 
1615
- /* Loop through the field choices */
1616
- if ( is_array( $field->choices ) ) {
1617
- foreach ( $field->choices as $choice ) {
1618
- $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], $choice['value'], $choice['text'] );
1619
 
1620
- /* Check if this is the correct field */
1621
- if ( isset( $choice['gquizIsCorrect'] ) && $choice['gquizIsCorrect'] == 1 ) {
1622
- $results['field_data'][ $field->id ]['misc']['correct_option_name'][] = esc_html( $choice['text'] );
 
1623
  }
1624
  }
1625
  }
@@ -1640,6 +1694,18 @@ class Model_PDF extends Helper_Abstract_Model {
1640
  * @since 4.0
1641
  */
1642
  private function get_addon_global_data( $form, $options, $fields ) {
 
 
 
 
 
 
 
 
 
 
 
 
1643
  /* If the results class isn't loaded, load it */
1644
  if ( ! class_exists( 'GFResults' ) ) {
1645
  require_once( GFCommon::get_base_path() . '/includes/addon/class-gf-results.php' );
15
  use GFPDF\Helper\Helper_Data;
16
  use GFPDF\Helper\Helper_Misc;
17
  use GFPDF\Helper\Helper_Notices;
18
+ use GFPDF\Helper\Helper_Sha256_Url_Signer;
19
  use GFPDF\Helper\Helper_Templates;
20
 
21
+ use Spatie\UrlSigner\Exceptions\InvalidSignatureKey;
22
+
23
  use Psr\Log\LoggerInterface;
24
 
25
  use GFFormsModel;
320
  return $action;
321
  }
322
 
323
+ /**
324
+ * Check if a signed URL exists and validate. If it passes, disable the remaining middleware capabilities
325
+ *
326
+ * @param boolean|object $action
327
+ * @param array $entry The Gravity Forms Entry
328
+ * @param array $settings The Gravity Form PDF Settings
329
+ *
330
+ * @return boolean|object
331
+ *
332
+ * @since 5.1
333
+ */
334
+ public function middle_signed_url_access( $action, $entry, $settings ) {
335
+
336
+ if ( isset( $_GET['expires'] ) && isset( $_GET['signature'] ) && isset( $_SERVER['REQUEST_URI'] ) ) {
337
+ $secret_key = $this->options->get_option( 'signed_secret_token', '' );
338
+
339
+ try {
340
+ $url_signer = new Helper_Sha256_Url_Signer( $secret_key );
341
+
342
+ $home_url = untrailingslashit( strtok( home_url(), '?' ) );
343
+ if ( $url_signer->validate($home_url . $_SERVER['REQUEST_URI'] ) ) {
344
+ remove_filter( 'gfpdf_pdf_middleware', [ $this, 'middle_owner_restriction' ], 40 );
345
+ remove_filter( 'gfpdf_pdf_middleware', [ $this, 'middle_logged_out_timeout' ], 50 );
346
+ remove_filter( 'gfpdf_pdf_middleware', [ $this, 'middle_auth_logged_out_user' ], 60 );
347
+ remove_filter( 'gfpdf_pdf_middleware', [ $this, 'middle_user_capability' ], 70 );
348
+ }
349
+
350
+ } catch ( InvalidSignatureKey $e ) {
351
+
352
+ }
353
+ }
354
+
355
+ return $action;
356
+ }
357
+
358
  /**
359
  * Check if the current PDF trying to be viewed is active
360
  *
419
  }
420
 
421
  if ( $type === 'all' || $type === 'logged_out' ) {
422
+ $user_ip = trim( GFFormsModel::get_ip() );
423
+ $server_ip = isset( $_SERVER['SERVER_ADDR'] ) ? $_SERVER['SERVER_ADDR'] : '127.0.0.1';
424
+
425
+ /* check if the user IP matches the entry IP */
426
+ if (
427
+ $entry['ip'] === $user_ip &&
428
+ $entry['ip'] !== $server_ip &&
429
+ strlen( $user_ip ) !== 0
430
+ ) {
431
  $owner = true;
432
  }
433
  }
1161
  );
1162
 
1163
  foreach ( $directory_list as $file ) {
1164
+ if ( in_array( $file->getFilename(), [ '.htaccess', 'index.html' ] ) || strpos( realpath( $file->getPathname() ), realpath( $this->data->mpdf_tmp_location ) ) !== false ) {
1165
  continue;
1166
  }
1167
 
1401
  'signature_details_id',
1402
  'products',
1403
  'products_totals',
1404
+ 'repeater',
1405
  'poll',
1406
  'survey',
1407
  'quiz',
1514
 
1515
  $results = $this->get_addon_global_data( $form, [], $fields );
1516
 
1517
+ if ( count( $results ) > 0 ) {
 
1518
 
1519
+ /* Loop through the global survey data and convert information correctly */
1520
+ foreach ( $fields as $field ) {
1521
 
1522
+ /* Check if we have a multifield likert and replace the row key */
1523
+ if ( isset( $field['gsurveyLikertEnableMultipleRows'] ) && $field['gsurveyLikertEnableMultipleRows'] == 1 ) {
1524
 
1525
+ foreach ( $field['gsurveyLikertRows'] as $row ) {
1526
 
1527
+ $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], $row['value'], $row['text'] );
1528
+
1529
+ if ( isset( $field->choices ) && is_array( $field->choices ) ) {
1530
+ foreach ( $field->choices as $choice ) {
1531
+ $results['field_data'][ $field->id ][ $row['text'] ] = $this->replace_key( $results['field_data'][ $field->id ][ $row['text'] ], $choice['value'], $choice['text'] );
1532
+ }
1533
  }
1534
  }
1535
  }
 
1536
 
1537
+ /* Replace the standard row data */
1538
+ if ( isset( $field->choices ) && is_array( $field->choices ) ) {
1539
+ foreach ( $field->choices as $choice ) {
1540
+ $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], $choice['value'], $choice['text'] );
1541
+ }
1542
  }
1543
  }
 
1544
 
1545
+ $data['survey']['global'] = $results;
1546
+ }
1547
  }
1548
 
1549
  return $data;
1607
  $fields = GFCommon::get_fields_by_type( $form, [ 'poll' ] );
1608
  $results = $this->get_addon_global_data( $form, [], $fields );
1609
 
1610
+ if ( count( $results ) > 0 ) {
 
1611
 
1612
+ /* Loop through our fields and update the results as needed */
1613
+ foreach ( $fields as $field ) {
1614
 
1615
+ /* Add the field name to a new 'misc' array key */
1616
+ $results['field_data'][ $field->id ]['misc']['label'] = $field->label;
1617
+
1618
+ /* Loop through the field choices */
1619
+ foreach ( $field->choices as $choice ) {
1620
+ $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], $choice['value'], $choice['text'] );
1621
+ }
1622
  }
 
1623
 
1624
+ $data['poll']['global'] = $results;
1625
+ }
1626
  }
1627
 
1628
  return $data;
1655
 
1656
  $results = $this->get_addon_global_data( $form, $options, $fields );
1657
 
1658
+ if ( count( $results ) > 0 ) {
1659
+ /* Loop through our fields and update our global results */
1660
+ foreach ( $fields as $field ) {
1661
 
1662
+ /* Replace ['totals'] key with ['misc'] key */
1663
+ $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], 'totals', 'misc' );
1664
 
1665
+ /* Add the field name to the ['misc'] key */
1666
+ $results['field_data'][ $field->id ]['misc']['label'] = $field->label;
1667
 
1668
+ /* Loop through the field choices */
1669
+ if ( is_array( $field->choices ) ) {
1670
+ foreach ( $field->choices as $choice ) {
1671
+ $results['field_data'][ $field->id ] = $this->replace_key( $results['field_data'][ $field->id ], $choice['value'], $choice['text'] );
1672
 
1673
+ /* Check if this is the correct field */
1674
+ if ( isset( $choice['gquizIsCorrect'] ) && $choice['gquizIsCorrect'] == 1 ) {
1675
+ $results['field_data'][ $field->id ]['misc']['correct_option_name'][] = esc_html( $choice['text'] );
1676
+ }
1677
  }
1678
  }
1679
  }
1694
  * @since 4.0
1695
  */
1696
  private function get_addon_global_data( $form, $options, $fields ) {
1697
+
1698
+ /**
1699
+ * Disable aggrigate addon data (speeds up PDF generation time)
1700
+ *
1701
+ * See https://gravitypdf.com/documentation/v5/gfpdf_disable_global_addon_data/
1702
+ *
1703
+ * @since 5.1
1704
+ */
1705
+ if ( apply_filters( 'gfpdf_disable_global_addon_data', false, $form, $options, $fields ) ) {
1706
+ return [];
1707
+ }
1708
+
1709
  /* If the results class isn't loaded, load it */
1710
  if ( ! class_exists( 'GFResults' ) ) {
1711
  require_once( GFCommon::get_base_path() . '/includes/addon/class-gf-results.php' );
src/model/Model_Settings.php CHANGED
@@ -861,15 +861,28 @@ class Model_Settings extends Helper_Abstract_Model {
861
  /* Get the required details */
862
  $addon_slug = ( isset( $_POST['addon_name'] ) ) ? $_POST['addon_name'] : '';
863
  $license = ( isset( $_POST['license'] ) ) ? $_POST['license'] : '';
 
864
 
865
  /* Check add-on currently installed */
866
- if ( isset( $this->data->addon[ $addon_slug ] ) && $this->deactivate_license_key( $this->data->addon[ $addon_slug ], $license ) ) {
867
- $this->log->addNotice( 'AJAX – Successfully Deactivated License' );
868
- echo json_encode( [
869
- 'success' => esc_html__( 'License deactivated.', 'gravity-forms-pdf-extended' ) ]
870
- );
871
-
872
- wp_die();
 
 
 
 
 
 
 
 
 
 
 
 
873
  }
874
 
875
  $this->log->addError( 'AJAX Endpoint Error' );
@@ -911,7 +924,6 @@ class Model_Settings extends Helper_Abstract_Model {
911
 
912
  /* Get API response and check license is now deactivated */
913
  $license_data = json_decode( wp_remote_retrieve_body( $response ) );
914
-
915
  if ( ! isset( $license_data->license ) || $license_data->license !== 'deactivated' ) {
916
  return false;
917
  }
861
  /* Get the required details */
862
  $addon_slug = ( isset( $_POST['addon_name'] ) ) ? $_POST['addon_name'] : '';
863
  $license = ( isset( $_POST['license'] ) ) ? $_POST['license'] : '';
864
+ $addon = ( isset( $this->data->addon[ $addon_slug ] ) ) ? $this->data->addon[ $addon_slug ] : false;
865
 
866
  /* Check add-on currently installed */
867
+ if ( ! empty( $addon ) ) {
868
+ if ( $this->deactivate_license_key( $addon, $license ) ) {
869
+ $this->log->addNotice( 'AJAX – Successfully Deactivated License' );
870
+ echo json_encode( [
871
+ 'success' => esc_html__( 'License deactivated.', 'gravity-forms-pdf-extended' ),
872
+ ]
873
+ );
874
+
875
+ wp_die();
876
+ } elseif( $addon->schedule_license_check() ) {
877
+ $license_info = $addon->get_license_info();
878
+
879
+ echo json_encode( [
880
+ 'error' => $license_info['message'],
881
+ ]
882
+ );
883
+
884
+ wp_die();
885
+ }
886
  }
887
 
888
  $this->log->addError( 'AJAX Endpoint Error' );
924
 
925
  /* Get API response and check license is now deactivated */
926
  $license_data = json_decode( wp_remote_retrieve_body( $response ) );
 
927
  if ( ! isset( $license_data->license ) || $license_data->license !== 'deactivated' ) {
928
  return false;
929
  }
src/model/Model_Shortcodes.php CHANGED
@@ -7,11 +7,13 @@ use GFPDF\Helper\Helper_Abstract_Form;
7
  use GFPDF\Helper\Helper_Abstract_Options;
8
  use GFPDF\Helper\Helper_Misc;
9
 
 
10
  use Psr\Log\LoggerInterface;
11
 
12
  use GPDFAPI;
13
  use GFCommon;
14
  use GravityView_View;
 
15
 
16
  /**
17
  * PDF Shortcode Model
@@ -125,8 +127,7 @@ class Model_Shortcodes extends Helper_Abstract_Model {
125
  public function gravitypdf( $attributes ) {
126
  $controller = $this->getController();
127
 
128
- $global_settings = $this->options->get_settings();
129
- $shortcode_error_messages_enabled = ( isset( $global_settings['shortcode_debug_messages'] ) && $global_settings['shortcode_debug_messages'] === 'Yes' ) ? true : false;
130
  $has_view_permissions = ( $shortcode_error_messages_enabled && $this->gform->has_capability( 'gravityforms_view_entries' ) );
131
 
132
  /* merge in any missing defaults */
@@ -134,22 +135,18 @@ class Model_Shortcodes extends Helper_Abstract_Model {
134
  'id' => '',
135
  'text' => 'Download PDF',
136
  'type' => 'download',
 
 
137
  'class' => 'gravitypdf-download-link',
138
  'classes' => '',
139
  'entry' => '',
140
  'print' => '',
 
141
  ], $attributes, 'gravitypdf' );
142
 
143
  /* See https://gravitypdf.com/documentation/v5/gfpdf_gravityforms_shortcode_attributes/ for more information about this filter */
144
  $attributes = apply_filters( 'gfpdf_gravityforms_shortcode_attributes', $attributes );
145
 
146
- /* Add Shortcake preview support */
147
- if ( defined( 'SHORTCODE_UI_DOING_PREVIEW' ) && SHORTCODE_UI_DOING_PREVIEW === true ) {
148
- $attributes['url'] = '#';
149
-
150
- return $controller->view->display_gravitypdf_shortcode( $attributes );
151
- }
152
-
153
  /* Check if we have an entry ID, otherwise check the GET and POST data */
154
  if ( empty( $attributes['entry'] ) ) {
155
  if ( isset( $_GET['lid'] ) || isset( $_GET['entry'] ) ) {
@@ -202,13 +199,41 @@ class Model_Shortcodes extends Helper_Abstract_Model {
202
  $pdf = new Model_PDF( $this->gform, $this->log, $this->options, GPDFAPI::get_data_class(), GPDFAPI::get_misc_class(), GPDFAPI::get_notice_class(), GPDFAPI::get_templates_class() );
203
  $download = ( $attributes['type'] == 'download' ) ? true : false;
204
  $print = ( ! empty( $attributes['print'] ) ) ? true : false;
205
- $attributes['url'] = $pdf->get_pdf_url( $attributes['id'], $attributes['entry'], $download, $print );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
 
207
  /* generate the markup and return */
208
  $this->log->addNotice( 'Generating Shortcode Markup', [
209
  'attr' => $attributes,
210
  ] );
211
 
 
 
 
 
212
  return $controller->view->display_gravitypdf_shortcode( $attributes );
213
  }
214
 
@@ -343,7 +368,7 @@ class Model_Shortcodes extends Helper_Abstract_Model {
343
 
344
  /**
345
  * Check if user is currently submitting a new confirmation redirect URL in the admin area,
346
- * if so replace any shortcodes with a direct link to the PDF (as Gravity Forms correctly validates the URL)
347
  *
348
  * @param array $form Gravity Form Array
349
  *
@@ -366,30 +391,55 @@ class Model_Shortcodes extends Helper_Abstract_Model {
366
  /* check if our shortcode exists and convert it to a URL */
367
  $gravitypdf = $this->get_shortcode_information( 'gravitypdf', $url );
368
 
369
- if ( sizeof( $gravitypdf ) > 0 ) {
 
 
 
370
 
371
- foreach ( $gravitypdf as $code ) {
 
 
 
 
 
 
 
 
372
 
373
- /* get the PDF Settings ID */
374
- $pid = ( isset( $code['attr']['id'] ) ) ? $code['attr']['id'] : '';
 
 
 
 
 
 
 
 
 
 
375
 
376
- if ( ! empty( $pid ) ) {
 
377
 
378
- /* generate the PDF URL */
379
- $pdf = new Model_PDF( $this->gform, $this->log, $this->options, GPDFAPI::get_data_class(), GPDFAPI::get_misc_class(), GPDFAPI::get_notice_class(), GPDFAPI::get_templates_class() );
380
- $download = ( ! isset( $code['attr']['type'] ) || $code['attr']['type'] == 'download' ) ? true : false;
381
- $pdf_url = $pdf->get_pdf_url( $pid, '{entry_id}', $download, false, false );
382
 
383
- /* override the confirmation URL submitted */
384
- $_POST['form_confirmation_url'] = str_replace( $code['shortcode'], $pdf_url, $url );
 
 
385
  }
 
 
386
  }
 
 
387
  }
388
  }
389
 
390
- /* it's a filter so return the $form array */
391
-
392
- return $form;
393
  }
394
 
395
  /**
7
  use GFPDF\Helper\Helper_Abstract_Options;
8
  use GFPDF\Helper\Helper_Misc;
9
 
10
+ use GFPDF\Helper\Helper_Sha256_Url_Signer;
11
  use Psr\Log\LoggerInterface;
12
 
13
  use GPDFAPI;
14
  use GFCommon;
15
  use GravityView_View;
16
+ use Spatie\UrlSigner\MD5UrlSigner;
17
 
18
  /**
19
  * PDF Shortcode Model
127
  public function gravitypdf( $attributes ) {
128
  $controller = $this->getController();
129
 
130
+ $shortcode_error_messages_enabled = ( $this->options->get_option( 'debug_mode', 'No' ) === 'Yes' ) ? true : false;
 
131
  $has_view_permissions = ( $shortcode_error_messages_enabled && $this->gform->has_capability( 'gravityforms_view_entries' ) );
132
 
133
  /* merge in any missing defaults */
135
  'id' => '',
136
  'text' => 'Download PDF',
137
  'type' => 'download',
138
+ 'signed' => '',
139
+ 'expires' => '',
140
  'class' => 'gravitypdf-download-link',
141
  'classes' => '',
142
  'entry' => '',
143
  'print' => '',
144
+ 'raw' => '',
145
  ], $attributes, 'gravitypdf' );
146
 
147
  /* See https://gravitypdf.com/documentation/v5/gfpdf_gravityforms_shortcode_attributes/ for more information about this filter */
148
  $attributes = apply_filters( 'gfpdf_gravityforms_shortcode_attributes', $attributes );
149
 
 
 
 
 
 
 
 
150
  /* Check if we have an entry ID, otherwise check the GET and POST data */
151
  if ( empty( $attributes['entry'] ) ) {
152
  if ( isset( $_GET['lid'] ) || isset( $_GET['entry'] ) ) {
199
  $pdf = new Model_PDF( $this->gform, $this->log, $this->options, GPDFAPI::get_data_class(), GPDFAPI::get_misc_class(), GPDFAPI::get_notice_class(), GPDFAPI::get_templates_class() );
200
  $download = ( $attributes['type'] == 'download' ) ? true : false;
201
  $print = ( ! empty( $attributes['print'] ) ) ? true : false;
202
+ $raw = ( ! empty( $attributes['raw'] ) ) ? true : false;
203
+ $attributes['url'] = $pdf->get_pdf_url( $attributes['id'], $attributes['entry'], $download, $print, ! $raw );
204
+
205
+ /* Sign the URL to allow direct access to the PDF until it expires */
206
+ if ( ! empty( $attributes['signed'] ) ) {
207
+ $secret_key = $this->options->get_option( 'signed_secret_token', '' );
208
+
209
+ /* If no secret key exists, generate it */
210
+ if ( empty( $secret_key ) ) {
211
+ $secret_key = wp_generate_password( 64 );
212
+ $this->options->update_option( 'signed_secret_token', $secret_key );
213
+ }
214
+
215
+ $url_signer = new Helper_Sha256_Url_Signer( $secret_key );
216
+
217
+ $expires = (int) $this->options->get_option( 'logged_out_timeout', '20' ) . ' minutes';
218
+ if ( ! empty( $attributes['expires'] ) ) {
219
+ $expires = $attributes['expires'];
220
+ }
221
+
222
+ $date = new \DateTime();
223
+ $timeout = $date->modify( $expires );
224
+
225
+ $attributes['url'] = $url_signer->sign( $attributes['url'], $timeout );
226
+ }
227
 
228
  /* generate the markup and return */
229
  $this->log->addNotice( 'Generating Shortcode Markup', [
230
  'attr' => $attributes,
231
  ] );
232
 
233
+ if ( $raw ) {
234
+ return $attributes['url'];
235
+ }
236
+
237
  return $controller->view->display_gravitypdf_shortcode( $attributes );
238
  }
239
 
368
 
369
  /**
370
  * Check if user is currently submitting a new confirmation redirect URL in the admin area,
371
+ * if so replace any shortcodes with a version that will be correctly saved and generated
372
  *
373
  * @param array $form Gravity Form Array
374
  *
391
  /* check if our shortcode exists and convert it to a URL */
392
  $gravitypdf = $this->get_shortcode_information( 'gravitypdf', $url );
393
 
394
+ if ( count( $gravitypdf ) > 0 ) {
395
+ foreach ( $gravitypdf as $shortcode ) {
396
+ $new_shortcode = $this->add_shortcode_attr( $shortcode, 'entry', '{entry_id}' );
397
+ $new_shortcode = $this->add_shortcode_attr( $new_shortcode, 'raw', '1' );
398
 
399
+ /* update our confirmation message */
400
+ $_POST['form_confirmation_url'] = str_replace( $shortcode['shortcode'], $new_shortcode['shortcode'], $url );
401
+ }
402
+ }
403
+ }
404
+
405
+ /* it's a filter so return the $form array */
406
+ return $form;
407
+ }
408
 
409
+ /**
410
+ * If a Redirect Confirmation, convert the Gravity PDF shortcode to it's URL form, if one exists
411
+ *
412
+ * @param string|array $confirmation
413
+ * @param array $form
414
+ * @param array $entry
415
+ *
416
+ * @return string|array
417
+ *
418
+ * @since 5.1
419
+ */
420
+ public function gravitypdf_redirect_confirmation_shortcode_processing( $confirmation, $form, $entry ) {
421
 
422
+ if ( isset( $confirmation['redirect'] ) ) {
423
+ $gravitypdf = $this->get_shortcode_information( 'gravitypdf', $form['confirmation']['url'] );
424
 
425
+ if ( count( $gravitypdf ) > 0 ) {
426
+ foreach ( $gravitypdf as $shortcode ) {
427
+ $url = do_shortcode( str_replace( '{entry_id}', $entry['id'], $shortcode['shortcode'] ) );
 
428
 
429
+ /* Add Query string parameters if they exist (but not with signed URLs) */
430
+ $query_string = substr( $confirmation['redirect'], strrpos( $confirmation['redirect'], '?' ) + 1 );
431
+ if ( empty( $shortcode['attr']['signed'] ) && strlen( $query_string ) > 0 ) {
432
+ $url .= ( strpos( $url, '?' ) !== false ) ? '&' . $query_string : '?' . $query_string;
433
  }
434
+
435
+ $form['confirmation']['url'] = str_replace( $shortcode['shortcode'], $url, $form['confirmation']['url'] );
436
  }
437
+
438
+ $confirmation['redirect'] = $form['confirmation']['url'];
439
  }
440
  }
441
 
442
+ return $confirmation;
 
 
443
  }
444
 
445
  /**
src/model/Model_Templates.php CHANGED
@@ -172,6 +172,7 @@ class Model_Templates extends Helper_Abstract_Model {
172
  $results = $this->misc->copyr( $unzipped_dir_name, $template_path );
173
 
174
  /* Get the template headers now all the files are in the right location */
 
175
  $headers = $this->get_template_info( glob( $unzipped_dir_name . '*.php' ) );
176
 
177
  /* Fix template path */
@@ -241,6 +242,8 @@ class Model_Templates extends Helper_Abstract_Model {
241
  wp_die( '400', 400 );
242
  }
243
 
 
 
244
  header( 'Content-Type: application/json' );
245
  echo json_encode( true );
246
 
@@ -392,7 +395,7 @@ class Model_Templates extends Helper_Abstract_Model {
392
  foreach ( $files as $file ) {
393
 
394
  /* Check if we have a valid v4 template header in the file */
395
- $info = get_file_data( $file, $this->templates->get_template_header_details() );
396
 
397
  if ( ! isset( $info['template'] ) || strlen( $info['template'] ) === 0 ) {
398
  /* Check if it's a v3 template */
172
  $results = $this->misc->copyr( $unzipped_dir_name, $template_path );
173
 
174
  /* Get the template headers now all the files are in the right location */
175
+ $this->templates->flush_template_transient_cache();
176
  $headers = $this->get_template_info( glob( $unzipped_dir_name . '*.php' ) );
177
 
178
  /* Fix template path */
242
  wp_die( '400', 400 );
243
  }
244
 
245
+ $this->templates->flush_template_transient_cache();
246
+
247
  header( 'Content-Type: application/json' );
248
  echo json_encode( true );
249
 
395
  foreach ( $files as $file ) {
396
 
397
  /* Check if we have a valid v4 template header in the file */
398
+ $info = $this->templates->get_template_info_by_path( $file );
399
 
400
  if ( ! isset( $info['template'] ) || strlen( $info['template'] ) === 0 ) {
401
  /* Check if it's a v3 template */
src/view/View_PDF.php CHANGED
@@ -450,10 +450,14 @@ class View_PDF extends Helper_Abstract_View {
450
  $container->close();
451
 
452
  /*
453
- * Output product table, if needed
454
- * Use the filter 'gfpdf_current_pdf_configuration' to programically disable this functionality
 
 
 
455
  */
456
- if ( $show_individual_product_fields === false && ! $products->is_empty() ) {
 
457
  echo $products->html();
458
  }
459
  }
450
  $container->close();
451
 
452
  /*
453
+ * Filter to prevent the product table showing
454
+ *
455
+ * See https://gravitypdf.com/documentation/v5/gfpdf_disable_product_table/
456
+ *
457
+ * @since 5.1
458
  */
459
+ $should_disable_product_table = apply_filters( 'gfpdf_disable_product_table', false, $entry, $form, $config, $products );
460
+ if ( ! $should_disable_product_table && $show_individual_product_fields === false && ! $products->is_empty() ) {
461
  echo $products->html();
462
  }
463
  }
src/view/html/Actions/core_font.php CHANGED
@@ -42,6 +42,6 @@ if ( ! defined( 'ABSPATH' ) ) {
42
 
43
  <br>
44
 
45
- <?php esc_html_e( 'Before you can generate a PDF using Gravity Forms the core fonts need to be saved to your server. This only needs to be done once.', 'gravity-forms-pdf-extended' ); ?>
46
 
47
  </div>
42
 
43
  <br>
44
 
45
+ <?php esc_html_e( 'Before you can generate a PDF using Gravity Forms, the core fonts need to be saved to your server. This only needs to be done once.', 'gravity-forms-pdf-extended' ); ?>
46
 
47
  </div>
src/view/html/PDF/core_template_styles.php CHANGED
@@ -196,6 +196,34 @@ $include_product_styles = apply_filters( 'gfpdf_include_product_styles', tru
196
  .pagebreak {
197
  page-break-before: always;
198
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  </style>
200
 
201
  <?php if ( ! empty($first_header) ) : ?>
196
  .pagebreak {
197
  page-break-before: always;
198
  }
199
+
200
+ /* Consent Field */
201
+ .consent-text {
202
+ font-size: 85%;
203
+ }
204
+
205
+ .consent-text a,
206
+ .consent-text li,
207
+ .consent-text td,
208
+ .consent-text th {
209
+ font-size: 100%;
210
+ }
211
+
212
+ .consent-tick {
213
+ font-size: 150%;
214
+ }
215
+
216
+ /* Repeater */
217
+ .gfpdf-repeater,
218
+ .gfpdf-form {
219
+ margin-bottom: 1.5%;
220
+ }
221
+
222
+ .repeater-container {
223
+ margin: 1% 0;
224
+ padding-left: 2%;
225
+ border-left: 1px solid #000;
226
+ }
227
  </style>
228
 
229
  <?php if ( ! empty($first_header) ) : ?>
vendor/composer/autoload_classmap.php CHANGED
@@ -35,6 +35,7 @@ return array(
35
  'FilterASCIIHexDecode' => $vendorDir . '/setasign/fpdi/filters/FilterASCIIHexDecode.php',
36
  'FilterLZW' => $vendorDir . '/setasign/fpdi/filters/FilterLZW.php',
37
  'GFPDF\\Controller\\Controller_Actions' => $baseDir . '/src/controller/Controller_Actions.php',
 
38
  'GFPDF\\Controller\\Controller_Form_Settings' => $baseDir . '/src/controller/Controller_Form_Settings.php',
39
  'GFPDF\\Controller\\Controller_Install' => $baseDir . '/src/controller/Controller_Install.php',
40
  'GFPDF\\Controller\\Controller_Mergetags' => $baseDir . '/src/controller/Controller_Mergetags.php',
@@ -48,6 +49,7 @@ return array(
48
  'GFPDF\\Helper\\Fields\\Field_Address' => $baseDir . '/src/helper/fields/Field_Address.php',
49
  'GFPDF\\Helper\\Fields\\Field_Chainedselect' => $baseDir . '/src/helper/fields/Field_Chainedselect.php',
50
  'GFPDF\\Helper\\Fields\\Field_Checkbox' => $baseDir . '/src/helper/fields/Field_Checkbox.php',
 
51
  'GFPDF\\Helper\\Fields\\Field_Coupon' => $baseDir . '/src/helper/fields/Field_Coupon.php',
52
  'GFPDF\\Helper\\Fields\\Field_CreditCard' => $baseDir . '/src/helper/fields/Field_Creditcard.php',
53
  'GFPDF\\Helper\\Fields\\Field_Date' => $baseDir . '/src/helper/fields/Field_Date.php',
@@ -55,6 +57,7 @@ return array(
55
  'GFPDF\\Helper\\Fields\\Field_Discount' => $baseDir . '/src/helper/fields/Field_Discount.php',
56
  'GFPDF\\Helper\\Fields\\Field_Email' => $baseDir . '/src/helper/fields/Field_Email.php',
57
  'GFPDF\\Helper\\Fields\\Field_Fileupload' => $baseDir . '/src/helper/fields/Field_Fileupload.php',
 
58
  'GFPDF\\Helper\\Fields\\Field_Hidden' => $baseDir . '/src/helper/fields/Field_Hidden.php',
59
  'GFPDF\\Helper\\Fields\\Field_Html' => $baseDir . '/src/helper/fields/Field_Html.php',
60
  'GFPDF\\Helper\\Fields\\Field_Likert' => $baseDir . '/src/helper/fields/Field_Likert.php',
@@ -79,6 +82,7 @@ return array(
79
  'GFPDF\\Helper\\Fields\\Field_Radio' => $baseDir . '/src/helper/fields/Field_Radio.php',
80
  'GFPDF\\Helper\\Fields\\Field_Rank' => $baseDir . '/src/helper/fields/Field_Rank.php',
81
  'GFPDF\\Helper\\Fields\\Field_Rating' => $baseDir . '/src/helper/fields/Field_Rating.php',
 
82
  'GFPDF\\Helper\\Fields\\Field_Section' => $baseDir . '/src/helper/fields/Field_Section.php',
83
  'GFPDF\\Helper\\Fields\\Field_Select' => $baseDir . '/src/helper/fields/Field_Select.php',
84
  'GFPDF\\Helper\\Fields\\Field_Shipping' => $baseDir . '/src/helper/fields/Field_Shipping.php',
@@ -123,6 +127,7 @@ return array(
123
  'GFPDF\\Helper\\Helper_PDF_List_Table' => $baseDir . '/src/helper/Helper_PDF_List_Table.php',
124
  'GFPDF\\Helper\\Helper_Pdf_Queue' => $baseDir . '/src/helper/Helper_Pdf_Queue.php',
125
  'GFPDF\\Helper\\Helper_QueryPath' => $baseDir . '/src/helper/Helper_QueryPath.php',
 
126
  'GFPDF\\Helper\\Helper_Singleton' => $baseDir . '/src/helper/Helper_Singleton.php',
127
  'GFPDF\\Helper\\Helper_Templates' => $baseDir . '/src/helper/Helper_Templates.php',
128
  'GFPDF\\Helper\\Helper_Trait_Logger' => $baseDir . '/src/helper/trait/Helper_Trait_Logger.php',
@@ -150,6 +155,28 @@ return array(
150
  'GFPDF\\View\\View_Settings' => $baseDir . '/src/view/View_Settings.php',
151
  'GFPDF\\View\\View_Shortcodes' => $baseDir . '/src/view/View_Shortcodes.php',
152
  'GFPDF\\View\\View_Welcome_Screen' => $baseDir . '/src/view/View_Welcome_Screen.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  'Masterminds\\HTML5' => $vendorDir . '/masterminds/html5/src/HTML5.php',
154
  'Masterminds\\HTML5\\Elements' => $vendorDir . '/masterminds/html5/src/HTML5/Elements.php',
155
  'Masterminds\\HTML5\\Entities' => $vendorDir . '/masterminds/html5/src/HTML5/Entities.php',
@@ -215,6 +242,7 @@ return array(
215
  'Monolog\\Handler\\HandlerWrapper' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
216
  'Monolog\\Handler\\HipChatHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php',
217
  'Monolog\\Handler\\IFTTTHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
 
218
  'Monolog\\Handler\\LogEntriesHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
219
  'Monolog\\Handler\\LogglyHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
220
  'Monolog\\Handler\\MailHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
@@ -253,11 +281,15 @@ return array(
253
  'Monolog\\Processor\\MemoryUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
254
  'Monolog\\Processor\\MercurialProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
255
  'Monolog\\Processor\\ProcessIdProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
 
256
  'Monolog\\Processor\\PsrLogMessageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
257
  'Monolog\\Processor\\TagProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
258
  'Monolog\\Processor\\UidProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
259
  'Monolog\\Processor\\WebProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
260
  'Monolog\\Registry' => $vendorDir . '/monolog/monolog/src/Monolog/Registry.php',
 
 
 
261
  'Mpdf\\Barcode' => $vendorDir . '/mpdf/mpdf/src/Barcode.php',
262
  'Mpdf\\Barcode\\AbstractBarcode' => $vendorDir . '/mpdf/mpdf/src/Barcode/AbstractBarcode.php',
263
  'Mpdf\\Barcode\\BarcodeException' => $vendorDir . '/mpdf/mpdf/src/Barcode/BarcodeException.php',
@@ -327,10 +359,13 @@ return array(
327
  'Mpdf\\Pdf\\Protection\\UniqidGenerator' => $vendorDir . '/mpdf/mpdf/src/Pdf/Protection/UniqidGenerator.php',
328
  'Mpdf\\QrCode\\QrCode' => $vendorDir . '/mpdf/mpdf/src/QrCode/QrCode.php',
329
  'Mpdf\\QrCode\\QrCodeException' => $vendorDir . '/mpdf/mpdf/src/QrCode/QrCodeException.php',
 
 
330
  'Mpdf\\Shaper\\Indic' => $vendorDir . '/mpdf/mpdf/src/Shaper/Indic.php',
331
  'Mpdf\\Shaper\\Myanmar' => $vendorDir . '/mpdf/mpdf/src/Shaper/Myanmar.php',
332
  'Mpdf\\Shaper\\Sea' => $vendorDir . '/mpdf/mpdf/src/Shaper/Sea.php',
333
  'Mpdf\\SizeConverter' => $vendorDir . '/mpdf/mpdf/src/SizeConverter.php',
 
334
  'Mpdf\\TTFontFile' => $vendorDir . '/mpdf/mpdf/src/TTFontFile.php',
335
  'Mpdf\\TTFontFileAnalysis' => $vendorDir . '/mpdf/mpdf/src/TTFontFileAnalysis.php',
336
  'Mpdf\\TableOfContents' => $vendorDir . '/mpdf/mpdf/src/TableOfContents.php',
@@ -449,6 +484,19 @@ return array(
449
  'Mpdf\\Utils\\NumericString' => $vendorDir . '/mpdf/mpdf/src/Utils/NumericString.php',
450
  'Mpdf\\Utils\\PdfDate' => $vendorDir . '/mpdf/mpdf/src/Utils/PdfDate.php',
451
  'Mpdf\\Utils\\UtfString' => $vendorDir . '/mpdf/mpdf/src/Utils/UtfString.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
452
  'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php',
453
  'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php',
454
  'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php',
@@ -486,6 +534,16 @@ return array(
486
  'QueryPath\\ParseException' => $vendorDir . '/querypath/querypath/src/QueryPath/ParseException.php',
487
  'QueryPath\\Query' => $vendorDir . '/querypath/querypath/src/QueryPath/Query.php',
488
  'QueryPath\\QueryPathIterator' => $vendorDir . '/querypath/querypath/src/QueryPath/QueryPathIterator.php',
 
 
 
 
 
 
 
 
 
 
489
  'Upload\\Autoloader' => $vendorDir . '/codeguy/upload/src/Upload/Autoloader.php',
490
  'Upload\\Exception\\UploadException' => $vendorDir . '/codeguy/upload/src/Upload/Exception/UploadException.php',
491
  'Upload\\File' => $vendorDir . '/codeguy/upload/src/Upload/File.php',
35
  'FilterASCIIHexDecode' => $vendorDir . '/setasign/fpdi/filters/FilterASCIIHexDecode.php',
36
  'FilterLZW' => $vendorDir . '/setasign/fpdi/filters/FilterLZW.php',
37
  'GFPDF\\Controller\\Controller_Actions' => $baseDir . '/src/controller/Controller_Actions.php',
38
+ 'GFPDF\\Controller\\Controller_Debug' => $baseDir . '/src/controller/Controller_Debug.php',
39
  'GFPDF\\Controller\\Controller_Form_Settings' => $baseDir . '/src/controller/Controller_Form_Settings.php',
40
  'GFPDF\\Controller\\Controller_Install' => $baseDir . '/src/controller/Controller_Install.php',
41
  'GFPDF\\Controller\\Controller_Mergetags' => $baseDir . '/src/controller/Controller_Mergetags.php',
49
  'GFPDF\\Helper\\Fields\\Field_Address' => $baseDir . '/src/helper/fields/Field_Address.php',
50
  'GFPDF\\Helper\\Fields\\Field_Chainedselect' => $baseDir . '/src/helper/fields/Field_Chainedselect.php',
51
  'GFPDF\\Helper\\Fields\\Field_Checkbox' => $baseDir . '/src/helper/fields/Field_Checkbox.php',
52
+ 'GFPDF\\Helper\\Fields\\Field_Consent' => $baseDir . '/src/helper/fields/Field_Consent.php',
53
  'GFPDF\\Helper\\Fields\\Field_Coupon' => $baseDir . '/src/helper/fields/Field_Coupon.php',
54
  'GFPDF\\Helper\\Fields\\Field_CreditCard' => $baseDir . '/src/helper/fields/Field_Creditcard.php',
55
  'GFPDF\\Helper\\Fields\\Field_Date' => $baseDir . '/src/helper/fields/Field_Date.php',
57
  'GFPDF\\Helper\\Fields\\Field_Discount' => $baseDir . '/src/helper/fields/Field_Discount.php',
58
  'GFPDF\\Helper\\Fields\\Field_Email' => $baseDir . '/src/helper/fields/Field_Email.php',
59
  'GFPDF\\Helper\\Fields\\Field_Fileupload' => $baseDir . '/src/helper/fields/Field_Fileupload.php',
60
+ 'GFPDF\\Helper\\Fields\\Field_Form' => $baseDir . '/src/helper/fields/Field_Form.php',
61
  'GFPDF\\Helper\\Fields\\Field_Hidden' => $baseDir . '/src/helper/fields/Field_Hidden.php',
62
  'GFPDF\\Helper\\Fields\\Field_Html' => $baseDir . '/src/helper/fields/Field_Html.php',
63
  'GFPDF\\Helper\\Fields\\Field_Likert' => $baseDir . '/src/helper/fields/Field_Likert.php',
82
  'GFPDF\\Helper\\Fields\\Field_Radio' => $baseDir . '/src/helper/fields/Field_Radio.php',
83
  'GFPDF\\Helper\\Fields\\Field_Rank' => $baseDir . '/src/helper/fields/Field_Rank.php',
84
  'GFPDF\\Helper\\Fields\\Field_Rating' => $baseDir . '/src/helper/fields/Field_Rating.php',
85
+ 'GFPDF\\Helper\\Fields\\Field_Repeater' => $baseDir . '/src/helper/fields/Field_Repeater.php',
86
  'GFPDF\\Helper\\Fields\\Field_Section' => $baseDir . '/src/helper/fields/Field_Section.php',
87
  'GFPDF\\Helper\\Fields\\Field_Select' => $baseDir . '/src/helper/fields/Field_Select.php',
88
  'GFPDF\\Helper\\Fields\\Field_Shipping' => $baseDir . '/src/helper/fields/Field_Shipping.php',
127
  'GFPDF\\Helper\\Helper_PDF_List_Table' => $baseDir . '/src/helper/Helper_PDF_List_Table.php',
128
  'GFPDF\\Helper\\Helper_Pdf_Queue' => $baseDir . '/src/helper/Helper_Pdf_Queue.php',
129
  'GFPDF\\Helper\\Helper_QueryPath' => $baseDir . '/src/helper/Helper_QueryPath.php',
130
+ 'GFPDF\\Helper\\Helper_Sha256_Url_Signer' => $baseDir . '/src/helper/Helper_Sha256_Url_Signer.php',
131
  'GFPDF\\Helper\\Helper_Singleton' => $baseDir . '/src/helper/Helper_Singleton.php',
132
  'GFPDF\\Helper\\Helper_Templates' => $baseDir . '/src/helper/Helper_Templates.php',
133
  'GFPDF\\Helper\\Helper_Trait_Logger' => $baseDir . '/src/helper/trait/Helper_Trait_Logger.php',
155
  'GFPDF\\View\\View_Settings' => $baseDir . '/src/view/View_Settings.php',
156
  'GFPDF\\View\\View_Shortcodes' => $baseDir . '/src/view/View_Shortcodes.php',
157
  'GFPDF\\View\\View_Welcome_Screen' => $baseDir . '/src/view/View_Welcome_Screen.php',
158
+ 'League\\Url\\AbstractUrl' => $vendorDir . '/league/url/src/AbstractUrl.php',
159
+ 'League\\Url\\Components\\AbstractArray' => $vendorDir . '/league/url/src/Components/AbstractArray.php',
160
+ 'League\\Url\\Components\\AbstractComponent' => $vendorDir . '/league/url/src/Components/AbstractComponent.php',
161
+ 'League\\Url\\Components\\AbstractSegment' => $vendorDir . '/league/url/src/Components/AbstractSegment.php',
162
+ 'League\\Url\\Components\\ComponentArrayInterface' => $vendorDir . '/league/url/src/Components/ComponentArrayInterface.php',
163
+ 'League\\Url\\Components\\ComponentInterface' => $vendorDir . '/league/url/src/Components/ComponentInterface.php',
164
+ 'League\\Url\\Components\\Fragment' => $vendorDir . '/league/url/src/Components/Fragment.php',
165
+ 'League\\Url\\Components\\Host' => $vendorDir . '/league/url/src/Components/Host.php',
166
+ 'League\\Url\\Components\\HostInterface' => $vendorDir . '/league/url/src/Components/HostInterface.php',
167
+ 'League\\Url\\Components\\Pass' => $vendorDir . '/league/url/src/Components/Pass.php',
168
+ 'League\\Url\\Components\\Path' => $vendorDir . '/league/url/src/Components/Path.php',
169
+ 'League\\Url\\Components\\PathInterface' => $vendorDir . '/league/url/src/Components/PathInterface.php',
170
+ 'League\\Url\\Components\\Port' => $vendorDir . '/league/url/src/Components/Port.php',
171
+ 'League\\Url\\Components\\Query' => $vendorDir . '/league/url/src/Components/Query.php',
172
+ 'League\\Url\\Components\\QueryInterface' => $vendorDir . '/league/url/src/Components/QueryInterface.php',
173
+ 'League\\Url\\Components\\Scheme' => $vendorDir . '/league/url/src/Components/Scheme.php',
174
+ 'League\\Url\\Components\\SegmentInterface' => $vendorDir . '/league/url/src/Components/SegmentInterface.php',
175
+ 'League\\Url\\Components\\User' => $vendorDir . '/league/url/src/Components/User.php',
176
+ 'League\\Url\\Url' => $vendorDir . '/league/url/src/Url.php',
177
+ 'League\\Url\\UrlConstants' => $vendorDir . '/league/url/src/UrlConstants.php',
178
+ 'League\\Url\\UrlImmutable' => $vendorDir . '/league/url/src/UrlImmutable.php',
179
+ 'League\\Url\\UrlInterface' => $vendorDir . '/league/url/src/UrlInterface.php',
180
  'Masterminds\\HTML5' => $vendorDir . '/masterminds/html5/src/HTML5.php',
181
  'Masterminds\\HTML5\\Elements' => $vendorDir . '/masterminds/html5/src/HTML5/Elements.php',
182
  'Masterminds\\HTML5\\Entities' => $vendorDir . '/masterminds/html5/src/HTML5/Entities.php',
242
  'Monolog\\Handler\\HandlerWrapper' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
243
  'Monolog\\Handler\\HipChatHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php',
244
  'Monolog\\Handler\\IFTTTHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
245
+ 'Monolog\\Handler\\InsightOpsHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php',
246
  'Monolog\\Handler\\LogEntriesHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
247
  'Monolog\\Handler\\LogglyHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
248
  'Monolog\\Handler\\MailHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
281
  'Monolog\\Processor\\MemoryUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
282
  'Monolog\\Processor\\MercurialProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
283
  'Monolog\\Processor\\ProcessIdProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
284
+ 'Monolog\\Processor\\ProcessorInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php',
285
  'Monolog\\Processor\\PsrLogMessageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
286
  'Monolog\\Processor\\TagProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
287
  'Monolog\\Processor\\UidProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
288
  'Monolog\\Processor\\WebProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
289
  'Monolog\\Registry' => $vendorDir . '/monolog/monolog/src/Monolog/Registry.php',
290
+ 'Monolog\\ResettableInterface' => $vendorDir . '/monolog/monolog/src/Monolog/ResettableInterface.php',
291
+ 'Monolog\\SignalHandler' => $vendorDir . '/monolog/monolog/src/Monolog/SignalHandler.php',
292
+ 'Monolog\\Utils' => $vendorDir . '/monolog/monolog/src/Monolog/Utils.php',
293
  'Mpdf\\Barcode' => $vendorDir . '/mpdf/mpdf/src/Barcode.php',
294
  'Mpdf\\Barcode\\AbstractBarcode' => $vendorDir . '/mpdf/mpdf/src/Barcode/AbstractBarcode.php',
295
  'Mpdf\\Barcode\\BarcodeException' => $vendorDir . '/mpdf/mpdf/src/Barcode/BarcodeException.php',
359
  'Mpdf\\Pdf\\Protection\\UniqidGenerator' => $vendorDir . '/mpdf/mpdf/src/Pdf/Protection/UniqidGenerator.php',
360
  'Mpdf\\QrCode\\QrCode' => $vendorDir . '/mpdf/mpdf/src/QrCode/QrCode.php',
361
  'Mpdf\\QrCode\\QrCodeException' => $vendorDir . '/mpdf/mpdf/src/QrCode/QrCodeException.php',
362
+ 'Mpdf\\RemoteContentFetcher' => $vendorDir . '/mpdf/mpdf/src/RemoteContentFetcher.php',
363
+ 'Mpdf\\ServiceFactory' => $vendorDir . '/mpdf/mpdf/src/ServiceFactory.php',
364
  'Mpdf\\Shaper\\Indic' => $vendorDir . '/mpdf/mpdf/src/Shaper/Indic.php',
365
  'Mpdf\\Shaper\\Myanmar' => $vendorDir . '/mpdf/mpdf/src/Shaper/Myanmar.php',
366
  'Mpdf\\Shaper\\Sea' => $vendorDir . '/mpdf/mpdf/src/Shaper/Sea.php',
367
  'Mpdf\\SizeConverter' => $vendorDir . '/mpdf/mpdf/src/SizeConverter.php',
368
+ 'Mpdf\\Strict' => $vendorDir . '/mpdf/mpdf/src/Strict.php',
369
  'Mpdf\\TTFontFile' => $vendorDir . '/mpdf/mpdf/src/TTFontFile.php',
370
  'Mpdf\\TTFontFileAnalysis' => $vendorDir . '/mpdf/mpdf/src/TTFontFileAnalysis.php',
371
  'Mpdf\\TableOfContents' => $vendorDir . '/mpdf/mpdf/src/TableOfContents.php',
484
  'Mpdf\\Utils\\NumericString' => $vendorDir . '/mpdf/mpdf/src/Utils/NumericString.php',
485
  'Mpdf\\Utils\\PdfDate' => $vendorDir . '/mpdf/mpdf/src/Utils/PdfDate.php',
486
  'Mpdf\\Utils\\UtfString' => $vendorDir . '/mpdf/mpdf/src/Utils/UtfString.php',
487
+ 'Mpdf\\Writer\\BackgroundWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/BackgroundWriter.php',
488
+ 'Mpdf\\Writer\\BaseWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/BaseWriter.php',
489
+ 'Mpdf\\Writer\\BookmarkWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/BookmarkWriter.php',
490
+ 'Mpdf\\Writer\\ColorWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/ColorWriter.php',
491
+ 'Mpdf\\Writer\\FontWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/FontWriter.php',
492
+ 'Mpdf\\Writer\\FormWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/FormWriter.php',
493
+ 'Mpdf\\Writer\\ImageWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/ImageWriter.php',
494
+ 'Mpdf\\Writer\\JavaScriptWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/JavaScriptWriter.php',
495
+ 'Mpdf\\Writer\\MetadataWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/MetadataWriter.php',
496
+ 'Mpdf\\Writer\\ObjectWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/ObjectWriter.php',
497
+ 'Mpdf\\Writer\\OptionalContentWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/OptionalContentWriter.php',
498
+ 'Mpdf\\Writer\\PageWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/PageWriter.php',
499
+ 'Mpdf\\Writer\\ResourceWriter' => $vendorDir . '/mpdf/mpdf/src/Writer/ResourceWriter.php',
500
  'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php',
501
  'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php',
502
  'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php',
534
  'QueryPath\\ParseException' => $vendorDir . '/querypath/querypath/src/QueryPath/ParseException.php',
535
  'QueryPath\\Query' => $vendorDir . '/querypath/querypath/src/QueryPath/Query.php',
536
  'QueryPath\\QueryPathIterator' => $vendorDir . '/querypath/querypath/src/QueryPath/QueryPathIterator.php',
537
+ 'Spatie\\UrlSigner\\BaseUrlSigner' => $vendorDir . '/spatie/url-signer/src/BaseUrlSigner.php',
538
+ 'Spatie\\UrlSigner\\Exceptions\\InvalidExpiration' => $vendorDir . '/spatie/url-signer/src/Exceptions/InvalidExpiration.php',
539
+ 'Spatie\\UrlSigner\\Exceptions\\InvalidSignatureKey' => $vendorDir . '/spatie/url-signer/src/Exceptions/InvalidSignatureKey.php',
540
+ 'Spatie\\UrlSigner\\MD5UrlSigner' => $vendorDir . '/spatie/url-signer/src/MD5UrlSigner.php',
541
+ 'Spatie\\UrlSigner\\UrlSigner' => $vendorDir . '/spatie/url-signer/src/UrlSigner.php',
542
+ 'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php',
543
+ 'TrueBV\\Exception\\DomainOutOfBoundsException' => $vendorDir . '/true/punycode/src/Exception/DomainOutOfBoundsException.php',
544
+ 'TrueBV\\Exception\\LabelOutOfBoundsException' => $vendorDir . '/true/punycode/src/Exception/LabelOutOfBoundsException.php',
545
+ 'TrueBV\\Exception\\OutOfBoundsException' => $vendorDir . '/true/punycode/src/Exception/OutOfBoundsException.php',
546
+ 'TrueBV\\Punycode' => $vendorDir . '/true/punycode/src/Punycode.php',
547
  'Upload\\Autoloader' => $vendorDir . '/codeguy/upload/src/Upload/Autoloader.php',
548
  'Upload\\Exception\\UploadException' => $vendorDir . '/codeguy/upload/src/Upload/Exception/UploadException.php',
549
  'Upload\\File' => $vendorDir . '/codeguy/upload/src/Upload/File.php',
vendor/composer/autoload_files.php CHANGED
@@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
9
  '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
10
  'e9b046393eb3376a21bcc1a30bd2fe64' => $vendorDir . '/querypath/querypath/src/qp_functions.php',
11
  );
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
10
  '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
11
  'e9b046393eb3376a21bcc1a30bd2fe64' => $vendorDir . '/querypath/querypath/src/qp_functions.php',
12
  );
vendor/composer/autoload_psr4.php CHANGED
@@ -6,10 +6,14 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
 
 
9
  'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
10
  'Mpdf\\' => array($vendorDir . '/mpdf/mpdf/src'),
11
  'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
12
  'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
 
13
  'GFPDF\\View\\' => array($baseDir . '/src/view'),
14
  'GFPDF\\Test\\' => array($baseDir . '/tests/unit-tests'),
15
  'GFPDF\\Statics\\' => array($baseDir . '/src/statics'),
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ 'TrueBV\\' => array($vendorDir . '/true/punycode/src'),
10
+ 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
11
+ 'Spatie\\UrlSigner\\' => array($vendorDir . '/spatie/url-signer/src'),
12
  'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
13
  'Mpdf\\' => array($vendorDir . '/mpdf/mpdf/src'),
14
  'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
15
  'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
16
+ 'League\\Url\\' => array($vendorDir . '/league/url/src'),
17
  'GFPDF\\View\\' => array($baseDir . '/src/view'),
18
  'GFPDF\\Test\\' => array($baseDir . '/tests/unit-tests'),
19
  'GFPDF\\Statics\\' => array($baseDir . '/src/statics'),
vendor/composer/autoload_static.php CHANGED
@@ -7,11 +7,21 @@ namespace Composer\Autoload;
7
  class ComposerStaticInitGravityPDFPlugin
8
  {
9
  public static $files = array (
 
10
  '6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
11
  'e9b046393eb3376a21bcc1a30bd2fe64' => __DIR__ . '/..' . '/querypath/querypath/src/qp_functions.php',
12
  );
13
 
14
  public static $prefixLengthsPsr4 = array (
 
 
 
 
 
 
 
 
 
15
  'P' =>
16
  array (
17
  'Psr\\Log\\' => 8,
@@ -22,6 +32,10 @@ class ComposerStaticInitGravityPDFPlugin
22
  'Monolog\\' => 8,
23
  'Masterminds\\' => 12,
24
  ),
 
 
 
 
25
  'G' =>
26
  array (
27
  'GFPDF\\View\\' => 11,
@@ -41,6 +55,18 @@ class ComposerStaticInitGravityPDFPlugin
41
  );
42
 
43
  public static $prefixDirsPsr4 = array (
 
 
 
 
 
 
 
 
 
 
 
 
44
  'Psr\\Log\\' =>
45
  array (
46
  0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
@@ -57,6 +83,10 @@ class ComposerStaticInitGravityPDFPlugin
57
  array (
58
  0 => __DIR__ . '/..' . '/masterminds/html5/src',
59
  ),
 
 
 
 
60
  'GFPDF\\View\\' =>
61
  array (
62
  0 => __DIR__ . '/../..' . '/src/view',
@@ -149,6 +179,7 @@ class ComposerStaticInitGravityPDFPlugin
149
  'FilterASCIIHexDecode' => __DIR__ . '/..' . '/setasign/fpdi/filters/FilterASCIIHexDecode.php',
150
  'FilterLZW' => __DIR__ . '/..' . '/setasign/fpdi/filters/FilterLZW.php',
151
  'GFPDF\\Controller\\Controller_Actions' => __DIR__ . '/../..' . '/src/controller/Controller_Actions.php',
 
152
  'GFPDF\\Controller\\Controller_Form_Settings' => __DIR__ . '/../..' . '/src/controller/Controller_Form_Settings.php',
153
  'GFPDF\\Controller\\Controller_Install' => __DIR__ . '/../..' . '/src/controller/Controller_Install.php',
154
  'GFPDF\\Controller\\Controller_Mergetags' => __DIR__ . '/../..' . '/src/controller/Controller_Mergetags.php',
@@ -162,6 +193,7 @@ class ComposerStaticInitGravityPDFPlugin
162
  'GFPDF\\Helper\\Fields\\Field_Address' => __DIR__ . '/../..' . '/src/helper/fields/Field_Address.php',
163
  'GFPDF\\Helper\\Fields\\Field_Chainedselect' => __DIR__ . '/../..' . '/src/helper/fields/Field_Chainedselect.php',
164
  'GFPDF\\Helper\\Fields\\Field_Checkbox' => __DIR__ . '/../..' . '/src/helper/fields/Field_Checkbox.php',
 
165
  'GFPDF\\Helper\\Fields\\Field_Coupon' => __DIR__ . '/../..' . '/src/helper/fields/Field_Coupon.php',
166
  'GFPDF\\Helper\\Fields\\Field_CreditCard' => __DIR__ . '/../..' . '/src/helper/fields/Field_Creditcard.php',
167
  'GFPDF\\Helper\\Fields\\Field_Date' => __DIR__ . '/../..' . '/src/helper/fields/Field_Date.php',
@@ -169,6 +201,7 @@ class ComposerStaticInitGravityPDFPlugin
169
  'GFPDF\\Helper\\Fields\\Field_Discount' => __DIR__ . '/../..' . '/src/helper/fields/Field_Discount.php',
170
  'GFPDF\\Helper\\Fields\\Field_Email' => __DIR__ . '/../..' . '/src/helper/fields/Field_Email.php',
171
  'GFPDF\\Helper\\Fields\\Field_Fileupload' => __DIR__ . '/../..' . '/src/helper/fields/Field_Fileupload.php',
 
172
  'GFPDF\\Helper\\Fields\\Field_Hidden' => __DIR__ . '/../..' . '/src/helper/fields/Field_Hidden.php',
173
  'GFPDF\\Helper\\Fields\\Field_Html' => __DIR__ . '/../..' . '/src/helper/fields/Field_Html.php',
174
  'GFPDF\\Helper\\Fields\\Field_Likert' => __DIR__ . '/../..' . '/src/helper/fields/Field_Likert.php',
@@ -193,6 +226,7 @@ class ComposerStaticInitGravityPDFPlugin
193
  'GFPDF\\Helper\\Fields\\Field_Radio' => __DIR__ . '/../..' . '/src/helper/fields/Field_Radio.php',
194
  'GFPDF\\Helper\\Fields\\Field_Rank' => __DIR__ . '/../..' . '/src/helper/fields/Field_Rank.php',
195
  'GFPDF\\Helper\\Fields\\Field_Rating' => __DIR__ . '/../..' . '/src/helper/fields/Field_Rating.php',
 
196
  'GFPDF\\Helper\\Fields\\Field_Section' => __DIR__ . '/../..' . '/src/helper/fields/Field_Section.php',
197
  'GFPDF\\Helper\\Fields\\Field_Select' => __DIR__ . '/../..' . '/src/helper/fields/Field_Select.php',
198
  'GFPDF\\Helper\\Fields\\Field_Shipping' => __DIR__ . '/../..' . '/src/helper/fields/Field_Shipping.php',
@@ -237,6 +271,7 @@ class ComposerStaticInitGravityPDFPlugin
237
  'GFPDF\\Helper\\Helper_PDF_List_Table' => __DIR__ . '/../..' . '/src/helper/Helper_PDF_List_Table.php',
238
  'GFPDF\\Helper\\Helper_Pdf_Queue' => __DIR__ . '/../..' . '/src/helper/Helper_Pdf_Queue.php',
239
  'GFPDF\\Helper\\Helper_QueryPath' => __DIR__ . '/../..' . '/src/helper/Helper_QueryPath.php',
 
240
  'GFPDF\\Helper\\Helper_Singleton' => __DIR__ . '/../..' . '/src/helper/Helper_Singleton.php',
241
  'GFPDF\\Helper\\Helper_Templates' => __DIR__ . '/../..' . '/src/helper/Helper_Templates.php',
242
  'GFPDF\\Helper\\Helper_Trait_Logger' => __DIR__ . '/../..' . '/src/helper/trait/Helper_Trait_Logger.php',
@@ -264,6 +299,28 @@ class ComposerStaticInitGravityPDFPlugin
264
  'GFPDF\\View\\View_Settings' => __DIR__ . '/../..' . '/src/view/View_Settings.php',
265
  'GFPDF\\View\\View_Shortcodes' => __DIR__ . '/../..' . '/src/view/View_Shortcodes.php',
266
  'GFPDF\\View\\View_Welcome_Screen' => __DIR__ . '/../..' . '/src/view/View_Welcome_Screen.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  'Masterminds\\HTML5' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5.php',
268
  'Masterminds\\HTML5\\Elements' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Elements.php',
269
  'Masterminds\\HTML5\\Entities' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Entities.php',
@@ -329,6 +386,7 @@ class ComposerStaticInitGravityPDFPlugin
329
  'Monolog\\Handler\\HandlerWrapper' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
330
  'Monolog\\Handler\\HipChatHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php',
331
  'Monolog\\Handler\\IFTTTHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
 
332
  'Monolog\\Handler\\LogEntriesHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
333
  'Monolog\\Handler\\LogglyHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
334
  'Monolog\\Handler\\MailHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
@@ -367,11 +425,15 @@ class ComposerStaticInitGravityPDFPlugin
367
  'Monolog\\Processor\\MemoryUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
368
  'Monolog\\Processor\\MercurialProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
369
  'Monolog\\Processor\\ProcessIdProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
 
370
  'Monolog\\Processor\\PsrLogMessageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
371
  'Monolog\\Processor\\TagProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
372
  'Monolog\\Processor\\UidProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
373
  'Monolog\\Processor\\WebProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
374
  'Monolog\\Registry' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Registry.php',
 
 
 
375
  'Mpdf\\Barcode' => __DIR__ . '/..' . '/mpdf/mpdf/src/Barcode.php',
376
  'Mpdf\\Barcode\\AbstractBarcode' => __DIR__ . '/..' . '/mpdf/mpdf/src/Barcode/AbstractBarcode.php',
377
  'Mpdf\\Barcode\\BarcodeException' => __DIR__ . '/..' . '/mpdf/mpdf/src/Barcode/BarcodeException.php',
@@ -441,10 +503,13 @@ class ComposerStaticInitGravityPDFPlugin
441
  'Mpdf\\Pdf\\Protection\\UniqidGenerator' => __DIR__ . '/..' . '/mpdf/mpdf/src/Pdf/Protection/UniqidGenerator.php',
442
  'Mpdf\\QrCode\\QrCode' => __DIR__ . '/..' . '/mpdf/mpdf/src/QrCode/QrCode.php',
443
  'Mpdf\\QrCode\\QrCodeException' => __DIR__ . '/..' . '/mpdf/mpdf/src/QrCode/QrCodeException.php',
 
 
444
  'Mpdf\\Shaper\\Indic' => __DIR__ . '/..' . '/mpdf/mpdf/src/Shaper/Indic.php',
445
  'Mpdf\\Shaper\\Myanmar' => __DIR__ . '/..' . '/mpdf/mpdf/src/Shaper/Myanmar.php',
446
  'Mpdf\\Shaper\\Sea' => __DIR__ . '/..' . '/mpdf/mpdf/src/Shaper/Sea.php',
447
  'Mpdf\\SizeConverter' => __DIR__ . '/..' . '/mpdf/mpdf/src/SizeConverter.php',
 
448
  'Mpdf\\TTFontFile' => __DIR__ . '/..' . '/mpdf/mpdf/src/TTFontFile.php',
449
  'Mpdf\\TTFontFileAnalysis' => __DIR__ . '/..' . '/mpdf/mpdf/src/TTFontFileAnalysis.php',
450
  'Mpdf\\TableOfContents' => __DIR__ . '/..' . '/mpdf/mpdf/src/TableOfContents.php',
@@ -563,6 +628,19 @@ class ComposerStaticInitGravityPDFPlugin
563
  'Mpdf\\Utils\\NumericString' => __DIR__ . '/..' . '/mpdf/mpdf/src/Utils/NumericString.php',
564
  'Mpdf\\Utils\\PdfDate' => __DIR__ . '/..' . '/mpdf/mpdf/src/Utils/PdfDate.php',
565
  'Mpdf\\Utils\\UtfString' => __DIR__ . '/..' . '/mpdf/mpdf/src/Utils/UtfString.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
566
  'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php',
567
  'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php',
568
  'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php',
@@ -600,6 +678,16 @@ class ComposerStaticInitGravityPDFPlugin
600
  'QueryPath\\ParseException' => __DIR__ . '/..' . '/querypath/querypath/src/QueryPath/ParseException.php',
601
  'QueryPath\\Query' => __DIR__ . '/..' . '/querypath/querypath/src/QueryPath/Query.php',
602
  'QueryPath\\QueryPathIterator' => __DIR__ . '/..' . '/querypath/querypath/src/QueryPath/QueryPathIterator.php',
 
 
 
 
 
 
 
 
 
 
603
  'Upload\\Autoloader' => __DIR__ . '/..' . '/codeguy/upload/src/Upload/Autoloader.php',
604
  'Upload\\Exception\\UploadException' => __DIR__ . '/..' . '/codeguy/upload/src/Upload/Exception/UploadException.php',
605
  'Upload\\File' => __DIR__ . '/..' . '/codeguy/upload/src/Upload/File.php',
7
  class ComposerStaticInitGravityPDFPlugin
8
  {
9
  public static $files = array (
10
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
11
  '6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
12
  'e9b046393eb3376a21bcc1a30bd2fe64' => __DIR__ . '/..' . '/querypath/querypath/src/qp_functions.php',
13
  );
14
 
15
  public static $prefixLengthsPsr4 = array (
16
+ 'T' =>
17
+ array (
18
+ 'TrueBV\\' => 7,
19
+ ),
20
+ 'S' =>
21
+ array (
22
+ 'Symfony\\Polyfill\\Mbstring\\' => 26,
23
+ 'Spatie\\UrlSigner\\' => 17,
24
+ ),
25
  'P' =>
26
  array (
27
  'Psr\\Log\\' => 8,
32
  'Monolog\\' => 8,
33
  'Masterminds\\' => 12,
34
  ),
35
+ 'L' =>
36
+ array (
37
+ 'League\\Url\\' => 11,
38
+ ),
39
  'G' =>
40
  array (
41
  'GFPDF\\View\\' => 11,
55
  );
56
 
57
  public static $prefixDirsPsr4 = array (
58
+ 'TrueBV\\' =>
59
+ array (
60
+ 0 => __DIR__ . '/..' . '/true/punycode/src',
61
+ ),
62
+ 'Symfony\\Polyfill\\Mbstring\\' =>
63
+ array (
64
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
65
+ ),
66
+ 'Spatie\\UrlSigner\\' =>
67
+ array (
68
+ 0 => __DIR__ . '/..' . '/spatie/url-signer/src',
69
+ ),
70
  'Psr\\Log\\' =>
71
  array (
72
  0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
83
  array (
84
  0 => __DIR__ . '/..' . '/masterminds/html5/src',
85
  ),
86
+ 'League\\Url\\' =>
87
+ array (
88
+ 0 => __DIR__ . '/..' . '/league/url/src',
89
+ ),
90
  'GFPDF\\View\\' =>
91
  array (
92
  0 => __DIR__ . '/../..' . '/src/view',
179
  'FilterASCIIHexDecode' => __DIR__ . '/..' . '/setasign/fpdi/filters/FilterASCIIHexDecode.php',
180
  'FilterLZW' => __DIR__ . '/..' . '/setasign/fpdi/filters/FilterLZW.php',
181
  'GFPDF\\Controller\\Controller_Actions' => __DIR__ . '/../..' . '/src/controller/Controller_Actions.php',
182
+ 'GFPDF\\Controller\\Controller_Debug' => __DIR__ . '/../..' . '/src/controller/Controller_Debug.php',
183
  'GFPDF\\Controller\\Controller_Form_Settings' => __DIR__ . '/../..' . '/src/controller/Controller_Form_Settings.php',
184
  'GFPDF\\Controller\\Controller_Install' => __DIR__ . '/../..' . '/src/controller/Controller_Install.php',
185
  'GFPDF\\Controller\\Controller_Mergetags' => __DIR__ . '/../..' . '/src/controller/Controller_Mergetags.php',
193
  'GFPDF\\Helper\\Fields\\Field_Address' => __DIR__ . '/../..' . '/src/helper/fields/Field_Address.php',
194
  'GFPDF\\Helper\\Fields\\Field_Chainedselect' => __DIR__ . '/../..' . '/src/helper/fields/Field_Chainedselect.php',
195
  'GFPDF\\Helper\\Fields\\Field_Checkbox' => __DIR__ . '/../..' . '/src/helper/fields/Field_Checkbox.php',
196
+ 'GFPDF\\Helper\\Fields\\Field_Consent' => __DIR__ . '/../..' . '/src/helper/fields/Field_Consent.php',
197
  'GFPDF\\Helper\\Fields\\Field_Coupon' => __DIR__ . '/../..' . '/src/helper/fields/Field_Coupon.php',
198
  'GFPDF\\Helper\\Fields\\Field_CreditCard' => __DIR__ . '/../..' . '/src/helper/fields/Field_Creditcard.php',
199
  'GFPDF\\Helper\\Fields\\Field_Date' => __DIR__ . '/../..' . '/src/helper/fields/Field_Date.php',
201
  'GFPDF\\Helper\\Fields\\Field_Discount' => __DIR__ . '/../..' . '/src/helper/fields/Field_Discount.php',
202
  'GFPDF\\Helper\\Fields\\Field_Email' => __DIR__ . '/../..' . '/src/helper/fields/Field_Email.php',
203
  'GFPDF\\Helper\\Fields\\Field_Fileupload' => __DIR__ . '/../..' . '/src/helper/fields/Field_Fileupload.php',
204
+ 'GFPDF\\Helper\\Fields\\Field_Form' => __DIR__ . '/../..' . '/src/helper/fields/Field_Form.php',
205
  'GFPDF\\Helper\\Fields\\Field_Hidden' => __DIR__ . '/../..' . '/src/helper/fields/Field_Hidden.php',
206
  'GFPDF\\Helper\\Fields\\Field_Html' => __DIR__ . '/../..' . '/src/helper/fields/Field_Html.php',
207
  'GFPDF\\Helper\\Fields\\Field_Likert' => __DIR__ . '/../..' . '/src/helper/fields/Field_Likert.php',
226
  'GFPDF\\Helper\\Fields\\Field_Radio' => __DIR__ . '/../..' . '/src/helper/fields/Field_Radio.php',
227
  'GFPDF\\Helper\\Fields\\Field_Rank' => __DIR__ . '/../..' . '/src/helper/fields/Field_Rank.php',
228
  'GFPDF\\Helper\\Fields\\Field_Rating' => __DIR__ . '/../..' . '/src/helper/fields/Field_Rating.php',
229
+ 'GFPDF\\Helper\\Fields\\Field_Repeater' => __DIR__ . '/../..' . '/src/helper/fields/Field_Repeater.php',
230
  'GFPDF\\Helper\\Fields\\Field_Section' => __DIR__ . '/../..' . '/src/helper/fields/Field_Section.php',
231
  'GFPDF\\Helper\\Fields\\Field_Select' => __DIR__ . '/../..' . '/src/helper/fields/Field_Select.php',
232
  'GFPDF\\Helper\\Fields\\Field_Shipping' => __DIR__ . '/../..' . '/src/helper/fields/Field_Shipping.php',
271
  'GFPDF\\Helper\\Helper_PDF_List_Table' => __DIR__ . '/../..' . '/src/helper/Helper_PDF_List_Table.php',
272
  'GFPDF\\Helper\\Helper_Pdf_Queue' => __DIR__ . '/../..' . '/src/helper/Helper_Pdf_Queue.php',
273
  'GFPDF\\Helper\\Helper_QueryPath' => __DIR__ . '/../..' . '/src/helper/Helper_QueryPath.php',
274
+ 'GFPDF\\Helper\\Helper_Sha256_Url_Signer' => __DIR__ . '/../..' . '/src/helper/Helper_Sha256_Url_Signer.php',
275
  'GFPDF\\Helper\\Helper_Singleton' => __DIR__ . '/../..' . '/src/helper/Helper_Singleton.php',
276
  'GFPDF\\Helper\\Helper_Templates' => __DIR__ . '/../..' . '/src/helper/Helper_Templates.php',
277
  'GFPDF\\Helper\\Helper_Trait_Logger' => __DIR__ . '/../..' . '/src/helper/trait/Helper_Trait_Logger.php',
299
  'GFPDF\\View\\View_Settings' => __DIR__ . '/../..' . '/src/view/View_Settings.php',
300
  'GFPDF\\View\\View_Shortcodes' => __DIR__ . '/../..' . '/src/view/View_Shortcodes.php',
301
  'GFPDF\\View\\View_Welcome_Screen' => __DIR__ . '/../..' . '/src/view/View_Welcome_Screen.php',
302
+ 'League\\Url\\AbstractUrl' => __DIR__ . '/..' . '/league/url/src/AbstractUrl.php',
303
+ 'League\\Url\\Components\\AbstractArray' => __DIR__ . '/..' . '/league/url/src/Components/AbstractArray.php',
304
+ 'League\\Url\\Components\\AbstractComponent' => __DIR__ . '/..' . '/league/url/src/Components/AbstractComponent.php',
305
+ 'League\\Url\\Components\\AbstractSegment' => __DIR__ . '/..' . '/league/url/src/Components/AbstractSegment.php',
306
+ 'League\\Url\\Components\\ComponentArrayInterface' => __DIR__ . '/..' . '/league/url/src/Components/ComponentArrayInterface.php',
307
+ 'League\\Url\\Components\\ComponentInterface' => __DIR__ . '/..' . '/league/url/src/Components/ComponentInterface.php',
308
+ 'League\\Url\\Components\\Fragment' => __DIR__ . '/..' . '/league/url/src/Components/Fragment.php',
309
+ 'League\\Url\\Components\\Host' => __DIR__ . '/..' . '/league/url/src/Components/Host.php',
310
+ 'League\\Url\\Components\\HostInterface' => __DIR__ . '/..' . '/league/url/src/Components/HostInterface.php',
311
+ 'League\\Url\\Components\\Pass' => __DIR__ . '/..' . '/league/url/src/Components/Pass.php',
312
+ 'League\\Url\\Components\\Path' => __DIR__ . '/..' . '/league/url/src/Components/Path.php',
313
+ 'League\\Url\\Components\\PathInterface' => __DIR__ . '/..' . '/league/url/src/Components/PathInterface.php',
314
+ 'League\\Url\\Components\\Port' => __DIR__ . '/..' . '/league/url/src/Components/Port.php',
315
+ 'League\\Url\\Components\\Query' => __DIR__ . '/..' . '/league/url/src/Components/Query.php',
316
+ 'League\\Url\\Components\\QueryInterface' => __DIR__ . '/..' . '/league/url/src/Components/QueryInterface.php',
317
+ 'League\\Url\\Components\\Scheme' => __DIR__ . '/..' . '/league/url/src/Components/Scheme.php',
318
+ 'League\\Url\\Components\\SegmentInterface' => __DIR__ . '/..' . '/league/url/src/Components/SegmentInterface.php',
319
+ 'League\\Url\\Components\\User' => __DIR__ . '/..' . '/league/url/src/Components/User.php',
320
+ 'League\\Url\\Url' => __DIR__ . '/..' . '/league/url/src/Url.php',
321
+ 'League\\Url\\UrlConstants' => __DIR__ . '/..' . '/league/url/src/UrlConstants.php',
322
+ 'League\\Url\\UrlImmutable' => __DIR__ . '/..' . '/league/url/src/UrlImmutable.php',
323
+ 'League\\Url\\UrlInterface' => __DIR__ . '/..' . '/league/url/src/UrlInterface.php',
324
  'Masterminds\\HTML5' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5.php',
325
  'Masterminds\\HTML5\\Elements' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Elements.php',
326
  'Masterminds\\HTML5\\Entities' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Entities.php',
386
  'Monolog\\Handler\\HandlerWrapper' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
387
  'Monolog\\Handler\\HipChatHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php',
388
  'Monolog\\Handler\\IFTTTHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
389
+ 'Monolog\\Handler\\InsightOpsHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php',
390
  'Monolog\\Handler\\LogEntriesHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
391
  'Monolog\\Handler\\LogglyHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
392
  'Monolog\\Handler\\MailHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
425
  'Monolog\\Processor\\MemoryUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
426
  'Monolog\\Processor\\MercurialProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
427
  'Monolog\\Processor\\ProcessIdProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
428
+ 'Monolog\\Processor\\ProcessorInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php',
429
  'Monolog\\Processor\\PsrLogMessageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
430
  'Monolog\\Processor\\TagProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
431
  'Monolog\\Processor\\UidProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
432
  'Monolog\\Processor\\WebProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
433
  'Monolog\\Registry' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Registry.php',
434
+ 'Monolog\\ResettableInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/ResettableInterface.php',
435
+ 'Monolog\\SignalHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/SignalHandler.php',
436
+ 'Monolog\\Utils' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Utils.php',
437
  'Mpdf\\Barcode' => __DIR__ . '/..' . '/mpdf/mpdf/src/Barcode.php',
438
  'Mpdf\\Barcode\\AbstractBarcode' => __DIR__ . '/..' . '/mpdf/mpdf/src/Barcode/AbstractBarcode.php',
439
  'Mpdf\\Barcode\\BarcodeException' => __DIR__ . '/..' . '/mpdf/mpdf/src/Barcode/BarcodeException.php',
503
  'Mpdf\\Pdf\\Protection\\UniqidGenerator' => __DIR__ . '/..' . '/mpdf/mpdf/src/Pdf/Protection/UniqidGenerator.php',
504
  'Mpdf\\QrCode\\QrCode' => __DIR__ . '/..' . '/mpdf/mpdf/src/QrCode/QrCode.php',
505
  'Mpdf\\QrCode\\QrCodeException' => __DIR__ . '/..' . '/mpdf/mpdf/src/QrCode/QrCodeException.php',
506
+ 'Mpdf\\RemoteContentFetcher' => __DIR__ . '/..' . '/mpdf/mpdf/src/RemoteContentFetcher.php',
507
+ 'Mpdf\\ServiceFactory' => __DIR__ . '/..' . '/mpdf/mpdf/src/ServiceFactory.php',
508
  'Mpdf\\Shaper\\Indic' => __DIR__ . '/..' . '/mpdf/mpdf/src/Shaper/Indic.php',
509
  'Mpdf\\Shaper\\Myanmar' => __DIR__ . '/..' . '/mpdf/mpdf/src/Shaper/Myanmar.php',
510
  'Mpdf\\Shaper\\Sea' => __DIR__ . '/..' . '/mpdf/mpdf/src/Shaper/Sea.php',
511
  'Mpdf\\SizeConverter' => __DIR__ . '/..' . '/mpdf/mpdf/src/SizeConverter.php',
512
+ 'Mpdf\\Strict' => __DIR__ . '/..' . '/mpdf/mpdf/src/Strict.php',
513
  'Mpdf\\TTFontFile' => __DIR__ . '/..' . '/mpdf/mpdf/src/TTFontFile.php',
514
  'Mpdf\\TTFontFileAnalysis' => __DIR__ . '/..' . '/mpdf/mpdf/src/TTFontFileAnalysis.php',
515
  'Mpdf\\TableOfContents' => __DIR__ . '/..' . '/mpdf/mpdf/src/TableOfContents.php',
628
  'Mpdf\\Utils\\NumericString' => __DIR__ . '/..' . '/mpdf/mpdf/src/Utils/NumericString.php',
629
  'Mpdf\\Utils\\PdfDate' => __DIR__ . '/..' . '/mpdf/mpdf/src/Utils/PdfDate.php',
630
  'Mpdf\\Utils\\UtfString' => __DIR__ . '/..' . '/mpdf/mpdf/src/Utils/UtfString.php',
631
+ 'Mpdf\\Writer\\BackgroundWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/BackgroundWriter.php',
632
+ 'Mpdf\\Writer\\BaseWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/BaseWriter.php',
633
+ 'Mpdf\\Writer\\BookmarkWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/BookmarkWriter.php',
634
+ 'Mpdf\\Writer\\ColorWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/ColorWriter.php',
635
+ 'Mpdf\\Writer\\FontWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/FontWriter.php',
636
+ 'Mpdf\\Writer\\FormWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/FormWriter.php',
637
+ 'Mpdf\\Writer\\ImageWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/ImageWriter.php',
638
+ 'Mpdf\\Writer\\JavaScriptWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/JavaScriptWriter.php',
639
+ 'Mpdf\\Writer\\MetadataWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/MetadataWriter.php',
640
+ 'Mpdf\\Writer\\ObjectWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/ObjectWriter.php',
641
+ 'Mpdf\\Writer\\OptionalContentWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/OptionalContentWriter.php',
642
+ 'Mpdf\\Writer\\PageWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/PageWriter.php',
643
+ 'Mpdf\\Writer\\ResourceWriter' => __DIR__ . '/..' . '/mpdf/mpdf/src/Writer/ResourceWriter.php',
644
  'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php',
645
  'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php',
646
  'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php',
678
  'QueryPath\\ParseException' => __DIR__ . '/..' . '/querypath/querypath/src/QueryPath/ParseException.php',
679
  'QueryPath\\Query' => __DIR__ . '/..' . '/querypath/querypath/src/QueryPath/Query.php',
680
  'QueryPath\\QueryPathIterator' => __DIR__ . '/..' . '/querypath/querypath/src/QueryPath/QueryPathIterator.php',
681
+ 'Spatie\\UrlSigner\\BaseUrlSigner' => __DIR__ . '/..' . '/spatie/url-signer/src/BaseUrlSigner.php',
682
+ 'Spatie\\UrlSigner\\Exceptions\\InvalidExpiration' => __DIR__ . '/..' . '/spatie/url-signer/src/Exceptions/InvalidExpiration.php',
683
+ 'Spatie\\UrlSigner\\Exceptions\\InvalidSignatureKey' => __DIR__ . '/..' . '/spatie/url-signer/src/Exceptions/InvalidSignatureKey.php',
684
+ 'Spatie\\UrlSigner\\MD5UrlSigner' => __DIR__ . '/..' . '/spatie/url-signer/src/MD5UrlSigner.php',
685
+ 'Spatie\\UrlSigner\\UrlSigner' => __DIR__ . '/..' . '/spatie/url-signer/src/UrlSigner.php',
686
+ 'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php',
687
+ 'TrueBV\\Exception\\DomainOutOfBoundsException' => __DIR__ . '/..' . '/true/punycode/src/Exception/DomainOutOfBoundsException.php',
688
+ 'TrueBV\\Exception\\LabelOutOfBoundsException' => __DIR__ . '/..' . '/true/punycode/src/Exception/LabelOutOfBoundsException.php',
689
+ 'TrueBV\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/true/punycode/src/Exception/OutOfBoundsException.php',
690
+ 'TrueBV\\Punycode' => __DIR__ . '/..' . '/true/punycode/src/Punycode.php',
691
  'Upload\\Autoloader' => __DIR__ . '/..' . '/codeguy/upload/src/Upload/Autoloader.php',
692
  'Upload\\Exception\\UploadException' => __DIR__ . '/..' . '/codeguy/upload/src/Upload/Exception/UploadException.php',
693
  'Upload\\File' => __DIR__ . '/..' . '/codeguy/upload/src/Upload/File.php',
vendor/composer/installed.json CHANGED
@@ -5,12 +5,12 @@
5
  "version_normalized": "1.3.2.0",
6
  "source": {
7
  "type": "git",
8
- "url": "https://github.com/codeguy/Upload.git",
9
  "reference": "6a9e5e1fb58d65346d0e557db2d46fb25efd3e37"
10
  },
11
  "dist": {
12
  "type": "zip",
13
- "url": "https://api.github.com/repos/codeguy/Upload/zipball/6a9e5e1fb58d65346d0e557db2d46fb25efd3e37",
14
  "reference": "6a9e5e1fb58d65346d0e557db2d46fb25efd3e37",
15
  "shasum": ""
16
  },
@@ -37,7 +37,7 @@
37
  {
38
  "name": "Josh Lockhart",
39
  "email": "info@joshlockhart.com",
40
- "homepage": "http://www.joshlockhart.com/"
41
  }
42
  ],
43
  "description": "Handle file uploads with extensible validation and storage strategies",
@@ -48,19 +48,76 @@
48
  "validation"
49
  ]
50
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  {
52
  "name": "masterminds/html5",
53
- "version": "2.3.0",
54
- "version_normalized": "2.3.0.0",
55
  "source": {
56
  "type": "git",
57
  "url": "https://github.com/Masterminds/html5-php.git",
58
- "reference": "2c37c6c520b995b761674de3be8455a381679067"
59
  },
60
  "dist": {
61
  "type": "zip",
62
- "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/2c37c6c520b995b761674de3be8455a381679067",
63
- "reference": "2c37c6c520b995b761674de3be8455a381679067",
64
  "shasum": ""
65
  },
66
  "require": {
@@ -72,7 +129,7 @@
72
  "sami/sami": "~2.0",
73
  "satooshi/php-coveralls": "1.0.*"
74
  },
75
- "time": "2017-09-04T12:26:28+00:00",
76
  "type": "library",
77
  "extra": {
78
  "branch-alias": {
@@ -117,17 +174,17 @@
117
  },
118
  {
119
  "name": "monolog/monolog",
120
- "version": "1.23.0",
121
- "version_normalized": "1.23.0.0",
122
  "source": {
123
  "type": "git",
124
  "url": "https://github.com/Seldaek/monolog.git",
125
- "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4"
126
  },
127
  "dist": {
128
  "type": "zip",
129
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4",
130
- "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4",
131
  "shasum": ""
132
  },
133
  "require": {
@@ -163,7 +220,7 @@
163
  "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
164
  "sentry/sentry": "Allow sending log messages to a Sentry server"
165
  },
166
- "time": "2017-06-19T01:22:40+00:00",
167
  "type": "library",
168
  "extra": {
169
  "branch-alias": {
@@ -197,17 +254,17 @@
197
  },
198
  {
199
  "name": "mpdf/mpdf",
200
- "version": "v7.1.5",
201
- "version_normalized": "7.1.5.0",
202
  "source": {
203
  "type": "git",
204
  "url": "https://github.com/mpdf/mpdf.git",
205
- "reference": "2ed29c3a59fa23e77052e9d7fa7e31c707fb7502"
206
  },
207
  "dist": {
208
  "type": "zip",
209
- "url": "https://api.github.com/repos/mpdf/mpdf/zipball/2ed29c3a59fa23e77052e9d7fa7e31c707fb7502",
210
- "reference": "2ed29c3a59fa23e77052e9d7fa7e31c707fb7502",
211
  "shasum": ""
212
  },
213
  "require": {
@@ -230,11 +287,11 @@
230
  "ext-xml": "Needed mainly for SVG manipulation",
231
  "ext-zlib": "Needed for compression of embedded resources, such as fonts"
232
  },
233
- "time": "2018-09-19T09:58:39+00:00",
234
  "type": "library",
235
  "extra": {
236
  "branch-alias": {
237
- "dev-development": "7.0-dev"
238
  }
239
  },
240
  "installation-source": "dist",
@@ -505,5 +562,172 @@
505
  "fpdi",
506
  "pdf"
507
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  }
509
  ]
5
  "version_normalized": "1.3.2.0",
6
  "source": {
7
  "type": "git",
8
+ "url": "https://github.com/brandonsavage/Upload.git",
9
  "reference": "6a9e5e1fb58d65346d0e557db2d46fb25efd3e37"
10
  },
11
  "dist": {
12
  "type": "zip",
13
+ "url": "https://api.github.com/repos/brandonsavage/Upload/zipball/6a9e5e1fb58d65346d0e557db2d46fb25efd3e37",
14
  "reference": "6a9e5e1fb58d65346d0e557db2d46fb25efd3e37",
15
  "shasum": ""
16
  },
37
  {
38
  "name": "Josh Lockhart",
39
  "email": "info@joshlockhart.com",
40
+ "homepage": "https://github.com/codeguy/"
41
  }
42
  ],
43
  "description": "Handle file uploads with extensible validation and storage strategies",
48
  "validation"
49
  ]
50
  },
51
+ {
52
+ "name": "league/url",
53
+ "version": "3.3.5",
54
+ "version_normalized": "3.3.5.0",
55
+ "source": {
56
+ "type": "git",
57
+ "url": "https://github.com/thephpleague/url.git",
58
+ "reference": "1ae2c3ce29a7c5438339ff6388225844e6479da8"
59
+ },
60
+ "dist": {
61
+ "type": "zip",
62
+ "url": "https://api.github.com/repos/thephpleague/url/zipball/1ae2c3ce29a7c5438339ff6388225844e6479da8",
63
+ "reference": "1ae2c3ce29a7c5438339ff6388225844e6479da8",
64
+ "shasum": ""
65
+ },
66
+ "require": {
67
+ "ext-mbstring": "*",
68
+ "php": ">=5.3.0",
69
+ "true/punycode": "^2.0"
70
+ },
71
+ "require-dev": {
72
+ "phpunit/phpunit": "^4.0"
73
+ },
74
+ "time": "2015-07-15T08:24:12+00:00",
75
+ "type": "library",
76
+ "extra": {
77
+ "branch-alias": {
78
+ "dev-master": "3.3-dev"
79
+ }
80
+ },
81
+ "installation-source": "dist",
82
+ "autoload": {
83
+ "psr-4": {
84
+ "League\\Url\\": "src"
85
+ }
86
+ },
87
+ "notification-url": "https://packagist.org/downloads/",
88
+ "license": [
89
+ "MIT"
90
+ ],
91
+ "authors": [
92
+ {
93
+ "name": "Ignace Nyamagana Butera",
94
+ "email": "nyamsprod@gmail.com",
95
+ "homepage": "https://github.com/nyamsprod/",
96
+ "role": "Developer"
97
+ }
98
+ ],
99
+ "description": "League/url is a lightweight PHP Url manipulating library",
100
+ "homepage": "http://url.thephpleague.com",
101
+ "keywords": [
102
+ "parse_url",
103
+ "php",
104
+ "url"
105
+ ],
106
+ "abandoned": "league/uri"
107
+ },
108
  {
109
  "name": "masterminds/html5",
110
+ "version": "2.3.1",
111
+ "version_normalized": "2.3.1.0",
112
  "source": {
113
  "type": "git",
114
  "url": "https://github.com/Masterminds/html5-php.git",
115
+ "reference": "33f8d475d28741398be26cdff7a10a63003324a3"
116
  },
117
  "dist": {
118
  "type": "zip",
119
+ "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/33f8d475d28741398be26cdff7a10a63003324a3",
120
+ "reference": "33f8d475d28741398be26cdff7a10a63003324a3",
121
  "shasum": ""
122
  },
123
  "require": {
129
  "sami/sami": "~2.0",
130
  "satooshi/php-coveralls": "1.0.*"
131
  },
132
+ "time": "2018-10-22T16:58:34+00:00",
133
  "type": "library",
134
  "extra": {
135
  "branch-alias": {
174
  },
175
  {
176
  "name": "monolog/monolog",
177
+ "version": "1.24.0",
178
+ "version_normalized": "1.24.0.0",
179
  "source": {
180
  "type": "git",
181
  "url": "https://github.com/Seldaek/monolog.git",
182
+ "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266"
183
  },
184
  "dist": {
185
  "type": "zip",
186
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266",
187
+ "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266",
188
  "shasum": ""
189
  },
190
  "require": {
220
  "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
221
  "sentry/sentry": "Allow sending log messages to a Sentry server"
222
  },
223
+ "time": "2018-11-05T09:00:11+00:00",
224
  "type": "library",
225
  "extra": {
226
  "branch-alias": {
254
  },
255
  {
256
  "name": "mpdf/mpdf",
257
+ "version": "v7.1.6",
258
+ "version_normalized": "7.1.6.0",
259
  "source": {
260
  "type": "git",
261
  "url": "https://github.com/mpdf/mpdf.git",
262
+ "reference": "ef5d8cf2c63def40fb76fc0a9e286721cb4dffcd"
263
  },
264
  "dist": {
265
  "type": "zip",
266
+ "url": "https://api.github.com/repos/mpdf/mpdf/zipball/ef5d8cf2c63def40fb76fc0a9e286721cb4dffcd",
267
+ "reference": "ef5d8cf2c63def40fb76fc0a9e286721cb4dffcd",
268
  "shasum": ""
269
  },
270
  "require": {
287
  "ext-xml": "Needed mainly for SVG manipulation",
288
  "ext-zlib": "Needed for compression of embedded resources, such as fonts"
289
  },
290
+ "time": "2018-10-18T11:37:12+00:00",
291
  "type": "library",
292
  "extra": {
293
  "branch-alias": {
294
+ "dev-development": "7.x-dev"
295
  }
296
  },
297
  "installation-source": "dist",
562
  "fpdi",
563
  "pdf"
564
  ]
565
+ },
566
+ {
567
+ "name": "spatie/url-signer",
568
+ "version": "1.0.2",
569
+ "version_normalized": "1.0.2.0",
570
+ "source": {
571
+ "type": "git",
572
+ "url": "https://github.com/spatie/url-signer.git",
573
+ "reference": "945bf049d50eeaadd774e777114c6507eb6df58a"
574
+ },
575
+ "dist": {
576
+ "type": "zip",
577
+ "url": "https://api.github.com/repos/spatie/url-signer/zipball/945bf049d50eeaadd774e777114c6507eb6df58a",
578
+ "reference": "945bf049d50eeaadd774e777114c6507eb6df58a",
579
+ "shasum": ""
580
+ },
581
+ "require": {
582
+ "league/url": "^3.3",
583
+ "php": ">=5.6.0"
584
+ },
585
+ "require-dev": {
586
+ "henrikbjorn/phpspec-code-coverage": "^1.0",
587
+ "phpspec/phpspec": "^2.2"
588
+ },
589
+ "time": "2017-04-09T08:13:03+00:00",
590
+ "type": "library",
591
+ "extra": {
592
+ "branch-alias": {
593
+ "dev-master": "1.0-dev"
594
+ }
595
+ },
596
+ "installation-source": "dist",
597
+ "autoload": {
598
+ "psr-4": {
599
+ "Spatie\\UrlSigner\\": "src"
600
+ }
601
+ },
602
+ "notification-url": "https://packagist.org/downloads/",
603
+ "license": [
604
+ "MIT"
605
+ ],
606
+ "authors": [
607
+ {
608
+ "name": "Sebastian De Deyne",
609
+ "email": "sebastian@spatie.be",
610
+ "homepage": "https://github.com/sebastiandedeyne",
611
+ "role": "Developer"
612
+ }
613
+ ],
614
+ "description": "Generate a url with an expiration date and signature to prevent unauthorized access",
615
+ "homepage": "https://github.com/spatie/url-signer",
616
+ "keywords": [
617
+ "encryption",
618
+ "security",
619
+ "sign",
620
+ "spatie",
621
+ "url"
622
+ ]
623
+ },
624
+ {
625
+ "name": "symfony/polyfill-mbstring",
626
+ "version": "v1.10.0",
627
+ "version_normalized": "1.10.0.0",
628
+ "source": {
629
+ "type": "git",
630
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
631
+ "reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
632
+ },
633
+ "dist": {
634
+ "type": "zip",
635
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
636
+ "reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
637
+ "shasum": ""
638
+ },
639
+ "require": {
640
+ "php": ">=5.3.3"
641
+ },
642
+ "suggest": {
643
+ "ext-mbstring": "For best performance"
644
+ },
645
+ "time": "2018-09-21T13:07:52+00:00",
646
+ "type": "library",
647
+ "extra": {
648
+ "branch-alias": {
649
+ "dev-master": "1.9-dev"
650
+ }
651
+ },
652
+ "installation-source": "dist",
653
+ "autoload": {
654
+ "psr-4": {
655
+ "Symfony\\Polyfill\\Mbstring\\": ""
656
+ },
657
+ "files": [
658
+ "bootstrap.php"
659
+ ]
660
+ },
661
+ "notification-url": "https://packagist.org/downloads/",
662
+ "license": [
663
+ "MIT"
664
+ ],
665
+ "authors": [
666
+ {
667
+ "name": "Nicolas Grekas",
668
+ "email": "p@tchwork.com"
669
+ },
670
+ {
671
+ "name": "Symfony Community",
672
+ "homepage": "https://symfony.com/contributors"
673
+ }
674
+ ],
675
+ "description": "Symfony polyfill for the Mbstring extension",
676
+ "homepage": "https://symfony.com",
677
+ "keywords": [
678
+ "compatibility",
679
+ "mbstring",
680
+ "polyfill",
681
+ "portable",
682
+ "shim"
683
+ ]
684
+ },
685
+ {
686
+ "name": "true/punycode",
687
+ "version": "v2.1.1",
688
+ "version_normalized": "2.1.1.0",
689
+ "source": {
690
+ "type": "git",
691
+ "url": "https://github.com/true/php-punycode.git",
692
+ "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e"
693
+ },
694
+ "dist": {
695
+ "type": "zip",
696
+ "url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
697
+ "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
698
+ "shasum": ""
699
+ },
700
+ "require": {
701
+ "php": ">=5.3.0",
702
+ "symfony/polyfill-mbstring": "^1.3"
703
+ },
704
+ "require-dev": {
705
+ "phpunit/phpunit": "~4.7",
706
+ "squizlabs/php_codesniffer": "~2.0"
707
+ },
708
+ "time": "2016-11-16T10:37:54+00:00",
709
+ "type": "library",
710
+ "installation-source": "dist",
711
+ "autoload": {
712
+ "psr-4": {
713
+ "TrueBV\\": "src/"
714
+ }
715
+ },
716
+ "notification-url": "https://packagist.org/downloads/",
717
+ "license": [
718
+ "MIT"
719
+ ],
720
+ "authors": [
721
+ {
722
+ "name": "Renan Gonçalves",
723
+ "email": "renan.saddam@gmail.com"
724
+ }
725
+ ],
726
+ "description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)",
727
+ "homepage": "https://github.com/true/php-punycode",
728
+ "keywords": [
729
+ "idna",
730
+ "punycode"
731
+ ]
732
  }
733
  ]
vendor/league/url/CHANGELOG.md ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #Changelog
2
+
3
+ All Notable changes to `League\Url` will be documented in this file
4
+
5
+ ## 3.3.5 - 2015-07-15
6
+
7
+ ### Fixed
8
+ - Bug fix path get relative [pull request #81](https://github.com/thephpleague/url/pull/81)
9
+
10
+ ## 3.3.4 - 2015-07-01
11
+
12
+ ### Fixed
13
+ - Bug fix Query parsing [pull request #79](https://github.com/thephpleague/url/pull/79)
14
+
15
+ ## 3.3.3 - 2015-06-25
16
+
17
+ ### Fixed
18
+ - Update `True\Punycode` requirement to 2.0.0 to allow PHP7 support
19
+
20
+ ## 3.3.2 - 2015-05-13
21
+
22
+ ### Fixed
23
+
24
+ - Bug fix URL parsing [issue #65](https://github.com/thephpleague/url/issues/58)
25
+
26
+ ## 3.3.1 - 2015-03-26
27
+
28
+ ### Fixed
29
+ - `League\Url\Components\Query` bug fix [issue #58](https://github.com/thephpleague/url/issues/58), improved bug fix [issue #31](https://github.com/thephpleague/url/issues/31)
30
+
31
+ ## 3.3.0 - 2015-03-20
32
+
33
+ ### Added
34
+ - adding the `toArray` method to `League\Url\AbstractUrl` to output the URL like PHP native `parse_url` [issue #56](https://github.com/thephpleague/url/issues/56)
35
+
36
+ ### Fixed
37
+ - `League\Url\Components\Query` bug fix remove parameter only if the value equals `null` [issue #58](https://github.com/thephpleague/url/issues/58)
38
+
39
+ ## 3.2.1 - 2014-11-27
40
+
41
+ ### Added
42
+ - Nothing
43
+
44
+ ### Deprecated
45
+ - Nothing
46
+
47
+ ### Fixed
48
+ - `League\Url\AbstractUrl\createFromServer` bug fix handling of `$_SERVER['HTTP_HOST']`
49
+
50
+ ### Remove
51
+ - Nothing
52
+
53
+ ### Security
54
+ - Nothing
55
+
56
+ ## 3.2.0 - 2014-11-12
57
+
58
+ ### Added
59
+ - adding the following methods to `League\Url\AbstractUrl`
60
+ - `getUserInfo`
61
+ - `getAuthority`
62
+ - `sameValueAs`
63
+
64
+ ### Deprecated
65
+ - Nothing
66
+
67
+ ### Fixed
68
+ - `League\Url\Components\Fragment::__toString` encoding symbols according to [RFC3986](http://tools.ietf.org/html/rfc3986#section-3.5)
69
+
70
+ ### Remove
71
+ - Nothing
72
+
73
+ ### Security
74
+ - Nothing
75
+
76
+ ## 3.1.1 - 2014-09-02
77
+
78
+ ### Added
79
+ - Nothing
80
+
81
+ ### Deprecated
82
+ - Nothing
83
+
84
+ ### Fixed
85
+ - `parse_str` does not preserve key params
86
+
87
+ ### Remove
88
+ - Nothing
89
+
90
+ ### Security
91
+ - Nothing
92
+
93
+ ## 3.1.0 - 2014-07-10
94
+
95
+ ### Added
96
+ - Adding IDN support using `True\Punycode` package
97
+ - The library now **requires** the `mbstring` extension to work.
98
+
99
+ The following methods were added:
100
+
101
+ - `League\Url\Components\Host::toAscii`
102
+ - `League\Url\Components\Host::toUnicode` as an alias of `League\Url\Components\Host::__toString`
103
+
104
+ ### Deprecated
105
+ - Nothing
106
+
107
+ ### Fixed
108
+ - invalid URI parsing
109
+
110
+ ### Remove
111
+ - Nothing
112
+
113
+ ### Security
114
+ - Nothing
115
+
116
+ ## 3.0.1 - 2014-06-31
117
+
118
+ ### Added
119
+ - Nothing
120
+
121
+ ### Deprecated
122
+ - Nothing
123
+
124
+ ### Fixed
125
+ - invalid URI parsing
126
+
127
+ ### Remove
128
+ - Nothing
129
+
130
+ ### Security
131
+ - Nothing
132
+
133
+ ## 3.0 - 2014-06-25
134
+
135
+ New Release, complete rewrite from `Bakame\Url`
vendor/league/url/CONTRIBUTING.md ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing
2
+
3
+ Contributions are **welcome** and will be fully **credited**.
4
+
5
+ We accept contributions via Pull Requests on [Github](https://github.com/nyamsprod/League.url).
6
+
7
+
8
+ ## Pull Requests
9
+
10
+ - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
11
+
12
+ - **Add tests!** - Your patch won't be accepted if it doesn't have tests.
13
+
14
+ - **Document any change in behaviour** - Make sure the README and any other relevant documentation are kept up-to-date.
15
+
16
+ - **Consider our release cycle** - We try to follow semver. Randomly breaking public APIs is not an option.
17
+
18
+ - **Create topic branches** - Don't ask us to pull from your master branch.
19
+
20
+ - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
21
+
22
+ - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
23
+
24
+
25
+ ## Running Tests
26
+
27
+ ``` bash
28
+ $ phpunit
29
+ ```
30
+
31
+
32
+ **Happy coding**!
vendor/league/url/LICENSE ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013-2014 ignace nyamagana butera
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
vendor/league/url/README.md ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Url
2
+
3
+ [![Build Status](https://img.shields.io/travis/thephpleague/url/3.x.svg?style=flat-square)](https://travis-ci.org/thephpleague/url)
4
+ [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/url/3.x.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/url/?branch=3.x)
5
+ [![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/url/3.x.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/url/?branch=3.x)
6
+ [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
7
+ [![Latest Version](https://img.shields.io/github/release/thephpleague/url.svg?style=flat-square)](https://github.com/thephpleague/url/releases)
8
+ [![Total Downloads](https://img.shields.io/packagist/dt/league/url.svg?style=flat-square)](https://packagist.org/packages/league/url)
9
+
10
+ Url is a simple library to ease creating and managing Urls in PHP.
11
+
12
+ This package is compliant with [PSR-2][], and [PSR-4][].
13
+
14
+ [PSR-4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md
15
+ [PSR-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
16
+
17
+ Requirements
18
+ -------
19
+
20
+ You need **PHP >= 5.3.0** and the `mbstring` extension to use the library, but the latest stable version of PHP is recommended.
21
+
22
+ Install
23
+ -------
24
+
25
+ Install `Url` using Composer.
26
+
27
+ ```
28
+ composer require league/url:~3.0
29
+ ```
30
+
31
+ This will edit (or create) your `composer.json` file and automatically choose the most recent version in the 3.x serie.
32
+
33
+ #### Going Solo
34
+
35
+ You can also use `League\Url` without using Composer by [downloading the library](https://github.com/thephpleague/url/releases) and using a [PSR-4](http://www.php-fig.org/psr/psr-4/) compatible autoloader.
36
+
37
+ Documentation
38
+ -------
39
+
40
+ `League\Url` is [fully documented](http://url.thephpleague.com). Contribute to this documentation in the [gh-pages branch](https://github.com/thephpleague/url/tree/gh-pages).
41
+
42
+ Testing
43
+ -------
44
+
45
+ ``` bash
46
+ $ phpunit
47
+ ```
48
+
49
+ Contributing
50
+ -------
51
+
52
+ Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
53
+
54
+ Credits
55
+ -------
56
+
57
+ - [ignace nyamagana butera](https://github.com/nyamsprod)
58
+ - [All Contributors](graphs/contributors)
59
+
60
+ License
61
+ -------
62
+
63
+ The MIT License (MIT). Please see [License File](LICENSE) for more information.
vendor/league/url/composer.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "league/url",
3
+ "type": "library",
4
+ "description" : "League/url is a lightweight PHP Url manipulating library",
5
+ "keywords": ["php", "url", "parse_url"],
6
+ "license": "MIT",
7
+ "homepage" : "http://url.thephpleague.com",
8
+ "authors": [
9
+ {
10
+ "name" : "Ignace Nyamagana Butera",
11
+ "email" : "nyamsprod@gmail.com",
12
+ "homepage" : "https://github.com/nyamsprod/",
13
+ "role" : "Developer"
14
+ }
15
+ ],
16
+ "support": {
17
+ "forum": "https://groups.google.com/forum/#!forum/thephpleague",
18
+ "issues": "https://github.com/thephpleague/url/issues"
19
+ },
20
+ "require": {
21
+ "php" : ">=5.3.0",
22
+ "ext-mbstring" : "*",
23
+ "true/punycode": "^2.0"
24
+ },
25
+ "require-dev": {
26
+ "phpunit/phpunit" : "^4.0"
27
+ },
28
+ "autoload": {
29
+ "psr-4": {
30
+ "League\\Url\\": "src"
31
+ }
32
+ },
33
+ "autoload-dev": {
34
+ "psr-4": {
35
+ "League\\Url\\Test\\": "tests"
36
+ }
37
+ },
38
+ "extra": {
39
+ "branch-alias": {
40
+ "dev-master": "3.3-dev"
41
+ }
42
+ }
43
+ }
vendor/league/url/src/AbstractUrl.php ADDED
@@ -0,0 +1,466 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url;
14
+
15
+ use RuntimeException;
16
+
17
+ /**
18
+ * A Factory to ease League\Url\Url Object instantiation
19
+ *
20
+ * @package League.url
21
+ * @since 3.0.0
22
+ */
23
+ abstract class AbstractUrl implements UrlInterface
24
+ {
25
+ /**
26
+ * Scheme
27
+ *
28
+ * @var Components\Scheme
29
+ */
30
+ protected $scheme;
31
+
32
+ /**
33
+ * User
34
+ *
35
+ * @var Components\User
36
+ */
37
+ protected $user;
38
+
39
+ /**
40
+ * Pass
41
+ *
42
+ * @var Components\Pass
43
+ */
44
+ protected $pass;
45
+
46
+ /**
47
+ * Host
48
+ *
49
+ * @var Components\Host
50
+ */
51
+ protected $host;
52
+
53
+ /**
54
+ * Port
55
+ *
56
+ *@var Components\Port
57
+ */
58
+ protected $port;
59
+
60
+ /**
61
+ * Path
62
+ *
63
+ * @var Components\Path
64
+ */
65
+ protected $path;
66
+
67
+ /**
68
+ * Query
69
+ *
70
+ * @var Components\Query
71
+ */
72
+ protected $query;
73
+
74
+ /**
75
+ * Fragment
76
+ *
77
+ * @var Components\Fragment
78
+ */
79
+ protected $fragment;
80
+
81
+ /**
82
+ * Tell whether PHP native parse_url is buggy
83
+ *
84
+ * @var bool
85
+ */
86
+ protected static $is_parse_url_bugged;
87
+
88
+ /**
89
+ * {@inheritdoc}
90
+ */
91
+ public function __toString()
92
+ {
93
+ $url = $this->getBaseUrl().$this->getRelativeUrl();
94
+ if ('/' == $url) {
95
+ return '';
96
+ }
97
+
98
+ return $url;
99
+ }
100
+
101
+ /**
102
+ * {@inheritdoc}
103
+ */
104
+ public function getRelativeUrl(UrlInterface $ref_url = null)
105
+ {
106
+ if (is_null($ref_url)) {
107
+ return $this->path->getUriComponent()
108
+ .$this->query->getUriComponent()
109
+ .$this->fragment->getUriComponent();
110
+ }
111
+
112
+ if ($this->getBaseUrl() != $ref_url->getBaseUrl()) {
113
+ return $this->__toString();
114
+ }
115
+
116
+ return $this->path->getRelativePath($ref_url->getPath())
117
+ .$this->query->getUriComponent()
118
+ .$this->fragment->getUriComponent();
119
+ }
120
+
121
+ /**
122
+ * {@inheritdoc}
123
+ */
124
+ public function getUserInfo()
125
+ {
126
+ $user = $this->user->getUriComponent().$this->pass->getUriComponent();
127
+ if ('' != $user) {
128
+ $user .= '@';
129
+ }
130
+
131
+ return $user;
132
+ }
133
+
134
+ /**
135
+ * {@inheritdoc}
136
+ */
137
+ public function getAuthority()
138
+ {
139
+ $user = $this->getUserInfo();
140
+ $host = $this->host->getUriComponent();
141
+ $port = $this->port->getUriComponent();
142
+
143
+ return $user.$host.$port;
144
+ }
145
+
146
+ /**
147
+ * {@inheritdoc}
148
+ */
149
+ public function getBaseUrl()
150
+ {
151
+ $scheme = $this->scheme->getUriComponent();
152
+ $auth = $this->getAuthority();
153
+ if ('' != $auth && '' == $scheme) {
154
+ $scheme = '//';
155
+ }
156
+
157
+ return $scheme.$auth;
158
+ }
159
+
160
+ /**
161
+ * {@inheritdoc}
162
+ */
163
+ public function sameValueAs(UrlInterface $url)
164
+ {
165
+ return $this->__toString() == $url->__toString();
166
+ }
167
+
168
+ /**
169
+ * Retuns a array representation like parse_url
170
+ * But includes all components
171
+ *
172
+ * @return array
173
+ */
174
+ public function toArray()
175
+ {
176
+ return array(
177
+ 'scheme' => $this->scheme->get(),
178
+ 'user' => $this->user->get(),
179
+ 'pass' => $this->pass->get(),
180
+ 'host' => $this->host->get(),
181
+ 'port' => $this->port->get(),
182
+ 'path' => $this->path->get(),
183
+ 'query' => $this->query->get(),
184
+ 'fragment' => $this->fragment->get(),
185
+ );
186
+ }
187
+
188
+ /**
189
+ * Return a instance of Url from a string
190
+ *
191
+ * @param string $url a string or an object that implement the __toString method
192
+ *
193
+ * @return static
194
+ *
195
+ * @throws RuntimeException If the URL can not be parse
196
+ */
197
+ public static function createFromUrl($url)
198
+ {
199
+ $url = (string) $url;
200
+ $url = trim($url);
201
+ $original_url = $url;
202
+ $url = self::sanitizeUrl($url);
203
+
204
+ //if no valid scheme is found we add one
205
+ if (is_null($url)) {
206
+ throw new RuntimeException(sprintf('The given URL: `%s` could not be parse', $original_url));
207
+ }
208
+
209
+ $components = array_merge(array(
210
+ 'scheme' => null,
211
+ 'user' => null,
212
+ 'pass' => null,
213
+ 'host' => null,
214
+ 'port' => null,
215
+ 'path' => null,
216
+ 'query' => null,
217
+ 'fragment' => null,
218
+ ), self::parseUrl($url));
219
+ $components = self::formatAuthComponent($components);
220
+ $components = self::formatPathComponent($components, $original_url);
221
+
222
+ return new static(
223
+ new Components\Scheme($components['scheme']),
224
+ new Components\User($components['user']),
225
+ new Components\Pass($components['pass']),
226
+ new Components\Host($components['host']),
227
+ new Components\Port($components['port']),
228
+ new Components\Path($components['path']),
229
+ new Components\Query($components['query']),
230
+ new Components\Fragment($components['fragment'])
231
+ );
232
+ }
233
+
234
+ /**
235
+ * Parse a string as an URL
236
+ *
237
+ * @param string $url The URL to parse
238
+ *
239
+ * @throws InvalidArgumentException if the URL can not be parsed
240
+ *
241
+ * @return array
242
+ */
243
+ protected static function parseUrl($url)
244
+ {
245
+ $components = @parse_url($url);
246
+ if (! empty($components)) {
247
+ return $components;
248
+ }
249
+
250
+ if (is_null(static::$is_parse_url_bugged)) {
251
+ static::$is_parse_url_bugged = ! is_array(@parse_url("//example.org:80"));
252
+ }
253
+
254
+ //bugfix for https://bugs.php.net/bug.php?id=68917
255
+ if (static::$is_parse_url_bugged &&
256
+ strpos($url, '/') === 0 &&
257
+ is_array($components = @parse_url('http:'.$url))
258
+ ) {
259
+ unset($components['scheme']);
260
+ return $components;
261
+ }
262
+ throw new RuntimeException(sprintf("The given URL: `%s` could not be parse", $url));
263
+ }
264
+
265
+ protected static function sanitizeUrl($url)
266
+ {
267
+ if ('' == $url || strpos($url, '//') === 0) {
268
+ return $url;
269
+ }
270
+
271
+ if (! preg_match(',^((http|ftp|ws)s?:),i', $url, $matches)) {
272
+ return '//'.$url;
273
+ }
274
+
275
+ $scheme_length = strlen($matches[0]);
276
+ if (strpos(substr($url, $scheme_length), '//') === 0) {
277
+ return $url;
278
+ }
279
+
280
+ return null;
281
+ }
282
+
283
+ /**
284
+ * Return a instance of Url from a server array
285
+ *
286
+ * @param array $server the server array
287
+ *
288
+ * @return static
289
+ *
290
+ * @throws RuntimeException If the URL can not be parse
291
+ */
292
+ public static function createFromServer(array $server)
293
+ {
294
+ $scheme = self::fetchServerScheme($server);
295
+ $host = self::fetchServerHost($server);
296
+ $port = self::fetchServerPort($server);
297
+ $request = self::fetchServerRequestUri($server);
298
+
299
+ return self::createFromUrl($scheme.$host.$port.$request);
300
+ }
301
+
302
+ /**
303
+ * Return the Server URL scheme component
304
+ *
305
+ * @param array $server the server array
306
+ *
307
+ * @return string
308
+ */
309
+ protected static function fetchServerScheme(array $server)
310
+ {
311
+ $scheme = '';
312
+ if (isset($server['SERVER_PROTOCOL'])) {
313
+ $scheme = explode('/', $server['SERVER_PROTOCOL']);
314
+ $scheme = strtolower($scheme[0]);
315
+ if (isset($server['HTTPS']) && 'off' != $server['HTTPS']) {
316
+ $scheme .= 's';
317
+ }
318
+ $scheme .= ':';
319
+ }
320
+
321
+ return $scheme.'//';
322
+ }
323
+
324
+ /**
325
+ * Return the Server URL host component
326
+ *
327
+ * @param array $server the server array
328
+ *
329
+ * @return string
330
+ *
331
+ * @throws \RuntimeException If no host is detected
332
+ */
333
+ protected static function fetchServerHost(array $server)
334
+ {
335
+ if (isset($server['HTTP_HOST'])) {
336
+ $header = $server['HTTP_HOST'];
337
+ if (! preg_match('/(:\d+)$/', $header, $matches)) {
338
+ return $header;
339
+ }
340
+
341
+ return substr($header, 0, -strlen($matches[1]));
342
+ }
343
+
344
+ if (isset($server['SERVER_ADDR'])) {
345
+ return $server['SERVER_ADDR'];
346
+ }
347
+
348
+ throw new RuntimeException('Host could not be detected');
349
+ }
350
+
351
+ /**
352
+ * Return the Server URL port component
353
+ *
354
+ * @param array $server the server array
355
+ *
356
+ * @return string
357
+ */
358
+ protected static function fetchServerPort(array $server)
359
+ {
360
+ $port = '';
361
+ if (isset($server['SERVER_PORT']) && '80' != $server['SERVER_PORT']) {
362
+ $port = ':'. (int) $server['SERVER_PORT'];
363
+ }
364
+
365
+ return $port;
366
+ }
367
+
368
+ /**
369
+ * Return the Server URL Request Uri component
370
+ *
371
+ * @param array $server the server array
372
+ *
373
+ * @return string
374
+ */
375
+ protected static function fetchServerRequestUri(array $server)
376
+ {
377
+ if (isset($server['REQUEST_URI'])) {
378
+ return $server['REQUEST_URI'];
379
+ }
380
+
381
+ if (isset($server['PHP_SELF'])) {
382
+ return $server['PHP_SELF'];
383
+ }
384
+
385
+ return '/';
386
+ }
387
+
388
+ /**
389
+ * Reformat the component according to the auth content
390
+ *
391
+ * @param array $components the result from parse_url
392
+ *
393
+ * @return array
394
+ */
395
+ protected static function formatAuthComponent(array $components)
396
+ {
397
+ if (!is_null($components['scheme'])
398
+ && is_null($components['host'])
399
+ && !empty($components['path'])
400
+ && strpos($components['path'], '@') !== false
401
+ ) {
402
+ $tmp = explode('@', $components['path'], 2);
403
+ $components['user'] = $components['scheme'];
404
+ $components['pass'] = $tmp[0];
405
+ $components['path'] = $tmp[1];
406
+ $components['scheme'] = null;
407
+ }
408
+
409
+ return $components;
410
+ }
411
+
412
+ /**
413
+ * Reformat the component according to the host content
414
+ *
415
+ * @param array $components the result from parse_url
416
+ *
417
+ * @return array
418
+ */
419
+ protected static function formatHostComponent(array $components)
420
+ {
421
+ if (strpos($components['host'], '@')) {
422
+ list($auth, $components['host']) = explode('@', $components['host']);
423
+ $components['user'] = $auth;
424
+ $components['pass'] = null;
425
+ if (false !== strpos($auth, ':')) {
426
+ list($components['user'], $components['pass']) = explode(':', $auth);
427
+ }
428
+ }
429
+
430
+ return $components;
431
+ }
432
+
433
+ /**
434
+ * Reformat the component according to the path content
435
+ *
436
+ * @param array $components the result from parse_url
437
+ * @param string $url the original URL to be parse
438
+ *
439
+ * @return array
440
+ */
441
+ protected static function formatPathComponent(array $components, $url)
442
+ {
443
+ if (is_null($components['scheme'])
444
+ && is_null($components['host'])
445
+ && !empty($components['path'])
446
+ ) {
447
+ if (0 === strpos($components['path'], '///')) {
448
+ //even with the added scheme the URL is still broken
449
+ throw new RuntimeException(sprintf('The given URL: `%s` could not be parse', $url));
450
+ }
451
+
452
+ if (0 === strpos($components['path'], '//')) {
453
+ $tmp = substr($components['path'], 2);
454
+ $components['path'] = null;
455
+ $res = explode('/', $tmp, 2);
456
+ $components['host'] = $res[0];
457
+ if (isset($res[1])) {
458
+ $components['path'] = $res[1];
459
+ }
460
+ $components = self::formatHostComponent($components);
461
+ }
462
+ }
463
+
464
+ return $components;
465
+ }
466
+ }
vendor/league/url/src/Components/AbstractArray.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ use ArrayIterator;
16
+ use Closure;
17
+ use Countable;
18
+ use IteratorAggregate;
19
+ use RuntimeException;
20
+ use Traversable;
21
+
22
+ /**
23
+ * A class to manipulate URL Array like components
24
+ *
25
+ * @package League.url
26
+ * @since 3.0.0
27
+ */
28
+ abstract class AbstractArray implements IteratorAggregate, Countable
29
+ {
30
+ /**
31
+ * container holder
32
+ *
33
+ * @var array
34
+ */
35
+ protected $data = array();
36
+
37
+ /**
38
+ * {@inheritdoc}
39
+ */
40
+ public function toArray()
41
+ {
42
+ return $this->data;
43
+ }
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function keys()
49
+ {
50
+ $args = func_get_args();
51
+ if (! $args) {
52
+ return array_keys($this->data);
53
+ }
54
+
55
+ return array_keys($this->data, $args[0], true);
56
+ }
57
+
58
+ /**
59
+ * IteratorAggregate Interface method
60
+ *
61
+ * @return ArrayIterator
62
+ */
63
+ public function getIterator()
64
+ {
65
+ return new ArrayIterator($this->data);
66
+ }
67
+
68
+ /**
69
+ * Countable Interface method
70
+ *
71
+ * @param int $mode
72
+ *
73
+ * @return integer
74
+ */
75
+ public function count($mode = COUNT_NORMAL)
76
+ {
77
+ return count($this->data, $mode);
78
+ }
79
+
80
+ /**
81
+ * ArrayAccess Interface method
82
+ *
83
+ * @param int|string $offset
84
+ *
85
+ * @return bool
86
+ */
87
+ public function offsetExists($offset)
88
+ {
89
+ return isset($this->data[$offset]);
90
+ }
91
+
92
+ /**
93
+ * ArrayAccess Interface method
94
+ *
95
+ * @param int|string $offset
96
+ */
97
+ public function offsetUnset($offset)
98
+ {
99
+ unset($this->data[$offset]);
100
+ }
101
+
102
+ /**
103
+ * ArrayAccess Interface method
104
+ *
105
+ * @param int|string $offset
106
+ *
107
+ * @return null
108
+ */
109
+ public function offsetGet($offset)
110
+ {
111
+ if (isset($this->data[$offset])) {
112
+ return $this->data[$offset];
113
+ }
114
+
115
+ return null;
116
+ }
117
+
118
+ public static function isStringable($data)
119
+ {
120
+ return is_string($data) || (is_object($data)) && (method_exists($data, '__toString'));
121
+ }
122
+
123
+ /**
124
+ * convert a given data into an array
125
+ *
126
+ * @param mixed $data the data to insert
127
+ * @param \Closure $callback a callable function to be called to parse
128
+ * a given string into the corresponding component
129
+ *
130
+ * @return array
131
+ *
132
+ * @throws \RuntimeException if the data is not valid
133
+ */
134
+ protected function convertToArray($data, Closure $callback)
135
+ {
136
+ if (is_null($data)) {
137
+ return array();
138
+ }
139
+
140
+ if ($data instanceof Traversable) {
141
+ return iterator_to_array($data);
142
+ }
143
+
144
+ if (self::isStringable($data)) {
145
+ $data = (string) $data;
146
+ $data = trim($data);
147
+ $data = $callback($data);
148
+ }
149
+
150
+ if (! is_array($data)) {
151
+ throw new RuntimeException('Your submitted data could not be converted into a proper array');
152
+ }
153
+
154
+ return $data;
155
+ }
156
+ }
vendor/league/url/src/Components/AbstractComponent.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ use InvalidArgumentException;
16
+
17
+ /**
18
+ * A class to manipulate URL string-like component
19
+ *
20
+ * @package League.url
21
+ * @since 3.0.0
22
+ */
23
+ abstract class AbstractComponent implements ComponentInterface
24
+ {
25
+ /**
26
+ * The component data
27
+ *
28
+ * @var string|null
29
+ */
30
+ protected $data;
31
+
32
+ /**
33
+ * The Constructor
34
+ *
35
+ * @param mixed $data the component data
36
+ */
37
+ public function __construct($data = null)
38
+ {
39
+ $this->set($data);
40
+ }
41
+
42
+ /**
43
+ * {@inheritdoc}
44
+ */
45
+ public function set($data)
46
+ {
47
+ $this->data = $this->validate($data);
48
+ }
49
+
50
+ /**
51
+ * {@inheritdoc}
52
+ */
53
+ public function get()
54
+ {
55
+ if (is_null($this->data) || ! $this->data) {
56
+ return null;
57
+ }
58
+
59
+ return $this->data;
60
+ }
61
+
62
+ /**
63
+ * {@inheritdoc}
64
+ */
65
+ public function __toString()
66
+ {
67
+ return str_replace(null, '', $this->get());
68
+ }
69
+
70
+ /**
71
+ * {@inheritdoc}
72
+ */
73
+ public function getUriComponent()
74
+ {
75
+ return $this->__toString();
76
+ }
77
+
78
+ /**
79
+ * Validate a component
80
+ *
81
+ * @param mixed $data the component value to be validate
82
+ *
83
+ * @return string|null
84
+ *
85
+ * @throws InvalidArgumentException If The data is invalid
86
+ */
87
+ protected function validate($data)
88
+ {
89
+ return $this->sanitizeComponent($data);
90
+ }
91
+
92
+ /**
93
+ * Sanitize a string component
94
+ *
95
+ * @param mixed $str
96
+ *
97
+ * @return string|null
98
+ */
99
+ protected function sanitizeComponent($str)
100
+ {
101
+ if (is_null($str)) {
102
+ return $str;
103
+ }
104
+ $str = filter_var((string) $str, FILTER_UNSAFE_RAW, array('flags' => FILTER_FLAG_STRIP_LOW));
105
+ $str = trim($str);
106
+
107
+ return $str;
108
+ }
109
+
110
+ /**
111
+ * {@inheritdoc}
112
+ */
113
+ public function sameValueAs(ComponentInterface $component)
114
+ {
115
+ return $this->__toString() == $component->__toString();
116
+ }
117
+ }
vendor/league/url/src/Components/AbstractSegment.php ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ use ArrayAccess;
16
+ use InvalidArgumentException;
17
+
18
+ /**
19
+ * A class to manipulate URL Segment like components
20
+ *
21
+ * @package League.url
22
+ * @since 3.0.0
23
+ */
24
+ abstract class AbstractSegment extends AbstractArray implements ArrayAccess
25
+ {
26
+ /**
27
+ * segment delimiter
28
+ *
29
+ * @var string
30
+ */
31
+ protected $delimiter;
32
+
33
+ /**
34
+ * The Constructor
35
+ * @param mixed $data The data to add
36
+ */
37
+ public function __construct($data = null)
38
+ {
39
+ $this->set($data);
40
+ }
41
+
42
+ /**
43
+ * {@inheritdoc}
44
+ */
45
+ public function set($data)
46
+ {
47
+ $this->data = array_filter($this->validate($data), function ($value) {
48
+ return ! is_null($value);
49
+ });
50
+ }
51
+
52
+ /**
53
+ * {@inheritdoc}
54
+ */
55
+ public function __toString()
56
+ {
57
+ return (string) $this->get();
58
+ }
59
+
60
+ /**
61
+ * {@inheritdoc}
62
+ */
63
+ public function getUriComponent()
64
+ {
65
+ return $this->__toString();
66
+ }
67
+
68
+ /**
69
+ * {@inheritdoc}
70
+ * @param string|array|\Traversable $data the data
71
+ */
72
+ public function remove($data)
73
+ {
74
+ $data = $this->fetchRemainingSegment($this->data, $data);
75
+ if (! is_null($data)) {
76
+ $this->set($data);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * {@inheritdoc}
82
+ */
83
+ public function sameValueAs(ComponentInterface $component)
84
+ {
85
+ return $this->__toString() == $component->__toString();
86
+ }
87
+
88
+ /**
89
+ * Sanitize a string component recursively
90
+ *
91
+ * @param mixed $str
92
+ *
93
+ * @return mixed
94
+ */
95
+ protected function sanitizeValue($str)
96
+ {
97
+ if (is_array($str)) {
98
+ foreach ($str as &$value) {
99
+ $value = $this->sanitizeValue($value);
100
+ }
101
+ unset($value);
102
+
103
+ return $str;
104
+ }
105
+
106
+ $str = filter_var((string) $str, FILTER_UNSAFE_RAW, array('flags' => FILTER_FLAG_STRIP_LOW));
107
+ $str = trim($str);
108
+
109
+ return $str;
110
+ }
111
+
112
+ /**
113
+ * ArrayAccess Interface method
114
+ *
115
+ * @param int|string $offset
116
+ * @param mixed $value
117
+ */
118
+ public function offsetSet($offset, $value)
119
+ {
120
+ $data = $this->data;
121
+ if (is_null($offset)) {
122
+ $data[] = $value;
123
+ $this->set($data);
124
+
125
+ return;
126
+ }
127
+ $offset = filter_var($offset, FILTER_VALIDATE_INT, array('min_range' => 0));
128
+ if (false === $offset) {
129
+ throw new InvalidArgumentException('Offset must be an integer');
130
+ }
131
+ $data[$offset] = $value;
132
+ $this->set($data);
133
+ }
134
+
135
+ /**
136
+ * Validate a component
137
+ *
138
+ * @param mixed $data the component value to be validate
139
+ *
140
+ * @return array
141
+ *
142
+ * @throws \InvalidArgumentException If The data is invalid
143
+ */
144
+ abstract protected function validate($data);
145
+
146
+ /**
147
+ * {@inheritdoc}
148
+ * @param string|array|\Traversable $data
149
+ * @param string $whence
150
+ * @param integer $whence_index
151
+ */
152
+ public function append($data, $whence = null, $whence_index = null)
153
+ {
154
+ $this->data = $this->appendSegment(
155
+ $this->data,
156
+ $this->validate($data),
157
+ $whence,
158
+ $whence_index
159
+ );
160
+ }
161
+
162
+ /**
163
+ * {@inheritdoc}
164
+ * @param string|array|\Traversable $data
165
+ * @param string $whence
166
+ * @param integer $whence_index
167
+ */
168
+ public function prepend($data, $whence = null, $whence_index = null)
169
+ {
170
+ $this->data = $this->prependSegment(
171
+ $this->data,
172
+ $this->validate($data),
173
+ $whence,
174
+ $whence_index
175
+ );
176
+ }
177
+
178
+ /**
179
+ * Format removing component labels
180
+ *
181
+ * @param string|array|\Traversable $data the component value to be validate
182
+ *
183
+ * @return array
184
+ */
185
+ protected function formatRemoveSegment($data)
186
+ {
187
+ return $this->sanitizeValue($this->validateSegment($data));
188
+ }
189
+
190
+ /**
191
+ * Validate data before insertion into a URL segment based component
192
+ *
193
+ * @param mixed $data the data to insert
194
+ *
195
+ * @return array
196
+ *
197
+ * @throws \RuntimeException if the data is not valid
198
+ */
199
+ protected function validateSegment($data)
200
+ {
201
+ $delimiter = $this->delimiter;
202
+
203
+ return $this->convertToArray($data, function ($str) use ($delimiter) {
204
+ if ('' == $str) {
205
+ return array();
206
+ }
207
+ if ($delimiter == $str[0]) {
208
+ $str = substr($str, 1);
209
+ }
210
+
211
+ return explode($delimiter, $str);
212
+ });
213
+ }
214
+
215
+ /**
216
+ * Append some data to a given array
217
+ *
218
+ * @param array $left the original array
219
+ * @param array $value the data to prepend
220
+ * @param string $whence the value of the data to prepend before
221
+ * @param integer $whence_index the occurrence index for $whence
222
+ *
223
+ * @return array
224
+ */
225
+ protected function appendSegment(array $left, array $value, $whence = null, $whence_index = null)
226
+ {
227
+ $right = array();
228
+ if (null !== $whence && count($found = array_keys($left, $whence))) {
229
+ array_reverse($found);
230
+ $index = $found[0];
231
+ if (array_key_exists($whence_index, $found)) {
232
+ $index = $found[$whence_index];
233
+ }
234
+ $right = array_slice($left, $index+1);
235
+ $left = array_slice($left, 0, $index+1);
236
+ }
237
+
238
+ return array_merge($left, $value, $right);
239
+ }
240
+
241
+ /**
242
+ * Prepend some data to a given array
243
+ *
244
+ * @param array $right the original array
245
+ * @param array $value the data to prepend
246
+ * @param string $whence the value of the data to prepend before
247
+ * @param integer $whence_index the occurrence index for $whence
248
+ *
249
+ * @return array
250
+ */
251
+ protected function prependSegment(array $right, array $value, $whence = null, $whence_index = null)
252
+ {
253
+ $left = array();
254
+ if (null !== $whence && count($found = array_keys($right, $whence))) {
255
+ $index = $found[0];
256
+ if (array_key_exists($whence_index, $found)) {
257
+ $index = $found[$whence_index];
258
+ }
259
+ $left = array_slice($right, 0, $index);
260
+ $right = array_slice($right, $index);
261
+ }
262
+
263
+ return array_merge($left, $value, $right);
264
+ }
265
+
266
+ /**
267
+ * Remove some data from a given array
268
+ *
269
+ * @param array $data the original array
270
+ * @param mixed $value the data to be removed (can be an array or a single segment)
271
+ *
272
+ * @return string|null
273
+ *
274
+ * @throws \RuntimeException If $value is invalid
275
+ */
276
+ protected function fetchRemainingSegment(array $data, $value)
277
+ {
278
+ $segment = implode($this->delimiter, $data);
279
+ if ('' == $value) {
280
+ if ($index = array_search('', $data, true)) {
281
+ $left = array_slice($data, 0, $index);
282
+ $right = array_slice($data, $index+1);
283
+
284
+ return implode($this->delimiter, array_merge($left, $right));
285
+ }
286
+
287
+ return $segment;
288
+ }
289
+
290
+ $part = implode($this->delimiter, $this->formatRemoveSegment($value));
291
+
292
+ $regexStart = '@(:?^|\\'.$this->delimiter.')';
293
+
294
+ if (! preg_match($regexStart.preg_quote($part, '@').'@', $segment, $matches, PREG_OFFSET_CAPTURE)) {
295
+ return null;
296
+ }
297
+
298
+ $pos = $matches[0][1];
299
+
300
+ return substr($segment, 0, $pos).substr($segment, $pos + strlen($part) + 1);
301
+ }
302
+ }
vendor/league/url/src/Components/ComponentArrayInterface.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A common interface for complex URL components
17
+ *
18
+ * @package League.url
19
+ * @since 3.0.0
20
+ */
21
+ interface ComponentArrayInterface extends ComponentInterface
22
+ {
23
+ /**
24
+ * Return the component as an array
25
+ *
26
+ * @return array
27
+ */
28
+ public function toArray();
29
+
30
+ /**
31
+ * Return all the keys or a subset of the keys of an array
32
+ *
33
+ * @return array
34
+ */
35
+ public function keys();
36
+ }
vendor/league/url/src/Components/ComponentInterface.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A common interface for URL components
17
+ *
18
+ * @package League.url
19
+ * @since 3.0.0
20
+ */
21
+ interface ComponentInterface
22
+ {
23
+ /**
24
+ * Set the component data
25
+ *
26
+ * @param mixed $data data to be added
27
+ *
28
+ * @return void
29
+ */
30
+ public function set($data);
31
+
32
+ /**
33
+ * Get the component data
34
+ *
35
+ * @return null|string
36
+ */
37
+ public function get();
38
+
39
+ /**
40
+ * String representation of an URL component
41
+ *
42
+ * @return string
43
+ */
44
+ public function __toString();
45
+
46
+ /**
47
+ * component representation of an URL component
48
+ *
49
+ * @return string
50
+ */
51
+ public function getUriComponent();
52
+
53
+ /**
54
+ * Compare two Url component object and tells whether they
55
+ * represent the same string value
56
+ *
57
+ * @param ComponentInterface $component
58
+ *
59
+ * @return boolean
60
+ */
61
+ public function sameValueAs(ComponentInterface $component);
62
+ }
vendor/league/url/src/Components/Fragment.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A class to manipulate URL Fragment component
17
+ *
18
+ * @package League.url
19
+ * @since 1.0.0
20
+ */
21
+ class Fragment extends AbstractComponent
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function __toString()
27
+ {
28
+ $value = parent::__toString();
29
+
30
+ // according to http://tools.ietf.org/html/rfc3986#section-3.5
31
+ $rawSymbols = array(
32
+ '/', '?', '-', '.', '_', '~', '!',
33
+ '$', '&', '\'', '(', ')', '*', '+',
34
+ ',', ';', '=', ':', '@',
35
+ );
36
+
37
+ $encodedSymbols = array_map(function ($symbol) {
38
+ return urlencode($symbol);
39
+ }, $rawSymbols);
40
+
41
+ return str_replace(
42
+ $encodedSymbols,
43
+ $rawSymbols,
44
+ rawurlencode($value)
45
+ );
46
+ }
47
+
48
+ /**
49
+ * {@inheritdoc}
50
+ */
51
+ public function getUriComponent()
52
+ {
53
+ $value = $this->__toString();
54
+ if ('' != $value) {
55
+ $value = '#'.$value;
56
+ }
57
+
58
+ return $value;
59
+ }
60
+ }
vendor/league/url/src/Components/Host.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ use RuntimeException;
16
+ use TrueBV\Punycode;
17
+
18
+ /**
19
+ * A class to manipulate URL Host component
20
+ *
21
+ * @package League.url
22
+ * @since 1.0.0
23
+ */
24
+ class Host extends AbstractSegment implements HostInterface
25
+ {
26
+ /**
27
+ * {@inheritdoc}
28
+ */
29
+ protected $delimiter = '.';
30
+
31
+ /**
32
+ * Punycode Algorithm Object
33
+ * @var Punycode
34
+ */
35
+ protected $punycode;
36
+
37
+ /**
38
+ * Environment Internal encoding
39
+ * @var mixed
40
+ */
41
+ protected $encoding;
42
+
43
+ /**
44
+ * Alter the Environment Internal Encoding if it is not utf-8
45
+ *
46
+ * @return void
47
+ */
48
+ protected function saveInternalEncoding()
49
+ {
50
+ $this->encoding = mb_internal_encoding();
51
+ if (stripos($this->encoding, 'utf-8') === false) {
52
+ mb_internal_encoding('UTF-8');
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Restore the Environment Internal Encoding
58
+ *
59
+ * @return void
60
+ */
61
+ protected function restoreInternalEncoding()
62
+ {
63
+ mb_internal_encoding($this->encoding);
64
+ }
65
+
66
+ /**
67
+ * {@inheritdoc}
68
+ */
69
+ public function __construct($data = null)
70
+ {
71
+ $this->punycode = new Punycode('UTF-8');
72
+ parent::__construct($data);
73
+ }
74
+
75
+ /**
76
+ * {@inheritdoc}
77
+ */
78
+ public function get()
79
+ {
80
+ $res = array();
81
+ foreach (array_values($this->data) as $value) {
82
+ $res[] = $this->punycode->decode($value);
83
+ }
84
+ if (! $res) {
85
+ return null;
86
+ }
87
+
88
+ return implode($this->delimiter, $res);
89
+ }
90
+
91
+ /**
92
+ * {@inheritdoc}
93
+ */
94
+ public function toAscii()
95
+ {
96
+ $this->saveInternalEncoding();
97
+ $res = $this->punycode->encode($this->__toString());
98
+ $this->restoreInternalEncoding();
99
+
100
+ return $res;
101
+ }
102
+
103
+ /**
104
+ * {@inheritdoc}
105
+ */
106
+ public function toUnicode()
107
+ {
108
+ return $this->__toString();
109
+ }
110
+
111
+ protected function isValidHostLength(array $data)
112
+ {
113
+ $res = array_filter($data, function ($label) {
114
+ return mb_strlen($label) > 63;
115
+ });
116
+
117
+ return 0 == count($res);
118
+ }
119
+
120
+ protected function isValidHostPattern(array $data)
121
+ {
122
+ $data = explode(
123
+ $this->delimiter,
124
+ $this->punycode->encode(implode($this->delimiter, $data))
125
+ );
126
+
127
+ $res = preg_grep('/^[0-9a-z]([0-9a-z-]{0,61}[0-9a-z])?$/i', $data, PREG_GREP_INVERT);
128
+
129
+ return 0 == count($res);
130
+ }
131
+
132
+ protected function isValidHostLabels(array $data = array())
133
+ {
134
+ $labels = array_merge($this->data, $data);
135
+ $count_labels = count($labels);
136
+
137
+ return $count_labels > 0 && $count_labels < 127 && 255 > strlen(implode($this->delimiter, $labels));
138
+ }
139
+
140
+ /**
141
+ * Validate Host data before insertion into a URL host component
142
+ *
143
+ * @param mixed $data the data to insert
144
+ *
145
+ * @return array
146
+ *
147
+ * @throws RuntimeException If the added is invalid
148
+ */
149
+ protected function validate($data)
150
+ {
151
+ $data = $this->validateSegment($data);
152
+ if (! $data) {
153
+ return $data;
154
+ }
155
+
156
+ $this->saveInternalEncoding();
157
+ if (! $this->isValidHostLength($data)) {
158
+ $this->restoreInternalEncoding();
159
+ throw new RuntimeException('Invalid hostname, check its length');
160
+ }
161
+
162
+ if (! $this->isValidHostPattern($data)) {
163
+ $this->restoreInternalEncoding();
164
+ throw new RuntimeException('Invalid host label, check its content');
165
+ }
166
+
167
+ if (! $this->isValidHostLabels($data)) {
168
+ $this->restoreInternalEncoding();
169
+ throw new RuntimeException('Invalid host label counts, check its count');
170
+ }
171
+
172
+ $data = $this->sanitizeValue($data);
173
+ $data = explode(
174
+ $this->delimiter,
175
+ $this->punycode->decode(implode($this->delimiter, $data))
176
+ );
177
+ $this->restoreInternalEncoding();
178
+
179
+ return $data;
180
+ }
181
+ }
vendor/league/url/src/Components/HostInterface.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A common interface for URL segment like component
17
+ *
18
+ * @package League.url
19
+ * @since 3.1.0
20
+ */
21
+ interface HostInterface extends SegmentInterface
22
+ {
23
+ /**
24
+ * Return the unicode string representation of a hostname
25
+ *
26
+ * @return string
27
+ */
28
+ public function toUnicode();
29
+
30
+ /**
31
+ * Return the ascii string representation of a hostname
32
+ *
33
+ * @return string
34
+ */
35
+ public function toAscii();
36
+ }
vendor/league/url/src/Components/Pass.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A class to manipulate URL Pass component
17
+ *
18
+ * @package League.url
19
+ * @since 1.0.0
20
+ */
21
+ class Pass extends AbstractComponent
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function getUriComponent()
27
+ {
28
+ $value = $this->__toString();
29
+ if ('' != $value) {
30
+ $value = ':'.$value;
31
+ }
32
+
33
+ return $value;
34
+ }
35
+ }
vendor/league/url/src/Components/Path.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A class to manipulate URL Path component
17
+ *
18
+ * @package League.url
19
+ * @since 1.0.0
20
+ */
21
+ class Path extends AbstractSegment implements PathInterface
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ protected $delimiter = '/';
27
+
28
+ /**
29
+ * {@inheritdoc}
30
+ */
31
+ public function get()
32
+ {
33
+ $res = array();
34
+ foreach (array_values($this->data) as $value) {
35
+ $res[] = rawurlencode($value);
36
+ }
37
+ if (! $res) {
38
+ return null;
39
+ }
40
+
41
+ return implode($this->delimiter, $res);
42
+ }
43
+
44
+ /**
45
+ * {@inheritdoc}
46
+ */
47
+ public function getUriComponent()
48
+ {
49
+ return '/'.$this->__toString();
50
+ }
51
+
52
+ /**
53
+ * {@inheritdoc}
54
+ */
55
+ public function getRelativePath(PathInterface $reference)
56
+ {
57
+ if ($this->sameValueAs($reference)) {
58
+ return '';
59
+ }
60
+
61
+ $ref_path = array_values($reference->toArray());
62
+ $this_path = array_values($this->data);
63
+ $filename = array_pop($this_path);
64
+
65
+ //retrieve the final consecutive identical segment in the current path
66
+ $index = 0;
67
+ foreach ($ref_path as $offset => $value) {
68
+ if (! isset($this_path[$offset]) || $value != $this_path[$offset]) {
69
+ break;
70
+ }
71
+ $index++;
72
+ }
73
+ //deduce the number of similar segment according to the reference path
74
+ $nb_common_segment = count($ref_path) - $index;
75
+ $nb_segments = array();
76
+ if ($nb_common_segment) {
77
+ $nb_segments = array_fill(0, $nb_common_segment, '..');
78
+ }
79
+
80
+ //let's output the relative path using a new Path object
81
+ $res = new Path(array_merge(
82
+ $nb_segments,
83
+ array_slice($this_path, $index),
84
+ array($filename)
85
+ ));
86
+
87
+ return $res->__toString();
88
+ }
89
+
90
+ /**
91
+ * {@inheritdoc}
92
+ */
93
+ protected function validate($data)
94
+ {
95
+ $data = $this->sanitizeValue($this->validateSegment($data));
96
+
97
+ return array_map('urldecode', $data);
98
+ }
99
+
100
+ /**
101
+ * {@inheritdoc}
102
+ */
103
+ protected function formatRemoveSegment($data)
104
+ {
105
+ return array_map('urldecode', parent::formatRemoveSegment($data));
106
+ }
107
+ }
vendor/league/url/src/Components/PathInterface.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A common interface for URL segment like component
17
+ *
18
+ * @package League.url
19
+ * @since 3.2.0
20
+ */
21
+ interface PathInterface extends SegmentInterface
22
+ {
23
+ /**
24
+ * return the string representation for a relative path
25
+ * {@link PathInterface} $path
26
+ *
27
+ * @param PathInterface $reference
28
+ *
29
+ * @return string
30
+ */
31
+ public function getRelativePath(PathInterface $reference);
32
+ }
vendor/league/url/src/Components/Port.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ use RuntimeException;
16
+
17
+ /**
18
+ * A class to manipulate URL Port component
19
+ *
20
+ * @package League.url
21
+ * @since 1.0.0
22
+ */
23
+ class Port extends AbstractComponent
24
+ {
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ protected function validate($data)
29
+ {
30
+ $data = parent::validate($data);
31
+ if (is_null($data)) {
32
+ return $data;
33
+ }
34
+
35
+ $data = filter_var($data, FILTER_VALIDATE_INT, array(
36
+ 'options' => array('min_range' => 1),
37
+ ));
38
+
39
+ if (! $data) {
40
+ throw new RuntimeException('A port must be a valid positive integer');
41
+ }
42
+
43
+ return (int) $data;
44
+ }
45
+
46
+ /**
47
+ * {@inheritdoc}
48
+ */
49
+ public function getUriComponent()
50
+ {
51
+ $value = $this->__toString();
52
+ if ('' != $value) {
53
+ $value = ':'.$value;
54
+ }
55
+
56
+ return $value;
57
+ }
58
+ }
vendor/league/url/src/Components/Query.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ use ArrayAccess;
16
+ use RuntimeException;
17
+
18
+ /**
19
+ * A class to manipulate URL Query component
20
+ *
21
+ * @package League.url
22
+ * @since 1.0.0
23
+ */
24
+ class Query extends AbstractArray implements QueryInterface, ArrayAccess
25
+ {
26
+ /**
27
+ * The Constructor
28
+ *
29
+ * @param mixed $data can be string, array or Traversable
30
+ * object convertible into Query String
31
+ */
32
+ public function __construct($data = null)
33
+ {
34
+ $this->set($data);
35
+ }
36
+
37
+ /**
38
+ * {@inheritdoc}
39
+ */
40
+ public function set($data)
41
+ {
42
+ $this->data = array_filter($this->validate($data), function ($value) {
43
+ if (is_string($value)) {
44
+ $value = trim($value);
45
+ }
46
+
47
+ return null !== $value;
48
+ });
49
+ }
50
+
51
+ /**
52
+ * {@inheritdoc}
53
+ */
54
+ public function get()
55
+ {
56
+ if (!$this->data) {
57
+ return null;
58
+ }
59
+
60
+ return str_replace(
61
+ array('+'),
62
+ array('%20'),
63
+ http_build_query($this->data, '', '&')
64
+ );
65
+ }
66
+
67
+ /**
68
+ * {@inheritdoc}
69
+ */
70
+ public function __toString()
71
+ {
72
+ return (string) $this->get();
73
+ }
74
+
75
+ /**
76
+ * {@inheritdoc}
77
+ */
78
+ public function sameValueAs(ComponentInterface $component)
79
+ {
80
+ return $this->__toString() == $component->__toString();
81
+ }
82
+
83
+ /**
84
+ * {@inheritdoc}
85
+ */
86
+ public function getUriComponent()
87
+ {
88
+ $value = $this->__toString();
89
+ if ('' != $value) {
90
+ $value = '?'.$value;
91
+ }
92
+
93
+ return $value;
94
+ }
95
+
96
+ /**
97
+ * {@inheritdoc}
98
+ */
99
+ public function modify($data)
100
+ {
101
+ $this->set(array_merge($this->data, $this->validate($data)));
102
+ }
103
+
104
+ /**
105
+ * {@inheritdoc}
106
+ */
107
+ protected function validate($data)
108
+ {
109
+ return $this->convertToArray($data, function ($str) {
110
+ if ('' == $str) {
111
+ return array();
112
+ }
113
+ if ('?' == $str[0]) {
114
+ $str = substr($str, 1);
115
+ }
116
+
117
+ //let's preserve the key params
118
+ $str = preg_replace_callback('/(?:^|(?<=&))[^=|&[]+/', function ($match) {
119
+ return bin2hex(urldecode($match[0]));
120
+ }, $str);
121
+ parse_str($str, $arr);
122
+
123
+ //hexbin does not work in PHP 5.3
124
+ $arr = array_combine(array_map(function ($value) {
125
+ return pack('H*', $value);
126
+
127
+ }, array_keys($arr)), $arr);
128
+
129
+ return $arr;
130
+ });
131
+ }
132
+
133
+ /**
134
+ * {@inheritdoc}
135
+ */
136
+ public function offsetSet($offset, $value)
137
+ {
138
+ if (is_null($offset)) {
139
+ throw new RuntimeException('offset can not be null');
140
+ }
141
+ $this->modify(array($offset => $value));
142
+ }
143
+ }
vendor/league/url/src/Components/QueryInterface.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A common interface for URL Query component
17
+ *
18
+ * @package League.url
19
+ * @since 3.0.0
20
+ */
21
+ interface QueryInterface extends ComponentArrayInterface
22
+ {
23
+ /**
24
+ * modify/update a Query component
25
+ *
26
+ * @param mixed $data the data can be a array, a Traversable or a string
27
+ *
28
+ * @return void
29
+ */
30
+ public function modify($data);
31
+ }
vendor/league/url/src/Components/Scheme.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ use League\Url\UrlConstants;
16
+ use RuntimeException;
17
+
18
+ /**
19
+ * A class to manipulate URL Scheme component
20
+ *
21
+ * @package League.url
22
+ * @since 1.0.0
23
+ */
24
+ class Scheme extends AbstractComponent
25
+ {
26
+ /**
27
+ * {@inheritdoc}
28
+ */
29
+ protected function validate($data)
30
+ {
31
+ $data = parent::validate($data);
32
+ if (is_null($data)) {
33
+ return $data;
34
+ }
35
+
36
+ $data = filter_var($data, FILTER_VALIDATE_REGEXP, array(
37
+ 'options' => array('regexp' => '/^'.UrlConstants::SCHEME_REGEXP.'$/i'),
38
+ ));
39
+
40
+ if (! $data) {
41
+ throw new RuntimeException('This class only deals with http URL');
42
+ }
43
+
44
+ return strtolower($data);
45
+ }
46
+
47
+ /**
48
+ * {@inheritdoc}
49
+ */
50
+ public function getUriComponent()
51
+ {
52
+ $value = $this->__toString();
53
+ if ('' != $value) {
54
+ $value .= '://';
55
+ }
56
+
57
+ return $value;
58
+ }
59
+ }
vendor/league/url/src/Components/SegmentInterface.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A common interface for URL segment like component
17
+ *
18
+ * @package League.url
19
+ * @since 3.0.0
20
+ */
21
+ interface SegmentInterface extends ComponentArrayInterface
22
+ {
23
+ /**
24
+ * Append data to the component
25
+ *
26
+ * @param mixed $data the data can be a array, a Traversable or a string
27
+ * @param string $whence where the data should be prepended to
28
+ * @param integer $whence_index the recurrence index of $whence
29
+ *
30
+ * @return void
31
+ */
32
+ public function append($data, $whence = null, $whence_index = null);
33
+
34
+ /**
35
+ * Prepend data to the component
36
+ *
37
+ * @param mixed $data the data can be a array, a Traversable or a string
38
+ * @param string $whence where the data should be prepended to
39
+ * @param integer $whence_index the recurrence index of $whence
40
+ *
41
+ * @return void
42
+ */
43
+ public function prepend($data, $whence = null, $whence_index = null);
44
+
45
+ /**
46
+ * Remove part of the component
47
+ *
48
+ * @param mixed $data the data can be a array, a Traversable or a string
49
+ *
50
+ * @return void
51
+ */
52
+ public function remove($data);
53
+ }
vendor/league/url/src/Components/User.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url\Components;
14
+
15
+ /**
16
+ * A class to manipulate URL User component
17
+ *
18
+ * @package League.url
19
+ * @since 1.0.0
20
+ */
21
+ class User extends AbstractComponent
22
+ {
23
+ }
vendor/league/url/src/Url.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url;
14
+
15
+ /**
16
+ * A class to manipulate URLs
17
+ *
18
+ * @package League.url
19
+ * @since 1.0.0
20
+ */
21
+ class Url extends AbstractUrl
22
+ {
23
+ /**
24
+ * The Constructor
25
+ * @param Components\Scheme $scheme The URL Scheme component
26
+ * @param Components\User $user The URL User component
27
+ * @param Components\Pass $pass The URL Pass component
28
+ * @param Components\HostInterface $host The URL Host component
29
+ * @param Components\Port $port The URL Port component
30
+ * @param Components\PathInterface $path The URL Path component
31
+ * @param Components\QueryInterface $query The URL Query component
32
+ * @param Components\Fragment $fragment The URL Fragment component
33
+ */
34
+ protected function __construct(
35
+ Components\Scheme $scheme,
36
+ Components\User $user,
37
+ Components\Pass $pass,
38
+ Components\HostInterface $host,
39
+ Components\Port $port,
40
+ Components\PathInterface $path,
41
+ Components\QueryInterface $query,
42
+ Components\Fragment $fragment
43
+ ) {
44
+ $this->scheme = $scheme;
45
+ $this->user = $user;
46
+ $this->pass = $pass;
47
+ $this->host = $host;
48
+ $this->port = $port;
49
+ $this->path = $path;
50
+ $this->query = $query;
51
+ $this->fragment = $fragment;
52
+ }
53
+
54
+ /**
55
+ * {@inheritdoc}
56
+ */
57
+ public function setScheme($data)
58
+ {
59
+ $this->scheme->set($data);
60
+
61
+ return $this;
62
+ }
63
+
64
+ /**
65
+ * {@inheritdoc}
66
+ */
67
+ public function getScheme()
68
+ {
69
+ return $this->scheme;
70
+ }
71
+
72
+ /**
73
+ * {@inheritdoc}
74
+ */
75
+ public function setUser($data)
76
+ {
77
+ $this->user->set($data);
78
+
79
+ return $this;
80
+ }
81
+
82
+ /**
83
+ * {@inheritdoc}
84
+ */
85
+ public function getUser()
86
+ {
87
+ return $this->user;
88
+ }
89
+
90
+ /**
91
+ * {@inheritdoc}
92
+ */
93
+ public function setPass($data)
94
+ {
95
+ $this->pass->set($data);
96
+
97
+ return $this;
98
+ }
99
+
100
+ /**
101
+ * {@inheritdoc}
102
+ */
103
+ public function getPass()
104
+ {
105
+ return $this->pass;
106
+ }
107
+
108
+ /**
109
+ * {@inheritdoc}
110
+ */
111
+ public function setHost($data)
112
+ {
113
+ $this->host->set($data);
114
+
115
+ return $this;
116
+ }
117
+
118
+ /**
119
+ * {@inheritdoc}
120
+ */
121
+ public function getHost()
122
+ {
123
+ return $this->host;
124
+ }
125
+
126
+ /**
127
+ * {@inheritdoc}
128
+ */
129
+ public function setPort($data)
130
+ {
131
+ $this->port->set($data);
132
+
133
+ return $this;
134
+ }
135
+
136
+ /**
137
+ * {@inheritdoc}
138
+ */
139
+ public function getPort()
140
+ {
141
+ return $this->port;
142
+ }
143
+
144
+ /**
145
+ * {@inheritdoc}
146
+ */
147
+ public function setPath($data)
148
+ {
149
+ $this->path->set($data);
150
+
151
+ return $this;
152
+ }
153
+
154
+ /**
155
+ * {@inheritdoc}
156
+ */
157
+ public function getPath()
158
+ {
159
+ return $this->path;
160
+ }
161
+
162
+ /**
163
+ * {@inheritdoc}
164
+ */
165
+ public function setQuery($data)
166
+ {
167
+ $this->query->set($data);
168
+
169
+ return $this;
170
+ }
171
+
172
+ /**
173
+ * {@inheritdoc}
174
+ */
175
+ public function getQuery()
176
+ {
177
+ return $this->query;
178
+ }
179
+
180
+ /**
181
+ * {@inheritdoc}
182
+ */
183
+ public function setFragment($data)
184
+ {
185
+ $this->fragment->set($data);
186
+
187
+ return $this;
188
+ }
189
+
190
+ /**
191
+ * {@inheritdoc}
192
+ */
193
+ public function getFragment()
194
+ {
195
+ return $this->fragment;
196
+ }
197
+ }
vendor/league/url/src/UrlConstants.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url;
14
+
15
+ /**
16
+ * Describe Library Constants
17
+ *
18
+ * @package League.url
19
+ * @since 3.2.0
20
+ */
21
+ class UrlConstants
22
+ {
23
+ const SCHEME_REGEXP = '(http|ftp|ws)(s?)'; //supported protocol
24
+ }
vendor/league/url/src/UrlImmutable.php ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url;
14
+
15
+ /**
16
+ * A Immutable Value Object class to manipulate URLs
17
+ *
18
+ * @package League.url
19
+ * @since 3.0.0
20
+ */
21
+ class UrlImmutable extends AbstractUrl
22
+ {
23
+ /**
24
+ * The Constructor
25
+ * @param Components\Scheme $scheme The URL Scheme component
26
+ * @param Components\User $user The URL User component
27
+ * @param Components\Pass $pass The URL Pass component
28
+ * @param Components\HostInterface $host The URL Host component
29
+ * @param Components\Port $port The URL Port component
30
+ * @param Components\PathInterface $path The URL Path component
31
+ * @param Components\QueryInterface $query The URL Query component
32
+ * @param Components\Fragment $fragment The URL Fragment component
33
+ */
34
+ protected function __construct(
35
+ Components\Scheme $scheme,
36
+ Components\User $user,
37
+ Components\Pass $pass,
38
+ Components\HostInterface $host,
39
+ Components\Port $port,
40
+ Components\PathInterface $path,
41
+ Components\QueryInterface $query,
42
+ Components\Fragment $fragment
43
+ ) {
44
+ $this->scheme = clone $scheme;
45
+ $this->user = clone $user;
46
+ $this->pass = clone $pass;
47
+ $this->host = clone $host;
48
+ $this->port = clone $port;
49
+ $this->path = clone $path;
50
+ $this->query = clone $query;
51
+ $this->fragment = clone $fragment;
52
+ }
53
+
54
+ /**
55
+ * To Enable cloning
56
+ */
57
+ public function __clone()
58
+ {
59
+ $this->scheme = clone $this->scheme;
60
+ $this->user = clone $this->user;
61
+ $this->pass = clone $this->pass;
62
+ $this->host = clone $this->host;
63
+ $this->port = clone $this->port;
64
+ $this->path = clone $this->path;
65
+ $this->query = clone $this->query;
66
+ $this->fragment = clone $this->fragment;
67
+ }
68
+
69
+ /**
70
+ * {@inheritdoc}
71
+ */
72
+ public function setScheme($data)
73
+ {
74
+ $clone = clone $this;
75
+ $clone->scheme->set($data);
76
+
77
+ return $clone;
78
+ }
79
+
80
+ /**
81
+ * {@inheritdoc}
82
+ */
83
+ public function getScheme()
84
+ {
85
+ return clone $this->scheme;
86
+ }
87
+
88
+ /**
89
+ * {@inheritdoc}
90
+ */
91
+ public function setUser($data)
92
+ {
93
+ $clone = clone $this;
94
+ $clone->user->set($data);
95
+
96
+ return $clone;
97
+ }
98
+
99
+ /**
100
+ * {@inheritdoc}
101
+ */
102
+ public function getUser()
103
+ {
104
+ return clone $this->user;
105
+ }
106
+
107
+ /**
108
+ * {@inheritdoc}
109
+ */
110
+ public function setPass($data)
111
+ {
112
+ $clone = clone $this;
113
+ $clone->pass->set($data);
114
+
115
+ return $clone;
116
+ }
117
+
118
+ /**
119
+ * {@inheritdoc}
120
+ */
121
+ public function getPass()
122
+ {
123
+ return clone $this->pass;
124
+ }
125
+
126
+ /**
127
+ * {@inheritdoc}
128
+ */
129
+ public function setHost($data)
130
+ {
131
+ $clone = clone $this;
132
+ $clone->host->set($data);
133
+
134
+ return $clone;
135
+ }
136
+
137
+ /**
138
+ * {@inheritdoc}
139
+ */
140
+ public function getHost()
141
+ {
142
+ return clone $this->host;
143
+ }
144
+
145
+ /**
146
+ * {@inheritdoc}
147
+ */
148
+ public function setPort($data)
149
+ {
150
+ $clone = clone $this;
151
+ $clone->port->set($data);
152
+
153
+ return $clone;
154
+ }
155
+
156
+ /**
157
+ * {@inheritdoc}
158
+ */
159
+ public function getPort()
160
+ {
161
+ return clone $this->port;
162
+ }
163
+
164
+ /**
165
+ * {@inheritdoc}
166
+ */
167
+ public function setPath($data)
168
+ {
169
+ $clone = clone $this;
170
+ $clone->path->set($data);
171
+
172
+ return $clone;
173
+ }
174
+
175
+ /**
176
+ * {@inheritdoc}
177
+ */
178
+ public function getPath()
179
+ {
180
+ return clone $this->path;
181
+ }
182
+
183
+ /**
184
+ * {@inheritdoc}
185
+ */
186
+ public function setQuery($data)
187
+ {
188
+ $clone = clone $this;
189
+ $clone->query->set($data);
190
+
191
+ return $clone;
192
+ }
193
+
194
+ /**
195
+ * {@inheritdoc}
196
+ */
197
+ public function getQuery()
198
+ {
199
+ return clone $this->query;
200
+ }
201
+
202
+ /**
203
+ * {@inheritdoc}
204
+ */
205
+ public function setFragment($data)
206
+ {
207
+ $clone = clone $this;
208
+ $clone->fragment->set($data);
209
+
210
+ return $clone;
211
+ }
212
+
213
+ /**
214
+ * {@inheritdoc}
215
+ */
216
+ public function getFragment()
217
+ {
218
+ return clone $this->fragment;
219
+ }
220
+ }
vendor/league/url/src/UrlInterface.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of the League.url library
4
+ *
5
+ * @license http://opensource.org/licenses/MIT
6
+ * @link https://github.com/thephpleague/url/
7
+ * @version 3.3.5
8
+ * @package League.url
9
+ *
10
+ * For the full copyright and license information, please view the LICENSE
11
+ * file that was distributed with this source code.
12
+ */
13
+ namespace League\Url;
14
+
15
+ /**
16
+ * A common interface for URL as Value Object
17
+ *
18
+ * @package League.url
19
+ * @since 3.0.0
20
+ */
21
+ interface UrlInterface
22
+ {
23
+ /**
24
+ * return the string representation for the current URL
25
+ *
26
+ * @return string
27
+ */
28
+ public function __toString();
29
+
30
+ /**
31
+ * return the string representation for the current URL
32
+ * user info
33
+ *
34
+ * @return string
35
+ */
36
+ public function getUserInfo();
37
+
38
+ /**
39
+ * return the string representation for the current URL
40
+ * authority part (user, pass, host, port components)
41
+ *
42
+ * @return string
43
+ */
44
+ public function getAuthority();
45
+
46
+ /**
47
+ * return the string representation for the current URL
48
+ * including the scheme and the authority parts.
49
+ *
50
+ * @return string
51
+ */
52
+ public function getBaseUrl();
53
+
54
+ /**
55
+ * return the string representation for a relative URL
56
+ * relative to another UrlInterface or to the current
57
+ * base URL
58
+ *
59
+ * @param UrlInterface $ref_url
60
+ *
61
+ * @return string
62
+ */
63
+ public function getRelativeUrl(UrlInterface $ref_url = null);
64
+
65
+ /**
66
+ * Compare two Url object and tells whether they can be considered equal
67
+ *
68
+ * @param \League\Url\UrlInterface $url
69
+ *
70
+ * @return boolean
71
+ */
72
+ public function sameValueAs(UrlInterface $url);
73
+
74
+ /**
75
+ * Set the URL scheme component
76
+ *
77
+ * @param string $data
78
+ *
79
+ * @return self
80
+ */
81
+ public function setScheme($data);
82
+
83
+ /**
84
+ * get the URL scheme component
85
+ *
86
+ * @return \League\Url\Components\ComponentInterface
87
+ */
88
+ public function getScheme();
89
+
90
+ /**
91
+ * Set the URL user component
92
+ *
93
+ * @param string $data
94
+ *
95
+ * @return self
96
+ */
97
+ public function setUser($data);
98
+
99
+ /**
100
+ * get the URL pass component
101
+ *
102
+ * @return \League\Url\Components\ComponentInterface
103
+ */
104
+ public function getUser();
105
+
106
+ /**
107
+ * Set the URL pass component
108
+ *
109
+ * @param string $data
110
+ *
111
+ * @return self
112
+ */
113
+ public function setPass($data);
114
+
115
+ /**
116
+ * get the URL pass component
117
+ *
118
+ * @return \League\Url\Components\ComponentInterface
119
+ */
120
+ public function getPass();
121
+
122
+ /**
123
+ * Set the URL host component
124
+ *
125
+ * @param string|array|\Traversable $data
126
+ *
127
+ * @return self
128
+ */
129
+ public function setHost($data);
130
+
131
+ /**
132
+ * get the URL pass component
133
+ *
134
+ * @return \League\Url\Components\ComponentInterface
135
+ */
136
+ public function getHost();
137
+
138
+ /**
139
+ * Set the URL port component
140
+ *
141
+ * @param string|integer $data
142
+ *
143
+ * @return self
144
+ */
145
+ public function setPort($data);
146
+
147
+ /**
148
+ * get the URL pass component
149
+ *
150
+ * @return \League\Url\Components\ComponentInterface
151
+ */
152
+ public function getPort();
153
+
154
+ /**
155
+ * Set the URL path component
156
+ *
157
+ * @param string|array|\Traversable $data
158
+ *
159
+ * @return self
160
+ */
161
+ public function setPath($data);
162
+
163
+ /**
164
+ * get the URL pass component
165
+ *
166
+ * @return \League\Url\Components\PathInterface
167
+ */
168
+ public function getPath();
169
+
170
+ /**
171
+ * Set the URL query component
172
+ *
173
+ * @param string|array|\Traversable $data
174
+ *
175
+ * @return self
176
+ */
177
+ public function setQuery($data);
178
+
179
+ /**
180
+ * get the URL pass component
181
+ *
182
+ * @return \League\Url\Components\QueryInterface
183
+ */
184
+ public function getQuery();
185
+
186
+ /**
187
+ * Set the URL fragment component
188
+ *
189
+ * @param string $data
190
+ *
191
+ * @return self
192
+ */
193
+ public function setFragment($data);
194
+
195
+ /**
196
+ * get the URL pass component
197
+ *
198
+ * @return \League\Url\Components\ComponentInterface
199
+ */
200
+ public function getFragment();
201
+ }
vendor/masterminds/html5/.travis.yml CHANGED
@@ -36,4 +36,4 @@ script:
36
  after_script:
37
  - bash -c 'if [ "$TRAVIS_PHP_VERSION" == "5.6" ] ; then wget https://scrutinizer-ci.com/ocular.phar; fi;'
38
  - bash -c 'if [ "$TRAVIS_PHP_VERSION" == "5.6" ] ; then php ocular.phar code-coverage:upload --format=php-clover coverage.xml; fi;'
39
- - php test/benchmark/run.php 50
36
  after_script:
37
  - bash -c 'if [ "$TRAVIS_PHP_VERSION" == "5.6" ] ; then wget https://scrutinizer-ci.com/ocular.phar; fi;'
38
  - bash -c 'if [ "$TRAVIS_PHP_VERSION" == "5.6" ] ; then php ocular.phar code-coverage:upload --format=php-clover coverage.xml; fi;'
39
+ - php test/benchmark/run.php 10
vendor/masterminds/html5/README.md CHANGED
@@ -202,7 +202,7 @@ issues known issues that are not presently on the roadmap:
202
  - PLAINTEXT: Unsupported.
203
  - Adoption Agency Algorithm: Not yet implemented. (8.2.5.4.7)
204
 
205
- ##XML Namespaces
206
 
207
  To use XML style namespaces you have to configure well the main `HTML5` instance.
208
 
@@ -219,7 +219,7 @@ $dom->documentElement->namespaceURI; // http://www.example.com
219
  ```
220
 
221
  You can also add some default prefixes that will not require the namespace declaration,
222
- but it's elements will be namespaced.
223
 
224
  ```php
225
  use Masterminds\HTML5;
@@ -243,7 +243,7 @@ a list of contributors.
243
 
244
  We owe a huge debt of gratitude to the original authors of html5lib.
245
 
246
- While not much of the orignal parser remains, we learned a lot from
247
  reading the html5lib library. And some pieces remain here. In
248
  particular, much of the UTF-8 and Unicode handling is derived from the
249
  html5lib project.
202
  - PLAINTEXT: Unsupported.
203
  - Adoption Agency Algorithm: Not yet implemented. (8.2.5.4.7)
204
 
205
+ ## XML Namespaces
206
 
207
  To use XML style namespaces you have to configure well the main `HTML5` instance.
208
 
219
  ```
220
 
221
  You can also add some default prefixes that will not require the namespace declaration,
222
+ but its elements will be namespaced.
223
 
224
  ```php
225
  use Masterminds\HTML5;
243
 
244
  We owe a huge debt of gratitude to the original authors of html5lib.
245
 
246
+ While not much of the original parser remains, we learned a lot from
247
  reading the html5lib library. And some pieces remain here. In
248
  particular, much of the UTF-8 and Unicode handling is derived from the
249
  html5lib project.
vendor/masterminds/html5/RELEASE.md CHANGED
@@ -1,5 +1,11 @@
1
  # Release Notes
2
 
 
 
 
 
 
 
3
  2.3.0 (2017-09-04)
4
 
5
  - #129: image within inline svg breaks system (fixed by #133)
1
  # Release Notes
2
 
3
+ 2.3.1 (2018-10-18)
4
+
5
+ - #121: Audio is not a block tag (fixed by #141)
6
+ - #136: Handle illegal self-closing according to spec (fixed by #137)
7
+ - #141: Minor fixes in the README
8
+
9
  2.3.0 (2017-09-04)
10
 
11
  - #129: image within inline svg breaks system (fixed by #133)
vendor/masterminds/html5/src/HTML5/Elements.php CHANGED
@@ -83,7 +83,7 @@ class Elements
83
  "area" => 9, // NORMAL | VOID_TAG
84
  "article" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
85
  "aside" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
86
- "audio" => 65, // NORMAL | BLOCK_TAG
87
  "b" => 1,
88
  "base" => 9, // NORMAL | VOID_TAG
89
  "bdi" => 1,
83
  "area" => 9, // NORMAL | VOID_TAG
84
  "article" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
85
  "aside" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
86
+ "audio" => 1, // NORMAL
87
  "b" => 1,
88
  "base" => 9, // NORMAL | VOID_TAG
89
  "bdi" => 1,
vendor/masterminds/html5/src/HTML5/Parser/DOMTreeBuilder.php CHANGED
@@ -433,10 +433,16 @@ class DOMTreeBuilder implements EventHandler
433
  else {
434
  $this->current->appendChild($ele);
435
 
436
- // XXX: Need to handle self-closing tags and unary tags.
437
  if (! Elements::isA($name, Elements::VOID_TAG)) {
438
  $this->current = $ele;
439
  }
 
 
 
 
 
 
 
440
  }
441
 
442
  // This is sort of a last-ditch attempt to correct for cases where no head/body
@@ -453,6 +459,11 @@ class DOMTreeBuilder implements EventHandler
453
  array_shift($this->nsStack);
454
  }
455
  }
 
 
 
 
 
456
  // Return the element mask, which the tokenizer can then use to set
457
  // various processing rules.
458
  return Elements::element($name);
433
  else {
434
  $this->current->appendChild($ele);
435
 
 
436
  if (! Elements::isA($name, Elements::VOID_TAG)) {
437
  $this->current = $ele;
438
  }
439
+
440
+ // Self-closing tags should only be respected on foreign elements
441
+ // (and are implied on void elements)
442
+ // See: https://www.w3.org/TR/html5/syntax.html#start-tags
443
+ if (Elements::isHtml5Element($name)) {
444
+ $selfClosing = false;
445
+ }
446
  }
447
 
448
  // This is sort of a last-ditch attempt to correct for cases where no head/body
459
  array_shift($this->nsStack);
460
  }
461
  }
462
+
463
+ if ($selfClosing) {
464
+ $this->endTag($name);
465
+ }
466
+
467
  // Return the element mask, which the tokenizer can then use to set
468
  // various processing rules.
469
  return Elements::element($name);
vendor/masterminds/html5/src/HTML5/Parser/Tokenizer.php CHANGED
@@ -383,11 +383,8 @@ class Tokenizer
383
  }
384
 
385
  $mode = $this->events->startTag($name, $attributes, $selfClose);
386
- // Should we do this? What does this buy that selfClose doesn't?
387
- if ($selfClose) {
388
- $this->events->endTag($name);
389
- } elseif (is_int($mode)) {
390
- // fprintf(STDOUT, "Event response says move into mode %d for tag %s", $mode, $name);
391
  $this->setTextMode($mode, $name);
392
  }
393
 
383
  }
384
 
385
  $mode = $this->events->startTag($name, $attributes, $selfClose);
386
+
387
+ if (is_int($mode)) {
 
 
 
388
  $this->setTextMode($mode, $name);
389
  }
390
 
vendor/masterminds/html5/test/HTML5/ElementsTest.php CHANGED
@@ -393,7 +393,6 @@ class ElementsTest extends TestCase
393
  'address',
394
  'article',
395
  'aside',
396
- 'audio',
397
  'blockquote',
398
  'canvas',
399
  'dd',
393
  'address',
394
  'article',
395
  'aside',
 
396
  'blockquote',
397
  'canvas',
398
  'dd',
vendor/masterminds/html5/test/HTML5/Parser/DOMTreeBuilderTest.php CHANGED
@@ -643,4 +643,66 @@ EOM;
643
  $this->assertSame(3, $dom->getElementById('first')->getElementsByTagName('option')->length);
644
  $this->assertSame(2, $dom->getElementById('second')->getElementsByTagName('option')->length);
645
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
  }
643
  $this->assertSame(3, $dom->getElementById('first')->getElementsByTagName('option')->length);
644
  $this->assertSame(2, $dom->getElementById('second')->getElementsByTagName('option')->length);
645
  }
646
+
647
+ public function testVoidTag() {
648
+ $html = <<<EOM
649
+ <!DOCTYPE html>
650
+ <html>
651
+ <head>
652
+ <title>testVoidTag</title>
653
+ <meta>
654
+ <meta>
655
+ </head>
656
+ <body></body>
657
+ </html>
658
+ EOM;
659
+
660
+ $dom = $this->parse($html);
661
+ $this->assertSame(2, $dom->getElementsByTagName('meta')->length);
662
+ $this->assertSame(0, $dom->getElementsByTagName('meta')->item(0)->childNodes->length);
663
+ $this->assertSame(0, $dom->getElementsByTagName('meta')->item(1)->childNodes->length);
664
+ }
665
+
666
+ public function testIgnoreSelfClosingTag() {
667
+ $html = <<<EOM
668
+ <!DOCTYPE html>
669
+ <html>
670
+ <head>
671
+ <title>testIllegalSelfClosingTag</title>
672
+ </head>
673
+ <body>
674
+ <div /><span>Hello, World!</span></div>
675
+ </body>
676
+ </html>
677
+ EOM;
678
+
679
+ $dom = $this->parse($html);
680
+ $this->assertSame(1, $dom->getElementsByTagName('div')->item(0)->childNodes->length);
681
+ }
682
+
683
+ public function testIAudioInParagraph() {
684
+ $html = <<<EOM
685
+ <!DOCTYPE html>
686
+ <html>
687
+ <head>
688
+ <title>testIllegalSelfClosingTag</title>
689
+ </head>
690
+ <body>
691
+ <p>
692
+ <audio preload="none" controls="controls">
693
+ <source src="https://example.com/test.mp3" type="audio/mpeg" />
694
+ Your browser does not support the audio element.
695
+ </audio>
696
+ </p>
697
+ </body>
698
+ </html>>
699
+ </html>
700
+ EOM;
701
+
702
+ $dom = $this->parse($html);
703
+ $audio = $dom->getElementsByTagName('audio')->item(0);
704
+
705
+ $this->assertSame('p', $audio->parentNode->nodeName);
706
+ $this->assertSame(3, $audio->childNodes->length);
707
+ }
708
  }
vendor/masterminds/html5/test/HTML5/Parser/TokenizerTest.php CHANGED
@@ -447,9 +447,10 @@ class TokenizerTest extends \Masterminds\HTML5\Tests\TestCase
447
  );
448
  foreach ($selfClose as $test => $expects) {
449
  $events = $this->parse($test);
450
- $this->assertEquals(3, $events->depth(), "Counting events for '$test'" . print_r($events, true));
451
  $this->assertEventEquals('startTag', $expects, $events->get(0));
452
- $this->assertEventEquals('endTag', $expects, $events->get(1));
 
453
  }
454
 
455
  $bad = array(
@@ -735,7 +736,7 @@ class TokenizerTest extends \Masterminds\HTML5\Tests\TestCase
735
  true
736
  )
737
  );
738
- $this->isAllGood('startTag', 3, $withEnd);
739
 
740
  // Cause a parse error.
741
  $bad = array(
447
  );
448
  foreach ($selfClose as $test => $expects) {
449
  $events = $this->parse($test);
450
+ $this->assertEquals(2, $events->depth(), "Counting events for '$test'" . print_r($events, true));
451
  $this->assertEventEquals('startTag', $expects, $events->get(0));
452
+ $event = $events->get(0);
453
+ $this->assertTrue($event['data'][2]);
454
  }
455
 
456
  $bad = array(
736
  true
737
  )
738
  );
739
+ $this->isAllGood('startTag', 2, $withEnd);
740
 
741
  // Cause a parse error.
742
  $bad = array(
vendor/monolog/monolog/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ### 1.23.0 (2017-06-19)
2
 
3
  * Improved SyslogUdpHandler's support for RFC5424 and added optional `$ident` argument
1
+ ### 1.24.0 (2018-11-05)
2
+
3
+ * Added a `ResettableInterface` in order to reset/reset/clear/flush handlers and processors
4
+ * Added a `ProcessorInterface` as an optional way to label a class as being a processor (mostly useful for autowiring dependency containers)
5
+ * Added a way to log signals being received using Monolog\SignalHandler
6
+ * Added ability to customize error handling at the Logger level using Logger::setExceptionHandler
7
+ * Added InsightOpsHandler to migrate users of the LogEntriesHandler
8
+ * Added protection to NormalizerHandler against circular and very deep structures, it now stops normalizing at a depth of 9
9
+ * Added capture of stack traces to ErrorHandler when logging PHP errors
10
+ * Added RavenHandler support for a `contexts` context or extra key to forward that to Sentry's contexts
11
+ * Added forwarding of context info to FluentdFormatter
12
+ * Added SocketHandler::setChunkSize to override the default chunk size in case you must send large log lines to rsyslog for example
13
+ * Added ability to extend/override BrowserConsoleHandler
14
+ * Added SlackWebhookHandler::getWebhookUrl and SlackHandler::getToken to enable class extensibility
15
+ * Added SwiftMailerHandler::getSubjectFormatter to enable class extensibility
16
+ * Dropped official support for HHVM in test builds
17
+ * Fixed normalization of exception traces when call_user_func is used to avoid serializing objects and the data they contain
18
+ * Fixed naming of fields in Slack handler, all field names are now capitalized in all cases
19
+ * Fixed HipChatHandler bug where slack dropped messages randomly
20
+ * Fixed normalization of objects in Slack handlers
21
+ * Fixed support for PHP7's Throwable in NewRelicHandler
22
+ * Fixed race bug when StreamHandler sometimes incorrectly reported it failed to create a directory
23
+ * Fixed table row styling issues in HtmlFormatter
24
+ * Fixed RavenHandler dropping the message when logging exception
25
+ * Fixed WhatFailureGroupHandler skipping processors when using handleBatch
26
+ and implement it where possible
27
+ * Fixed display of anonymous class names
28
+
29
  ### 1.23.0 (2017-06-19)
30
 
31
  * Improved SyslogUdpHandler's support for RFC5424 and added optional `$ident` argument
vendor/monolog/monolog/README.md CHANGED
@@ -2,7 +2,6 @@
2
 
3
  [![Total Downloads](https://img.shields.io/packagist/dt/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog)
4
  [![Latest Stable Version](https://img.shields.io/packagist/v/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog)
5
- [![Reference Status](https://www.versioneye.com/php/monolog:monolog/reference_badge.svg)](https://www.versioneye.com/php/monolog:monolog/references)
6
 
7
 
8
  Monolog sends your logs to files, sockets, inboxes, databases and various
2
 
3
  [![Total Downloads](https://img.shields.io/packagist/dt/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog)
4
  [![Latest Stable Version](https://img.shields.io/packagist/v/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog)
 
5
 
6
 
7
  Monolog sends your logs to files, sockets, inboxes, databases and various
vendor/monolog/monolog/doc/02-handlers-formatters-processors.md CHANGED
@@ -55,6 +55,7 @@
55
  - _RollbarHandler_: Logs records to a [Rollbar](https://rollbar.com/) account.
56
  - _SyslogUdpHandler_: Logs records to a remote [Syslogd](http://www.rsyslog.com/) server.
57
  - _LogEntriesHandler_: Logs records to a [LogEntries](http://logentries.com/) account.
 
58
 
59
  ### Logging in development
60
 
55
  - _RollbarHandler_: Logs records to a [Rollbar](https://rollbar.com/) account.
56
  - _SyslogUdpHandler_: Logs records to a remote [Syslogd](http://www.rsyslog.com/) server.
57
  - _LogEntriesHandler_: Logs records to a [LogEntries](http://logentries.com/) account.
58
+ - _InsightOpsHandler_: Logs records to a [InsightOps](https://www.rapid7.com/products/insightops/) account.
59
 
60
  ### Logging in development
61
 
vendor/monolog/monolog/doc/03-utilities.md CHANGED
@@ -5,6 +5,8 @@
5
  help in some older codebases or for ease of use.
6
  - _ErrorHandler_: The `Monolog\ErrorHandler` class allows you to easily register
7
  a Logger instance as an exception handler, error handler or fatal error handler.
 
 
8
  - _ErrorLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain log
9
  level is reached.
10
  - _ChannelLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain
5
  help in some older codebases or for ease of use.
6
  - _ErrorHandler_: The `Monolog\ErrorHandler` class allows you to easily register
7
  a Logger instance as an exception handler, error handler or fatal error handler.
8
+ - _SignalHandler_: The `Monolog\SignalHandler` class allows you to easily register
9
+ a Logger instance as a POSIX signal handler.
10
  - _ErrorLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain log
11
  level is reached.
12
  - _ChannelLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain
vendor/monolog/monolog/src/Monolog/ErrorHandler.php CHANGED
@@ -14,6 +14,7 @@ namespace Monolog;
14
  use Psr\Log\LoggerInterface;
15
  use Psr\Log\LogLevel;
16
  use Monolog\Handler\AbstractHandler;
 
17
 
18
  /**
19
  * Monolog error handler
@@ -38,6 +39,7 @@ class ErrorHandler
38
  private $hasFatalErrorHandler;
39
  private $fatalLevel;
40
  private $reservedMemory;
 
41
  private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR);
42
 
43
  public function __construct(LoggerInterface $logger)
@@ -132,7 +134,7 @@ class ErrorHandler
132
  {
133
  $this->logger->log(
134
  $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel,
135
- sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()),
136
  array('exception' => $e)
137
  );
138
 
@@ -156,6 +158,13 @@ class ErrorHandler
156
  if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
157
  $level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL;
158
  $this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line));
 
 
 
 
 
 
 
159
  }
160
 
161
  if ($this->previousErrorHandler === true) {
@@ -177,7 +186,7 @@ class ErrorHandler
177
  $this->logger->log(
178
  $this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel,
179
  'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],
180
- array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'])
181
  );
182
 
183
  if ($this->logger instanceof Logger) {
14
  use Psr\Log\LoggerInterface;
15
  use Psr\Log\LogLevel;
16
  use Monolog\Handler\AbstractHandler;
17
+ use Monolog\Registry;
18
 
19
  /**
20
  * Monolog error handler
39
  private $hasFatalErrorHandler;
40
  private $fatalLevel;
41
  private $reservedMemory;
42
+ private $lastFatalTrace;
43
  private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR);
44
 
45
  public function __construct(LoggerInterface $logger)
134
  {
135
  $this->logger->log(
136
  $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel,
137
+ sprintf('Uncaught Exception %s: "%s" at %s line %s', Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()),
138
  array('exception' => $e)
139
  );
140
 
158
  if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
159
  $level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL;
160
  $this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line));
161
+ } else {
162
+ // http://php.net/manual/en/function.debug-backtrace.php
163
+ // As of 5.3.6, DEBUG_BACKTRACE_IGNORE_ARGS option was added.
164
+ // Any version less than 5.3.6 must use the DEBUG_BACKTRACE_IGNORE_ARGS constant value '2'.
165
+ $trace = debug_backtrace((PHP_VERSION_ID < 50306) ? 2 : DEBUG_BACKTRACE_IGNORE_ARGS);
166
+ array_shift($trace); // Exclude handleError from trace
167
+ $this->lastFatalTrace = $trace;
168
  }
169
 
170
  if ($this->previousErrorHandler === true) {
186
  $this->logger->log(
187
  $this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel,
188
  'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],
189
+ array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace)
190
  );
191
 
192
  if ($this->logger instanceof Logger) {
vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php CHANGED
@@ -62,6 +62,7 @@ class FluentdFormatter implements FormatterInterface
62
 
63
  $message = array(
64
  'message' => $record['message'],
 
65
  'extra' => $record['extra'],
66
  );
67
 
62
 
63
  $message = array(
64
  'message' => $record['message'],
65
+ 'context' => $record['context'],
66
  'extra' => $record['extra'],
67
  );
68
 
vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php CHANGED
@@ -58,7 +58,7 @@ class HtmlFormatter extends NormalizerFormatter
58
  $td = '<pre>'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'</pre>';
59
  }
60
 
61
- return "<tr style=\"padding: 4px;spacing: 0;text-align: left;\">\n<th style=\"background: #cccccc\" width=\"100px\">$th:</th>\n<td style=\"padding: 4px;spacing: 0;text-align: left;background: #eeeeee\">".$td."</td>\n</tr>";
62
  }
63
 
64
  /**
58
  $td = '<pre>'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'</pre>';
59
  }
60
 
61
+ return "<tr style=\"padding: 4px;text-align: left;\">\n<th style=\"vertical-align: top;background: #ccc;color: #000\" width=\"100\">$th:</th>\n<td style=\"padding: 4px;text-align: left;vertical-align: top;background: #eee;color: #000\">".$td."</td>\n</tr>";
62
  }
63
 
64
  /**
vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php CHANGED
@@ -12,6 +12,7 @@
12
  namespace Monolog\Formatter;
13
 
14
  use Exception;
 
15
  use Throwable;
16
 
17
  /**
@@ -138,18 +139,23 @@ class JsonFormatter extends NormalizerFormatter
138
  *
139
  * @return mixed
140
  */
141
- protected function normalize($data)
142
  {
 
 
 
 
143
  if (is_array($data) || $data instanceof \Traversable) {
144
  $normalized = array();
145
 
146
  $count = 1;
147
  foreach ($data as $key => $value) {
148
- if ($count++ >= 1000) {
149
- $normalized['...'] = 'Over 1000 items, aborting normalization';
150
  break;
151
  }
152
- $normalized[$key] = $this->normalize($value);
 
153
  }
154
 
155
  return $normalized;
@@ -174,11 +180,11 @@ class JsonFormatter extends NormalizerFormatter
174
  {
175
  // TODO 2.0 only check for Throwable
176
  if (!$e instanceof Exception && !$e instanceof Throwable) {
177
- throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
178
  }
179
 
180
  $data = array(
181
- 'class' => get_class($e),
182
  'message' => $e->getMessage(),
183
  'code' => $e->getCode(),
184
  'file' => $e->getFile().':'.$e->getLine(),
12
  namespace Monolog\Formatter;
13
 
14
  use Exception;
15
+ use Monolog\Utils;
16
  use Throwable;
17
 
18
  /**
139
  *
140
  * @return mixed
141
  */
142
+ protected function normalize($data, $depth = 0)
143
  {
144
+ if ($depth > 9) {
145
+ return 'Over 9 levels deep, aborting normalization';
146
+ }
147
+
148
  if (is_array($data) || $data instanceof \Traversable) {
149
  $normalized = array();
150
 
151
  $count = 1;
152
  foreach ($data as $key => $value) {
153
+ if ($count++ > 1000) {
154
+ $normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization';
155
  break;
156
  }
157
+
158
+ $normalized[$key] = $this->normalize($value, $depth+1);
159
  }
160
 
161
  return $normalized;
180
  {
181
  // TODO 2.0 only check for Throwable
182
  if (!$e instanceof Exception && !$e instanceof Throwable) {
183
+ throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e));
184
  }
185
 
186
  $data = array(
187
+ 'class' => Utils::getClass($e),
188
  'message' => $e->getMessage(),
189
  'code' => $e->getCode(),
190
  'file' => $e->getFile().':'.$e->getLine(),
vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php CHANGED
@@ -11,6 +11,8 @@
11
 
12
  namespace Monolog\Formatter;
13
 
 
 
14
  /**
15
  * Formats incoming records into a one-line string
16
  *
@@ -129,17 +131,17 @@ class LineFormatter extends NormalizerFormatter
129
  {
130
  // TODO 2.0 only check for Throwable
131
  if (!$e instanceof \Exception && !$e instanceof \Throwable) {
132
- throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
133
  }
134
 
135
  $previousText = '';
136
  if ($previous = $e->getPrevious()) {
137
  do {
138
- $previousText .= ', '.get_class($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
139
  } while ($previous = $previous->getPrevious());
140
  }
141
 
142
- $str = '[object] ('.get_class($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')';
143
  if ($this->includeStacktraces) {
144
  $str .= "\n[stacktrace]\n".$e->getTraceAsString()."\n";
145
  }
11
 
12
  namespace Monolog\Formatter;
13
 
14
+ use Monolog\Utils;
15
+
16
  /**
17
  * Formats incoming records into a one-line string
18
  *
131
  {
132
  // TODO 2.0 only check for Throwable
133
  if (!$e instanceof \Exception && !$e instanceof \Throwable) {
134
+ throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e));
135
  }
136
 
137
  $previousText = '';
138
  if ($previous = $e->getPrevious()) {
139
  do {
140
+ $previousText .= ', '.Utils::getClass($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
141
  } while ($previous = $previous->getPrevious());
142
  }
143
 
144
+ $str = '[object] ('.Utils::getClass($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')';
145
  if ($this->includeStacktraces) {
146
  $str .= "\n[stacktrace]\n".$e->getTraceAsString()."\n";
147
  }
vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php CHANGED
@@ -11,6 +11,8 @@
11
 
12
  namespace Monolog\Formatter;
13
 
 
 
14
  /**
15
  * Formats a record for use with the MongoDBHandler.
16
  *
@@ -75,7 +77,7 @@ class MongoDBFormatter implements FormatterInterface
75
  protected function formatObject($value, $nestingLevel)
76
  {
77
  $objectVars = get_object_vars($value);
78
- $objectVars['class'] = get_class($value);
79
 
80
  return $this->formatArray($objectVars, $nestingLevel);
81
  }
@@ -83,7 +85,7 @@ class MongoDBFormatter implements FormatterInterface
83
  protected function formatException(\Exception $exception, $nestingLevel)
84
  {
85
  $formattedException = array(
86
- 'class' => get_class($exception),
87
  'message' => $exception->getMessage(),
88
  'code' => $exception->getCode(),
89
  'file' => $exception->getFile() . ':' . $exception->getLine(),
11
 
12
  namespace Monolog\Formatter;
13
 
14
+ use Monolog\Utils;
15
+
16
  /**
17
  * Formats a record for use with the MongoDBHandler.
18
  *
77
  protected function formatObject($value, $nestingLevel)
78
  {
79
  $objectVars = get_object_vars($value);
80
+ $objectVars['class'] = Utils::getClass($value);
81
 
82
  return $this->formatArray($objectVars, $nestingLevel);
83
  }
85
  protected function formatException(\Exception $exception, $nestingLevel)
86
  {
87
  $formattedException = array(
88
+ 'class' => Utils::getClass($exception),
89
  'message' => $exception->getMessage(),
90
  'code' => $exception->getCode(),
91
  'file' => $exception->getFile() . ':' . $exception->getLine(),
vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php CHANGED
@@ -12,6 +12,7 @@
12
  namespace Monolog\Formatter;
13
 
14
  use Exception;
 
15
 
16
  /**
17
  * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
@@ -55,8 +56,12 @@ class NormalizerFormatter implements FormatterInterface
55
  return $records;
56
  }
57
 
58
- protected function normalize($data)
59
  {
 
 
 
 
60
  if (null === $data || is_scalar($data)) {
61
  if (is_float($data)) {
62
  if (is_infinite($data)) {
@@ -75,11 +80,12 @@ class NormalizerFormatter implements FormatterInterface
75
 
76
  $count = 1;
77
  foreach ($data as $key => $value) {
78
- if ($count++ >= 1000) {
79
  $normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization';
80
  break;
81
  }
82
- $normalized[$key] = $this->normalize($value);
 
83
  }
84
 
85
  return $normalized;
@@ -103,7 +109,7 @@ class NormalizerFormatter implements FormatterInterface
103
  $value = $this->toJson($data, true);
104
  }
105
 
106
- return sprintf("[object] (%s: %s)", get_class($data), $value);
107
  }
108
 
109
  if (is_resource($data)) {
@@ -117,11 +123,11 @@ class NormalizerFormatter implements FormatterInterface
117
  {
118
  // TODO 2.0 only check for Throwable
119
  if (!$e instanceof Exception && !$e instanceof \Throwable) {
120
- throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
121
  }
122
 
123
  $data = array(
124
- 'class' => get_class($e),
125
  'message' => $e->getMessage(),
126
  'code' => $e->getCode(),
127
  'file' => $e->getFile().':'.$e->getLine(),
@@ -146,9 +152,20 @@ class NormalizerFormatter implements FormatterInterface
146
  if (isset($frame['file'])) {
147
  $data['trace'][] = $frame['file'].':'.$frame['line'];
148
  } elseif (isset($frame['function']) && $frame['function'] === '{closure}') {
149
- // We should again normalize the frames, because it might contain invalid items
150
  $data['trace'][] = $frame['function'];
151
  } else {
 
 
 
 
 
 
 
 
 
 
 
152
  // We should again normalize the frames, because it might contain invalid items
153
  $data['trace'][] = $this->toJson($this->normalize($frame), true);
154
  }
12
  namespace Monolog\Formatter;
13
 
14
  use Exception;
15
+ use Monolog\Utils;
16
 
17
  /**
18
  * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
56
  return $records;
57
  }
58
 
59
+ protected function normalize($data, $depth = 0)
60
  {
61
+ if ($depth > 9) {
62
+ return 'Over 9 levels deep, aborting normalization';
63
+ }
64
+
65
  if (null === $data || is_scalar($data)) {
66
  if (is_float($data)) {
67
  if (is_infinite($data)) {
80
 
81
  $count = 1;
82
  foreach ($data as $key => $value) {
83
+ if ($count++ > 1000) {
84
  $normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization';
85
  break;
86
  }
87
+
88
+ $normalized[$key] = $this->normalize($value, $depth+1);
89
  }
90
 
91
  return $normalized;
109
  $value = $this->toJson($data, true);
110
  }
111
 
112
+ return sprintf("[object] (%s: %s)", Utils::getClass($data), $value);
113
  }
114
 
115
  if (is_resource($data)) {
123
  {
124
  // TODO 2.0 only check for Throwable
125
  if (!$e instanceof Exception && !$e instanceof \Throwable) {
126
+ throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e));
127
  }
128
 
129
  $data = array(
130
+ 'class' => Utils::getClass($e),
131
  'message' => $e->getMessage(),
132
  'code' => $e->getCode(),
133
  'file' => $e->getFile().':'.$e->getLine(),
152
  if (isset($frame['file'])) {
153
  $data['trace'][] = $frame['file'].':'.$frame['line'];
154
  } elseif (isset($frame['function']) && $frame['function'] === '{closure}') {
155
+ // Simplify closures handling
156
  $data['trace'][] = $frame['function'];
157
  } else {
158
+ if (isset($frame['args'])) {
159
+ // Make sure that objects present as arguments are not serialized nicely but rather only
160
+ // as a class name to avoid any unexpected leak of sensitive information
161
+ $frame['args'] = array_map(function ($arg) {
162
+ if (is_object($arg) && !($arg instanceof \DateTime || $arg instanceof \DateTimeInterface)) {
163
+ return sprintf("[object] (%s)", Utils::getClass($arg));
164
+ }
165
+
166
+ return $arg;
167
+ }, $frame['args']);
168
+ }
169
  // We should again normalize the frames, because it might contain invalid items
170
  $data['trace'][] = $this->toJson($this->normalize($frame), true);
171
  }
vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php CHANGED
@@ -102,12 +102,12 @@ class WildfireFormatter extends NormalizerFormatter
102
  throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
103
  }
104
 
105
- protected function normalize($data)
106
  {
107
  if (is_object($data) && !$data instanceof \DateTime) {
108
  return $data;
109
  }
110
 
111
- return parent::normalize($data);
112
  }
113
  }
102
  throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
103
  }
104
 
105
+ protected function normalize($data, $depth = 0)
106
  {
107
  if (is_object($data) && !$data instanceof \DateTime) {
108
  return $data;
109
  }
110
 
111
+ return parent::normalize($data, $depth);
112
  }
113
  }
vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php CHANGED
@@ -11,16 +11,17 @@
11
 
12
  namespace Monolog\Handler;
13
 
14
- use Monolog\Logger;
15
  use Monolog\Formatter\FormatterInterface;
16
  use Monolog\Formatter\LineFormatter;
 
 
17
 
18
  /**
19
  * Base Handler class providing the Handler structure
20
  *
21
  * @author Jordi Boggiano <j.boggiano@seld.be>
22
  */
23
- abstract class AbstractHandler implements HandlerInterface
24
  {
25
  protected $level = Logger::DEBUG;
26
  protected $bubble = true;
@@ -32,8 +33,8 @@ abstract class AbstractHandler implements HandlerInterface
32
  protected $processors = array();
33
 
34
  /**
35
- * @param int $level The minimum logging level at which this handler will be triggered
36
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
37
  */
38
  public function __construct($level = Logger::DEBUG, $bubble = true)
39
  {
@@ -141,8 +142,8 @@ abstract class AbstractHandler implements HandlerInterface
141
  /**
142
  * Sets the bubbling behavior.
143
  *
144
- * @param Boolean $bubble true means that this handler allows bubbling.
145
- * false means that bubbling is not permitted.
146
  * @return self
147
  */
148
  public function setBubble($bubble)
@@ -155,8 +156,8 @@ abstract class AbstractHandler implements HandlerInterface
155
  /**
156
  * Gets the bubbling behavior.
157
  *
158
- * @return Boolean true means that this handler allows bubbling.
159
- * false means that bubbling is not permitted.
160
  */
161
  public function getBubble()
162
  {
@@ -174,6 +175,15 @@ abstract class AbstractHandler implements HandlerInterface
174
  }
175
  }
176
 
 
 
 
 
 
 
 
 
 
177
  /**
178
  * Gets the default formatter.
179
  *
11
 
12
  namespace Monolog\Handler;
13
 
 
14
  use Monolog\Formatter\FormatterInterface;
15
  use Monolog\Formatter\LineFormatter;
16
+ use Monolog\Logger;
17
+ use Monolog\ResettableInterface;
18
 
19
  /**
20
  * Base Handler class providing the Handler structure
21
  *
22
  * @author Jordi Boggiano <j.boggiano@seld.be>
23
  */
24
+ abstract class AbstractHandler implements HandlerInterface, ResettableInterface
25
  {
26
  protected $level = Logger::DEBUG;
27
  protected $bubble = true;
33
  protected $processors = array();
34
 
35
  /**
36
+ * @param int $level The minimum logging level at which this handler will be triggered
37
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
38
  */
39
  public function __construct($level = Logger::DEBUG, $bubble = true)
40
  {
142
  /**
143
  * Sets the bubbling behavior.
144
  *
145
+ * @param bool $bubble true means that this handler allows bubbling.
146
+ * false means that bubbling is not permitted.
147
  * @return self
148
  */
149
  public function setBubble($bubble)
156
  /**
157
  * Gets the bubbling behavior.
158
  *
159
+ * @return bool true means that this handler allows bubbling.
160
+ * false means that bubbling is not permitted.
161
  */
162
  public function getBubble()
163
  {
175
  }
176
  }
177
 
178
+ public function reset()
179
+ {
180
+ foreach ($this->processors as $processor) {
181
+ if ($processor instanceof ResettableInterface) {
182
+ $processor->reset();
183
+ }
184
+ }
185
+ }
186
+
187
  /**
188
  * Gets the default formatter.
189
  *
vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php CHANGED
@@ -11,6 +11,8 @@
11
 
12
  namespace Monolog\Handler;
13
 
 
 
14
  /**
15
  * Base Handler class providing the Handler structure
16
  *
11
 
12
  namespace Monolog\Handler;
13
 
14
+ use Monolog\ResettableInterface;
15
+
16
  /**
17
  * Base Handler class providing the Handler structure
18
  *
vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php CHANGED
@@ -53,9 +53,9 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler
53
  );
54
 
55
  /**
56
- * @param mixed $facility
57
- * @param int $level The minimum logging level at which this handler will be triggered
58
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
59
  */
60
  public function __construct($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true)
61
  {
53
  );
54
 
55
  /**
56
+ * @param mixed $facility
57
+ * @param int $level The minimum logging level at which this handler will be triggered
58
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
59
  */
60
  public function __construct($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true)
61
  {
vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php CHANGED
@@ -43,11 +43,11 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
43
  protected function write(array $record)
44
  {
45
  // Accumulate records
46
- self::$records[] = $record;
47
 
48
  // Register shutdown handler if not already done
49
- if (!self::$initialized) {
50
- self::$initialized = true;
51
  $this->registerShutdownFunction();
52
  }
53
  }
@@ -58,27 +58,37 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
58
  */
59
  public static function send()
60
  {
61
- $format = self::getResponseFormat();
62
  if ($format === 'unknown') {
63
  return;
64
  }
65
 
66
- if (count(self::$records)) {
67
  if ($format === 'html') {
68
- self::writeOutput('<script>' . self::generateScript() . '</script>');
69
  } elseif ($format === 'js') {
70
- self::writeOutput(self::generateScript());
71
  }
72
- self::reset();
73
  }
74
  }
75
 
 
 
 
 
 
 
 
 
 
 
76
  /**
77
  * Forget all logged records
78
  */
79
- public static function reset()
80
  {
81
- self::$records = array();
82
  }
83
 
84
  /**
@@ -133,18 +143,18 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
133
  private static function generateScript()
134
  {
135
  $script = array();
136
- foreach (self::$records as $record) {
137
- $context = self::dump('Context', $record['context']);
138
- $extra = self::dump('Extra', $record['extra']);
139
 
140
  if (empty($context) && empty($extra)) {
141
- $script[] = self::call_array('log', self::handleStyles($record['formatted']));
142
  } else {
143
  $script = array_merge($script,
144
- array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))),
145
  $context,
146
  $extra,
147
- array(self::call('groupEnd'))
148
  );
149
  }
150
  }
@@ -154,19 +164,19 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
154
 
155
  private static function handleStyles($formatted)
156
  {
157
- $args = array(self::quote('font-weight: normal'));
158
  $format = '%c' . $formatted;
159
  preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
160
 
161
  foreach (array_reverse($matches) as $match) {
162
- $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0]));
163
  $args[] = '"font-weight: normal"';
164
 
165
  $pos = $match[0][1];
166
  $format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0]));
167
  }
168
 
169
- array_unshift($args, self::quote($format));
170
 
171
  return $args;
172
  }
@@ -198,13 +208,13 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
198
  if (empty($dict)) {
199
  return $script;
200
  }
201
- $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title));
202
  foreach ($dict as $key => $value) {
203
  $value = json_encode($value);
204
  if (empty($value)) {
205
- $value = self::quote('');
206
  }
207
- $script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value);
208
  }
209
 
210
  return $script;
@@ -220,7 +230,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
220
  $args = func_get_args();
221
  $method = array_shift($args);
222
 
223
- return self::call_array($method, $args);
224
  }
225
 
226
  private static function call_array($method, array $args)
43
  protected function write(array $record)
44
  {
45
  // Accumulate records
46
+ static::$records[] = $record;
47
 
48
  // Register shutdown handler if not already done
49
+ if (!static::$initialized) {
50
+ static::$initialized = true;
51
  $this->registerShutdownFunction();
52
  }
53
  }
58
  */
59
  public static function send()
60
  {
61
+ $format = static::getResponseFormat();
62
  if ($format === 'unknown') {
63
  return;
64
  }
65
 
66
+ if (count(static::$records)) {
67
  if ($format === 'html') {
68
+ static::writeOutput('<script>' . static::generateScript() . '</script>');
69
  } elseif ($format === 'js') {
70
+ static::writeOutput(static::generateScript());
71
  }
72
+ static::resetStatic();
73
  }
74
  }
75
 
76
+ public function close()
77
+ {
78
+ self::resetStatic();
79
+ }
80
+
81
+ public function reset()
82
+ {
83
+ self::resetStatic();
84
+ }
85
+
86
  /**
87
  * Forget all logged records
88
  */
89
+ public static function resetStatic()
90
  {
91
+ static::$records = array();
92
  }
93
 
94
  /**
143
  private static function generateScript()
144
  {
145
  $script = array();
146
+ foreach (static::$records as $record) {
147
+ $context = static::dump('Context', $record['context']);
148
+ $extra = static::dump('Extra', $record['extra']);
149
 
150
  if (empty($context) && empty($extra)) {
151
+ $script[] = static::call_array('log', static::handleStyles($record['formatted']));
152
  } else {
153
  $script = array_merge($script,
154
+ array(static::call_array('groupCollapsed', static::handleStyles($record['formatted']))),
155
  $context,
156
  $extra,
157
+ array(static::call('groupEnd'))
158
  );
159
  }
160
  }
164
 
165
  private static function handleStyles($formatted)
166
  {
167
+ $args = array(static::quote('font-weight: normal'));
168
  $format = '%c' . $formatted;
169
  preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
170
 
171
  foreach (array_reverse($matches) as $match) {
172
+ $args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
173
  $args[] = '"font-weight: normal"';
174
 
175
  $pos = $match[0][1];
176
  $format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0]));
177
  }
178
 
179
+ array_unshift($args, static::quote($format));
180
 
181
  return $args;
182
  }
208
  if (empty($dict)) {
209
  return $script;
210
  }
211
+ $script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title));
212
  foreach ($dict as $key => $value) {
213
  $value = json_encode($value);
214
  if (empty($value)) {
215
+ $value = static::quote('');
216
  }
217
+ $script[] = static::call('log', static::quote('%s: %o'), static::quote($key), $value);
218
  }
219
 
220
  return $script;
230
  $args = func_get_args();
231
  $method = array_shift($args);
232
 
233
+ return static::call_array($method, $args);
234
  }
235
 
236
  private static function call_array($method, array $args)
vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php CHANGED
@@ -12,6 +12,7 @@
12
  namespace Monolog\Handler;
13
 
14
  use Monolog\Logger;
 
15
 
16
  /**
17
  * Buffers all records until closing the handler and then pass them as batch.
@@ -34,8 +35,8 @@ class BufferHandler extends AbstractHandler
34
  * @param HandlerInterface $handler Handler.
35
  * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
36
  * @param int $level The minimum logging level at which this handler will be triggered
37
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
38
- * @param Boolean $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
39
  */
40
  public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false)
41
  {
@@ -114,4 +115,15 @@ class BufferHandler extends AbstractHandler
114
  $this->bufferSize = 0;
115
  $this->buffer = array();
116
  }
 
 
 
 
 
 
 
 
 
 
 
117
  }
12
  namespace Monolog\Handler;
13
 
14
  use Monolog\Logger;
15
+ use Monolog\ResettableInterface;
16
 
17
  /**
18
  * Buffers all records until closing the handler and then pass them as batch.
35
  * @param HandlerInterface $handler Handler.
36
  * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
37
  * @param int $level The minimum logging level at which this handler will be triggered
38
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
39
+ * @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
40
  */
41
  public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false)
42
  {
115
  $this->bufferSize = 0;
116
  $this->buffer = array();
117
  }
118
+
119
+ public function reset()
120
+ {
121
+ $this->flush();
122
+
123
+ parent::reset();
124
+
125
+ if ($this->handler instanceof ResettableInterface) {
126
+ $this->handler->reset();
127
+ }
128
+ }
129
  }
vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php CHANGED
@@ -32,7 +32,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
32
  * Header name
33
  */
34
  const HEADER_NAME = 'X-ChromeLogger-Data';
35
-
36
  /**
37
  * Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
38
  */
@@ -45,7 +45,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
45
  *
46
  * Chrome limits the headers to 256KB, so when we sent 240KB we stop sending
47
  *
48
- * @var Boolean
49
  */
50
  protected static $overflowed = false;
51
 
@@ -58,8 +58,8 @@ class ChromePHPHandler extends AbstractProcessingHandler
58
  protected static $sendHeaders = true;
59
 
60
  /**
61
- * @param int $level The minimum logging level at which this handler will be triggered
62
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
63
  */
64
  public function __construct($level = Logger::DEBUG, $bubble = true)
65
  {
@@ -174,7 +174,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
174
  /**
175
  * Verifies if the headers are accepted by the current user agent
176
  *
177
- * @return Boolean
178
  */
179
  protected function headersAccepted()
180
  {
32
  * Header name
33
  */
34
  const HEADER_NAME = 'X-ChromeLogger-Data';
35
+
36
  /**
37
  * Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
38
  */
45
  *
46
  * Chrome limits the headers to 256KB, so when we sent 240KB we stop sending
47
  *
48
+ * @var bool
49
  */
50
  protected static $overflowed = false;
51
 
58
  protected static $sendHeaders = true;
59
 
60
  /**
61
+ * @param int $level The minimum logging level at which this handler will be triggered
62
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
63
  */
64
  public function __construct($level = Logger::DEBUG, $bubble = true)
65
  {
174
  /**
175
  * Verifies if the headers are accepted by the current user agent
176
  *
177
+ * @return bool
178
  */
179
  protected function headersAccepted()
180
  {
vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php CHANGED
@@ -60,7 +60,7 @@ class DeduplicationHandler extends BufferHandler
60
  * @param string $deduplicationStore The file/path where the deduplication log should be kept
61
  * @param int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
62
  * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
63
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
64
  */
65
  public function __construct(HandlerInterface $handler, $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, $time = 60, $bubble = true)
66
  {
60
  * @param string $deduplicationStore The file/path where the deduplication log should be kept
61
  * @param int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
62
  * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
63
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
64
  */
65
  public function __construct(HandlerInterface $handler, $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, $time = 60, $bubble = true)
66
  {
vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php CHANGED
@@ -46,10 +46,10 @@ class ElasticSearchHandler extends AbstractProcessingHandler
46
  protected $options = array();
47
 
48
  /**
49
- * @param Client $client Elastica Client object
50
- * @param array $options Handler configuration
51
- * @param int $level The minimum logging level at which this handler will be triggered
52
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
53
  */
54
  public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true)
55
  {
46
  protected $options = array();
47
 
48
  /**
49
+ * @param Client $client Elastica Client object
50
+ * @param array $options Handler configuration
51
+ * @param int $level The minimum logging level at which this handler will be triggered
52
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
53
  */
54
  public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true)
55
  {
vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php CHANGED
@@ -28,10 +28,10 @@ class ErrorLogHandler extends AbstractProcessingHandler
28
  protected $expandNewlines;
29
 
30
  /**
31
- * @param int $messageType Says where the error should go.
32
- * @param int $level The minimum logging level at which this handler will be triggered
33
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
34
- * @param Boolean $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
35
  */
36
  public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true, $expandNewlines = false)
37
  {
28
  protected $expandNewlines;
29
 
30
  /**
31
+ * @param int $messageType Says where the error should go.
32
+ * @param int $level The minimum logging level at which this handler will be triggered
33
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
34
+ * @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
35
  */
36
  public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true, $expandNewlines = false)
37
  {
vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php CHANGED
@@ -40,7 +40,7 @@ class FilterHandler extends AbstractHandler
40
  /**
41
  * Whether the messages that are handled can bubble up the stack or not
42
  *
43
- * @var Boolean
44
  */
45
  protected $bubble;
46
 
@@ -48,7 +48,7 @@ class FilterHandler extends AbstractHandler
48
  * @param callable|HandlerInterface $handler Handler or factory callable($record, $this).
49
  * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
50
  * @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
51
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
52
  */
53
  public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, $bubble = true)
54
  {
40
  /**
41
  * Whether the messages that are handled can bubble up the stack or not
42
  *
43
+ * @var bool
44
  */
45
  protected $bubble;
46
 
48
  * @param callable|HandlerInterface $handler Handler or factory callable($record, $this).
49
  * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
50
  * @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
51
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
52
  */
53
  public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, $bubble = true)
54
  {
vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php CHANGED
@@ -22,7 +22,7 @@ interface ActivationStrategyInterface
22
  * Returns whether the given record activates the handler.
23
  *
24
  * @param array $record
25
- * @return Boolean
26
  */
27
  public function isHandlerActivated(array $record);
28
  }
22
  * Returns whether the given record activates the handler.
23
  *
24
  * @param array $record
25
+ * @return bool
26
  */
27
  public function isHandlerActivated(array $record);
28
  }
vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php CHANGED
@@ -14,6 +14,7 @@ namespace Monolog\Handler;
14
  use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
15
  use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
16
  use Monolog\Logger;
 
17
 
18
  /**
19
  * Buffers all records until a certain level is reached
@@ -41,8 +42,8 @@ class FingersCrossedHandler extends AbstractHandler
41
  * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler).
42
  * @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action
43
  * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
44
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
45
- * @param Boolean $stopBuffering Whether the handler should stop buffering after being triggered (default true)
46
  * @param int $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
47
  */
48
  public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true, $passthruLevel = null)
@@ -130,24 +131,18 @@ class FingersCrossedHandler extends AbstractHandler
130
  */
131
  public function close()
132
  {
133
- if (null !== $this->passthruLevel) {
134
- $level = $this->passthruLevel;
135
- $this->buffer = array_filter($this->buffer, function ($record) use ($level) {
136
- return $record['level'] >= $level;
137
- });
138
- if (count($this->buffer) > 0) {
139
- $this->handler->handleBatch($this->buffer);
140
- $this->buffer = array();
141
- }
142
- }
143
  }
144
 
145
- /**
146
- * Resets the state of the handler. Stops forwarding records to the wrapped handler.
147
- */
148
  public function reset()
149
  {
150
- $this->buffering = true;
 
 
 
 
 
 
151
  }
152
 
153
  /**
@@ -160,4 +155,23 @@ class FingersCrossedHandler extends AbstractHandler
160
  $this->buffer = array();
161
  $this->reset();
162
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  }
14
  use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
15
  use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
16
  use Monolog\Logger;
17
+ use Monolog\ResettableInterface;
18
 
19
  /**
20
  * Buffers all records until a certain level is reached
42
  * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler).
43
  * @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action
44
  * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
45
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
46
+ * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
47
  * @param int $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
48
  */
49
  public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true, $passthruLevel = null)
131
  */
132
  public function close()
133
  {
134
+ $this->flushBuffer();
 
 
 
 
 
 
 
 
 
135
  }
136
 
 
 
 
137
  public function reset()
138
  {
139
+ $this->flushBuffer();
140
+
141
+ parent::reset();
142
+
143
+ if ($this->handler instanceof ResettableInterface) {
144
+ $this->handler->reset();
145
+ }
146
  }
147
 
148
  /**
155
  $this->buffer = array();
156
  $this->reset();
157
  }
158
+
159
+ /**
160
+ * Resets the state of the handler. Stops forwarding records to the wrapped handler.
161
+ */
162
+ private function flushBuffer()
163
+ {
164
+ if (null !== $this->passthruLevel) {
165
+ $level = $this->passthruLevel;
166
+ $this->buffer = array_filter($this->buffer, function ($record) use ($level) {
167
+ return $record['level'] >= $level;
168
+ });
169
+ if (count($this->buffer) > 0) {
170
+ $this->handler->handleBatch($this->buffer);
171
+ }
172
+ }
173
+
174
+ $this->buffer = array();
175
+ $this->buffering = true;
176
+ }
177
  }
vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php CHANGED
@@ -158,7 +158,7 @@ class FirePHPHandler extends AbstractProcessingHandler
158
  /**
159
  * Verifies if the headers are accepted by the current user agent
160
  *
161
- * @return Boolean
162
  */
163
  protected function headersAccepted()
164
  {
158
  /**
159
  * Verifies if the headers are accepted by the current user agent
160
  *
161
+ * @return bool
162
  */
163
  protected function headersAccepted()
164
  {
vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php CHANGED
@@ -47,14 +47,6 @@ class GelfHandler extends AbstractProcessingHandler
47
  $this->publisher = $publisher;
48
  }
49
 
50
- /**
51
- * {@inheritdoc}
52
- */
53
- public function close()
54
- {
55
- $this->publisher = null;
56
- }
57
-
58
  /**
59
  * {@inheritdoc}
60
  */
47
  $this->publisher = $publisher;
48
  }
49
 
 
 
 
 
 
 
 
 
50
  /**
51
  * {@inheritdoc}
52
  */
vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php CHANGED
@@ -12,6 +12,7 @@
12
  namespace Monolog\Handler;
13
 
14
  use Monolog\Formatter\FormatterInterface;
 
15
 
16
  /**
17
  * Forwards records to multiple handlers
@@ -23,8 +24,8 @@ class GroupHandler extends AbstractHandler
23
  protected $handlers;
24
 
25
  /**
26
- * @param array $handlers Array of Handlers.
27
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
28
  */
29
  public function __construct(array $handlers, $bubble = true)
30
  {
@@ -90,6 +91,17 @@ class GroupHandler extends AbstractHandler
90
  }
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
93
  /**
94
  * {@inheritdoc}
95
  */
12
  namespace Monolog\Handler;
13
 
14
  use Monolog\Formatter\FormatterInterface;
15
+ use Monolog\ResettableInterface;
16
 
17
  /**
18
  * Forwards records to multiple handlers
24
  protected $handlers;
25
 
26
  /**
27
+ * @param array $handlers Array of Handlers.
28
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
29
  */
30
  public function __construct(array $handlers, $bubble = true)
31
  {
91
  }
92
  }
93
 
94
+ public function reset()
95
+ {
96
+ parent::reset();
97
+
98
+ foreach ($this->handlers as $handler) {
99
+ if ($handler instanceof ResettableInterface) {
100
+ $handler->reset();
101
+ }
102
+ }
103
+ }
104
+
105
  /**
106
  * {@inheritdoc}
107
  */
vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php CHANGED
@@ -31,7 +31,7 @@ interface HandlerInterface
31
  *
32
  * @param array $record Partial log record containing only a level key
33
  *
34
- * @return Boolean
35
  */
36
  public function isHandling(array $record);
37
 
@@ -46,7 +46,7 @@ interface HandlerInterface
46
  * calling further handlers in the stack with a given log record.
47
  *
48
  * @param array $record The record to handle
49
- * @return Boolean true means that this handler handled the record, and that bubbling is not permitted.
50
  * false means the record was either not processed or that this handler allows bubbling.
51
  */
52
  public function handle(array $record);
31
  *
32
  * @param array $record Partial log record containing only a level key
33
  *
34
+ * @return bool
35
  */
36
  public function isHandling(array $record);
37
 
46
  * calling further handlers in the stack with a given log record.
47
  *
48
  * @param array $record The record to handle
49
+ * @return bool true means that this handler handled the record, and that bubbling is not permitted.
50
  * false means the record was either not processed or that this handler allows bubbling.
51
  */
52
  public function handle(array $record);
vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php CHANGED
@@ -11,6 +11,7 @@
11
 
12
  namespace Monolog\Handler;
13
 
 
14
  use Monolog\Formatter\FormatterInterface;
15
 
16
  /**
@@ -30,7 +31,7 @@ use Monolog\Formatter\FormatterInterface;
30
  *
31
  * @author Alexey Karapetov <alexey@karapetov.com>
32
  */
33
- class HandlerWrapper implements HandlerInterface
34
  {
35
  /**
36
  * @var HandlerInterface
@@ -105,4 +106,11 @@ class HandlerWrapper implements HandlerInterface
105
  {
106
  return $this->handler->getFormatter();
107
  }
 
 
 
 
 
 
 
108
  }
11
 
12
  namespace Monolog\Handler;
13
 
14
+ use Monolog\ResettableInterface;
15
  use Monolog\Formatter\FormatterInterface;
16
 
17
  /**
31
  *
32
  * @author Alexey Karapetov <alexey@karapetov.com>
33
  */
34
+ class HandlerWrapper implements HandlerInterface, ResettableInterface
35
  {
36
  /**
37
  * @var HandlerInterface
106
  {
107
  return $this->handler->getFormatter();
108
  }
109
+
110
+ public function reset()
111
+ {
112
+ if ($this->handler instanceof ResettableInterface) {
113
+ return $this->handler->reset();
114
+ }
115
+ }
116
  }
vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php CHANGED
@@ -219,6 +219,21 @@ class HipChatHandler extends SocketHandler
219
  protected function write(array $record)
220
  {
221
  parent::write($record);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  $this->closeSocket();
223
  }
224
 
219
  protected function write(array $record)
220
  {
221
  parent::write($record);
222
+ $this->finalizeWrite();
223
+ }
224
+
225
+ /**
226
+ * Finalizes the request by reading some bytes and then closing the socket
227
+ *
228
+ * If we do not read some but close the socket too early, hipchat sometimes
229
+ * drops the request entirely.
230
+ */
231
+ protected function finalizeWrite()
232
+ {
233
+ $res = $this->getResource();
234
+ if (is_resource($res)) {
235
+ @fread($res, 2048);
236
+ }
237
  $this->closeSocket();
238
  }
239
 
vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php CHANGED
@@ -30,10 +30,10 @@ class IFTTTHandler extends AbstractProcessingHandler
30
  private $secretKey;
31
 
32
  /**
33
- * @param string $eventName The name of the IFTTT Maker event that should be triggered
34
- * @param string $secretKey A valid IFTTT secret key
35
- * @param int $level The minimum logging level at which this handler will be triggered
36
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
37
  */
38
  public function __construct($eventName, $secretKey, $level = Logger::ERROR, $bubble = true)
39
  {
30
  private $secretKey;
31
 
32
  /**
33
+ * @param string $eventName The name of the IFTTT Maker event that should be triggered
34
+ * @param string $secretKey A valid IFTTT secret key
35
+ * @param int $level The minimum logging level at which this handler will be triggered
36
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
37
  */
38
  public function __construct($eventName, $secretKey, $level = Logger::ERROR, $bubble = true)
39
  {
vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of the Monolog package.
5
+ *
6
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Monolog\Handler;
13
+
14
+ use Monolog\Logger;
15
+
16
+ /**
17
+ * Inspired on LogEntriesHandler.
18
+ *
19
+ * @author Robert Kaufmann III <rok3@rok3.me>
20
+ * @author Gabriel Machado <gabriel.ms1@hotmail.com>
21
+ */
22
+ class InsightOpsHandler extends SocketHandler
23
+ {
24
+ /**
25
+ * @var string
26
+ */
27
+ protected $logToken;
28
+
29
+ /**
30
+ * @param string $token Log token supplied by InsightOps
31
+ * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
32
+ * @param bool $useSSL Whether or not SSL encryption should be used
33
+ * @param int $level The minimum logging level to trigger this handler
34
+ * @param bool $bubble Whether or not messages that are handled should bubble up the stack.
35
+ *
36
+ * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
37
+ */
38
+ public function __construct($token, $region = 'us', $useSSL = true, $level = Logger::DEBUG, $bubble = true)
39
+ {
40
+ if ($useSSL && !extension_loaded('openssl')) {
41
+ throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
42
+ }
43
+
44
+ $endpoint = $useSSL
45
+ ? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443'
46
+ : $region . '.data.logs.insight.rapid7.com:80';
47
+
48
+ parent::__construct($endpoint, $level, $bubble);
49
+ $this->logToken = $token;
50
+ }
51
+
52
+ /**
53
+ * {@inheritdoc}
54
+ *
55
+ * @param array $record
56
+ * @return string
57
+ */
58
+ protected function generateDataStream($record)
59
+ {
60
+ return $this->logToken . ' ' . $record['formatted'];
61
+ }
62
+ }
vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php CHANGED
@@ -31,13 +31,13 @@ class LogEntriesHandler extends SocketHandler
31
  *
32
  * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
33
  */
34
- public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true)
35
  {
36
  if ($useSSL && !extension_loaded('openssl')) {
37
  throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
38
  }
39
 
40
- $endpoint = $useSSL ? 'ssl://data.logentries.com:443' : 'data.logentries.com:80';
41
  parent::__construct($endpoint, $level, $bubble);
42
  $this->logToken = $token;
43
  }
31
  *
32
  * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
33
  */
34
+ public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true, $host = 'data.logentries.com')
35
  {
36
  if ($useSSL && !extension_loaded('openssl')) {
37
  throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
38
  }
39
 
40
+ $endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80';
41
  parent::__construct($endpoint, $level, $bubble);
42
  $this->logToken = $token;
43
  }
vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php CHANGED
@@ -27,7 +27,7 @@ class MandrillHandler extends MailHandler
27
  * @param string $apiKey A valid Mandrill API key
28
  * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
29
  * @param int $level The minimum logging level at which this handler will be triggered
30
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
31
  */
32
  public function __construct($apiKey, $message, $level = Logger::ERROR, $bubble = true)
33
  {
27
  * @param string $apiKey A valid Mandrill API key
28
  * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
29
  * @param int $level The minimum logging level at which this handler will be triggered
30
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
31
  */
32
  public function __construct($apiKey, $message, $level = Logger::ERROR, $bubble = true)
33
  {
vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php CHANGED
@@ -18,6 +18,8 @@ use Monolog\Formatter\NormalizerFormatter;
18
  * Class to record a log on a NewRelic application.
19
  * Enabling New Relic High Security mode may prevent capture of useful information.
20
  *
 
 
21
  * @see https://docs.newrelic.com/docs/agents/php-agent
22
  * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
23
  */
@@ -84,7 +86,7 @@ class NewRelicHandler extends AbstractProcessingHandler
84
  unset($record['formatted']['context']['transaction_name']);
85
  }
86
 
87
- if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
88
  newrelic_notice_error($record['message'], $record['context']['exception']);
89
  unset($record['formatted']['context']['exception']);
90
  } else {
18
  * Class to record a log on a NewRelic application.
19
  * Enabling New Relic High Security mode may prevent capture of useful information.
20
  *
21
+ * This handler requires a NormalizerFormatter to function and expects an array in $record['formatted']
22
+ *
23
  * @see https://docs.newrelic.com/docs/agents/php-agent
24
  * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
25
  */
86
  unset($record['formatted']['context']['transaction_name']);
87
  }
88
 
89
+ if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
90
  newrelic_notice_error($record['message'], $record['context']['exception']);
91
  unset($record['formatted']['context']['exception']);
92
  } else {
vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php CHANGED
@@ -31,7 +31,7 @@ class PsrHandler extends AbstractHandler
31
  /**
32
  * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
33
  * @param int $level The minimum logging level at which this handler will be triggered
34
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
35
  */
36
  public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true)
37
  {
31
  /**
32
  * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
33
  * @param int $level The minimum logging level at which this handler will be triggered
34
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
35
  */
36
  public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true)
37
  {
vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php CHANGED
@@ -69,8 +69,8 @@ class PushoverHandler extends SocketHandler
69
  * @param string|array $users Pushover user id or array of ids the message will be sent to
70
  * @param string $title Title sent to the Pushover API
71
  * @param int $level The minimum logging level at which this handler will be triggered
72
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
73
- * @param Boolean $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
74
  * the pushover.net app owner. OpenSSL is required for this option.
75
  * @param int $highPriorityLevel The minimum logging level at which this handler will start
76
  * sending "high priority" requests to the Pushover API
@@ -180,6 +180,6 @@ class PushoverHandler extends SocketHandler
180
  */
181
  public function useFormattedMessage($value)
182
  {
183
- $this->useFormattedMessage = (boolean) $value;
184
  }
185
  }
69
  * @param string|array $users Pushover user id or array of ids the message will be sent to
70
  * @param string $title Title sent to the Pushover API
71
  * @param int $level The minimum logging level at which this handler will be triggered
72
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
73
+ * @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
74
  * the pushover.net app owner. OpenSSL is required for this option.
75
  * @param int $highPriorityLevel The minimum logging level at which this handler will start
76
  * sending "high priority" requests to the Pushover API
180
  */
181
  public function useFormattedMessage($value)
182
  {
183
+ $this->useFormattedMessage = (bool) $value;
184
  }
185
  }
vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php CHANGED
@@ -18,7 +18,7 @@ use Raven_Client;
18
 
19
  /**
20
  * Handler to send messages to a Sentry (https://github.com/getsentry/sentry) server
21
- * using raven-php (https://github.com/getsentry/raven-php)
22
  *
23
  * @author Marc Abramowitz <marc@marc-abramowitz.com>
24
  */
@@ -27,7 +27,7 @@ class RavenHandler extends AbstractProcessingHandler
27
  /**
28
  * Translates Monolog log levels to Raven log levels.
29
  */
30
- private $logLevels = array(
31
  Logger::DEBUG => Raven_Client::DEBUG,
32
  Logger::INFO => Raven_Client::INFO,
33
  Logger::NOTICE => Raven_Client::INFO,
@@ -42,7 +42,7 @@ class RavenHandler extends AbstractProcessingHandler
42
  * @var string should represent the current version of the calling
43
  * software. Can be any string (git commit, version number)
44
  */
45
- private $release;
46
 
47
  /**
48
  * @var Raven_Client the client object that sends the message to the server
@@ -57,7 +57,7 @@ class RavenHandler extends AbstractProcessingHandler
57
  /**
58
  * @param Raven_Client $ravenClient
59
  * @param int $level The minimum logging level at which this handler will be triggered
60
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
61
  */
62
  public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
63
  {
@@ -180,7 +180,7 @@ class RavenHandler extends AbstractProcessingHandler
180
  }
181
 
182
  if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
183
- $options['extra']['message'] = $record['formatted'];
184
  $this->ravenClient->captureException($record['context']['exception'], $options);
185
  } else {
186
  $this->ravenClient->captureMessage($record['formatted'], array(), $options);
@@ -216,7 +216,7 @@ class RavenHandler extends AbstractProcessingHandler
216
  */
217
  protected function getExtraParameters()
218
  {
219
- return array('checksum', 'release', 'event_id');
220
  }
221
 
222
  /**
18
 
19
  /**
20
  * Handler to send messages to a Sentry (https://github.com/getsentry/sentry) server
21
+ * using sentry-php (https://github.com/getsentry/sentry-php)
22
  *
23
  * @author Marc Abramowitz <marc@marc-abramowitz.com>
24
  */
27
  /**
28
  * Translates Monolog log levels to Raven log levels.
29
  */
30
+ protected $logLevels = array(
31
  Logger::DEBUG => Raven_Client::DEBUG,
32
  Logger::INFO => Raven_Client::INFO,
33
  Logger::NOTICE => Raven_Client::INFO,
42
  * @var string should represent the current version of the calling
43
  * software. Can be any string (git commit, version number)
44
  */
45
+ protected $release;
46
 
47
  /**
48
  * @var Raven_Client the client object that sends the message to the server
57
  /**
58
  * @param Raven_Client $ravenClient
59
  * @param int $level The minimum logging level at which this handler will be triggered
60
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
61
  */
62
  public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
63
  {
180
  }
181
 
182
  if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
183
+ $options['message'] = $record['formatted'];
184
  $this->ravenClient->captureException($record['context']['exception'], $options);
185
  } else {
186
  $this->ravenClient->captureMessage($record['formatted'], array(), $options);
216
  */
217
  protected function getExtraParameters()
218
  {
219
+ return array('contexts', 'checksum', 'release', 'event_id');
220
  }
221
 
222
  /**
vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php CHANGED
@@ -129,4 +129,16 @@ class RollbarHandler extends AbstractProcessingHandler
129
  {
130
  $this->flush();
131
  }
 
 
 
 
 
 
 
 
 
 
 
 
132
  }
129
  {
130
  $this->flush();
131
  }
132
+
133
+ /**
134
+ * {@inheritdoc}
135
+ */
136
+ public function reset()
137
+ {
138
+ $this->flush();
139
+
140
+ parent::reset();
141
+ }
142
+
143
+
144
  }
vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php CHANGED
@@ -39,9 +39,9 @@ class RotatingFileHandler extends StreamHandler
39
  * @param string $filename
40
  * @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
41
  * @param int $level The minimum logging level at which this handler will be triggered
42
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
43
  * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
44
- * @param Boolean $useLocking Try to lock log file before doing any writes
45
  */
46
  public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)
47
  {
@@ -66,6 +66,18 @@ class RotatingFileHandler extends StreamHandler
66
  }
67
  }
68
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  public function setFilenameFormat($filenameFormat, $dateFormat)
70
  {
71
  if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
@@ -166,7 +178,7 @@ class RotatingFileHandler extends StreamHandler
166
  $fileInfo = pathinfo($this->filename);
167
  $glob = str_replace(
168
  array('{filename}', '{date}'),
169
- array($fileInfo['filename'], '*'),
170
  $fileInfo['dirname'] . '/' . $this->filenameFormat
171
  );
172
  if (!empty($fileInfo['extension'])) {
39
  * @param string $filename
40
  * @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
41
  * @param int $level The minimum logging level at which this handler will be triggered
42
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
43
  * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
44
+ * @param bool $useLocking Try to lock log file before doing any writes
45
  */
46
  public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)
47
  {
66
  }
67
  }
68
 
69
+ /**
70
+ * {@inheritdoc}
71
+ */
72
+ public function reset()
73
+ {
74
+ parent::reset();
75
+
76
+ if (true === $this->mustRotate) {
77
+ $this->rotate();
78
+ }
79
+ }
80
+
81
  public function setFilenameFormat($filenameFormat, $dateFormat)
82
  {
83
  if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
178
  $fileInfo = pathinfo($this->filename);
179
  $glob = str_replace(
180
  array('{filename}', '{date}'),
181
+ array($fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'),
182
  $fileInfo['dirname'] . '/' . $this->filenameFormat
183
  );
184
  if (!empty($fileInfo['extension'])) {
vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php CHANGED
@@ -146,7 +146,7 @@ class SlackRecord
146
 
147
  if ($this->useShortAttachment) {
148
  $attachment['fields'][] = $this->generateAttachmentField(
149
- ucfirst($key),
150
  $record[$key]
151
  );
152
  } else {
@@ -229,8 +229,8 @@ class SlackRecord
229
  /**
230
  * Generates attachment field
231
  *
232
- * @param string $title
233
- * @param string|array $value\
234
  *
235
  * @return array
236
  */
@@ -241,7 +241,7 @@ class SlackRecord
241
  : $value;
242
 
243
  return array(
244
- 'title' => $title,
245
  'value' => $value,
246
  'short' => false
247
  );
@@ -257,7 +257,7 @@ class SlackRecord
257
  private function generateAttachmentFields(array $data)
258
  {
259
  $fields = array();
260
- foreach ($data as $key => $value) {
261
  $fields[] = $this->generateAttachmentField($key, $value);
262
  }
263
 
146
 
147
  if ($this->useShortAttachment) {
148
  $attachment['fields'][] = $this->generateAttachmentField(
149
+ $key,
150
  $record[$key]
151
  );
152
  } else {
229
  /**
230
  * Generates attachment field
231
  *
232
+ * @param string $title
233
+ * @param string|array $value
234
  *
235
  * @return array
236
  */
241
  : $value;
242
 
243
  return array(
244
+ 'title' => ucfirst($title),
245
  'value' => $value,
246
  'short' => false
247
  );
257
  private function generateAttachmentFields(array $data)
258
  {
259
  $fields = array();
260
+ foreach ($this->normalizerFormatter->format($data) as $key => $value) {
261
  $fields[] = $this->generateAttachmentField($key, $value);
262
  }
263
 
vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php CHANGED
@@ -75,6 +75,11 @@ class SlackHandler extends SocketHandler
75
  return $this->slackRecord;
76
  }
77
 
 
 
 
 
 
78
  /**
79
  * {@inheritdoc}
80
  *
75
  return $this->slackRecord;
76
  }
77
 
78
+ public function getToken()
79
+ {
80
+ return $this->token;
81
+ }
82
+
83
  /**
84
  * {@inheritdoc}
85
  *
vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php CHANGED
@@ -70,6 +70,11 @@ class SlackWebhookHandler extends AbstractProcessingHandler
70
  return $this->slackRecord;
71
  }
72
 
 
 
 
 
 
73
  /**
74
  * {@inheritdoc}
75
  *
70
  return $this->slackRecord;
71
  }
72
 
73
+ public function getWebhookUrl()
74
+ {
75
+ return $this->webhookUrl;
76
+ }
77
+
78
  /**
79
  * {@inheritdoc}
80
  *
vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php CHANGED
@@ -27,15 +27,16 @@ class SocketHandler extends AbstractProcessingHandler
27
  private $timeout = 0;
28
  private $writingTimeout = 10;
29
  private $lastSentBytes = null;
 
30
  private $persistent = false;
31
  private $errno;
32
  private $errstr;
33
  private $lastWritingAt;
34
 
35
  /**
36
- * @param string $connectionString Socket connection string
37
- * @param int $level The minimum logging level at which this handler will be triggered
38
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
39
  */
40
  public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true)
41
  {
@@ -87,7 +88,7 @@ class SocketHandler extends AbstractProcessingHandler
87
  */
88
  public function setPersistent($persistent)
89
  {
90
- $this->persistent = (boolean) $persistent;
91
  }
92
 
93
  /**
@@ -127,6 +128,16 @@ class SocketHandler extends AbstractProcessingHandler
127
  $this->writingTimeout = (float) $seconds;
128
  }
129
 
 
 
 
 
 
 
 
 
 
 
130
  /**
131
  * Get current connection string
132
  *
@@ -177,6 +188,16 @@ class SocketHandler extends AbstractProcessingHandler
177
  return $this->writingTimeout;
178
  }
179
 
 
 
 
 
 
 
 
 
 
 
180
  /**
181
  * Check to see if the socket is currently available.
182
  *
@@ -219,6 +240,16 @@ class SocketHandler extends AbstractProcessingHandler
219
  return stream_set_timeout($this->resource, $seconds, $microseconds);
220
  }
221
 
 
 
 
 
 
 
 
 
 
 
222
  /**
223
  * Wrapper to allow mocking
224
  */
@@ -268,6 +299,7 @@ class SocketHandler extends AbstractProcessingHandler
268
  {
269
  $this->createSocketResource();
270
  $this->setSocketTimeout();
 
271
  }
272
 
273
  private function createSocketResource()
@@ -290,6 +322,13 @@ class SocketHandler extends AbstractProcessingHandler
290
  }
291
  }
292
 
 
 
 
 
 
 
 
293
  private function writeToSocket($data)
294
  {
295
  $length = strlen($data);
27
  private $timeout = 0;
28
  private $writingTimeout = 10;
29
  private $lastSentBytes = null;
30
+ private $chunkSize = null;
31
  private $persistent = false;
32
  private $errno;
33
  private $errstr;
34
  private $lastWritingAt;
35
 
36
  /**
37
+ * @param string $connectionString Socket connection string
38
+ * @param int $level The minimum logging level at which this handler will be triggered
39
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
40
  */
41
  public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true)
42
  {
88
  */
89
  public function setPersistent($persistent)
90
  {
91
+ $this->persistent = (bool) $persistent;
92
  }
93
 
94
  /**
128
  $this->writingTimeout = (float) $seconds;
129
  }
130
 
131
+ /**
132
+ * Set chunk size. Only has effect during connection in the writing cycle.
133
+ *
134
+ * @param float $bytes
135
+ */
136
+ public function setChunkSize($bytes)
137
+ {
138
+ $this->chunkSize = $bytes;
139
+ }
140
+
141
  /**
142
  * Get current connection string
143
  *
188
  return $this->writingTimeout;
189
  }
190
 
191
+ /**
192
+ * Get current chunk size
193
+ *
194
+ * @return float
195
+ */
196
+ public function getChunkSize()
197
+ {
198
+ return $this->chunkSize;
199
+ }
200
+
201
  /**
202
  * Check to see if the socket is currently available.
203
  *
240
  return stream_set_timeout($this->resource, $seconds, $microseconds);
241
  }
242
 
243
+ /**
244
+ * Wrapper to allow mocking
245
+ *
246
+ * @see http://php.net/manual/en/function.stream-set-chunk-size.php
247
+ */
248
+ protected function streamSetChunkSize()
249
+ {
250
+ return stream_set_chunk_size($this->resource, $this->chunkSize);
251
+ }
252
+
253
  /**
254
  * Wrapper to allow mocking
255
  */
299
  {
300
  $this->createSocketResource();
301
  $this->setSocketTimeout();
302
+ $this->setStreamChunkSize();
303
  }
304
 
305
  private function createSocketResource()
322
  }
323
  }
324
 
325
+ private function setStreamChunkSize()
326
+ {
327
+ if ($this->chunkSize && !$this->streamSetChunkSize()) {
328
+ throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
329
+ }
330
+ }
331
+
332
  private function writeToSocket($data)
333
  {
334
  $length = strlen($data);
vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php CHANGED
@@ -32,9 +32,9 @@ class StreamHandler extends AbstractProcessingHandler
32
  /**
33
  * @param resource|string $stream
34
  * @param int $level The minimum logging level at which this handler will be triggered
35
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
36
  * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
37
- * @param Boolean $useLocking Try to lock log file before doing any writes
38
  *
39
  * @throws \Exception If a missing directory is not buildable
40
  * @throws \InvalidArgumentException If stream is not a resource or string
@@ -167,7 +167,7 @@ class StreamHandler extends AbstractProcessingHandler
167
  set_error_handler(array($this, 'customErrorHandler'));
168
  $status = mkdir($dir, 0777, true);
169
  restore_error_handler();
170
- if (false === $status) {
171
  throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage, $dir));
172
  }
173
  }
32
  /**
33
  * @param resource|string $stream
34
  * @param int $level The minimum logging level at which this handler will be triggered
35
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
36
  * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
37
+ * @param bool $useLocking Try to lock log file before doing any writes
38
  *
39
  * @throws \Exception If a missing directory is not buildable
40
  * @throws \InvalidArgumentException If stream is not a resource or string
167
  set_error_handler(array($this, 'customErrorHandler'));
168
  $status = mkdir($dir, 0777, true);
169
  restore_error_handler();
170
+ if (false === $status && !is_dir($dir)) {
171
  throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage, $dir));
172
  }
173
  }
vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php CHANGED
@@ -12,6 +12,7 @@
12
  namespace Monolog\Handler;
13
 
14
  use Monolog\Logger;
 
15
  use Monolog\Formatter\LineFormatter;
16
  use Swift;
17
 
@@ -29,7 +30,7 @@ class SwiftMailerHandler extends MailHandler
29
  * @param \Swift_Mailer $mailer The mailer to use
30
  * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
31
  * @param int $level The minimum logging level at which this handler will be triggered
32
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
33
  */
34
  public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true)
35
  {
@@ -47,6 +48,17 @@ class SwiftMailerHandler extends MailHandler
47
  $this->mailer->send($this->buildMessage($content, $records));
48
  }
49
 
 
 
 
 
 
 
 
 
 
 
 
50
  /**
51
  * Creates instance of Swift_Message to be sent
52
  *
@@ -69,7 +81,7 @@ class SwiftMailerHandler extends MailHandler
69
  }
70
 
71
  if ($records) {
72
- $subjectFormatter = new LineFormatter($message->getSubject());
73
  $message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
74
  }
75
 
12
  namespace Monolog\Handler;
13
 
14
  use Monolog\Logger;
15
+ use Monolog\Formatter\FormatterInterface;
16
  use Monolog\Formatter\LineFormatter;
17
  use Swift;
18
 
30
  * @param \Swift_Mailer $mailer The mailer to use
31
  * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
32
  * @param int $level The minimum logging level at which this handler will be triggered
33
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
34
  */
35
  public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true)
36
  {
48
  $this->mailer->send($this->buildMessage($content, $records));
49
  }
50
 
51
+ /**
52
+ * Gets the formatter for the Swift_Message subject.
53
+ *
54
+ * @param string $format The format of the subject
55
+ * @return FormatterInterface
56
+ */
57
+ protected function getSubjectFormatter($format)
58
+ {
59
+ return new LineFormatter($format);
60
+ }
61
+
62
  /**
63
  * Creates instance of Swift_Message to be sent
64
  *
81
  }
82
 
83
  if ($records) {
84
+ $subjectFormatter = $this->getSubjectFormatter($message->getSubject());
85
  $message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
86
  }
87
 
vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php CHANGED
@@ -32,11 +32,11 @@ class SyslogHandler extends AbstractSyslogHandler
32
  protected $logopts;
33
 
34
  /**
35
- * @param string $ident
36
- * @param mixed $facility
37
- * @param int $level The minimum logging level at which this handler will be triggered
38
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
39
- * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
40
  */
41
  public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID)
42
  {
32
  protected $logopts;
33
 
34
  /**
35
+ * @param string $ident
36
+ * @param mixed $facility
37
+ * @param int $level The minimum logging level at which this handler will be triggered
38
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
39
+ * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
40
  */
41
  public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID)
42
  {
vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php CHANGED
@@ -25,12 +25,12 @@ class SyslogUdpHandler extends AbstractSyslogHandler
25
  protected $ident;
26
 
27
  /**
28
- * @param string $host
29
- * @param int $port
30
- * @param mixed $facility
31
- * @param int $level The minimum logging level at which this handler will be triggered
32
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
33
- * @param string $ident Program name or tag for each log message.
34
  */
35
  public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $ident = 'php')
36
  {
25
  protected $ident;
26
 
27
  /**
28
+ * @param string $host
29
+ * @param int $port
30
+ * @param mixed $facility
31
+ * @param int $level The minimum logging level at which this handler will be triggered
32
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
33
+ * @param string $ident Program name or tag for each log message.
34
  */
35
  public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $ident = 'php')
36
  {
vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php CHANGED
@@ -84,14 +84,24 @@ class TestHandler extends AbstractProcessingHandler
84
  return isset($this->recordsByLevel[$level]);
85
  }
86
 
 
 
 
 
87
  public function hasRecord($record, $level)
88
  {
89
- if (is_array($record)) {
90
- $record = $record['message'];
91
  }
92
 
93
  return $this->hasRecordThatPasses(function ($rec) use ($record) {
94
- return $rec['message'] === $record;
 
 
 
 
 
 
95
  }, $level);
96
  }
97
 
84
  return isset($this->recordsByLevel[$level]);
85
  }
86
 
87
+ /**
88
+ * @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records
89
+ * @param int $level Logger::LEVEL constant value
90
+ */
91
  public function hasRecord($record, $level)
92
  {
93
+ if (is_string($record)) {
94
+ $record = array('message' => $record);
95
  }
96
 
97
  return $this->hasRecordThatPasses(function ($rec) use ($record) {
98
+ if ($rec['message'] !== $record['message']) {
99
+ return false;
100
+ }
101
+ if (isset($record['context']) && $rec['context'] !== $record['context']) {
102
+ return false;
103
+ }
104
+ return true;
105
  }, $level);
106
  }
107
 
vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php CHANGED
@@ -48,6 +48,16 @@ class WhatFailureGroupHandler extends GroupHandler
48
  */
49
  public function handleBatch(array $records)
50
  {
 
 
 
 
 
 
 
 
 
 
51
  foreach ($this->handlers as $handler) {
52
  try {
53
  $handler->handleBatch($records);
48
  */
49
  public function handleBatch(array $records)
50
  {
51
+ if ($this->processors) {
52
+ $processed = array();
53
+ foreach ($records as $record) {
54
+ foreach ($this->processors as $processor) {
55
+ $processed[] = call_user_func($processor, $record);
56
+ }
57
+ }
58
+ $records = $processed;
59
+ }
60
+
61
  foreach ($this->handlers as $handler) {
62
  try {
63
  $handler->handleBatch($records);
vendor/monolog/monolog/src/Monolog/Logger.php CHANGED
@@ -15,6 +15,7 @@ use Monolog\Handler\HandlerInterface;
15
  use Monolog\Handler\StreamHandler;
16
  use Psr\Log\LoggerInterface;
17
  use Psr\Log\InvalidArgumentException;
 
18
 
19
  /**
20
  * Monolog log channel
@@ -24,7 +25,7 @@ use Psr\Log\InvalidArgumentException;
24
  *
25
  * @author Jordi Boggiano <j.boggiano@seld.be>
26
  */
27
- class Logger implements LoggerInterface
28
  {
29
  /**
30
  * Detailed debug information
@@ -133,6 +134,11 @@ class Logger implements LoggerInterface
133
  */
134
  protected $microsecondTimestamps = true;
135
 
 
 
 
 
 
136
  /**
137
  * @param string $name The logging channel
138
  * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
@@ -141,7 +147,7 @@ class Logger implements LoggerInterface
141
  public function __construct($name, array $handlers = array(), array $processors = array())
142
  {
143
  $this->name = $name;
144
- $this->handlers = $handlers;
145
  $this->processors = $processors;
146
  }
147
 
@@ -281,7 +287,7 @@ class Logger implements LoggerInterface
281
  * @param int $level The logging level
282
  * @param string $message The log message
283
  * @param array $context The log context
284
- * @return Boolean Whether the record has been processed
285
  */
286
  public function addRecord($level, $message, array $context = array())
287
  {
@@ -329,27 +335,75 @@ class Logger implements LoggerInterface
329
  'extra' => array(),
330
  );
331
 
332
- foreach ($this->processors as $processor) {
333
- $record = call_user_func($processor, $record);
 
 
 
 
 
 
 
 
 
 
 
 
334
  }
335
 
336
- while ($handler = current($this->handlers)) {
337
- if (true === $handler->handle($record)) {
338
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  }
 
 
340
 
341
- next($this->handlers);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  }
343
 
344
- return true;
 
 
 
 
345
  }
346
 
347
  /**
348
  * Adds a log record at the DEBUG level.
349
  *
350
- * @param string $message The log message
351
- * @param array $context The log context
352
- * @return Boolean Whether the record has been processed
353
  */
354
  public function addDebug($message, array $context = array())
355
  {
@@ -359,9 +413,9 @@ class Logger implements LoggerInterface
359
  /**
360
  * Adds a log record at the INFO level.
361
  *
362
- * @param string $message The log message
363
- * @param array $context The log context
364
- * @return Boolean Whether the record has been processed
365
  */
366
  public function addInfo($message, array $context = array())
367
  {
@@ -371,9 +425,9 @@ class Logger implements LoggerInterface
371
  /**
372
  * Adds a log record at the NOTICE level.
373
  *
374
- * @param string $message The log message
375
- * @param array $context The log context
376
- * @return Boolean Whether the record has been processed
377
  */
378
  public function addNotice($message, array $context = array())
379
  {
@@ -383,9 +437,9 @@ class Logger implements LoggerInterface
383
  /**
384
  * Adds a log record at the WARNING level.
385
  *
386
- * @param string $message The log message
387
- * @param array $context The log context
388
- * @return Boolean Whether the record has been processed
389
  */
390
  public function addWarning($message, array $context = array())
391
  {
@@ -395,9 +449,9 @@ class Logger implements LoggerInterface
395
  /**
396
  * Adds a log record at the ERROR level.
397
  *
398
- * @param string $message The log message
399
- * @param array $context The log context
400
- * @return Boolean Whether the record has been processed
401
  */
402
  public function addError($message, array $context = array())
403
  {
@@ -407,9 +461,9 @@ class Logger implements LoggerInterface
407
  /**
408
  * Adds a log record at the CRITICAL level.
409
  *
410
- * @param string $message The log message
411
- * @param array $context The log context
412
- * @return Boolean Whether the record has been processed
413
  */
414
  public function addCritical($message, array $context = array())
415
  {
@@ -419,9 +473,9 @@ class Logger implements LoggerInterface
419
  /**
420
  * Adds a log record at the ALERT level.
421
  *
422
- * @param string $message The log message
423
- * @param array $context The log context
424
- * @return Boolean Whether the record has been processed
425
  */
426
  public function addAlert($message, array $context = array())
427
  {
@@ -431,9 +485,9 @@ class Logger implements LoggerInterface
431
  /**
432
  * Adds a log record at the EMERGENCY level.
433
  *
434
- * @param string $message The log message
435
- * @param array $context The log context
436
- * @return Boolean Whether the record has been processed
437
  */
438
  public function addEmergency($message, array $context = array())
439
  {
@@ -484,7 +538,7 @@ class Logger implements LoggerInterface
484
  * Checks whether the Logger has a handler that listens on the given level
485
  *
486
  * @param int $level
487
- * @return Boolean
488
  */
489
  public function isHandling($level)
490
  {
@@ -501,15 +555,52 @@ class Logger implements LoggerInterface
501
  return false;
502
  }
503
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
  /**
505
  * Adds a log record at an arbitrary level.
506
  *
507
  * This method allows for compatibility with common interfaces.
508
  *
509
  * @param mixed $level The log level
510
- * @param string $message The log message
511
- * @param array $context The log context
512
- * @return Boolean Whether the record has been processed
513
  */
514
  public function log($level, $message, array $context = array())
515
  {
@@ -523,9 +614,9 @@ class Logger implements LoggerInterface
523
  *
524
  * This method allows for compatibility with common interfaces.
525
  *
526
- * @param string $message The log message
527
- * @param array $context The log context
528
- * @return Boolean Whether the record has been processed
529
  */
530
  public function debug($message, array $context = array())
531
  {
@@ -537,9 +628,9 @@ class Logger implements LoggerInterface
537
  *
538
  * This method allows for compatibility with common interfaces.
539
  *
540
- * @param string $message The log message
541
- * @param array $context The log context
542
- * @return Boolean Whether the record has been processed
543
  */
544
  public function info($message, array $context = array())
545
  {
@@ -551,9 +642,9 @@ class Logger implements LoggerInterface
551
  *
552
  * This method allows for compatibility with common interfaces.
553
  *
554
- * @param string $message The log message
555
- * @param array $context The log context
556
- * @return Boolean Whether the record has been processed
557
  */
558
  public function notice($message, array $context = array())
559
  {
@@ -565,9 +656,9 @@ class Logger implements LoggerInterface
565
  *
566
  * This method allows for compatibility with common interfaces.
567
  *
568
- * @param string $message The log message
569
- * @param array $context The log context
570
- * @return Boolean Whether the record has been processed
571
  */
572
  public function warn($message, array $context = array())
573
  {
@@ -579,9 +670,9 @@ class Logger implements LoggerInterface
579
  *
580
  * This method allows for compatibility with common interfaces.
581
  *
582
- * @param string $message The log message
583
- * @param array $context The log context
584
- * @return Boolean Whether the record has been processed
585
  */
586
  public function warning($message, array $context = array())
587
  {
@@ -593,9 +684,9 @@ class Logger implements LoggerInterface
593
  *
594
  * This method allows for compatibility with common interfaces.
595
  *
596
- * @param string $message The log message
597
- * @param array $context The log context
598
- * @return Boolean Whether the record has been processed
599
  */
600
  public function err($message, array $context = array())
601
  {
@@ -607,9 +698,9 @@ class Logger implements LoggerInterface
607
  *
608
  * This method allows for compatibility with common interfaces.
609
  *
610
- * @param string $message The log message
611
- * @param array $context The log context
612
- * @return Boolean Whether the record has been processed
613
  */
614
  public function error($message, array $context = array())
615
  {
@@ -621,9 +712,9 @@ class Logger implements LoggerInterface
621
  *
622
  * This method allows for compatibility with common interfaces.
623
  *
624
- * @param string $message The log message
625
- * @param array $context The log context
626
- * @return Boolean Whether the record has been processed
627
  */
628
  public function crit($message, array $context = array())
629
  {
@@ -635,9 +726,9 @@ class Logger implements LoggerInterface
635
  *
636
  * This method allows for compatibility with common interfaces.
637
  *
638
- * @param string $message The log message
639
- * @param array $context The log context
640
- * @return Boolean Whether the record has been processed
641
  */
642
  public function critical($message, array $context = array())
643
  {
@@ -649,9 +740,9 @@ class Logger implements LoggerInterface
649
  *
650
  * This method allows for compatibility with common interfaces.
651
  *
652
- * @param string $message The log message
653
- * @param array $context The log context
654
- * @return Boolean Whether the record has been processed
655
  */
656
  public function alert($message, array $context = array())
657
  {
@@ -663,9 +754,9 @@ class Logger implements LoggerInterface
663
  *
664
  * This method allows for compatibility with common interfaces.
665
  *
666
- * @param string $message The log message
667
- * @param array $context The log context
668
- * @return Boolean Whether the record has been processed
669
  */
670
  public function emerg($message, array $context = array())
671
  {
@@ -677,9 +768,9 @@ class Logger implements LoggerInterface
677
  *
678
  * This method allows for compatibility with common interfaces.
679
  *
680
- * @param string $message The log message
681
- * @param array $context The log context
682
- * @return Boolean Whether the record has been processed
683
  */
684
  public function emergency($message, array $context = array())
685
  {
15
  use Monolog\Handler\StreamHandler;
16
  use Psr\Log\LoggerInterface;
17
  use Psr\Log\InvalidArgumentException;
18
+ use Exception;
19
 
20
  /**
21
  * Monolog log channel
25
  *
26
  * @author Jordi Boggiano <j.boggiano@seld.be>
27
  */
28
+ class Logger implements LoggerInterface, ResettableInterface
29
  {
30
  /**
31
  * Detailed debug information
134
  */
135
  protected $microsecondTimestamps = true;
136
 
137
+ /**
138
+ * @var callable
139
+ */
140
+ protected $exceptionHandler;
141
+
142
  /**
143
  * @param string $name The logging channel
144
  * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
147
  public function __construct($name, array $handlers = array(), array $processors = array())
148
  {
149
  $this->name = $name;
150
+ $this->setHandlers($handlers);
151
  $this->processors = $processors;
152
  }
153
 
287
  * @param int $level The logging level
288
  * @param string $message The log message
289
  * @param array $context The log context
290
+ * @return bool Whether the record has been processed
291
  */
292
  public function addRecord($level, $message, array $context = array())
293
  {
335
  'extra' => array(),
336
  );
337
 
338
+ try {
339
+ foreach ($this->processors as $processor) {
340
+ $record = call_user_func($processor, $record);
341
+ }
342
+
343
+ while ($handler = current($this->handlers)) {
344
+ if (true === $handler->handle($record)) {
345
+ break;
346
+ }
347
+
348
+ next($this->handlers);
349
+ }
350
+ } catch (Exception $e) {
351
+ $this->handleException($e, $record);
352
  }
353
 
354
+ return true;
355
+ }
356
+
357
+ /**
358
+ * Ends a log cycle and frees all resources used by handlers.
359
+ *
360
+ * Closing a Handler means flushing all buffers and freeing any open resources/handles.
361
+ * Handlers that have been closed should be able to accept log records again and re-open
362
+ * themselves on demand, but this may not always be possible depending on implementation.
363
+ *
364
+ * This is useful at the end of a request and will be called automatically on every handler
365
+ * when they get destructed.
366
+ */
367
+ public function close()
368
+ {
369
+ foreach ($this->handlers as $handler) {
370
+ if (method_exists($handler, 'close')) {
371
+ $handler->close();
372
  }
373
+ }
374
+ }
375
 
376
+ /**
377
+ * Ends a log cycle and resets all handlers and processors to their initial state.
378
+ *
379
+ * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
380
+ * state, and getting it back to a state in which it can receive log records again.
381
+ *
382
+ * This is useful in case you want to avoid logs leaking between two requests or jobs when you
383
+ * have a long running process like a worker or an application server serving multiple requests
384
+ * in one process.
385
+ */
386
+ public function reset()
387
+ {
388
+ foreach ($this->handlers as $handler) {
389
+ if ($handler instanceof ResettableInterface) {
390
+ $handler->reset();
391
+ }
392
  }
393
 
394
+ foreach ($this->processors as $processor) {
395
+ if ($processor instanceof ResettableInterface) {
396
+ $processor->reset();
397
+ }
398
+ }
399
  }
400
 
401
  /**
402
  * Adds a log record at the DEBUG level.
403
  *
404
+ * @param string $message The log message
405
+ * @param array $context The log context
406
+ * @return bool Whether the record has been processed
407
  */
408
  public function addDebug($message, array $context = array())
409
  {
413
  /**
414
  * Adds a log record at the INFO level.
415
  *
416
+ * @param string $message The log message
417
+ * @param array $context The log context
418
+ * @return bool Whether the record has been processed
419
  */
420
  public function addInfo($message, array $context = array())
421
  {
425
  /**
426
  * Adds a log record at the NOTICE level.
427
  *
428
+ * @param string $message The log message
429
+ * @param array $context The log context
430
+ * @return bool Whether the record has been processed
431
  */
432
  public function addNotice($message, array $context = array())
433
  {
437
  /**
438
  * Adds a log record at the WARNING level.
439
  *
440
+ * @param string $message The log message
441
+ * @param array $context The log context
442
+ * @return bool Whether the record has been processed
443
  */
444
  public function addWarning($message, array $context = array())
445
  {
449
  /**
450
  * Adds a log record at the ERROR level.
451
  *
452
+ * @param string $message The log message
453
+ * @param array $context The log context
454
+ * @return bool Whether the record has been processed
455
  */
456
  public function addError($message, array $context = array())
457
  {
461
  /**
462
  * Adds a log record at the CRITICAL level.
463
  *
464
+ * @param string $message The log message
465
+ * @param array $context The log context
466
+ * @return bool Whether the record has been processed
467
  */
468
  public function addCritical($message, array $context = array())
469
  {
473
  /**
474
  * Adds a log record at the ALERT level.
475
  *
476
+ * @param string $message The log message
477
+ * @param array $context The log context
478
+ * @return bool Whether the record has been processed
479
  */
480
  public function addAlert($message, array $context = array())
481
  {
485
  /**
486
  * Adds a log record at the EMERGENCY level.
487
  *
488
+ * @param string $message The log message
489
+ * @param array $context The log context
490
+ * @return bool Whether the record has been processed
491
  */
492
  public function addEmergency($message, array $context = array())
493
  {
538
  * Checks whether the Logger has a handler that listens on the given level
539
  *
540
  * @param int $level
541
+ * @return bool
542
  */
543
  public function isHandling($level)
544
  {
555
  return false;
556
  }
557
 
558
+ /**
559
+ * Set a custom exception handler
560
+ *
561
+ * @param callable $callback
562
+ * @return $this
563
+ */
564
+ public function setExceptionHandler($callback)
565
+ {
566
+ if (!is_callable($callback)) {
567
+ throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), '.var_export($callback, true).' given');
568
+ }
569
+ $this->exceptionHandler = $callback;
570
+
571
+ return $this;
572
+ }
573
+
574
+ /**
575
+ * @return callable
576
+ */
577
+ public function getExceptionHandler()
578
+ {
579
+ return $this->exceptionHandler;
580
+ }
581
+
582
+ /**
583
+ * Delegates exception management to the custom exception handler,
584
+ * or throws the exception if no custom handler is set.
585
+ */
586
+ protected function handleException(Exception $e, array $record)
587
+ {
588
+ if (!$this->exceptionHandler) {
589
+ throw $e;
590
+ }
591
+
592
+ call_user_func($this->exceptionHandler, $e, $record);
593
+ }
594
+
595
  /**
596
  * Adds a log record at an arbitrary level.
597
  *
598
  * This method allows for compatibility with common interfaces.
599
  *
600
  * @param mixed $level The log level
601
+ * @param string $message The log message
602
+ * @param array $context The log context
603
+ * @return bool Whether the record has been processed
604
  */
605
  public function log($level, $message, array $context = array())
606
  {
614
  *
615
  * This method allows for compatibility with common interfaces.
616
  *
617
+ * @param string $message The log message
618
+ * @param array $context The log context
619
+ * @return bool Whether the record has been processed
620
  */
621
  public function debug($message, array $context = array())
622
  {
628
  *
629
  * This method allows for compatibility with common interfaces.
630
  *
631
+ * @param string $message The log message
632
+ * @param array $context The log context
633
+ * @return bool Whether the record has been processed
634
  */
635
  public function info($message, array $context = array())
636
  {
642
  *
643
  * This method allows for compatibility with common interfaces.
644
  *
645
+ * @param string $message The log message
646
+ * @param array $context The log context
647
+ * @return bool Whether the record has been processed
648
  */
649
  public function notice($message, array $context = array())
650
  {
656
  *
657
  * This method allows for compatibility with common interfaces.
658
  *
659
+ * @param string $message The log message
660
+ * @param array $context The log context
661
+ * @return bool Whether the record has been processed
662
  */
663
  public function warn($message, array $context = array())
664
  {
670
  *
671
  * This method allows for compatibility with common interfaces.
672
  *
673
+ * @param string $message The log message
674
+ * @param array $context The log context
675
+ * @return bool Whether the record has been processed
676
  */
677
  public function warning($message, array $context = array())
678
  {
684
  *
685
  * This method allows for compatibility with common interfaces.
686
  *
687
+ * @param string $message The log message
688
+ * @param array $context The log context
689
+ * @return bool Whether the record has been processed
690
  */
691
  public function err($message, array $context = array())
692
  {
698
  *
699
  * This method allows for compatibility with common interfaces.
700
  *
701
+ * @param string $message The log message
702
+ * @param array $context The log context
703
+ * @return bool Whether the record has been processed
704
  */
705
  public function error($message, array $context = array())
706
  {
712
  *
713
  * This method allows for compatibility with common interfaces.
714
  *
715
+ * @param string $message The log message
716
+ * @param array $context The log context
717
+ * @return bool Whether the record has been processed
718
  */
719
  public function crit($message, array $context = array())
720
  {
726
  *
727
  * This method allows for compatibility with common interfaces.
728
  *
729
+ * @param string $message The log message
730
+ * @param array $context The log context
731
+ * @return bool Whether the record has been processed
732
  */
733
  public function critical($message, array $context = array())
734
  {
740
  *
741
  * This method allows for compatibility with common interfaces.
742
  *
743
+ * @param string $message The log message
744
+ * @param array $context The log context
745
+ * @return bool Whether the record has been processed
746
  */
747
  public function alert($message, array $context = array())
748
  {
754
  *
755
  * This method allows for compatibility with common interfaces.
756
  *
757
+ * @param string $message The log message
758
+ * @param array $context The log context
759
+ * @return bool Whether the record has been processed
760
  */
761
  public function emerg($message, array $context = array())
762
  {
768
  *
769
  * This method allows for compatibility with common interfaces.
770
  *
771
+ * @param string $message The log message
772
+ * @param array $context The log context
773
+ * @return bool Whether the record has been processed
774
  */
775
  public function emergency($message, array $context = array())
776
  {
vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php CHANGED
@@ -19,7 +19,7 @@ use Monolog\Logger;
19
  * @author Nick Otter
20
  * @author Jordi Boggiano <j.boggiano@seld.be>
21
  */
22
- class GitProcessor
23
  {
24
  private $level;
25
  private static $cache;
19
  * @author Nick Otter
20
  * @author Jordi Boggiano <j.boggiano@seld.be>
21
  */
22
+ class GitProcessor implements ProcessorInterface
23
  {
24
  private $level;
25
  private static $cache;
vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php CHANGED
@@ -24,7 +24,7 @@ use Monolog\Logger;
24
  *
25
  * @author Jordi Boggiano <j.boggiano@seld.be>
26
  */
27
- class IntrospectionProcessor
28
  {
29
  private $level;
30
 
24
  *
25
  * @author Jordi Boggiano <j.boggiano@seld.be>
26
  */
27
+ class IntrospectionProcessor implements ProcessorInterface
28
  {
29
  private $level;
30
 
vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php CHANGED
@@ -16,7 +16,7 @@ namespace Monolog\Processor;
16
  *
17
  * @author Rob Jensen
18
  */
19
- abstract class MemoryProcessor
20
  {
21
  /**
22
  * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported.
@@ -34,8 +34,8 @@ abstract class MemoryProcessor
34
  */
35
  public function __construct($realUsage = true, $useFormatting = true)
36
  {
37
- $this->realUsage = (boolean) $realUsage;
38
- $this->useFormatting = (boolean) $useFormatting;
39
  }
40
 
41
  /**
16
  *
17
  * @author Rob Jensen
18
  */
19
+ abstract class MemoryProcessor implements ProcessorInterface
20
  {
21
  /**
22
  * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported.
34
  */
35
  public function __construct($realUsage = true, $useFormatting = true)
36
  {
37
+ $this->realUsage = (bool) $realUsage;
38
+ $this->useFormatting = (bool) $useFormatting;
39
  }
40
 
41
  /**
vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php CHANGED
@@ -18,7 +18,7 @@ use Monolog\Logger;
18
  *
19
  * @author Jonathan A. Schweder <jonathanschweder@gmail.com>
20
  */
21
- class MercurialProcessor
22
  {
23
  private $level;
24
  private static $cache;
18
  *
19
  * @author Jonathan A. Schweder <jonathanschweder@gmail.com>
20
  */
21
+ class MercurialProcessor implements ProcessorInterface
22
  {
23
  private $level;
24
  private static $cache;
vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php CHANGED
@@ -16,7 +16,7 @@ namespace Monolog\Processor;
16
  *
17
  * @author Andreas Hörnicke
18
  */
19
- class ProcessIdProcessor
20
  {
21
  /**
22
  * @param array $record
16
  *
17
  * @author Andreas Hörnicke
18
  */
19
+ class ProcessIdProcessor implements ProcessorInterface
20
  {
21
  /**
22
  * @param array $record
vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of the Monolog package.
5
+ *
6
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Monolog\Processor;
13
+
14
+ /**
15
+ * An optional interface to allow labelling Monolog processors.
16
+ *
17
+ * @author Nicolas Grekas <p@tchwork.com>
18
+ */
19
+ interface ProcessorInterface
20
+ {
21
+ /**
22
+ * @return array The processed records
23
+ */
24
+ public function __invoke(array $records);
25
+ }
vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php CHANGED
@@ -11,6 +11,8 @@
11
 
12
  namespace Monolog\Processor;
13
 
 
 
14
  /**
15
  * Processes a record's message according to PSR-3 rules
16
  *
@@ -18,7 +20,7 @@ namespace Monolog\Processor;
18
  *
19
  * @author Jordi Boggiano <j.boggiano@seld.be>
20
  */
21
- class PsrLogMessageProcessor
22
  {
23
  /**
24
  * @param array $record
@@ -35,7 +37,7 @@ class PsrLogMessageProcessor
35
  if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) {
36
  $replacements['{'.$key.'}'] = $val;
37
  } elseif (is_object($val)) {
38
- $replacements['{'.$key.'}'] = '[object '.get_class($val).']';
39
  } else {
40
  $replacements['{'.$key.'}'] = '['.gettype($val).']';
41
  }
11
 
12
  namespace Monolog\Processor;
13
 
14
+ use Monolog\Utils;
15
+
16
  /**
17
  * Processes a record's message according to PSR-3 rules
18
  *
20
  *
21
  * @author Jordi Boggiano <j.boggiano@seld.be>
22
  */
23
+ class PsrLogMessageProcessor implements ProcessorInterface
24
  {
25
  /**
26
  * @param array $record
37
  if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) {
38
  $replacements['{'.$key.'}'] = $val;
39
  } elseif (is_object($val)) {
40
+ $replacements['{'.$key.'}'] = '[object '.Utils::getClass($val).']';
41
  } else {
42
  $replacements['{'.$key.'}'] = '['.gettype($val).']';
43
  }
vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php CHANGED
@@ -16,7 +16,7 @@ namespace Monolog\Processor;
16
  *
17
  * @author Martijn Riemers
18
  */
19
- class TagProcessor
20
  {
21
  private $tags;
22
 
16
  *
17
  * @author Martijn Riemers
18
  */
19
+ class TagProcessor implements ProcessorInterface
20
  {
21
  private $tags;
22
 
vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php CHANGED
@@ -11,12 +11,14 @@
11
 
12
  namespace Monolog\Processor;
13
 
 
 
14
  /**
15
  * Adds a unique identifier into records
16
  *
17
  * @author Simon Mönch <sm@webfactory.de>
18
  */
19
- class UidProcessor
20
  {
21
  private $uid;
22
 
@@ -26,7 +28,8 @@ class UidProcessor
26
  throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
27
  }
28
 
29
- $this->uid = substr(hash('md5', uniqid('', true)), 0, $length);
 
30
  }
31
 
32
  public function __invoke(array $record)
@@ -43,4 +46,14 @@ class UidProcessor
43
  {
44
  return $this->uid;
45
  }
 
 
 
 
 
 
 
 
 
 
46
  }
11
 
12
  namespace Monolog\Processor;
13
 
14
+ use Monolog\ResettableInterface;
15
+
16
  /**
17
  * Adds a unique identifier into records
18
  *
19
  * @author Simon Mönch <sm@webfactory.de>
20
  */
21
+ class UidProcessor implements ProcessorInterface, ResettableInterface
22
  {
23
  private $uid;
24
 
28
  throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
29
  }
30
 
31
+
32
+ $this->uid = $this->generateUid($length);
33
  }
34
 
35
  public function __invoke(array $record)
46
  {
47
  return $this->uid;
48
  }
49
+
50
+ public function reset()
51
+ {
52
+ $this->uid = $this->generateUid(strlen($this->uid));
53
+ }
54
+
55
+ private function generateUid($length)
56
+ {
57
+ return substr(hash('md5', uniqid('', true)), 0, $length);
58
+ }
59
  }
vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php CHANGED
@@ -16,7 +16,7 @@ namespace Monolog\Processor;
16
  *
17
  * @author Jordi Boggiano <j.boggiano@seld.be>
18
  */
19
- class WebProcessor
20
  {
21
  /**
22
  * @var array|\ArrayAccess
16
  *
17
  * @author Jordi Boggiano <j.boggiano@seld.be>
18
  */
19
+ class WebProcessor implements ProcessorInterface
20
  {
21
  /**
22
  * @var array|\ArrayAccess
vendor/monolog/monolog/src/Monolog/ResettableInterface.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of the Monolog package.
5
+ *
6
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Monolog;
13
+
14
+ /**
15
+ * Handler or Processor implementing this interface will be reset when Logger::reset() is called.
16
+ *
17
+ * Resetting ends a log cycle gets them back to their initial state.
18
+ *
19
+ * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
20
+ * state, and getting it back to a state in which it can receive log records again.
21
+ *
22
+ * This is useful in case you want to avoid logs leaking between two requests or jobs when you
23
+ * have a long running process like a worker or an application server serving multiple requests
24
+ * in one process.
25
+ *
26
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
27
+ */
28
+ interface ResettableInterface
29
+ {
30
+ public function reset();
31
+ }
vendor/monolog/monolog/src/Monolog/SignalHandler.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of the Monolog package.
5
+ *
6
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Monolog;
13
+
14
+ use Psr\Log\LoggerInterface;
15
+ use Psr\Log\LogLevel;
16
+ use ReflectionExtension;
17
+
18
+ /**
19
+ * Monolog POSIX signal handler
20
+ *
21
+ * @author Robert Gust-Bardon <robert@gust-bardon.org>
22
+ */
23
+ class SignalHandler
24
+ {
25
+ private $logger;
26
+
27
+ private $previousSignalHandler = array();
28
+ private $signalLevelMap = array();
29
+ private $signalRestartSyscalls = array();
30
+
31
+ public function __construct(LoggerInterface $logger)
32
+ {
33
+ $this->logger = $logger;
34
+ }
35
+
36
+ public function registerSignalHandler($signo, $level = LogLevel::CRITICAL, $callPrevious = true, $restartSyscalls = true, $async = true)
37
+ {
38
+ if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) {
39
+ return $this;
40
+ }
41
+
42
+ if ($callPrevious) {
43
+ if (function_exists('pcntl_signal_get_handler')) {
44
+ $handler = pcntl_signal_get_handler($signo);
45
+ if ($handler === false) {
46
+ return $this;
47
+ }
48
+ $this->previousSignalHandler[$signo] = $handler;
49
+ } else {
50
+ $this->previousSignalHandler[$signo] = true;
51
+ }
52
+ } else {
53
+ unset($this->previousSignalHandler[$signo]);
54
+ }
55
+ $this->signalLevelMap[$signo] = $level;
56
+ $this->signalRestartSyscalls[$signo] = $restartSyscalls;
57
+
58
+ if (function_exists('pcntl_async_signals') && $async !== null) {
59
+ pcntl_async_signals($async);
60
+ }
61
+
62
+ pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls);
63
+
64
+ return $this;
65
+ }
66
+
67
+ public function handleSignal($signo, array $siginfo = null)
68
+ {
69
+ static $signals = array();
70
+
71
+ if (!$signals && extension_loaded('pcntl')) {
72
+ $pcntl = new ReflectionExtension('pcntl');
73
+ $constants = $pcntl->getConstants();
74
+ if (!$constants) {
75
+ // HHVM 3.24.2 returns an empty array.
76
+ $constants = get_defined_constants(true);
77
+ $constants = $constants['Core'];
78
+ }
79
+ foreach ($constants as $name => $value) {
80
+ if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) {
81
+ $signals[$value] = $name;
82
+ }
83
+ }
84
+ unset($constants);
85
+ }
86
+
87
+ $level = isset($this->signalLevelMap[$signo]) ? $this->signalLevelMap[$signo] : LogLevel::CRITICAL;
88
+ $signal = isset($signals[$signo]) ? $signals[$signo] : $signo;
89
+ $context = isset($siginfo) ? $siginfo : array();
90
+ $this->logger->log($level, sprintf('Program received signal %s', $signal), $context);
91
+
92
+ if (!isset($this->previousSignalHandler[$signo])) {
93
+ return;
94
+ }
95
+
96
+ if ($this->previousSignalHandler[$signo] === true || $this->previousSignalHandler[$signo] === SIG_DFL) {
97
+ if (extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_sigprocmask') && function_exists('pcntl_signal_dispatch')
98
+ && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill')) {
99
+ $restartSyscalls = isset($this->restartSyscalls[$signo]) ? $this->restartSyscalls[$signo] : true;
100
+ pcntl_signal($signo, SIG_DFL, $restartSyscalls);
101
+ pcntl_sigprocmask(SIG_UNBLOCK, array($signo), $oldset);
102
+ posix_kill(posix_getpid(), $signo);
103
+ pcntl_signal_dispatch();
104
+ pcntl_sigprocmask(SIG_SETMASK, $oldset);
105
+ pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls);
106
+ }
107
+ } elseif (is_callable($this->previousSignalHandler[$signo])) {
108
+ if (PHP_VERSION_ID >= 70100) {
109
+ $this->previousSignalHandler[$signo]($signo, $siginfo);
110
+ } else {
111
+ $this->previousSignalHandler[$signo]($signo);
112
+ }
113
+ }
114
+ }
115
+ }
vendor/monolog/monolog/src/Monolog/Utils.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of the Monolog package.
5
+ *
6
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Monolog;
13
+
14
+ class Utils
15
+ {
16
+ /**
17
+ * @internal
18
+ */
19
+ public static function getClass($object)
20
+ {
21
+ $class = \get_class($object);
22
+
23
+ return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
24
+ }
25
+ }
vendor/monolog/monolog/tests/Monolog/Formatter/FluentdFormatterTest.php CHANGED
@@ -40,7 +40,7 @@ class FluentdFormatterTest extends TestCase
40
 
41
  $formatter = new FluentdFormatter();
42
  $this->assertEquals(
43
- '["test",0,{"message":"test","extra":[],"level":300,"level_name":"WARNING"}]',
44
  $formatter->format($record)
45
  );
46
  }
@@ -55,7 +55,7 @@ class FluentdFormatterTest extends TestCase
55
 
56
  $formatter = new FluentdFormatter(true);
57
  $this->assertEquals(
58
- '["test.error",0,{"message":"test","extra":[]}]',
59
  $formatter->format($record)
60
  );
61
  }
40
 
41
  $formatter = new FluentdFormatter();
42
  $this->assertEquals(
43
+ '["test",0,{"message":"test","context":[],"extra":[],"level":300,"level_name":"WARNING"}]',
44
  $formatter->format($record)
45
  );
46
  }
55
 
56
  $formatter = new FluentdFormatter(true);
57
  $this->assertEquals(
58
+ '["test.error",0,{"message":"test","context":[],"extra":[]}]',
59
  $formatter->format($record)
60
  );
61
  }
vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php CHANGED
@@ -180,4 +180,40 @@ class JsonFormatterTest extends TestCase
180
  '}';
181
  return $formattedException;
182
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  }
180
  '}';
181
  return $formattedException;
182
  }
183
+
184
+ public function testNormalizeHandleLargeArraysWithExactly1000Items()
185
+ {
186
+ $formatter = new NormalizerFormatter();
187
+ $largeArray = range(1, 1000);
188
+
189
+ $res = $formatter->format(array(
190
+ 'level_name' => 'CRITICAL',
191
+ 'channel' => 'test',
192
+ 'message' => 'bar',
193
+ 'context' => array($largeArray),
194
+ 'datetime' => new \DateTime,
195
+ 'extra' => array(),
196
+ ));
197
+
198
+ $this->assertCount(1000, $res['context'][0]);
199
+ $this->assertArrayNotHasKey('...', $res['context'][0]);
200
+ }
201
+
202
+ public function testNormalizeHandleLargeArrays()
203
+ {
204
+ $formatter = new NormalizerFormatter();
205
+ $largeArray = range(1, 2000);
206
+
207
+ $res = $formatter->format(array(
208
+ 'level_name' => 'CRITICAL',
209
+ 'channel' => 'test',
210
+ 'message' => 'bar',
211
+ 'context' => array($largeArray),
212
+ 'datetime' => new \DateTime,
213
+ 'extra' => array(),
214
+ ));
215
+
216
+ $this->assertCount(1001, $res['context'][0]);
217
+ $this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']);
218
+ }
219
  }
vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php CHANGED
@@ -193,6 +193,15 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase
193
  $this->assertEquals(@json_encode(array($foo, $bar)), $res);
194
  }
195
 
 
 
 
 
 
 
 
 
 
196
  public function testIgnoresInvalidTypes()
197
  {
198
  // set up the recursion
@@ -217,6 +226,24 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase
217
  $this->assertEquals(@json_encode(array($resource)), $res);
218
  }
219
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  public function testNormalizeHandleLargeArrays()
221
  {
222
  $formatter = new NormalizerFormatter();
@@ -231,7 +258,7 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase
231
  'extra' => array(),
232
  ));
233
 
234
- $this->assertCount(1000, $res['context'][0]);
235
  $this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']);
236
  }
237
 
@@ -380,6 +407,29 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase
380
  $result['context']['exception']['trace'][0]
381
  );
382
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  }
384
 
385
  class TestFooNorm
@@ -421,3 +471,11 @@ class TestToStringError
421
  throw new \RuntimeException('Could not convert to string');
422
  }
423
  }
 
 
 
 
 
 
 
 
193
  $this->assertEquals(@json_encode(array($foo, $bar)), $res);
194
  }
195
 
196
+ public function testCanNormalizeReferences()
197
+ {
198
+ $formatter = new NormalizerFormatter();
199
+ $x = array('foo' => 'bar');
200
+ $y = array('x' => &$x);
201
+ $x['y'] = &$y;
202
+ $formatter->format($y);
203
+ }
204
+
205
  public function testIgnoresInvalidTypes()
206
  {
207
  // set up the recursion
226
  $this->assertEquals(@json_encode(array($resource)), $res);
227
  }
228
 
229
+ public function testNormalizeHandleLargeArraysWithExactly1000Items()
230
+ {
231
+ $formatter = new NormalizerFormatter();
232
+ $largeArray = range(1, 1000);
233
+
234
+ $res = $formatter->format(array(
235
+ 'level_name' => 'CRITICAL',
236
+ 'channel' => 'test',
237
+ 'message' => 'bar',
238
+ 'context' => array($largeArray),
239
+ 'datetime' => new \DateTime,
240
+ 'extra' => array(),
241
+ ));
242
+
243
+ $this->assertCount(1000, $res['context'][0]);
244
+ $this->assertArrayNotHasKey('...', $res['context'][0]);
245
+ }
246
+
247
  public function testNormalizeHandleLargeArrays()
248
  {
249
  $formatter = new NormalizerFormatter();
258
  'extra' => array(),
259
  ));
260
 
261
+ $this->assertCount(1001, $res['context'][0]);
262
  $this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']);
263
  }
264
 
407
  $result['context']['exception']['trace'][0]
408
  );
409
  }
410
+
411
+ public function testExceptionTraceDoesNotLeakCallUserFuncArgs()
412
+ {
413
+ try {
414
+ $arg = new TestInfoLeak;
415
+ call_user_func(array($this, 'throwHelper'), $arg, $dt = new \DateTime());
416
+ } catch (\Exception $e) {
417
+ }
418
+
419
+ $formatter = new NormalizerFormatter();
420
+ $record = array('context' => array('exception' => $e));
421
+ $result = $formatter->format($record);
422
+
423
+ $this->assertSame(
424
+ '{"function":"throwHelper","class":"Monolog\\\\Formatter\\\\NormalizerFormatterTest","type":"->","args":["[object] (Monolog\\\\Formatter\\\\TestInfoLeak)","'.$dt->format('Y-m-d H:i:s').'"]}',
425
+ $result['context']['exception']['trace'][0]
426
+ );
427
+ }
428
+
429
+ private function throwHelper($arg)
430
+ {
431
+ throw new \RuntimeException('Thrown');
432
+ }
433
  }
434
 
435
  class TestFooNorm
471
  throw new \RuntimeException('Could not convert to string');
472
  }
473
  }
474
+
475
+ class TestInfoLeak
476
+ {
477
+ public function __toString()
478
+ {
479
+ return 'Sensitive information';
480
+ }
481
+ }
vendor/monolog/monolog/tests/Monolog/Handler/BrowserConsoleHandlerTest.php CHANGED
@@ -21,7 +21,7 @@ class BrowserConsoleHandlerTest extends TestCase
21
  {
22
  protected function setUp()
23
  {
24
- BrowserConsoleHandler::reset();
25
  }
26
 
27
  protected function generateScript()
21
  {
22
  protected function setUp()
23
  {
24
+ BrowserConsoleHandler::resetStatic();
25
  }
26
 
27
  protected function generateScript()
vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php CHANGED
@@ -21,7 +21,7 @@ class ChromePHPHandlerTest extends TestCase
21
  {
22
  protected function setUp()
23
  {
24
- TestChromePHPHandler::reset();
25
  $_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; Chrome/1.0';
26
  }
27
 
@@ -136,7 +136,7 @@ class TestChromePHPHandler extends ChromePHPHandler
136
  {
137
  protected $headers = array();
138
 
139
- public static function reset()
140
  {
141
  self::$initialized = false;
142
  self::$overflowed = false;
21
  {
22
  protected function setUp()
23
  {
24
+ TestChromePHPHandler::resetStatic();
25
  $_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; Chrome/1.0';
26
  }
27
 
136
  {
137
  protected $headers = array();
138
 
139
+ public static function resetStatic()
140
  {
141
  self::$initialized = false;
142
  self::$overflowed = false;
vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php CHANGED
@@ -58,7 +58,7 @@ class FingersCrossedHandlerTest extends TestCase
58
  * @covers Monolog\Handler\FingersCrossedHandler::activate
59
  * @covers Monolog\Handler\FingersCrossedHandler::reset
60
  */
61
- public function testHandleRestartBufferingAfterReset()
62
  {
63
  $test = new TestHandler();
64
  $handler = new FingersCrossedHandler($test);
@@ -76,7 +76,7 @@ class FingersCrossedHandlerTest extends TestCase
76
  * @covers Monolog\Handler\FingersCrossedHandler::handle
77
  * @covers Monolog\Handler\FingersCrossedHandler::activate
78
  */
79
- public function testHandleRestartBufferingAfterBeingTriggeredWhenStopBufferingIsDisabled()
80
  {
81
  $test = new TestHandler();
82
  $handler = new FingersCrossedHandler($test, Logger::WARNING, 0, false, false);
58
  * @covers Monolog\Handler\FingersCrossedHandler::activate
59
  * @covers Monolog\Handler\FingersCrossedHandler::reset
60
  */
61
+ public function testHandleResetBufferingAfterReset()
62
  {
63
  $test = new TestHandler();
64
  $handler = new FingersCrossedHandler($test);
76
  * @covers Monolog\Handler\FingersCrossedHandler::handle
77
  * @covers Monolog\Handler\FingersCrossedHandler::activate
78
  */
79
+ public function testHandleResetBufferingAfterBeingTriggeredWhenStopBufferingIsDisabled()
80
  {
81
  $test = new TestHandler();
82
  $handler = new FingersCrossedHandler($test, Logger::WARNING, 0, false, false);
vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php CHANGED
@@ -21,7 +21,7 @@ class FirePHPHandlerTest extends TestCase
21
  {
22
  public function setUp()
23
  {
24
- TestFirePHPHandler::reset();
25
  $_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; FirePHP/1.0';
26
  }
27
 
@@ -77,7 +77,7 @@ class TestFirePHPHandler extends FirePHPHandler
77
  {
78
  protected $headers = array();
79
 
80
- public static function reset()
81
  {
82
  self::$initialized = false;
83
  self::$sendHeaders = true;
21
  {
22
  public function setUp()
23
  {
24
+ TestFirePHPHandler::resetStatic();
25
  $_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; FirePHP/1.0';
26
  }
27
 
77
  {
78
  protected $headers = array();
79
 
80
+ public static function resetStatic()
81
  {
82
  self::$initialized = false;
83
  self::$sendHeaders = true;
vendor/monolog/monolog/tests/Monolog/Handler/InsightOpsHandlerTest.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of the Monolog package.
5
+ *
6
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Monolog\Handler;
13
+
14
+ use Monolog\TestCase;
15
+ use Monolog\Logger;
16
+
17
+ /**
18
+ * @author Robert Kaufmann III <rok3@rok3.me>
19
+ * @author Gabriel Machado <gabriel.ms1@hotmail.com>
20
+ */
21
+ class InsightOpsHandlerTest extends TestCase
22
+ {
23
+ /**
24
+ * @var resource
25
+ */
26
+ private $resource;
27
+
28
+ /**
29
+ * @var LogEntriesHandler
30
+ */
31
+ private $handler;
32
+
33
+ public function testWriteContent()
34
+ {
35
+ $this->createHandler();
36
+ $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test'));
37
+
38
+ fseek($this->resource, 0);
39
+ $content = fread($this->resource, 1024);
40
+
41
+ $this->assertRegexp('/testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] test.CRITICAL: Critical write test/', $content);
42
+ }
43
+
44
+ public function testWriteBatchContent()
45
+ {
46
+ $this->createHandler();
47
+ $this->handler->handleBatch($this->getMultipleRecords());
48
+
49
+ fseek($this->resource, 0);
50
+ $content = fread($this->resource, 1024);
51
+
52
+ $this->assertRegexp('/(testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] .* \[\] \[\]\n){3}/', $content);
53
+ }
54
+
55
+ private function createHandler()
56
+ {
57
+ $useSSL = extension_loaded('openssl');
58
+ $args = array('testToken', 'us', $useSSL, Logger::DEBUG, true);
59
+ $this->resource = fopen('php://memory', 'a');
60
+ $this->handler = $this->getMock(
61
+ '\Monolog\Handler\InsightOpsHandler',
62
+ array('fsockopen', 'streamSetTimeout', 'closeSocket'),
63
+ $args
64
+ );
65
+
66
+ $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
67
+ $reflectionProperty->setAccessible(true);
68
+ $reflectionProperty->setValue($this->handler, 'localhost:1234');
69
+
70
+ $this->handler->expects($this->any())
71
+ ->method('fsockopen')
72
+ ->will($this->returnValue($this->resource));
73
+ $this->handler->expects($this->any())
74
+ ->method('streamSetTimeout')
75
+ ->will($this->returnValue(true));
76
+ $this->handler->expects($this->any())
77
+ ->method('closeSocket')
78
+ ->will($this->returnValue(true));
79
+ }
80
+ }
vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php CHANGED
@@ -191,6 +191,40 @@ class RotatingFileHandlerTest extends TestCase
191
  );
192
  }
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  public function testReuseCurrentFile()
195
  {
196
  $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';
191
  );
192
  }
193
 
194
+ /**
195
+ * @dataProvider rotationWhenSimilarFilesExistTests
196
+ */
197
+ public function testRotationWhenSimilarFileNamesExist($dateFormat)
198
+ {
199
+ touch($old1 = __DIR__.'/Fixtures/foo-foo-'.date($dateFormat).'.rot');
200
+ touch($old2 = __DIR__.'/Fixtures/foo-bar-'.date($dateFormat).'.rot');
201
+
202
+ $log = __DIR__.'/Fixtures/foo-'.date($dateFormat).'.rot';
203
+
204
+ $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2);
205
+ $handler->setFormatter($this->getIdentityFormatter());
206
+ $handler->setFilenameFormat('{filename}-{date}', $dateFormat);
207
+ $handler->handle($this->getRecord());
208
+ $handler->close();
209
+
210
+ $this->assertTrue(file_exists($log));
211
+ }
212
+
213
+ public function rotationWhenSimilarFilesExistTests()
214
+ {
215
+
216
+ return array(
217
+ 'Rotation is triggered when the file of the current day is not present but similar exists'
218
+ => array(RotatingFileHandler::FILE_PER_DAY),
219
+
220
+ 'Rotation is triggered when the file of the current month is not present but similar exists'
221
+ => array(RotatingFileHandler::FILE_PER_MONTH),
222
+
223
+ 'Rotation is triggered when the file of the current year is not present but similar exists'
224
+ => array(RotatingFileHandler::FILE_PER_YEAR),
225
+ );
226
+ }
227
+
228
  public function testReuseCurrentFile()
229
  {
230
  $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';
vendor/monolog/monolog/tests/Monolog/Handler/Slack/SlackRecordTest.php CHANGED
@@ -320,12 +320,12 @@ class SlackRecordTest extends TestCase
320
  'short' => false,
321
  ),
322
  array(
323
- 'title' => 'tags',
324
  'value' => sprintf('```%s```', json_encode($extra['tags'])),
325
  'short' => false
326
  ),
327
  array(
328
- 'title' => 'test',
329
  'value' => $context['test'],
330
  'short' => false
331
  )
@@ -353,6 +353,14 @@ class SlackRecordTest extends TestCase
353
  $this->assertSame($record['datetime']->getTimestamp(), $attachment['ts']);
354
  }
355
 
 
 
 
 
 
 
 
 
356
  public function testExcludeExtraAndContextFields()
357
  {
358
  $record = $this->getRecord(
@@ -368,12 +376,12 @@ class SlackRecordTest extends TestCase
368
 
369
  $expected = array(
370
  array(
371
- 'title' => 'info',
372
  'value' => sprintf('```%s```', json_encode(array('author' => 'Jordi'), $this->jsonPrettyPrintFlag)),
373
  'short' => false
374
  ),
375
  array(
376
- 'title' => 'tags',
377
  'value' => sprintf('```%s```', json_encode(array('web'))),
378
  'short' => false
379
  ),
320
  'short' => false,
321
  ),
322
  array(
323
+ 'title' => 'Tags',
324
  'value' => sprintf('```%s```', json_encode($extra['tags'])),
325
  'short' => false
326
  ),
327
  array(
328
+ 'title' => 'Test',
329
  'value' => $context['test'],
330
  'short' => false
331
  )
353
  $this->assertSame($record['datetime']->getTimestamp(), $attachment['ts']);
354
  }
355
 
356
+ public function testContextHasException()
357
+ {
358
+ $record = $this->getRecord(Logger::CRITICAL, 'This is a critical message.', array('exception' => new \Exception()));
359
+ $slackRecord = new SlackRecord(null, null, true, null, false, true);
360
+ $data = $slackRecord->getSlackData($record);
361
+ $this->assertInternalType('string', $data['attachments'][0]['fields'][1]['value']);
362
+ }
363
+
364
  public function testExcludeExtraAndContextFields()
365
  {
366
  $record = $this->getRecord(
376
 
377
  $expected = array(
378
  array(
379
+ 'title' => 'Info',
380
  'value' => sprintf('```%s```', json_encode(array('author' => 'Jordi'), $this->jsonPrettyPrintFlag)),
381
  'short' => false
382
  ),
383
  array(
384
+ 'title' => 'Tags',
385
  'value' => sprintf('```%s```', json_encode(array('web'))),
386
  'short' => false
387
  ),
vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php CHANGED
@@ -77,6 +77,13 @@ class SocketHandlerTest extends TestCase
77
  $this->assertEquals(10.25, $this->handler->getWritingTimeout());
78
  }
79
 
 
 
 
 
 
 
 
80
  public function testSetConnectionString()
81
  {
82
  $this->createHandler('tcp://localhost:9090');
@@ -120,6 +127,19 @@ class SocketHandlerTest extends TestCase
120
  $this->writeRecord('Hello world');
121
  }
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  /**
124
  * @expectedException RuntimeException
125
  */
@@ -304,6 +324,12 @@ class SocketHandlerTest extends TestCase
304
  ->will($this->returnValue(true));
305
  }
306
 
 
 
 
 
 
 
307
  $this->handler->setFormatter($this->getIdentityFormatter());
308
  }
309
  }
77
  $this->assertEquals(10.25, $this->handler->getWritingTimeout());
78
  }
79
 
80
+ public function testSetChunkSize()
81
+ {
82
+ $this->createHandler('localhost:1234');
83
+ $this->handler->setChunkSize(1025);
84
+ $this->assertEquals(1025, $this->handler->getChunkSize());
85
+ }
86
+
87
  public function testSetConnectionString()
88
  {
89
  $this->createHandler('tcp://localhost:9090');
127
  $this->writeRecord('Hello world');
128
  }
129
 
130
+ /**
131
+ * @expectedException UnexpectedValueException
132
+ */
133
+ public function testExceptionIsThrownIfCannotSetChunkSize()
134
+ {
135
+ $this->setMockHandler(array('streamSetChunkSize'));
136
+ $this->handler->setChunkSize(8192);
137
+ $this->handler->expects($this->once())
138
+ ->method('streamSetChunkSize')
139
+ ->will($this->returnValue(false));
140
+ $this->writeRecord('Hello world');
141
+ }
142
+
143
  /**
144
  * @expectedException RuntimeException
145
  */
324
  ->will($this->returnValue(true));
325
  }
326
 
327
+ if (!in_array('streamSetChunkSize', $methods)) {
328
+ $this->handler->expects($this->any())
329
+ ->method('streamSetChunkSize')
330
+ ->will($this->returnValue(8192));
331
+ }
332
+
333
  $this->handler->setFormatter($this->getIdentityFormatter());
334
  }
335
  }
vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php CHANGED
@@ -54,6 +54,52 @@ class TestHandlerTest extends TestCase
54
  $this->assertEquals(array($record), $records);
55
  }
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  public function methodProvider()
58
  {
59
  return array(
54
  $this->assertEquals(array($record), $records);
55
  }
56
 
57
+ public function testHandlerAssertEmptyContext() {
58
+ $handler = new TestHandler;
59
+ $record = $this->getRecord(Logger::WARNING, 'test', array());
60
+ $this->assertFalse($handler->hasWarning(array(
61
+ 'message' => 'test',
62
+ 'context' => array(),
63
+ )));
64
+
65
+ $handler->handle($record);
66
+
67
+ $this->assertTrue($handler->hasWarning(array(
68
+ 'message' => 'test',
69
+ 'context' => array(),
70
+ )));
71
+ $this->assertFalse($handler->hasWarning(array(
72
+ 'message' => 'test',
73
+ 'context' => array(
74
+ 'foo' => 'bar'
75
+ ),
76
+ )));
77
+ }
78
+
79
+ public function testHandlerAssertNonEmptyContext() {
80
+ $handler = new TestHandler;
81
+ $record = $this->getRecord(Logger::WARNING, 'test', array('foo' => 'bar'));
82
+ $this->assertFalse($handler->hasWarning(array(
83
+ 'message' => 'test',
84
+ 'context' => array(
85
+ 'foo' => 'bar'
86
+ ),
87
+ )));
88
+
89
+ $handler->handle($record);
90
+
91
+ $this->assertTrue($handler->hasWarning(array(
92
+ 'message' => 'test',
93
+ 'context' => array(
94
+ 'foo' => 'bar'
95
+ ),
96
+ )));
97
+ $this->assertFalse($handler->hasWarning(array(
98
+ 'message' => 'test',
99
+ 'context' => array(),
100
+ )));
101
+ }
102
+
103
  public function methodProvider()
104
  {
105
  return array(
vendor/monolog/monolog/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php CHANGED
@@ -87,6 +87,29 @@ class WhatFailureGroupHandlerTest extends TestCase
87
  $this->assertTrue($records[0]['extra']['foo']);
88
  }
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  /**
91
  * @covers Monolog\Handler\WhatFailureGroupHandler::handle
92
  */
87
  $this->assertTrue($records[0]['extra']['foo']);
88
  }
89
 
90
+ /**
91
+ * @covers Monolog\Handler\WhatFailureGroupHandler::handleBatch
92
+ */
93
+ public function testHandleBatchUsesProcessors()
94
+ {
95
+ $testHandlers = array(new TestHandler(), new TestHandler());
96
+ $handler = new WhatFailureGroupHandler($testHandlers);
97
+ $handler->pushProcessor(function ($record) {
98
+ $record['extra']['foo'] = true;
99
+
100
+ return $record;
101
+ });
102
+ $handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO)));
103
+ foreach ($testHandlers as $test) {
104
+ $this->assertTrue($test->hasDebugRecords());
105
+ $this->assertTrue($test->hasInfoRecords());
106
+ $this->assertTrue(count($test->getRecords()) === 2);
107
+ $records = $test->getRecords();
108
+ $this->assertTrue($records[0]['extra']['foo']);
109
+ $this->assertTrue($records[1]['extra']['foo']);
110
+ }
111
+ }
112
+
113
  /**
114
  * @covers Monolog\Handler\WhatFailureGroupHandler::handle
115
  */
vendor/monolog/monolog/tests/Monolog/LoggerTest.php CHANGED
@@ -545,4 +545,146 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
545
  'without microseconds' => array(false, PHP_VERSION_ID >= 70100 ? 'assertNotSame' : 'assertSame'),
546
  );
547
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  }
545
  'without microseconds' => array(false, PHP_VERSION_ID >= 70100 ? 'assertNotSame' : 'assertSame'),
546
  );
547
  }
548
+
549
+ /**
550
+ * @covers Monolog\Logger::setExceptionHandler
551
+ */
552
+ public function testSetExceptionHandler()
553
+ {
554
+ $logger = new Logger(__METHOD__);
555
+ $this->assertNull($logger->getExceptionHandler());
556
+ $callback = function ($ex) {
557
+ };
558
+ $logger->setExceptionHandler($callback);
559
+ $this->assertEquals($callback, $logger->getExceptionHandler());
560
+ }
561
+
562
+ /**
563
+ * @covers Monolog\Logger::setExceptionHandler
564
+ * @expectedException InvalidArgumentException
565
+ */
566
+ public function testBadExceptionHandlerType()
567
+ {
568
+ $logger = new Logger(__METHOD__);
569
+ $logger->setExceptionHandler(false);
570
+ }
571
+
572
+ /**
573
+ * @covers Monolog\Logger::handleException
574
+ * @expectedException Exception
575
+ */
576
+ public function testDefaultHandleException()
577
+ {
578
+ $logger = new Logger(__METHOD__);
579
+ $handler = $this->getMock('Monolog\Handler\HandlerInterface');
580
+ $handler->expects($this->any())
581
+ ->method('isHandling')
582
+ ->will($this->returnValue(true))
583
+ ;
584
+ $handler->expects($this->any())
585
+ ->method('handle')
586
+ ->will($this->throwException(new \Exception('Some handler exception')))
587
+ ;
588
+ $logger->pushHandler($handler);
589
+ $logger->info('test');
590
+ }
591
+
592
+ /**
593
+ * @covers Monolog\Logger::handleException
594
+ * @covers Monolog\Logger::addRecord
595
+ */
596
+ public function testCustomHandleException()
597
+ {
598
+ $logger = new Logger(__METHOD__);
599
+ $that = $this;
600
+ $logger->setExceptionHandler(function ($e, $record) use ($that) {
601
+ $that->assertEquals($e->getMessage(), 'Some handler exception');
602
+ $that->assertTrue(is_array($record));
603
+ $that->assertEquals($record['message'], 'test');
604
+ });
605
+ $handler = $this->getMock('Monolog\Handler\HandlerInterface');
606
+ $handler->expects($this->any())
607
+ ->method('isHandling')
608
+ ->will($this->returnValue(true))
609
+ ;
610
+ $handler->expects($this->any())
611
+ ->method('handle')
612
+ ->will($this->throwException(new \Exception('Some handler exception')))
613
+ ;
614
+ $logger->pushHandler($handler);
615
+ $logger->info('test');
616
+ }
617
+
618
+ public function testReset()
619
+ {
620
+ $logger = new Logger('app');
621
+
622
+ $testHandler = new Handler\TestHandler();
623
+ $bufferHandler = new Handler\BufferHandler($testHandler);
624
+ $groupHandler = new Handler\GroupHandler(array($bufferHandler));
625
+ $fingersCrossedHandler = new Handler\FingersCrossedHandler($groupHandler);
626
+
627
+ $logger->pushHandler($fingersCrossedHandler);
628
+
629
+ $processorUid1 = new Processor\UidProcessor(10);
630
+ $uid1 = $processorUid1->getUid();
631
+ $groupHandler->pushProcessor($processorUid1);
632
+
633
+ $processorUid2 = new Processor\UidProcessor(5);
634
+ $uid2 = $processorUid2->getUid();
635
+ $logger->pushProcessor($processorUid2);
636
+
637
+ $getProperty = function ($object, $property) {
638
+ $reflectionProperty = new \ReflectionProperty(get_class($object), $property);
639
+ $reflectionProperty->setAccessible(true);
640
+
641
+ return $reflectionProperty->getValue($object);
642
+ };
643
+ $that = $this;
644
+ $assertBufferOfBufferHandlerEmpty = function () use ($getProperty, $bufferHandler, $that) {
645
+ $that->assertEmpty($getProperty($bufferHandler, 'buffer'));
646
+ };
647
+ $assertBuffersEmpty = function() use ($assertBufferOfBufferHandlerEmpty, $getProperty, $fingersCrossedHandler, $that) {
648
+ $assertBufferOfBufferHandlerEmpty();
649
+ $that->assertEmpty($getProperty($fingersCrossedHandler, 'buffer'));
650
+ };
651
+
652
+ $logger->debug('debug');
653
+ $logger->reset();
654
+ $assertBuffersEmpty();
655
+ $this->assertFalse($testHandler->hasDebugRecords());
656
+ $this->assertFalse($testHandler->hasErrorRecords());
657
+ $this->assertNotSame($uid1, $uid1 = $processorUid1->getUid());
658
+ $this->assertNotSame($uid2, $uid2 = $processorUid2->getUid());
659
+
660
+ $logger->debug('debug');
661
+ $logger->error('error');
662
+ $logger->reset();
663
+ $assertBuffersEmpty();
664
+ $this->assertTrue($testHandler->hasDebugRecords());
665
+ $this->assertTrue($testHandler->hasErrorRecords());
666
+ $this->assertNotSame($uid1, $uid1 = $processorUid1->getUid());
667
+ $this->assertNotSame($uid2, $uid2 = $processorUid2->getUid());
668
+
669
+ $logger->info('info');
670
+ $this->assertNotEmpty($getProperty($fingersCrossedHandler, 'buffer'));
671
+ $assertBufferOfBufferHandlerEmpty();
672
+ $this->assertFalse($testHandler->hasInfoRecords());
673
+
674
+ $logger->reset();
675
+ $assertBuffersEmpty();
676
+ $this->assertFalse($testHandler->hasInfoRecords());
677
+ $this->assertNotSame($uid1, $uid1 = $processorUid1->getUid());
678
+ $this->assertNotSame($uid2, $uid2 = $processorUid2->getUid());
679
+
680
+ $logger->notice('notice');
681
+ $logger->emergency('emergency');
682
+ $logger->reset();
683
+ $assertBuffersEmpty();
684
+ $this->assertFalse($testHandler->hasInfoRecords());
685
+ $this->assertTrue($testHandler->hasNoticeRecords());
686
+ $this->assertTrue($testHandler->hasEmergencyRecords());
687
+ $this->assertNotSame($uid1, $processorUid1->getUid());
688
+ $this->assertNotSame($uid2, $processorUid2->getUid());
689
+ }
690
  }
vendor/monolog/monolog/tests/Monolog/SignalHandlerTest.php ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of the Monolog package.
5
+ *
6
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Monolog;
13
+
14
+ use Monolog\Handler\StreamHandler;
15
+ use Monolog\Handler\TestHandler;
16
+ use Psr\Log\LogLevel;
17
+
18
+ /**
19
+ * @author Robert Gust-Bardon <robert@gust-bardon.org>
20
+ * @covers Monolog\SignalHandler
21
+ */
22
+ class SignalHandlerTest extends TestCase
23
+ {
24
+
25
+ private $asyncSignalHandling;
26
+ private $blockedSignals;
27
+ private $signalHandlers;
28
+
29
+ protected function setUp()
30
+ {
31
+ $this->signalHandlers = array();
32
+ if (extension_loaded('pcntl')) {
33
+ if (function_exists('pcntl_async_signals')) {
34
+ $this->asyncSignalHandling = pcntl_async_signals();
35
+ }
36
+ if (function_exists('pcntl_sigprocmask')) {
37
+ pcntl_sigprocmask(SIG_BLOCK, array(), $this->blockedSignals);
38
+ }
39
+ }
40
+ }
41
+
42
+ protected function tearDown()
43
+ {
44
+ if ($this->asyncSignalHandling !== null) {
45
+ pcntl_async_signals($this->asyncSignalHandling);
46
+ }
47
+ if ($this->blockedSignals !== null) {
48
+ pcntl_sigprocmask(SIG_SETMASK, $this->blockedSignals);
49
+ }
50
+ if ($this->signalHandlers) {
51
+ pcntl_signal_dispatch();
52
+ foreach ($this->signalHandlers as $signo => $handler) {
53
+ pcntl_signal($signo, $handler);
54
+ }
55
+ }
56
+ }
57
+
58
+ private function setSignalHandler($signo, $handler = SIG_DFL) {
59
+ if (function_exists('pcntl_signal_get_handler')) {
60
+ $this->signalHandlers[$signo] = pcntl_signal_get_handler($signo);
61
+ } else {
62
+ $this->signalHandlers[$signo] = SIG_DFL;
63
+ }
64
+ $this->assertTrue(pcntl_signal($signo, $handler));
65
+ }
66
+
67
+ public function testHandleSignal()
68
+ {
69
+ $logger = new Logger('test', array($handler = new TestHandler));
70
+ $errHandler = new SignalHandler($logger);
71
+ $signo = 2; // SIGINT.
72
+ $siginfo = array('signo' => $signo, 'errno' => 0, 'code' => 0);
73
+ $errHandler->handleSignal($signo, $siginfo);
74
+ $this->assertCount(1, $handler->getRecords());
75
+ $this->assertTrue($handler->hasCriticalRecords());
76
+ $records = $handler->getRecords();
77
+ $this->assertSame($siginfo, $records[0]['context']);
78
+ }
79
+
80
+ /**
81
+ * @depends testHandleSignal
82
+ * @requires extension pcntl
83
+ * @requires extension posix
84
+ * @requires function pcntl_signal
85
+ * @requires function pcntl_signal_dispatch
86
+ * @requires function posix_getpid
87
+ * @requires function posix_kill
88
+ */
89
+ public function testRegisterSignalHandler()
90
+ {
91
+ // SIGCONT and SIGURG should be ignored by default.
92
+ if (!defined('SIGCONT') || !defined('SIGURG')) {
93
+ $this->markTestSkipped('This test requires the SIGCONT and SIGURG pcntl constants.');
94
+ }
95
+
96
+ $this->setSignalHandler(SIGCONT, SIG_IGN);
97
+ $this->setSignalHandler(SIGURG, SIG_IGN);
98
+
99
+ $logger = new Logger('test', array($handler = new TestHandler));
100
+ $errHandler = new SignalHandler($logger);
101
+ $pid = posix_getpid();
102
+
103
+ $this->assertTrue(posix_kill($pid, SIGURG));
104
+ $this->assertTrue(pcntl_signal_dispatch());
105
+ $this->assertCount(0, $handler->getRecords());
106
+
107
+ $errHandler->registerSignalHandler(SIGURG, LogLevel::INFO, false, false, false);
108
+
109
+ $this->assertTrue(posix_kill($pid, SIGCONT));
110
+ $this->assertTrue(pcntl_signal_dispatch());
111
+ $this->assertCount(0, $handler->getRecords());
112
+
113
+ $this->assertTrue(posix_kill($pid, SIGURG));
114
+ $this->assertTrue(pcntl_signal_dispatch());
115
+ $this->assertCount(1, $handler->getRecords());
116
+ $this->assertTrue($handler->hasInfoThatContains('SIGURG'));
117
+ }
118
+
119
+ /**
120
+ * @dataProvider defaultPreviousProvider
121
+ * @depends testRegisterSignalHandler
122
+ * @requires function pcntl_fork
123
+ * @requires function pcntl_sigprocmask
124
+ * @requires function pcntl_waitpid
125
+ */
126
+ public function testRegisterDefaultPreviousSignalHandler($signo, $callPrevious, $expected)
127
+ {
128
+ $this->setSignalHandler($signo, SIG_DFL);
129
+
130
+ $path = tempnam(sys_get_temp_dir(), 'monolog-');
131
+ $this->assertNotFalse($path);
132
+
133
+ $pid = pcntl_fork();
134
+ if ($pid === 0) { // Child.
135
+ $streamHandler = new StreamHandler($path);
136
+ $streamHandler->setFormatter($this->getIdentityFormatter());
137
+ $logger = new Logger('test', array($streamHandler));
138
+ $errHandler = new SignalHandler($logger);
139
+ $errHandler->registerSignalHandler($signo, LogLevel::INFO, $callPrevious, false, false);
140
+ pcntl_sigprocmask(SIG_SETMASK, array(SIGCONT));
141
+ posix_kill(posix_getpid(), $signo);
142
+ pcntl_signal_dispatch();
143
+ // If $callPrevious is true, SIGINT should terminate by this line.
144
+ pcntl_sigprocmask(SIG_BLOCK, array(), $oldset);
145
+ file_put_contents($path, implode(' ', $oldset), FILE_APPEND);
146
+ posix_kill(posix_getpid(), $signo);
147
+ pcntl_signal_dispatch();
148
+ exit();
149
+ }
150
+
151
+ $this->assertNotSame(-1, $pid);
152
+ $this->assertNotSame(-1, pcntl_waitpid($pid, $status));
153
+ $this->assertNotSame(-1, $status);
154
+ $this->assertSame($expected, file_get_contents($path));
155
+ }
156
+
157
+ public function defaultPreviousProvider()
158
+ {
159
+ if (!defined('SIGCONT') || !defined('SIGINT') || !defined('SIGURG')) {
160
+ return array();
161
+ }
162
+
163
+ return array(
164
+ array(SIGINT, false, 'Program received signal SIGINT'.SIGCONT.'Program received signal SIGINT'),
165
+ array(SIGINT, true, 'Program received signal SIGINT'),
166
+ array(SIGURG, false, 'Program received signal SIGURG'.SIGCONT.'Program received signal SIGURG'),
167
+ array(SIGURG, true, 'Program received signal SIGURG'.SIGCONT.'Program received signal SIGURG'),
168
+ );
169
+ }
170
+
171
+ /**
172
+ * @dataProvider callablePreviousProvider
173
+ * @depends testRegisterSignalHandler
174
+ * @requires function pcntl_signal_get_handler
175
+ */
176
+ public function testRegisterCallablePreviousSignalHandler($callPrevious)
177
+ {
178
+ $this->setSignalHandler(SIGURG, SIG_IGN);
179
+
180
+ $logger = new Logger('test', array($handler = new TestHandler));
181
+ $errHandler = new SignalHandler($logger);
182
+ $previousCalled = 0;
183
+ pcntl_signal(SIGURG, function ($signo, array $siginfo = null) use (&$previousCalled) {
184
+ ++$previousCalled;
185
+ });
186
+ $errHandler->registerSignalHandler(SIGURG, LogLevel::INFO, $callPrevious, false, false);
187
+ $this->assertTrue(posix_kill(posix_getpid(), SIGURG));
188
+ $this->assertTrue(pcntl_signal_dispatch());
189
+ $this->assertCount(1, $handler->getRecords());
190
+ $this->assertTrue($handler->hasInfoThatContains('SIGURG'));
191
+ $this->assertSame($callPrevious ? 1 : 0, $previousCalled);
192
+ }
193
+
194
+ public function callablePreviousProvider()
195
+ {
196
+ return array(
197
+ array(false),
198
+ array(true),
199
+ );
200
+ }
201
+
202
+ /**
203
+ * @dataProvider restartSyscallsProvider
204
+ * @depends testRegisterDefaultPreviousSignalHandler
205
+ * @requires function pcntl_fork
206
+ * @requires function pcntl_waitpid
207
+ */
208
+ public function testRegisterSyscallRestartingSignalHandler($restartSyscalls)
209
+ {
210
+ $this->setSignalHandler(SIGURG, SIG_IGN);
211
+
212
+ $parentPid = posix_getpid();
213
+ $microtime = microtime(true);
214
+
215
+ $pid = pcntl_fork();
216
+ if ($pid === 0) { // Child.
217
+ usleep(100000);
218
+ posix_kill($parentPid, SIGURG);
219
+ usleep(100000);
220
+ exit();
221
+ }
222
+
223
+ $this->assertNotSame(-1, $pid);
224
+ $logger = new Logger('test', array($handler = new TestHandler));
225
+ $errHandler = new SignalHandler($logger);
226
+ $errHandler->registerSignalHandler(SIGURG, LogLevel::INFO, false, $restartSyscalls, false);
227
+ if ($restartSyscalls) {
228
+ // pcntl_wait is expected to be restarted after the signal handler.
229
+ $this->assertNotSame(-1, pcntl_waitpid($pid, $status));
230
+ } else {
231
+ // pcntl_wait is expected to be interrupted when the signal handler is invoked.
232
+ $this->assertSame(-1, pcntl_waitpid($pid, $status));
233
+ }
234
+ $this->assertSame($restartSyscalls, microtime(true) - $microtime > 0.15);
235
+ $this->assertTrue(pcntl_signal_dispatch());
236
+ $this->assertCount(1, $handler->getRecords());
237
+ if ($restartSyscalls) {
238
+ // The child has already exited.
239
+ $this->assertSame(-1, pcntl_waitpid($pid, $status));
240
+ } else {
241
+ // The child has not exited yet.
242
+ $this->assertNotSame(-1, pcntl_waitpid($pid, $status));
243
+ }
244
+ }
245
+
246
+ public function restartSyscallsProvider()
247
+ {
248
+ return array(
249
+ array(false),
250
+ array(true),
251
+ array(false),
252
+ array(true),
253
+ );
254
+ }
255
+
256
+ /**
257
+ * @dataProvider asyncProvider
258
+ * @depends testRegisterDefaultPreviousSignalHandler
259
+ * @requires function pcntl_async_signals
260
+ */
261
+ public function testRegisterAsyncSignalHandler($initialAsync, $desiredAsync, $expectedBefore, $expectedAfter)
262
+ {
263
+ $this->setSignalHandler(SIGURG, SIG_IGN);
264
+ pcntl_async_signals($initialAsync);
265
+
266
+ $logger = new Logger('test', array($handler = new TestHandler));
267
+ $errHandler = new SignalHandler($logger);
268
+ $errHandler->registerSignalHandler(SIGURG, LogLevel::INFO, false, false, $desiredAsync);
269
+ $this->assertTrue(posix_kill(posix_getpid(), SIGURG));
270
+ $this->assertCount($expectedBefore, $handler->getRecords());
271
+ $this->assertTrue(pcntl_signal_dispatch());
272
+ $this->assertCount($expectedAfter, $handler->getRecords());
273
+ }
274
+
275
+ public function asyncProvider()
276
+ {
277
+ return array(
278
+ array(false, false, 0, 1),
279
+ array(false, null, 0, 1),
280
+ array(false, true, 1, 1),
281
+ array(true, false, 0, 1),
282
+ array(true, null, 1, 1),
283
+ array(true, true, 1, 1),
284
+ );
285
+ }
286
+
287
+ }
vendor/mpdf/mpdf/composer.json CHANGED
@@ -88,7 +88,7 @@
88
 
89
  "extra": {
90
  "branch-alias": {
91
- "dev-development": "7.0-dev"
92
  }
93
  }
94
 
88
 
89
  "extra": {
90
  "branch-alias": {
91
+ "dev-development": "7.x-dev"
92
  }
93
  }
94
 
vendor/mpdf/mpdf/src/CssManager.php CHANGED
@@ -1494,11 +1494,12 @@ class CssManager
1494
  $shortlang = substr($attr['LANG'], 0, 2);
1495
  }
1496
  }
1497
- //===============================================
1498
  /* -- TABLES -- */
 
1499
  // Set Inherited properties
1500
  if ($inherit === 'TOPTABLE') { // $tag = TABLE
1501
- //===============================================
1502
  // Save Cascading CSS e.g. "div.topic p" at this block level
1503
  if (isset($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'])) {
1504
  $this->tablecascadeCSS[0] = $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'];
@@ -1506,24 +1507,42 @@ class CssManager
1506
  $this->tablecascadeCSS[0] = $this->cascadeCSS;
1507
  }
1508
  }
1509
- //===============================================
1510
  // Set Inherited properties
1511
  if ($inherit === 'TOPTABLE' || $inherit === 'TABLE') {
1512
- //Cascade everything from last level that is not an actual property, or defined by current tag/attributes
 
1513
  if (isset($this->tablecascadeCSS[$this->tbCSSlvl - 1]) && is_array($this->tablecascadeCSS[$this->tbCSSlvl - 1])) {
1514
  foreach ($this->tablecascadeCSS[$this->tbCSSlvl - 1] as $k => $v) {
1515
  $this->tablecascadeCSS[$this->tbCSSlvl][$k] = $v;
1516
  }
1517
  }
1518
- $this->_mergeFullCSS($this->cascadeCSS, $this->tablecascadeCSS[$this->tbCSSlvl], $tag, $classes, $attr['ID'], $attr['LANG']);
1519
- //===============================================
 
 
 
 
 
 
 
 
1520
  // Cascading forward CSS e.g. "table.topic td" for this table in $this->tablecascadeCSS
1521
- //===============================================
1522
  // STYLESHEET TAG e.g. table
1523
- $this->_mergeFullCSS($this->tablecascadeCSS[$this->tbCSSlvl - 1], $this->tablecascadeCSS[$this->tbCSSlvl], $tag, $classes, $attr['ID'], $attr['LANG']);
1524
- //===============================================
 
 
 
 
 
 
 
 
1525
  }
 
1526
  /* -- END TABLES -- */
 
1527
  //===============================================
1528
  // Set Inherited properties
1529
  if ($inherit === 'BLOCK') {
1494
  $shortlang = substr($attr['LANG'], 0, 2);
1495
  }
1496
  }
1497
+
1498
  /* -- TABLES -- */
1499
+
1500
  // Set Inherited properties
1501
  if ($inherit === 'TOPTABLE') { // $tag = TABLE
1502
+
1503
  // Save Cascading CSS e.g. "div.topic p" at this block level
1504
  if (isset($this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'])) {
1505
  $this->tablecascadeCSS[0] = $this->mpdf->blk[$this->mpdf->blklvl]['cascadeCSS'];
1507
  $this->tablecascadeCSS[0] = $this->cascadeCSS;
1508
  }
1509
  }
1510
+
1511
  // Set Inherited properties
1512
  if ($inherit === 'TOPTABLE' || $inherit === 'TABLE') {
1513
+
1514
+ // Cascade everything from last level that is not an actual property, or defined by current tag/attributes
1515
  if (isset($this->tablecascadeCSS[$this->tbCSSlvl - 1]) && is_array($this->tablecascadeCSS[$this->tbCSSlvl - 1])) {
1516
  foreach ($this->tablecascadeCSS[$this->tbCSSlvl - 1] as $k => $v) {
1517
  $this->tablecascadeCSS[$this->tbCSSlvl][$k] = $v;
1518
  }
1519
  }
1520
+
1521
+ $this->_mergeFullCSS(
1522
+ $this->cascadeCSS,
1523
+ $this->tablecascadeCSS[$this->tbCSSlvl],
1524
+ $tag,
1525
+ $classes,
1526
+ $attr['ID'],
1527
+ $attr['LANG']
1528
+ );
1529
+
1530
  // Cascading forward CSS e.g. "table.topic td" for this table in $this->tablecascadeCSS
 
1531
  // STYLESHEET TAG e.g. table
1532
+ if (isset($this->tablecascadeCSS[$this->tbCSSlvl - 1])) {
1533
+ $this->_mergeFullCSS(
1534
+ $this->tablecascadeCSS[$this->tbCSSlvl - 1],
1535
+ $this->tablecascadeCSS[$this->tbCSSlvl],
1536
+ $tag,
1537
+ $classes,
1538
+ $attr['ID'],
1539
+ $attr['LANG']
1540
+ );
1541
+ }
1542
  }
1543
+
1544
  /* -- END TABLES -- */
1545
+
1546
  //===============================================
1547
  // Set Inherited properties
1548
  if ($inherit === 'BLOCK') {
vendor/mpdf/mpdf/src/Form.php CHANGED
@@ -2,11 +2,32 @@
2
 
3
  namespace Mpdf;
4
 
 
 
5
  use Mpdf\Color\ColorConverter;
6
 
 
 
 
7
  class Form
8
  {
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  /**
11
  * @var \Mpdf\Mpdf
12
  */
@@ -22,6 +43,16 @@ class Form
22
  */
23
  private $colorConverter;
24
 
 
 
 
 
 
 
 
 
 
 
25
  /**
26
  * @var array
27
  */
@@ -32,20 +63,6 @@ class Form
32
  */
33
  private $formCount;
34
 
35
- // Input flags
36
- const FLAG_READONLY = 1;
37
- const FLAG_REQUIRED = 2;
38
- const FLAG_NO_EXPORT = 3;
39
- const FLAG_TEXTAREA = 13;
40
- const FLAG_PASSWORD = 14;
41
- const FLAG_RADIO = 15;
42
- const FLAG_NOTOGGLEOFF = 16;
43
- const FLAG_COMBOBOX = 18;
44
- const FLAG_EDITABLE = 19;
45
- const FLAG_MULTISELECT = 22;
46
- const FLAG_NO_SPELLCHECK = 23;
47
- const FLAG_NO_SCROLL = 24;
48
-
49
  // Active Forms
50
  var $formSubmitNoValueFields;
51
  var $formExportType;
@@ -86,11 +103,13 @@ class Form
86
  // FORMS
87
  var $textarea_lineheight;
88
 
89
- public function __construct(Mpdf $mpdf, Otl $otl, ColorConverter $colorConverter)
90
  {
91
  $this->mpdf = $mpdf;
92
  $this->otl = $otl;
93
  $this->colorConverter = $colorConverter;
 
 
94
 
95
  // ACTIVE FORMS
96
  $this->formExportType = 'xfdf'; // 'xfdf' or 'html'
@@ -312,7 +331,7 @@ class Form
312
  }
313
  $this->mpdf->Rect($this->mpdf->x, $this->mpdf->y, $w, $h, 'DF');
314
  $ClipPath = sprintf('q %.3F %.3F %.3F %.3F re W n ', $this->mpdf->x * Mpdf::SCALE, ($this->mpdf->h - $this->mpdf->y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$h * Mpdf::SCALE);
315
- $this->mpdf->_out($ClipPath);
316
 
317
  $w -= $this->form_element_spacing['textarea']['inner']['h'] * 2 / $k;
318
  $this->mpdf->x += $this->form_element_spacing['textarea']['inner']['h'] / $k;
@@ -321,7 +340,7 @@ class Form
321
  if ($texto != '') {
322
  $this->mpdf->MultiCell($w, $this->mpdf->FontSize * $this->textarea_lineheight, $texto, 0, '', 0, '', $blockdir, true, $objattr['OTLdata'], $objattr['rows']);
323
  }
324
- $this->mpdf->_out('Q');
325
  $this->mpdf->SetFColor($this->colorConverter->convert(255, $this->mpdf->PDFAXwarnings));
326
  $this->mpdf->SetTColor($this->colorConverter->convert(0, $this->mpdf->PDFAXwarnings));
327
  }
@@ -446,7 +465,7 @@ class Form
446
  $this->SetJSButton($w, $h, $objattr['fieldname'], (isset($objattr['value']) ? $objattr['value'] : ''), $js, $objattr['ID'], $objattr['title'], $flags, (isset($objattr['Indexed']) ? $objattr['Indexed'] : false));
447
  } else {
448
  $this->mpdf->y = $objattr['INNER-Y'];
449
- $this->mpdf->_out(sprintf('q %.3F 0 0 %.3F %.3F %.3F cm /I%d Do Q', $objattr['INNER-WIDTH'] * Mpdf::SCALE, $objattr['INNER-HEIGHT'] * Mpdf::SCALE, $objattr['INNER-X'] * Mpdf::SCALE, ($this->mpdf->h - ($objattr['INNER-Y'] + $objattr['INNER-HEIGHT'] )) * Mpdf::SCALE, $objattr['ID']));
450
  if (!empty($objattr['BORDER-WIDTH'])) {
451
  $this->mpdf->PaintImgBorder($objattr, $is_table);
452
  }
@@ -634,6 +653,7 @@ class Form
634
  }
635
  }
636
  }
 
637
  if ($form['typ'] === 'Bt') {
638
  if (isset($this->array_form_button_js[$form['T']])) {
639
  $total++;
@@ -706,29 +726,29 @@ class Form
706
  // Output Radio Groups
707
  $key = 1;
708
  foreach ($this->form_radio_groups as $name => $frg) {
709
- $this->mpdf->_newobj();
710
  $this->pdf_acro_array .= $this->mpdf->n . ' 0 R ';
711
- $this->mpdf->_out('<<');
712
- $this->mpdf->_out('/Type /Annot ');
713
- $this->mpdf->_out('/Subtype /Widget');
714
- $this->mpdf->_out('/NM ' . $this->mpdf->_textstring(sprintf('%04u-%04u', $n, 3000 + $key++)));
715
- $this->mpdf->_out('/M ' . $this->mpdf->_textstring('D:' . date('YmdHis')));
716
- $this->mpdf->_out('/Rect [0 0 0 0] ');
717
- $this->mpdf->_out('/FT /Btn ');
718
  if (!empty($frg['disabled'])) {
719
  $flags = [self::FLAG_READONLY, self::FLAG_NO_EXPORT, self::FLAG_RADIO, self::FLAG_NOTOGGLEOFF];
720
  } else {
721
  $flags = [self::FLAG_RADIO, self::FLAG_NOTOGGLEOFF];
722
  }
723
- $this->mpdf->_out('/Ff ' . $this->_setflag($flags));
724
  $kstr = '';
725
  // $optstr = '';
726
  foreach ($frg['kids'] as $kid) {
727
  $kstr .= $this->forms[$kid['n']]['obj'] . ' 0 R ';
728
- // $optstr .= ' '.$this->mpdf->_textstring($kid['OPT']).' ';
729
  }
730
- $this->mpdf->_out('/Kids [ ' . $kstr . ' ] '); // 11 0 R 12 0 R etc.
731
- // $this->mpdf->_out('/Opt [ '.$optstr.' ] ');
732
  //V entry holds index corresponding to the appearance state of
733
  //whichever child field is currently in the on state = or Off
734
  if (isset($frg['on'])) {
@@ -736,34 +756,34 @@ class Form
736
  } else {
737
  $state = 'Off';
738
  }
739
- $this->mpdf->_out('/V /' . $state . ' ');
740
- $this->mpdf->_out('/DV /' . $state . ' ');
741
- $this->mpdf->_out('/T ' . $this->mpdf->_textstring($name) . ' ');
742
- $this->mpdf->_out('>>');
743
- $this->mpdf->_out('endobj');
744
  }
745
  }
746
 
747
  function _putFormsCatalog()
748
  {
749
  if (isset($this->pdf_acro_array)) {
750
- $this->mpdf->_out('/AcroForm << /DA (/F1 0 Tf 0 g )');
751
- $this->mpdf->_out('/Q 0');
752
- $this->mpdf->_out('/Fields [' . $this->pdf_acro_array . ']');
753
  $f = '';
754
  foreach ($this->form_fonts as $fn) {
755
  if (is_array($this->mpdf->fonts[$fn]['n'])) {
756
- $this->mpdf->Error('Cannot use fonts with SMP or SIP characters for interactive Form elements');
757
  }
758
  $f .= '/F' . $this->mpdf->fonts[$fn]['i'] . ' ' . $this->mpdf->fonts[$fn]['n'] . ' 0 R ';
759
  }
760
- $this->mpdf->_out('/DR << /Font << ' . $f . ' >> >>');
761
  // CO Calculation Order
762
  if ($this->pdf_array_co) {
763
- $this->mpdf->_out('/CO [' . $this->pdf_array_co . ']');
764
  }
765
- $this->mpdf->_out('/NeedAppearances true');
766
- $this->mpdf->_out('>>');
767
  }
768
  }
769
 
@@ -771,7 +791,7 @@ class Form
771
  {
772
  $js = str_replace("\t", ' ', trim($js));
773
  if (isset($name) && isset($js)) {
774
- $this->array_form_button_js[$this->mpdf->_escape($name)] = [
775
  'js' => $js
776
  ];
777
  }
@@ -781,7 +801,7 @@ class Form
781
  {
782
  $js = str_replace("\t", ' ', trim($js));
783
  if (isset($name) && isset($js)) {
784
- $this->array_form_choice_js[$this->mpdf->_escape($name)] = [
785
  'js' => $js
786
  ];
787
  }
@@ -793,7 +813,7 @@ class Form
793
  $j = str_replace("\t", ' ', trim($js[$i][1]));
794
  $format = $js[$i][0];
795
  if ($name) {
796
- $this->array_form_text_js[$this->mpdf->_escape($name)][$format] = ['js' => $j];
797
  }
798
  }
799
  }
@@ -826,7 +846,7 @@ class Form
826
  $maxlen = false;
827
  }
828
  if (!preg_match('/^[a-zA-Z0-9_:\-]+$/', $name)) {
829
- $this->mpdf->Error('Field [' . $name . '] must have a name attribute, which can only contain letters, numbers, colon(:), undersore(_) or hyphen(-)');
830
  }
831
  if ($this->mpdf->onlyCoreFonts) {
832
  $value = $this->Win1252ToPDFDocEncoding($value);
@@ -839,12 +859,12 @@ class Form
839
  $this->mpdf->UTF8StringToArray($title); // Add characters to font subset
840
  }
841
  if ($value) {
842
- $value = $this->mpdf->UTF8ToUTF16BE($value);
843
  }
844
  if ($default) {
845
- $default = $this->mpdf->UTF8ToUTF16BE($default);
846
  }
847
- $title = $this->mpdf->UTF8ToUTF16BE($title);
848
  }
849
  if ($background_col) {
850
  $bg_c = $this->mpdf->SetColor($background_col, 'CodeOnly');
@@ -856,7 +876,9 @@ class Form
856
  } else {
857
  $bc_c = $this->form_border_color;
858
  }
859
- $f = ['n' => $this->formCount,
 
 
860
  'typ' => 'Tx',
861
  'page' => $this->mpdf->page,
862
  'x' => $this->mpdf->x,
@@ -881,6 +903,7 @@ class Form
881
  'fontcolor' => $this->mpdf->TextColor,
882
  ]
883
  ];
 
884
  if (is_array($js) && count($js) > 0) {
885
  $this->SetFormTextJS($name, $js);
886
  } // mPDF 5.3.25
@@ -890,8 +913,13 @@ class Form
890
  $this->mpdf->HTMLheaderPageForms[] = $f;
891
  } else {
892
  if ($this->mpdf->ColActive) {
893
- $this->mpdf->columnbuffer[] = ['s' => 'ACROFORM', 'col' => $this->mpdf->CurrCol, 'x' => $this->mpdf->x, 'y' => $this->mpdf->y,
894
- 'h' => $h];
 
 
 
 
 
895
  $this->mpdf->columnForms[$this->mpdf->CurrCol][(int)$this->mpdf->x][(int)$this->mpdf->y] = $this->formCount;
896
  }
897
  $this->forms[$this->formCount] = $f;
@@ -928,10 +956,10 @@ class Form
928
  $this->mpdf->UTF8StringToArray($array['OPT'][$i]); // Add characters to font subset
929
  }
930
  if ($array['VAL'][$i]) {
931
- $array['VAL'][$i] = $this->mpdf->UTF8ToUTF16BE($array['VAL'][$i]);
932
  }
933
  if ($array['OPT'][$i]) {
934
- $array['OPT'][$i] = $this->mpdf->UTF8ToUTF16BE($array['OPT'][$i]);
935
  }
936
  }
937
  }
@@ -1006,7 +1034,7 @@ class Form
1006
  $this->SetFormButton($w, $h, $name, $value, 'js_button', $title, $flags, false, false, $background_col, $border_col, $noprint);
1007
  // pos => 1 = no caption, icon only; 0 = caption only
1008
  if ($image_id) {
1009
- $this->form_button_icon[$this->mpdf->_escape($name)] = [
1010
  'pos' => 1,
1011
  'image_id' => $image_id,
1012
  'Indexed' => $indexed,
@@ -1045,18 +1073,18 @@ class Form
1045
  if (isset($this->mpdf->CurrentFont['subset'])) {
1046
  $this->mpdf->UTF8StringToArray($ca); // Add characters to font subset
1047
  }
1048
- $ca = $this->mpdf->UTF8ToUTF16BE($ca);
1049
  if ($rc) {
1050
  if (isset($this->mpdf->CurrentFont['subset'])) {
1051
  $this->mpdf->UTF8StringToArray($rc);
1052
  }
1053
- $rc = $this->mpdf->UTF8ToUTF16BE($rc);
1054
  }
1055
  if ($ac) {
1056
  if (isset($this->mpdf->CurrentFont['subset'])) {
1057
  $this->mpdf->UTF8StringToArray($ac);
1058
  }
1059
- $ac = $this->mpdf->UTF8ToUTF16BE($ac);
1060
  }
1061
  }
1062
  $this->form_button_text = $ca;
@@ -1068,32 +1096,32 @@ class Form
1068
  {
1069
  $this->formCount++;
1070
  if (!preg_match('/^[a-zA-Z0-9_:\-]+$/', $name)) {
1071
- $this->mpdf->Error('Field [' . $name . '] must have a name attribute, which can only contain letters, numbers, colon(:), undersore(_) or hyphen(-)');
1072
  }
1073
  if (!$this->mpdf->onlyCoreFonts) {
1074
  if (isset($this->mpdf->CurrentFont['subset'])) {
1075
  $this->mpdf->UTF8StringToArray($title); // Add characters to font subset
1076
  $this->mpdf->UTF8StringToArray($value); // Add characters to font subset
1077
  }
1078
- $title = $this->mpdf->UTF8ToUTF16BE($title);
1079
  if ($type === 'checkbox') {
1080
- $uvalue = $this->mpdf->UTF8ToUTF16BE($value);
1081
  } else if ($type === 'radio') {
1082
- $uvalue = $this->mpdf->UTF8ToUTF16BE($value);
1083
  $value = mb_convert_encoding($value, 'Windows-1252', 'UTF-8');
1084
  } else {
1085
- $value = $this->mpdf->UTF8ToUTF16BE($value);
1086
  $uvalue = $value;
1087
  }
1088
  } else {
1089
  $title = $this->Win1252ToPDFDocEncoding($title);
1090
  $value = $this->Win1252ToPDFDocEncoding($value); //// ??? not needed
1091
  $uvalue = mb_convert_encoding($value, 'UTF-8', 'Windows-1252');
1092
- $uvalue = $this->mpdf->UTF8ToUTF16BE($uvalue);
1093
  }
1094
  if ($type === 'radio' || $type === 'checkbox') {
1095
  if (!preg_match('/^[a-zA-Z0-9_:\-\.]+$/', $value)) {
1096
- $this->mpdf->Error("Field '" . $name . "' must have a value, which can only contain letters, numbers, colon(:), underscore(_), hyphen(-) or period(.)");
1097
  }
1098
  }
1099
  if ($type === 'radio') {
@@ -1269,11 +1297,14 @@ class Form
1269
  $y = $hPt - ($y * Mpdf::SCALE);
1270
  $x2 = $x + ($w * Mpdf::SCALE);
1271
  $y2 = $y - ($h * Mpdf::SCALE);
 
1272
  return sprintf('%.3F %.3F %.3F %.3F', $x, $y2, $x2, $y);
1273
  }
1274
 
1275
  function _put_button_icon($array, $w, $h)
1276
  {
 
 
1277
  if (isset($array['image_id'])) {
1278
  $info = false;
1279
  foreach ($this->mpdf->images as $iid => $img) {
@@ -1283,46 +1314,52 @@ class Form
1283
  }
1284
  }
1285
  }
 
1286
  if (!$info) {
1287
  throw new \Mpdf\MpdfException('Cannot find Button image');
1288
  }
1289
- $this->mpdf->_newobj();
1290
- $this->mpdf->_out('<<');
1291
- $this->mpdf->_out('/Type /XObject');
1292
- $this->mpdf->_out('/Subtype /Image');
1293
- $this->mpdf->_out('/BBox [0 0 1 1]');
1294
- $this->mpdf->_out('/Length ' . strlen($info['data']));
1295
- $this->mpdf->_out('/BitsPerComponent ' . $info['bpc']);
 
 
1296
  if ($info['cs'] === 'Indexed') {
1297
- $this->mpdf->_out('/ColorSpace [/Indexed /DeviceRGB ' . (strlen($info['pal']) / 3 - 1) . ' ' . ($this->mpdf->n + 1) . ' 0 R]');
1298
  } else {
1299
- $this->mpdf->_out('/ColorSpace /' . $info['cs']);
1300
  if ($info['cs'] === 'DeviceCMYK') {
1301
  if ($info['type'] === 'jpg') {
1302
- $this->mpdf->_out('/Decode [1 0 1 0 1 0 1 0]');
1303
  }
1304
  }
1305
  }
 
1306
  if (isset($info['f'])) {
1307
- $this->mpdf->_out('/Filter /' . $info['f']);
1308
  }
 
1309
  if (isset($info['parms'])) {
1310
- $this->mpdf->_out($info['parms']);
1311
- }
1312
- $this->mpdf->_out('/Width ' . $info['w']);
1313
- $this->mpdf->_out('/Height ' . $info['h']);
1314
- $this->mpdf->_out('>>');
1315
- $this->mpdf->_putstream($info['data']);
1316
- $this->mpdf->_out('endobj');
1317
- unset($array);
 
1318
  //Palette
1319
  if ($info['cs'] === 'Indexed') {
1320
  $filter = $this->mpdf->compress ? '/Filter /FlateDecode ' : '';
1321
- $this->mpdf->_newobj();
1322
  $pal = $this->mpdf->compress ? gzcompress($info['pal']) : $info['pal'];
1323
- $this->mpdf->_out('<<' . $filter . '/Length ' . strlen($pal) . '>>');
1324
- $this->mpdf->_putstream($pal);
1325
- $this->mpdf->_out('endobj');
1326
  }
1327
  }
1328
 
@@ -1331,38 +1368,49 @@ class Form
1331
  $cc = 0;
1332
  $put_js = 0;
1333
  $put_icon = 0;
1334
- $this->mpdf->_newobj();
1335
  $n = $this->mpdf->n;
 
1336
  if ($form['subtype'] !== 'radio') {
1337
  $this->pdf_acro_array .= $n . ' 0 R '; // Add to /Field element
1338
  }
 
1339
  $this->forms[$form['n']]['obj'] = $n;
1340
- $this->mpdf->_out('<<');
1341
- $this->mpdf->_out('/Type /Annot ');
1342
- $this->mpdf->_out('/Subtype /Widget');
1343
- $this->mpdf->_out('/NM ' . $this->mpdf->_textstring(sprintf('%04u-%04u', $n, 7000 + $form['n'])));
1344
- $this->mpdf->_out('/M ' . $this->mpdf->_textstring('D:' . date('YmdHis')));
1345
- $this->mpdf->_out('/Rect [ ' . $this->_form_rect($form['x'], $form['y'], $form['w'], $form['h'], $hPt) . ' ]');
1346
- $form['noprint'] ? $this->mpdf->_out('/F 0 ') : $this->mpdf->_out('/F 4 ');
1347
- $this->mpdf->_out('/FT /Btn ');
1348
- $this->mpdf->_out('/H /P ');
 
 
 
1349
  if ($form['subtype'] !== 'radio') { // mPDF 5.3.23
1350
- $this->mpdf->_out('/T ' . $this->mpdf->_textstring($form['T']));
1351
  }
1352
- $this->mpdf->_out('/TU ' . $this->mpdf->_textstring($form['TU']));
 
 
1353
  if (isset($this->form_button_icon[$form['T']])) {
1354
  $form['BS_W'] = 0;
1355
  }
 
1356
  if ($form['BS_W'] == 0) {
1357
  $form['BC_C'] = $form['BG_C'];
1358
  }
 
1359
  $bstemp = '';
1360
  $bstemp .= '/W ' . $form['BS_W'] . ' ';
1361
  $bstemp .= '/S /' . $form['BS_S'] . ' ';
1362
  $temp = '';
1363
  $temp .= '/BC [ ' . $form['BC_C'] . ' ] ';
1364
  $temp .= '/BG [ ' . $form['BG_C'] . ' ] ';
 
1365
  if ($form['subtype'] === 'checkbox') {
 
1366
  if ($form['disabled']) {
1367
  $radio_color = '0.5 0.5 0.5';
1368
  $radio_background_color = '0.9 0.9 0.9';
@@ -1370,31 +1418,35 @@ class Form
1370
  $radio_color = $this->form_radio_color;
1371
  $radio_background_color = $this->form_radio_background_color;
1372
  }
 
1373
  $temp = '';
1374
  $temp .= '/BC [ ' . $radio_color . ' ] ';
1375
  $temp .= '/BG [ ' . $radio_background_color . ' ] ';
1376
- $this->mpdf->_out('/BS << /W 1 /S /S >>');
1377
- $this->mpdf->_out("/MK << $temp >>");
1378
- $this->mpdf->_out('/Ff ' . $this->_setflag($form['FF']));
 
1379
  if ($form['activ']) {
1380
- $this->mpdf->_out('/V /' . $this->mpdf->_escape($form['V']) . ' ');
1381
- $this->mpdf->_out('/DV /' . $this->mpdf->_escape($form['V']) . ' ');
1382
- $this->mpdf->_out('/AS /' . $this->mpdf->_escape($form['V']) . ' ');
1383
  } else {
1384
- $this->mpdf->_out('/AS /Off ');
1385
  }
 
1386
  if ($this->formUseZapD) {
1387
- $this->mpdf->_out('/DA (/F' . $this->mpdf->fonts['czapfdingbats']['i'] . ' 0 Tf ' . $radio_color . ' rg)');
1388
- $this->mpdf->_out('/AP << /N << /' . $this->mpdf->_escape($form['V']) . ' ' . ($this->mpdf->n + 1) . ' 0 R /Off /Off >> >>');
1389
  } else {
1390
- $this->mpdf->_out('/DA (/F' . $this->mpdf->fonts[$this->mpdf->CurrentFont['fontkey']]['i'] . ' 0 Tf ' . $radio_color . ' rg)');
1391
- $this->mpdf->_out('/AP << /N << /' . $this->mpdf->_escape($form['V']) . ' ' . ($this->mpdf->n + 1) . ' 0 R /Off ' . ($this->mpdf->n + 2) . ' 0 R >> >>');
1392
  }
1393
- $this->mpdf->_out('/Opt [ ' . $this->mpdf->_textstring($form['OPT']) . ' ' . $this->mpdf->_textstring($form['OPT']) . ' ]');
1394
- }
1395
 
 
 
1396
 
1397
  if ($form['subtype'] === 'radio') {
 
1398
  if ((isset($form['disabled']) && $form['disabled']) || (isset($this->form_radio_groups[$form['T']]['disabled']) && $this->form_radio_groups[$form['T']]['disabled'])) {
1399
  $radio_color = '0.5 0.5 0.5';
1400
  $radio_background_color = '0.9 0.9 0.9';
@@ -1402,64 +1454,69 @@ class Form
1402
  $radio_color = $this->form_radio_color;
1403
  $radio_background_color = $this->form_radio_background_color;
1404
  }
1405
- $this->mpdf->_out('/Parent ' . $this->form_radio_groups[$form['T']]['obj_id'] . ' 0 R ');
 
 
1406
  $temp = '';
1407
  $temp .= '/BC [ ' . $radio_color . ' ] ';
1408
  $temp .= '/BG [ ' . $radio_background_color . ' ] ';
1409
- $this->mpdf->_out('/BS << /W 1 /S /S >>');
1410
- $this->mpdf->_out('/MK << ' . $temp . ' >> ');
 
 
1411
  $form['FF'][] = self::FLAG_NOTOGGLEOFF;
1412
  $form['FF'][] = self::FLAG_RADIO; // must be same as radio button group setting?
1413
- $this->mpdf->_out('/Ff ' . $this->_setflag($form['FF']));
 
1414
  if ($this->formUseZapD) {
1415
- $this->mpdf->_out('/DA (/F' . $this->mpdf->fonts['czapfdingbats']['i'] . ' 0 Tf ' . $radio_color . ' rg)');
1416
  } else {
1417
- $this->mpdf->_out('/DA (/F' . $this->mpdf->fonts[$this->mpdf->CurrentFont['fontkey']]['i'] . ' 0 Tf ' . $radio_color . ' rg)');
1418
  }
1419
- $this->mpdf->_out('/AP << /N << /' . $this->mpdf->_escape($form['V']) . ' ' . ($this->mpdf->n + 1) . ' 0 R /Off ' . ($this->mpdf->n + 2) . ' 0 R >> >>');
 
 
1420
  if ($form['activ']) {
1421
- $this->mpdf->_out('/V /' . $this->mpdf->_escape($form['V']) . ' ');
1422
- $this->mpdf->_out('/DV /' . $this->mpdf->_escape($form['V']) . ' ');
1423
- $this->mpdf->_out('/AS /' . $this->mpdf->_escape($form['V']) . ' ');
1424
  } else {
1425
- $this->mpdf->_out('/AS /Off ');
1426
  }
1427
- $this->mpdf->_out('/AP << /N << /' . $this->mpdf->_escape($form['V']) . ' ' . ($this->mpdf->n + 1) . ' 0 R /Off ' . ($this->mpdf->n + 2) . ' 0 R >> >>');
1428
- // $this->mpdf->_out('/Opt [ '.$this->mpdf->_textstring($form['OPT']).' '.$this->mpdf->_textstring($form['OPT']).' ]');
1429
  }
1430
 
1431
  if ($form['subtype'] === 'reset') {
1432
- $temp .= $form['CA'] ? '/CA ' . $this->mpdf->_textstring($form['CA']) . ' ' : '/CA ' . $this->mpdf->_textstring($form['T']) . ' ';
1433
- $temp .= $form['RC'] ? '/RC ' . $this->mpdf->_textstring($form['RC']) . ' ' : '/RC ' . $this->mpdf->_textstring($form['T']) . ' ';
1434
- $temp .= $form['AC'] ? '/AC ' . $this->mpdf->_textstring($form['AC']) . ' ' : '/AC ' . $this->mpdf->_textstring($form['T']) . ' ';
1435
- $this->mpdf->_out("/BS << $bstemp >>");
1436
- $this->mpdf->_out('/MK << ' . $temp . ' >>');
1437
- $this->mpdf->_out('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
1438
- $this->mpdf->_out('/AA << /D << /S /ResetForm /Flags 1 >> >>');
1439
  $form['FF'][] = 17;
1440
- $this->mpdf->_out('/Ff ' . $this->_setflag($form['FF']));
1441
  }
1442
 
1443
-
1444
  if ($form['subtype'] === 'submit') {
1445
- $temp .= $form['CA'] ? '/CA ' . $this->mpdf->_textstring($form['CA']) . ' ' : '/CA ' . $this->mpdf->_textstring($form['T']) . ' ';
1446
- $temp .= $form['RC'] ? '/RC ' . $this->mpdf->_textstring($form['RC']) . ' ' : '/RC ' . $this->mpdf->_textstring($form['T']) . ' ';
1447
- $temp .= $form['AC'] ? '/AC ' . $this->mpdf->_textstring($form['AC']) . ' ' : '/AC ' . $this->mpdf->_textstring($form['T']) . ' ';
1448
- $this->mpdf->_out("/BS << $bstemp >>");
1449
- $this->mpdf->_out("/MK << $temp >>");
1450
- $this->mpdf->_out('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
 
 
1451
  // Bit 4 (8) = useGETmethod else use POST
1452
  // Bit 3 (4) = HTML export format (charset chosen by Adobe)--- OR ---
1453
  // Bit 6 (32) = XFDF export format (form of XML in UTF-8)
1454
  if ($form['exporttype'] === 'xfdf') {
1455
  $flag = 32;
1456
- } // 'xfdf' or 'html'
1457
- else {
1458
- if ($form['method'] === 'GET') {
1459
- $flag = 12;
1460
- } else {
1461
- $flag = 4;
1462
- }
1463
  }
1464
  // Bit 2 (2) = IncludeNoValueFields
1465
  if ($this->formSubmitNoValueFields) {
@@ -1467,9 +1524,9 @@ class Form
1467
  }
1468
  // To submit a value, needs to be in /AP dictionary, AND this object must contain a /Fields entry
1469
  // listing all fields to output
1470
- $this->mpdf->_out('/AA << /D << /S /SubmitForm /F (' . $form['URL'] . ') /Flags ' . $flag . ' >> >>');
1471
  $form['FF'][] = 17;
1472
- $this->mpdf->_out('/Ff ' . $this->_setflag($form['FF']));
1473
  }
1474
 
1475
  if ($form['subtype'] === 'js_button') {
@@ -1486,33 +1543,33 @@ class Form
1486
  }
1487
  $put_icon = 1;
1488
  }
1489
- $temp .= $form['CA'] ? '/CA ' . $this->mpdf->_textstring($form['CA']) . ' ' : '/CA ' . $this->mpdf->_textstring($form['T']) . ' ';
1490
- $temp .= $form['RC'] ? '/RC ' . $this->mpdf->_textstring($form['RC']) . ' ' : '/RC ' . $this->mpdf->_textstring($form['T']) . ' ';
1491
- $temp .= $form['AC'] ? '/AC ' . $this->mpdf->_textstring($form['AC']) . ' ' : '/AC ' . $this->mpdf->_textstring($form['T']) . ' ';
1492
- $this->mpdf->_out("/BS << $bstemp >>");
1493
- $this->mpdf->_out("/MK << $temp >>");
1494
- $this->mpdf->_out('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
1495
  $form['FF'][] = 17;
1496
- $this->mpdf->_out('/Ff ' . $this->_setflag($form['FF']));
1497
  // Javascript
1498
  if (isset($this->array_form_button_js[$form['T']])) {
1499
  $cc++;
1500
- $this->mpdf->_out('/AA << /D ' . ($cc + $this->mpdf->n) . ' 0 R >>');
1501
  $put_js = 1;
1502
  }
1503
  }
1504
 
1505
- $this->mpdf->_out('>>');
1506
- $this->mpdf->_out('endobj');
1507
 
1508
  // additional objects
1509
  // obj icon
1510
- if ($put_icon == 1) {
1511
  $this->_put_button_icon($this->form_button_icon[$form['T']], $form['w'], $form['h']);
1512
  $put_icon = null;
1513
  }
1514
  // obj + 1
1515
- if ($put_js == 1) {
1516
  $this->mpdf->_set_object_javascript($this->array_form_button_js[$form['T']]['js']);
1517
  unset($this->array_form_button_js[$form['T']]);
1518
  $put_js = null;
@@ -1537,18 +1594,19 @@ f Q ';
1537
  $r_off = 'q ' . $matrix . ' cm ' . $fill . $radio_color . ' rg ' . $circle . ' Q ';
1538
  }
1539
 
1540
- $this->mpdf->_newobj();
1541
  $p = $this->mpdf->compress ? gzcompress($r_on) : $r_on;
1542
- $this->mpdf->_out('<<' . $filter . '/Length ' . strlen($p) . ' /Resources 2 0 R>>');
1543
- $this->mpdf->_putstream($p);
1544
- $this->mpdf->_out('endobj');
1545
 
1546
- $this->mpdf->_newobj();
1547
  $p = $this->mpdf->compress ? gzcompress($r_off) : $r_off;
1548
- $this->mpdf->_out('<<' . $filter . '/Length ' . strlen($p) . ' /Resources 2 0 R>>');
1549
- $this->mpdf->_putstream($p);
1550
- $this->mpdf->_out('endobj');
1551
  }
 
1552
  if ($form['subtype'] === 'checkbox') {
1553
  // First output appearance stream for check box on
1554
  if ($this->formUseZapD) {
@@ -1564,19 +1622,19 @@ f Q ';
1564
  6.321 -1.352 m 5.669 -2.075 5.070 -2.801 4.525 -3.532 c 3.979 -4.262 3.508 -4.967 3.112 -5.649 c 3.080 -5.706 3.039 -5.779 2.993 -5.868 c 2.858 -6.118 2.638 -6.243 2.334 -6.243 c 2.194 -6.243 2.100 -6.231 2.052 -6.205 c 2.003 -6.180 1.954 -6.118 1.904 -6.020 c 1.787 -5.788 1.688 -5.523 1.604 -5.226 c 1.521 -4.930 1.480 -4.721 1.480 -4.600 c 1.480 -4.535 1.491 -4.484 1.512 -4.447 c 1.535 -4.410 1.579 -4.367 1.647 -4.319 c 1.733 -4.259 1.828 -4.210 1.935 -4.172 c 2.040 -4.134 2.131 -4.115 2.205 -4.115 c 2.267 -4.115 2.341 -4.232 2.429 -4.469 c 2.437 -4.494 2.444 -4.511 2.448 -4.522 c 2.451 -4.531 2.456 -4.546 2.465 -4.568 c 2.546 -4.795 2.614 -4.910 2.668 -4.910 c 2.714 -4.910 2.898 -4.652 3.219 -4.136 c 3.539 -3.620 3.866 -3.136 4.197 -2.683 c 4.426 -2.367 4.633 -2.103 4.816 -1.889 c 4.998 -1.676 5.131 -1.544 5.211 -1.493 c 5.329 -1.426 5.483 -1.368 5.670 -1.319 c 5.856 -1.271 6.066 -1.238 6.296 -1.217 c 6.321 -1.352 l h f Q ';
1565
  $cb_off = 'q ' . $matrix . ' cm ' . $fill . $radio_color . ' rg ' . $square . ' f Q ';
1566
  }
1567
- $this->mpdf->_newobj();
1568
  $p = $this->mpdf->compress ? gzcompress($cb_on) : $cb_on;
1569
- $this->mpdf->_out('<<' . $filter . '/Length ' . strlen($p) . ' /Resources 2 0 R>>');
1570
- $this->mpdf->_putstream($p);
1571
- $this->mpdf->_out('endobj');
1572
 
1573
  // output appearance stream for check box off (only if not using ZapfDingbats)
1574
  if (!$this->formUseZapD) {
1575
- $this->mpdf->_newobj();
1576
  $p = $this->mpdf->compress ? gzcompress($cb_off) : $cb_off;
1577
- $this->mpdf->_out('<<' . $filter . '/Length ' . strlen($p) . ' /Resources 2 0 R>>');
1578
- $this->mpdf->_putstream($p);
1579
- $this->mpdf->_out('endobj');
1580
  }
1581
  }
1582
  return $n;
@@ -1585,74 +1643,77 @@ f Q ';
1585
  function _putform_ch($form, $hPt)
1586
  {
1587
  $put_js = 0;
1588
- $this->mpdf->_newobj();
1589
  $n = $this->mpdf->n;
1590
  $this->pdf_acro_array .= $n . ' 0 R ';
1591
  $this->forms[$form['n']]['obj'] = $n;
1592
 
1593
- $this->mpdf->_out('<<');
1594
- $this->mpdf->_out('/Type /Annot ');
1595
- $this->mpdf->_out('/Subtype /Widget');
1596
- $this->mpdf->_out('/Rect [ ' . $this->_form_rect($form['x'], $form['y'], $form['w'], $form['h'], $hPt) . ' ]');
1597
- $this->mpdf->_out('/F 4');
1598
- $this->mpdf->_out('/FT /Ch');
1599
  if ($form['Q']) {
1600
- $this->mpdf->_out('/Q ' . $form['Q'] . '');
1601
  }
1602
  $temp = '';
1603
  $temp .= '/W ' . $form['BS_W'] . ' ';
1604
  $temp .= '/S /' . $form['BS_S'] . ' ';
1605
- $this->mpdf->_out("/BS << $temp >>");
1606
 
1607
  $temp = '';
1608
  $temp .= '/BC [ ' . $form['BC_C'] . ' ] ';
1609
  $temp .= '/BG [ ' . $form['BG_C'] . ' ] ';
1610
- $this->mpdf->_out('/MK << ' . $temp . ' >>');
1611
 
1612
- $this->mpdf->_out('/NM ' . $this->mpdf->_textstring(sprintf('%04u-%04u', $n, 6000 + $form['n'])));
1613
- $this->mpdf->_out('/M ' . $this->mpdf->_textstring('D:' . date('YmdHis')));
1614
 
1615
- $this->mpdf->_out('/T ' . $this->mpdf->_textstring($form['T']));
1616
- $this->mpdf->_out('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
1617
 
1618
  $opt = '';
1619
- for ($i = 0; $i < count($form['OPT']['VAL']); $i++) {
1620
- $opt .= '[ ' . $this->mpdf->_textstring($form['OPT']['VAL'][$i]) . ' ' . $this->mpdf->_textstring($form['OPT']['OPT'][$i]) . ' ] ';
 
1621
  }
1622
- $this->mpdf->_out('/Opt [ ' . $opt . ']');
1623
 
1624
  // selected
1625
  $selectItem = false;
1626
  $selectIndex = false;
1627
  foreach ($form['OPT']['SEL'] as $selectKey => $selectVal) {
1628
- $selectName = $this->mpdf->_textstring($form['OPT']['VAL'][$selectVal]);
1629
  $selectItem .= ' ' . $selectName . ' ';
1630
  $selectIndex .= ' ' . $selectVal . ' ';
1631
  }
1632
  if ($selectItem) {
1633
  if (count($form['OPT']['SEL']) < 2) {
1634
- $this->mpdf->_out('/V ' . $selectItem . ' ');
1635
- $this->mpdf->_out('/DV ' . $selectItem . ' ');
1636
  } else {
1637
- $this->mpdf->_out('/V [' . $selectItem . '] ');
1638
- $this->mpdf->_out('/DV [' . $selectItem . '] ');
1639
  }
1640
- $this->mpdf->_out('/I [' . $selectIndex . '] ');
1641
  }
1642
 
1643
  if (is_array($form['FF']) && count($form['FF']) > 0) {
1644
- $this->mpdf->_out('/Ff ' . $this->_setflag($form['FF']) . ' ');
1645
  }
 
1646
  // Javascript
1647
  if (isset($this->array_form_choice_js[$form['T']])) {
1648
- $this->mpdf->_out('/AA << /V ' . ($this->mpdf->n + 1) . ' 0 R >>');
1649
  $put_js = 1;
1650
  }
1651
 
1652
- $this->mpdf->_out('>>');
1653
- $this->mpdf->_out('endobj');
 
1654
  // obj + 1
1655
- if ($put_js == 1) {
1656
  $this->mpdf->_set_object_javascript($this->array_form_choice_js[$form['T']]['js']);
1657
  unset($this->array_form_choice_js[$form['T']]);
1658
  $put_js = null;
@@ -1664,52 +1725,52 @@ f Q ';
1664
  function _putform_tx($form, $hPt)
1665
  {
1666
  $put_js = 0;
1667
- $this->mpdf->_newobj();
1668
  $n = $this->mpdf->n;
1669
  $this->pdf_acro_array .= $n . ' 0 R ';
1670
  $this->forms[$form['n']]['obj'] = $n;
1671
 
1672
- $this->mpdf->_out('<<');
1673
- $this->mpdf->_out('/Type /Annot ');
1674
- $this->mpdf->_out('/Subtype /Widget ');
1675
 
1676
- $this->mpdf->_out('/Rect [ ' . $this->_form_rect($form['x'], $form['y'], $form['w'], $form['h'], $hPt) . ' ] ');
1677
- $form['hidden'] ? $this->mpdf->_out('/F 2 ') : $this->mpdf->_out('/F 4 ');
1678
- $this->mpdf->_out('/FT /Tx ');
1679
 
1680
- $this->mpdf->_out('/H /N ');
1681
- $this->mpdf->_out('/R 0 ');
1682
 
1683
  if (is_array($form['FF']) && count($form['FF']) > 0) {
1684
- $this->mpdf->_out('/Ff ' . $this->_setflag($form['FF']) . ' ');
1685
  }
1686
  if (isset($form['maxlen']) && $form['maxlen'] > 0) {
1687
- $this->mpdf->_out('/MaxLen ' . $form['maxlen']);
1688
  }
1689
 
1690
  $temp = '';
1691
  $temp .= '/W ' . $form['BS_W'] . ' ';
1692
  $temp .= '/S /' . $form['BS_S'] . ' ';
1693
- $this->mpdf->_out("/BS << $temp >>");
1694
 
1695
  $temp = '';
1696
  $temp .= '/BC [ ' . $form['BC_C'] . ' ] ';
1697
  $temp .= '/BG [ ' . $form['BG_C'] . ' ] ';
1698
- $this->mpdf->_out('/MK <<' . $temp . ' >>');
1699
 
1700
- $this->mpdf->_out('/T ' . $this->mpdf->_textstring($form['T']));
1701
- $this->mpdf->_out('/TU ' . $this->mpdf->_textstring($form['TU']));
1702
  if ($form['V'] || $form['V'] === '0') {
1703
- $this->mpdf->_out('/V ' . $this->mpdf->_textstring($form['V']));
1704
  }
1705
- $this->mpdf->_out('/DV ' . $this->mpdf->_textstring($form['DV']));
1706
- $this->mpdf->_out('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
1707
  if ($form['Q']) {
1708
- $this->mpdf->_out('/Q ' . $form['Q'] . '');
1709
  }
1710
 
1711
- $this->mpdf->_out('/NM ' . $this->mpdf->_textstring(sprintf('%04u-%04u', $n, 5000 + $form['n'])));
1712
- $this->mpdf->_out('/M ' . $this->mpdf->_textstring('D:' . date('YmdHis')));
1713
 
1714
 
1715
  if (isset($this->array_form_text_js[$form['T']])) {
@@ -1734,11 +1795,11 @@ f Q ';
1734
  $js_str .= '/C ' . ($cc + $this->mpdf->n) . ' 0 R ';
1735
  $this->pdf_array_co .= $this->mpdf->n . ' 0 R ';
1736
  }
1737
- $this->mpdf->_out('/AA << ' . $js_str . ' >>');
1738
  }
1739
 
1740
- $this->mpdf->_out('>>');
1741
- $this->mpdf->_out('endobj');
1742
 
1743
  if ($put_js == 1) {
1744
  if (isset($this->array_form_text_js[$form['T']]['F'])) {
2
 
3
  namespace Mpdf;
4
 
5
+ use Mpdf\Strict;
6
+
7
  use Mpdf\Color\ColorConverter;
8
 
9
+ use Mpdf\Writer\BaseWriter;
10
+ use Mpdf\Writer\FormWriter;
11
+
12
  class Form
13
  {
14
 
15
+ use Strict;
16
+
17
+ // Input flags
18
+ const FLAG_READONLY = 1;
19
+ const FLAG_REQUIRED = 2;
20
+ const FLAG_NO_EXPORT = 3;
21
+ const FLAG_TEXTAREA = 13;
22
+ const FLAG_PASSWORD = 14;
23
+ const FLAG_RADIO = 15;
24
+ const FLAG_NOTOGGLEOFF = 16;
25
+ const FLAG_COMBOBOX = 18;
26
+ const FLAG_EDITABLE = 19;
27
+ const FLAG_MULTISELECT = 22;
28
+ const FLAG_NO_SPELLCHECK = 23;
29
+ const FLAG_NO_SCROLL = 24;
30
+
31
  /**
32
  * @var \Mpdf\Mpdf
33
  */
43
  */
44
  private $colorConverter;
45
 
46
+ /**
47
+ * @var \Mpdf\Writer\BaseWriter
48
+ */
49
+ private $writer;
50
+
51
+ /**
52
+ * @var \Mpdf\Writer\FormWriter
53
+ */
54
+ private $formWriter;
55
+
56
  /**
57
  * @var array
58
  */
63
  */
64
  private $formCount;
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  // Active Forms
67
  var $formSubmitNoValueFields;
68
  var $formExportType;
103
  // FORMS
104
  var $textarea_lineheight;
105
 
106
+ public function __construct(Mpdf $mpdf, Otl $otl, ColorConverter $colorConverter, BaseWriter $writer, FormWriter $formWriter)
107
  {
108
  $this->mpdf = $mpdf;
109
  $this->otl = $otl;
110
  $this->colorConverter = $colorConverter;
111
+ $this->writer = $writer;
112
+ $this->formWriter = $formWriter;
113
 
114
  // ACTIVE FORMS
115
  $this->formExportType = 'xfdf'; // 'xfdf' or 'html'
331
  }
332
  $this->mpdf->Rect($this->mpdf->x, $this->mpdf->y, $w, $h, 'DF');
333
  $ClipPath = sprintf('q %.3F %.3F %.3F %.3F re W n ', $this->mpdf->x * Mpdf::SCALE, ($this->mpdf->h - $this->mpdf->y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$h * Mpdf::SCALE);
334
+ $this->writer->write($ClipPath);
335
 
336
  $w -= $this->form_element_spacing['textarea']['inner']['h'] * 2 / $k;
337
  $this->mpdf->x += $this->form_element_spacing['textarea']['inner']['h'] / $k;
340
  if ($texto != '') {
341
  $this->mpdf->MultiCell($w, $this->mpdf->FontSize * $this->textarea_lineheight, $texto, 0, '', 0, '', $blockdir, true, $objattr['OTLdata'], $objattr['rows']);
342
  }
343
+ $this->writer->write('Q');
344
  $this->mpdf->SetFColor($this->colorConverter->convert(255, $this->mpdf->PDFAXwarnings));
345
  $this->mpdf->SetTColor($this->colorConverter->convert(0, $this->mpdf->PDFAXwarnings));
346
  }
465
  $this->SetJSButton($w, $h, $objattr['fieldname'], (isset($objattr['value']) ? $objattr['value'] : ''), $js, $objattr['ID'], $objattr['title'], $flags, (isset($objattr['Indexed']) ? $objattr['Indexed'] : false));
466
  } else {
467
  $this->mpdf->y = $objattr['INNER-Y'];
468
+ $this->writer->write(sprintf('q %.3F 0 0 %.3F %.3F %.3F cm /I%d Do Q', $objattr['INNER-WIDTH'] * Mpdf::SCALE, $objattr['INNER-HEIGHT'] * Mpdf::SCALE, $objattr['INNER-X'] * Mpdf::SCALE, ($this->mpdf->h - ($objattr['INNER-Y'] + $objattr['INNER-HEIGHT'] )) * Mpdf::SCALE, $objattr['ID']));
469
  if (!empty($objattr['BORDER-WIDTH'])) {
470
  $this->mpdf->PaintImgBorder($objattr, $is_table);
471
  }
653
  }
654
  }
655
  }
656
+
657
  if ($form['typ'] === 'Bt') {
658
  if (isset($this->array_form_button_js[$form['T']])) {
659
  $total++;
726
  // Output Radio Groups
727
  $key = 1;
728
  foreach ($this->form_radio_groups as $name => $frg) {
729
+ $this->writer->object();
730
  $this->pdf_acro_array .= $this->mpdf->n . ' 0 R ';
731
+ $this->writer->write('<<');
732
+ $this->writer->write('/Type /Annot ');
733
+ $this->writer->write('/Subtype /Widget');
734
+ $this->writer->write('/NM ' . $this->writer->string(sprintf('%04u-%04u', $n, 3000 + $key++)));
735
+ $this->writer->write('/M ' . $this->writer->string('D:' . date('YmdHis')));
736
+ $this->writer->write('/Rect [0 0 0 0] ');
737
+ $this->writer->write('/FT /Btn ');
738
  if (!empty($frg['disabled'])) {
739
  $flags = [self::FLAG_READONLY, self::FLAG_NO_EXPORT, self::FLAG_RADIO, self::FLAG_NOTOGGLEOFF];
740
  } else {
741
  $flags = [self::FLAG_RADIO, self::FLAG_NOTOGGLEOFF];
742
  }
743
+ $this->writer->write('/Ff ' . $this->_setflag($flags));
744
  $kstr = '';
745
  // $optstr = '';
746
  foreach ($frg['kids'] as $kid) {
747
  $kstr .= $this->forms[$kid['n']]['obj'] . ' 0 R ';
748
+ // $optstr .= ' '.$this->writer->string($kid['OPT']).' ';
749
  }
750
+ $this->writer->write('/Kids [ ' . $kstr . ' ] '); // 11 0 R 12 0 R etc.
751
+ // $this->writer->write('/Opt [ '.$optstr.' ] ');
752
  //V entry holds index corresponding to the appearance state of
753
  //whichever child field is currently in the on state = or Off
754
  if (isset($frg['on'])) {
756
  } else {
757
  $state = 'Off';
758
  }
759
+ $this->writer->write('/V /' . $state . ' ');
760
+ $this->writer->write('/DV /' . $state . ' ');
761
+ $this->writer->write('/T ' . $this->writer->string($name) . ' ');
762
+ $this->writer->write('>>');
763
+ $this->writer->write('endobj');
764
  }
765
  }
766
 
767
  function _putFormsCatalog()
768
  {
769
  if (isset($this->pdf_acro_array)) {
770
+ $this->writer->write('/AcroForm << /DA (/F1 0 Tf 0 g )');
771
+ $this->writer->write('/Q 0');
772
+ $this->writer->write('/Fields [' . $this->pdf_acro_array . ']');
773
  $f = '';
774
  foreach ($this->form_fonts as $fn) {
775
  if (is_array($this->mpdf->fonts[$fn]['n'])) {
776
+ throw new \Mpdf\MpdfException('Cannot use fonts with SMP or SIP characters for interactive Form elements');
777
  }
778
  $f .= '/F' . $this->mpdf->fonts[$fn]['i'] . ' ' . $this->mpdf->fonts[$fn]['n'] . ' 0 R ';
779
  }
780
+ $this->writer->write('/DR << /Font << ' . $f . ' >> >>');
781
  // CO Calculation Order
782
  if ($this->pdf_array_co) {
783
+ $this->writer->write('/CO [' . $this->pdf_array_co . ']');
784
  }
785
+ $this->writer->write('/NeedAppearances true');
786
+ $this->writer->write('>>');
787
  }
788
  }
789
 
791
  {
792
  $js = str_replace("\t", ' ', trim($js));
793
  if (isset($name) && isset($js)) {
794
+ $this->array_form_button_js[$this->writer->escape($name)] = [
795
  'js' => $js
796
  ];
797
  }
801
  {
802
  $js = str_replace("\t", ' ', trim($js));
803
  if (isset($name) && isset($js)) {
804
+ $this->array_form_choice_js[$this->writer->escape($name)] = [
805
  'js' => $js
806
  ];
807
  }
813
  $j = str_replace("\t", ' ', trim($js[$i][1]));
814
  $format = $js[$i][0];
815
  if ($name) {
816
+ $this->array_form_text_js[$this->writer->escape($name)][$format] = ['js' => $j];
817
  }
818
  }
819
  }
846
  $maxlen = false;
847
  }
848
  if (!preg_match('/^[a-zA-Z0-9_:\-]+$/', $name)) {
849
+ throw new \Mpdf\MpdfException('Field [' . $name . '] must have a name attribute, which can only contain letters, numbers, colon(:), undersore(_) or hyphen(-)');
850
  }
851
  if ($this->mpdf->onlyCoreFonts) {
852
  $value = $this->Win1252ToPDFDocEncoding($value);
859
  $this->mpdf->UTF8StringToArray($title); // Add characters to font subset
860
  }
861
  if ($value) {
862
+ $value = $this->writer->utf8ToUtf16BigEndian($value);
863
  }
864
  if ($default) {
865
+ $default = $this->writer->utf8ToUtf16BigEndian($default);
866
  }
867
+ $title = $this->writer->utf8ToUtf16BigEndian($title);
868
  }
869
  if ($background_col) {
870
  $bg_c = $this->mpdf->SetColor($background_col, 'CodeOnly');
876
  } else {
877
  $bc_c = $this->form_border_color;
878
  }
879
+
880
+ $f = [
881
+ 'n' => $this->formCount,
882
  'typ' => 'Tx',
883
  'page' => $this->mpdf->page,
884
  'x' => $this->mpdf->x,
903
  'fontcolor' => $this->mpdf->TextColor,
904
  ]
905
  ];
906
+
907
  if (is_array($js) && count($js) > 0) {
908
  $this->SetFormTextJS($name, $js);
909
  } // mPDF 5.3.25
913
  $this->mpdf->HTMLheaderPageForms[] = $f;
914
  } else {
915
  if ($this->mpdf->ColActive) {
916
+ $this->mpdf->columnbuffer[] = [
917
+ 's' => 'ACROFORM',
918
+ 'col' => $this->mpdf->CurrCol,
919
+ 'x' => $this->mpdf->x,
920
+ 'y' => $this->mpdf->y,
921
+ 'h' => $h
922
+ ];
923
  $this->mpdf->columnForms[$this->mpdf->CurrCol][(int)$this->mpdf->x][(int)$this->mpdf->y] = $this->formCount;
924
  }
925
  $this->forms[$this->formCount] = $f;
956
  $this->mpdf->UTF8StringToArray($array['OPT'][$i]); // Add characters to font subset
957
  }
958
  if ($array['VAL'][$i]) {
959
+ $array['VAL'][$i] = $this->writer->utf8ToUtf16BigEndian($array['VAL'][$i]);
960
  }
961
  if ($array['OPT'][$i]) {
962
+ $array['OPT'][$i] = $this->writer->utf8ToUtf16BigEndian($array['OPT'][$i]);
963
  }
964
  }
965
  }
1034
  $this->SetFormButton($w, $h, $name, $value, 'js_button', $title, $flags, false, false, $background_col, $border_col, $noprint);
1035
  // pos => 1 = no caption, icon only; 0 = caption only
1036
  if ($image_id) {
1037
+ $this->form_button_icon[$this->writer->escape($name)] = [
1038
  'pos' => 1,
1039
  'image_id' => $image_id,
1040
  'Indexed' => $indexed,
1073
  if (isset($this->mpdf->CurrentFont['subset'])) {
1074
  $this->mpdf->UTF8StringToArray($ca); // Add characters to font subset
1075
  }
1076
+ $ca = $this->writer->utf8ToUtf16BigEndian($ca);
1077
  if ($rc) {
1078
  if (isset($this->mpdf->CurrentFont['subset'])) {
1079
  $this->mpdf->UTF8StringToArray($rc);
1080
  }
1081
+ $rc = $this->writer->utf8ToUtf16BigEndian($rc);
1082
  }
1083
  if ($ac) {
1084
  if (isset($this->mpdf->CurrentFont['subset'])) {
1085
  $this->mpdf->UTF8StringToArray($ac);
1086
  }
1087
+ $ac = $this->writer->utf8ToUtf16BigEndian($ac);
1088
  }
1089
  }
1090
  $this->form_button_text = $ca;
1096
  {
1097
  $this->formCount++;
1098
  if (!preg_match('/^[a-zA-Z0-9_:\-]+$/', $name)) {
1099
+ throw new \Mpdf\MpdfException('Field [' . $name . '] must have a name attribute, which can only contain letters, numbers, colon(:), undersore(_) or hyphen(-)');
1100
  }
1101
  if (!$this->mpdf->onlyCoreFonts) {
1102
  if (isset($this->mpdf->CurrentFont['subset'])) {
1103
  $this->mpdf->UTF8StringToArray($title); // Add characters to font subset
1104
  $this->mpdf->UTF8StringToArray($value); // Add characters to font subset
1105
  }
1106
+ $title = $this->writer->utf8ToUtf16BigEndian($title);
1107
  if ($type === 'checkbox') {
1108
+ $uvalue = $this->writer->utf8ToUtf16BigEndian($value);
1109
  } else if ($type === 'radio') {
1110
+ $uvalue = $this->writer->utf8ToUtf16BigEndian($value);
1111
  $value = mb_convert_encoding($value, 'Windows-1252', 'UTF-8');
1112
  } else {
1113
+ $value = $this->writer->utf8ToUtf16BigEndian($value);
1114
  $uvalue = $value;
1115
  }
1116
  } else {
1117
  $title = $this->Win1252ToPDFDocEncoding($title);
1118
  $value = $this->Win1252ToPDFDocEncoding($value); //// ??? not needed
1119
  $uvalue = mb_convert_encoding($value, 'UTF-8', 'Windows-1252');
1120
+ $uvalue = $this->writer->utf8ToUtf16BigEndian($uvalue);
1121
  }
1122
  if ($type === 'radio' || $type === 'checkbox') {
1123
  if (!preg_match('/^[a-zA-Z0-9_:\-\.]+$/', $value)) {
1124
+ throw new \Mpdf\MpdfException("Field '" . $name . "' must have a value, which can only contain letters, numbers, colon(:), underscore(_), hyphen(-) or period(.)");
1125
  }
1126
  }
1127
  if ($type === 'radio') {
1297
  $y = $hPt - ($y * Mpdf::SCALE);
1298
  $x2 = $x + ($w * Mpdf::SCALE);
1299
  $y2 = $y - ($h * Mpdf::SCALE);
1300
+
1301
  return sprintf('%.3F %.3F %.3F %.3F', $x, $y2, $x2, $y);
1302
  }
1303
 
1304
  function _put_button_icon($array, $w, $h)
1305
  {
1306
+ $info = true;
1307
+
1308
  if (isset($array['image_id'])) {
1309
  $info = false;
1310
  foreach ($this->mpdf->images as $iid => $img) {
1314
  }
1315
  }
1316
  }
1317
+
1318
  if (!$info) {
1319
  throw new \Mpdf\MpdfException('Cannot find Button image');
1320
  }
1321
+
1322
+ $this->writer->object();
1323
+ $this->writer->write('<<');
1324
+ $this->writer->write('/Type /XObject');
1325
+ $this->writer->write('/Subtype /Image');
1326
+ $this->writer->write('/BBox [0 0 1 1]');
1327
+ $this->writer->write('/Length ' . strlen($info['data']));
1328
+ $this->writer->write('/BitsPerComponent ' . $info['bpc']);
1329
+
1330
  if ($info['cs'] === 'Indexed') {
1331
+ $this->writer->write('/ColorSpace [/Indexed /DeviceRGB ' . (strlen($info['pal']) / 3 - 1) . ' ' . ($this->mpdf->n + 1) . ' 0 R]');
1332
  } else {
1333
+ $this->writer->write('/ColorSpace /' . $info['cs']);
1334
  if ($info['cs'] === 'DeviceCMYK') {
1335
  if ($info['type'] === 'jpg') {
1336
+ $this->writer->write('/Decode [1 0 1 0 1 0 1 0]');
1337
  }
1338
  }
1339
  }
1340
+
1341
  if (isset($info['f'])) {
1342
+ $this->writer->write('/Filter /' . $info['f']);
1343
  }
1344
+
1345
  if (isset($info['parms'])) {
1346
+ $this->writer->write($info['parms']);
1347
+ }
1348
+
1349
+ $this->writer->write('/Width ' . $info['w']);
1350
+ $this->writer->write('/Height ' . $info['h']);
1351
+ $this->writer->write('>>');
1352
+ $this->writer->stream($info['data']);
1353
+ $this->writer->write('endobj');
1354
+
1355
  //Palette
1356
  if ($info['cs'] === 'Indexed') {
1357
  $filter = $this->mpdf->compress ? '/Filter /FlateDecode ' : '';
1358
+ $this->writer->object();
1359
  $pal = $this->mpdf->compress ? gzcompress($info['pal']) : $info['pal'];
1360
+ $this->writer->write('<<' . $filter . '/Length ' . strlen($pal) . '>>');
1361
+ $this->writer->stream($pal);
1362
+ $this->writer->write('endobj');
1363
  }
1364
  }
1365
 
1368
  $cc = 0;
1369
  $put_js = 0;
1370
  $put_icon = 0;
1371
+ $this->writer->object();
1372
  $n = $this->mpdf->n;
1373
+
1374
  if ($form['subtype'] !== 'radio') {
1375
  $this->pdf_acro_array .= $n . ' 0 R '; // Add to /Field element
1376
  }
1377
+
1378
  $this->forms[$form['n']]['obj'] = $n;
1379
+ $this->writer->write('<<');
1380
+ $this->writer->write('/Type /Annot ');
1381
+ $this->writer->write('/Subtype /Widget');
1382
+ $this->writer->write('/NM ' . $this->writer->string(sprintf('%04u-%04u', $n, 7000 + $form['n'])));
1383
+ $this->writer->write('/M ' . $this->writer->string('D:' . date('YmdHis')));
1384
+ $this->writer->write('/Rect [ ' . $this->_form_rect($form['x'], $form['y'], $form['w'], $form['h'], $hPt) . ' ]');
1385
+
1386
+ $form['noprint'] ? $this->writer->write('/F 0 ') : $this->writer->write('/F 4 ');
1387
+
1388
+ $this->writer->write('/FT /Btn ');
1389
+ $this->writer->write('/H /P ');
1390
+
1391
  if ($form['subtype'] !== 'radio') { // mPDF 5.3.23
1392
+ $this->writer->write('/T ' . $this->writer->string($form['T']));
1393
  }
1394
+
1395
+ $this->writer->write('/TU ' . $this->writer->string($form['TU']));
1396
+
1397
  if (isset($this->form_button_icon[$form['T']])) {
1398
  $form['BS_W'] = 0;
1399
  }
1400
+
1401
  if ($form['BS_W'] == 0) {
1402
  $form['BC_C'] = $form['BG_C'];
1403
  }
1404
+
1405
  $bstemp = '';
1406
  $bstemp .= '/W ' . $form['BS_W'] . ' ';
1407
  $bstemp .= '/S /' . $form['BS_S'] . ' ';
1408
  $temp = '';
1409
  $temp .= '/BC [ ' . $form['BC_C'] . ' ] ';
1410
  $temp .= '/BG [ ' . $form['BG_C'] . ' ] ';
1411
+
1412
  if ($form['subtype'] === 'checkbox') {
1413
+
1414
  if ($form['disabled']) {
1415
  $radio_color = '0.5 0.5 0.5';
1416
  $radio_background_color = '0.9 0.9 0.9';
1418
  $radio_color = $this->form_radio_color;
1419
  $radio_background_color = $this->form_radio_background_color;
1420
  }
1421
+
1422
  $temp = '';
1423
  $temp .= '/BC [ ' . $radio_color . ' ] ';
1424
  $temp .= '/BG [ ' . $radio_background_color . ' ] ';
1425
+ $this->writer->write('/BS << /W 1 /S /S >>');
1426
+ $this->writer->write("/MK << $temp >>");
1427
+ $this->writer->write('/Ff ' . $this->_setflag($form['FF']));
1428
+
1429
  if ($form['activ']) {
1430
+ $this->writer->write('/V /' . $this->writer->escape($form['V']) . ' ');
1431
+ $this->writer->write('/DV /' . $this->writer->escape($form['V']) . ' ');
1432
+ $this->writer->write('/AS /' . $this->writer->escape($form['V']) . ' ');
1433
  } else {
1434
+ $this->writer->write('/AS /Off ');
1435
  }
1436
+
1437
  if ($this->formUseZapD) {
1438
+ $this->writer->write('/DA (/F' . $this->mpdf->fonts['czapfdingbats']['i'] . ' 0 Tf ' . $radio_color . ' rg)');
1439
+ $this->writer->write('/AP << /N << /' . $this->writer->escape($form['V']) . ' ' . ($this->mpdf->n + 1) . ' 0 R /Off /Off >> >>');
1440
  } else {
1441
+ $this->writer->write('/DA (/F' . $this->mpdf->fonts[$this->mpdf->CurrentFont['fontkey']]['i'] . ' 0 Tf ' . $radio_color . ' rg)');
1442
+ $this->writer->write('/AP << /N << /' . $this->writer->escape($form['V']) . ' ' . ($this->mpdf->n + 1) . ' 0 R /Off ' . ($this->mpdf->n + 2) . ' 0 R >> >>');
1443
  }
 
 
1444
 
1445
+ $this->writer->write('/Opt [ ' . $this->writer->string($form['OPT']) . ' ' . $this->writer->string($form['OPT']) . ' ]');
1446
+ }
1447
 
1448
  if ($form['subtype'] === 'radio') {
1449
+
1450
  if ((isset($form['disabled']) && $form['disabled']) || (isset($this->form_radio_groups[$form['T']]['disabled']) && $this->form_radio_groups[$form['T']]['disabled'])) {
1451
  $radio_color = '0.5 0.5 0.5';
1452
  $radio_background_color = '0.9 0.9 0.9';
1454
  $radio_color = $this->form_radio_color;
1455
  $radio_background_color = $this->form_radio_background_color;
1456
  }
1457
+
1458
+ $this->writer->write('/Parent ' . $this->form_radio_groups[$form['T']]['obj_id'] . ' 0 R ');
1459
+
1460
  $temp = '';
1461
  $temp .= '/BC [ ' . $radio_color . ' ] ';
1462
  $temp .= '/BG [ ' . $radio_background_color . ' ] ';
1463
+
1464
+ $this->writer->write('/BS << /W 1 /S /S >>');
1465
+ $this->writer->write('/MK << ' . $temp . ' >> ');
1466
+
1467
  $form['FF'][] = self::FLAG_NOTOGGLEOFF;
1468
  $form['FF'][] = self::FLAG_RADIO; // must be same as radio button group setting?
1469
+ $this->writer->write('/Ff ' . $this->_setflag($form['FF']));
1470
+
1471
  if ($this->formUseZapD) {
1472
+ $this->writer->write('/DA (/F' . $this->mpdf->fonts['czapfdingbats']['i'] . ' 0 Tf ' . $radio_color . ' rg)');
1473
  } else {
1474
+ $this->writer->write('/DA (/F' . $this->mpdf->fonts[$this->mpdf->CurrentFont['fontkey']]['i'] . ' 0 Tf ' . $radio_color . ' rg)');
1475
  }
1476
+
1477
+ $this->writer->write('/AP << /N << /' . $this->writer->escape($form['V']) . ' ' . ($this->mpdf->n + 1) . ' 0 R /Off ' . ($this->mpdf->n + 2) . ' 0 R >> >>');
1478
+
1479
  if ($form['activ']) {
1480
+ $this->writer->write('/V /' . $this->writer->escape($form['V']) . ' ');
1481
+ $this->writer->write('/DV /' . $this->writer->escape($form['V']) . ' ');
1482
+ $this->writer->write('/AS /' . $this->writer->escape($form['V']) . ' ');
1483
  } else {
1484
+ $this->writer->write('/AS /Off ');
1485
  }
1486
+ $this->writer->write('/AP << /N << /' . $this->writer->escape($form['V']) . ' ' . ($this->mpdf->n + 1) . ' 0 R /Off ' . ($this->mpdf->n + 2) . ' 0 R >> >>');
1487
+ // $this->writer->write('/Opt [ '.$this->writer->string($form['OPT']).' '.$this->writer->string($form['OPT']).' ]');
1488
  }
1489
 
1490
  if ($form['subtype'] === 'reset') {
1491
+ $temp .= $form['CA'] ? '/CA ' . $this->writer->string($form['CA']) . ' ' : '/CA ' . $this->writer->string($form['T']) . ' ';
1492
+ $temp .= $form['RC'] ? '/RC ' . $this->writer->string($form['RC']) . ' ' : '/RC ' . $this->writer->string($form['T']) . ' ';
1493
+ $temp .= $form['AC'] ? '/AC ' . $this->writer->string($form['AC']) . ' ' : '/AC ' . $this->writer->string($form['T']) . ' ';
1494
+ $this->writer->write("/BS << $bstemp >>");
1495
+ $this->writer->write('/MK << ' . $temp . ' >>');
1496
+ $this->writer->write('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
1497
+ $this->writer->write('/AA << /D << /S /ResetForm /Flags 1 >> >>');
1498
  $form['FF'][] = 17;
1499
+ $this->writer->write('/Ff ' . $this->_setflag($form['FF']));
1500
  }
1501
 
 
1502
  if ($form['subtype'] === 'submit') {
1503
+
1504
+ $temp .= $form['CA'] ? '/CA ' . $this->writer->string($form['CA']) . ' ' : '/CA ' . $this->writer->string($form['T']) . ' ';
1505
+ $temp .= $form['RC'] ? '/RC ' . $this->writer->string($form['RC']) . ' ' : '/RC ' . $this->writer->string($form['T']) . ' ';
1506
+ $temp .= $form['AC'] ? '/AC ' . $this->writer->string($form['AC']) . ' ' : '/AC ' . $this->writer->string($form['T']) . ' ';
1507
+ $this->writer->write("/BS << $bstemp >>");
1508
+ $this->writer->write("/MK << $temp >>");
1509
+ $this->writer->write('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
1510
+
1511
  // Bit 4 (8) = useGETmethod else use POST
1512
  // Bit 3 (4) = HTML export format (charset chosen by Adobe)--- OR ---
1513
  // Bit 6 (32) = XFDF export format (form of XML in UTF-8)
1514
  if ($form['exporttype'] === 'xfdf') {
1515
  $flag = 32;
1516
+ } elseif ($form['method'] === 'GET') { // 'xfdf' or 'html'
1517
+ $flag = 12;
1518
+ } else {
1519
+ $flag = 4;
 
 
 
1520
  }
1521
  // Bit 2 (2) = IncludeNoValueFields
1522
  if ($this->formSubmitNoValueFields) {
1524
  }
1525
  // To submit a value, needs to be in /AP dictionary, AND this object must contain a /Fields entry
1526
  // listing all fields to output
1527
+ $this->writer->write('/AA << /D << /S /SubmitForm /F (' . $form['URL'] . ') /Flags ' . $flag . ' >> >>');
1528
  $form['FF'][] = 17;
1529
+ $this->writer->write('/Ff ' . $this->_setflag($form['FF']));
1530
  }
1531
 
1532
  if ($form['subtype'] === 'js_button') {
1543
  }
1544
  $put_icon = 1;
1545
  }
1546
+ $temp .= $form['CA'] ? '/CA ' . $this->writer->string($form['CA']) . ' ' : '/CA ' . $this->writer->string($form['T']) . ' ';
1547
+ $temp .= $form['RC'] ? '/RC ' . $this->writer->string($form['RC']) . ' ' : '/RC ' . $this->writer->string($form['T']) . ' ';
1548
+ $temp .= $form['AC'] ? '/AC ' . $this->writer->string($form['AC']) . ' ' : '/AC ' . $this->writer->string($form['T']) . ' ';
1549
+ $this->writer->write("/BS << $bstemp >>");
1550
+ $this->writer->write("/MK << $temp >>");
1551
+ $this->writer->write('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
1552
  $form['FF'][] = 17;
1553
+ $this->writer->write('/Ff ' . $this->_setflag($form['FF']));
1554
  // Javascript
1555
  if (isset($this->array_form_button_js[$form['T']])) {
1556
  $cc++;
1557
+ $this->writer->write('/AA << /D ' . ($cc + $this->mpdf->n) . ' 0 R >>');
1558
  $put_js = 1;
1559
  }
1560
  }
1561
 
1562
+ $this->writer->write('>>');
1563
+ $this->writer->write('endobj');
1564
 
1565
  // additional objects
1566
  // obj icon
1567
+ if ($put_icon === 1) {
1568
  $this->_put_button_icon($this->form_button_icon[$form['T']], $form['w'], $form['h']);
1569
  $put_icon = null;
1570
  }
1571
  // obj + 1
1572
+ if ($put_js === 1) {
1573
  $this->mpdf->_set_object_javascript($this->array_form_button_js[$form['T']]['js']);
1574
  unset($this->array_form_button_js[$form['T']]);
1575
  $put_js = null;
1594
  $r_off = 'q ' . $matrix . ' cm ' . $fill . $radio_color . ' rg ' . $circle . ' Q ';
1595
  }
1596
 
1597
+ $this->writer->object();
1598
  $p = $this->mpdf->compress ? gzcompress($r_on) : $r_on;
1599
+ $this->writer->write('<<' . $filter . '/Length ' . strlen($p) . ' /Resources 2 0 R>>');
1600
+ $this->writer->stream($p);
1601
+ $this->writer->write('endobj');
1602
 
1603
+ $this->writer->object();
1604
  $p = $this->mpdf->compress ? gzcompress($r_off) : $r_off;
1605
+ $this->writer->write('<<' . $filter . '/Length ' . strlen($p) . ' /Resources 2 0 R>>');
1606
+ $this->writer->stream($p);
1607
+ $this->writer->write('endobj');
1608
  }
1609
+
1610
  if ($form['subtype'] === 'checkbox') {
1611
  // First output appearance stream for check box on
1612
  if ($this->formUseZapD) {
1622
  6.321 -1.352 m 5.669 -2.075 5.070 -2.801 4.525 -3.532 c 3.979 -4.262 3.508 -4.967 3.112 -5.649 c 3.080 -5.706 3.039 -5.779 2.993 -5.868 c 2.858 -6.118 2.638 -6.243 2.334 -6.243 c 2.194 -6.243 2.100 -6.231 2.052 -6.205 c 2.003 -6.180 1.954 -6.118 1.904 -6.020 c 1.787 -5.788 1.688 -5.523 1.604 -5.226 c 1.521 -4.930 1.480 -4.721 1.480 -4.600 c 1.480 -4.535 1.491 -4.484 1.512 -4.447 c 1.535 -4.410 1.579 -4.367 1.647 -4.319 c 1.733 -4.259 1.828 -4.210 1.935 -4.172 c 2.040 -4.134 2.131 -4.115 2.205 -4.115 c 2.267 -4.115 2.341 -4.232 2.429 -4.469 c 2.437 -4.494 2.444 -4.511 2.448 -4.522 c 2.451 -4.531 2.456 -4.546 2.465 -4.568 c 2.546 -4.795 2.614 -4.910 2.668 -4.910 c 2.714 -4.910 2.898 -4.652 3.219 -4.136 c 3.539 -3.620 3.866 -3.136 4.197 -2.683 c 4.426 -2.367 4.633 -2.103 4.816 -1.889 c 4.998 -1.676 5.131 -1.544 5.211 -1.493 c 5.329 -1.426 5.483 -1.368 5.670 -1.319 c 5.856 -1.271 6.066 -1.238 6.296 -1.217 c 6.321 -1.352 l h f Q ';
1623
  $cb_off = 'q ' . $matrix . ' cm ' . $fill . $radio_color . ' rg ' . $square . ' f Q ';
1624
  }
1625
+ $this->writer->object();
1626
  $p = $this->mpdf->compress ? gzcompress($cb_on) : $cb_on;
1627
+ $this->writer->write('<<' . $filter . '/Length ' . strlen($p) . ' /Resources 2 0 R>>');
1628
+ $this->writer->stream($p);
1629
+ $this->writer->write('endobj');
1630
 
1631
  // output appearance stream for check box off (only if not using ZapfDingbats)
1632
  if (!$this->formUseZapD) {
1633
+ $this->writer->object();
1634
  $p = $this->mpdf->compress ? gzcompress($cb_off) : $cb_off;
1635
+ $this->writer->write('<<' . $filter . '/Length ' . strlen($p) . ' /Resources 2 0 R>>');
1636
+ $this->writer->stream($p);
1637
+ $this->writer->write('endobj');
1638
  }
1639
  }
1640
  return $n;
1643
  function _putform_ch($form, $hPt)
1644
  {
1645
  $put_js = 0;
1646
+ $this->writer->object();
1647
  $n = $this->mpdf->n;
1648
  $this->pdf_acro_array .= $n . ' 0 R ';
1649
  $this->forms[$form['n']]['obj'] = $n;
1650
 
1651
+ $this->writer->write('<<');
1652
+ $this->writer->write('/Type /Annot ');
1653
+ $this->writer->write('/Subtype /Widget');
1654
+ $this->writer->write('/Rect [ ' . $this->_form_rect($form['x'], $form['y'], $form['w'], $form['h'], $hPt) . ' ]');
1655
+ $this->writer->write('/F 4');
1656
+ $this->writer->write('/FT /Ch');
1657
  if ($form['Q']) {
1658
+ $this->writer->write('/Q ' . $form['Q'] . '');
1659
  }
1660
  $temp = '';
1661
  $temp .= '/W ' . $form['BS_W'] . ' ';
1662
  $temp .= '/S /' . $form['BS_S'] . ' ';
1663
+ $this->writer->write("/BS << $temp >>");
1664
 
1665
  $temp = '';
1666
  $temp .= '/BC [ ' . $form['BC_C'] . ' ] ';
1667
  $temp .= '/BG [ ' . $form['BG_C'] . ' ] ';
1668
+ $this->writer->write('/MK << ' . $temp . ' >>');
1669
 
1670
+ $this->writer->write('/NM ' . $this->writer->string(sprintf('%04u-%04u', $n, 6000 + $form['n'])));
1671
+ $this->writer->write('/M ' . $this->writer->string('D:' . date('YmdHis')));
1672
 
1673
+ $this->writer->write('/T ' . $this->writer->string($form['T']));
1674
+ $this->writer->write('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
1675
 
1676
  $opt = '';
1677
+ $count = count($form['OPT']['VAL']);
1678
+ for ($i = 0; $i < $count; $i++) {
1679
+ $opt .= '[ ' . $this->writer->string($form['OPT']['VAL'][$i]) . ' ' . $this->writer->string($form['OPT']['OPT'][$i]) . ' ] ';
1680
  }
1681
+ $this->writer->write('/Opt [ ' . $opt . ']');
1682
 
1683
  // selected
1684
  $selectItem = false;
1685
  $selectIndex = false;
1686
  foreach ($form['OPT']['SEL'] as $selectKey => $selectVal) {
1687
+ $selectName = $this->writer->string($form['OPT']['VAL'][$selectVal]);
1688
  $selectItem .= ' ' . $selectName . ' ';
1689
  $selectIndex .= ' ' . $selectVal . ' ';
1690
  }
1691
  if ($selectItem) {
1692
  if (count($form['OPT']['SEL']) < 2) {
1693
+ $this->writer->write('/V ' . $selectItem . ' ');
1694
+ $this->writer->write('/DV ' . $selectItem . ' ');
1695
  } else {
1696
+ $this->writer->write('/V [' . $selectItem . '] ');
1697
+ $this->writer->write('/DV [' . $selectItem . '] ');
1698
  }
1699
+ $this->writer->write('/I [' . $selectIndex . '] ');
1700
  }
1701
 
1702
  if (is_array($form['FF']) && count($form['FF']) > 0) {
1703
+ $this->writer->write('/Ff ' . $this->_setflag($form['FF']) . ' ');
1704
  }
1705
+
1706
  // Javascript
1707
  if (isset($this->array_form_choice_js[$form['T']])) {
1708
+ $this->writer->write('/AA << /V ' . ($this->mpdf->n + 1) . ' 0 R >>');
1709
  $put_js = 1;
1710
  }
1711
 
1712
+ $this->writer->write('>>');
1713
+ $this->writer->write('endobj');
1714
+
1715
  // obj + 1
1716
+ if ($put_js === 1) {
1717
  $this->mpdf->_set_object_javascript($this->array_form_choice_js[$form['T']]['js']);
1718
  unset($this->array_form_choice_js[$form['T']]);
1719
  $put_js = null;
1725
  function _putform_tx($form, $hPt)
1726
  {
1727
  $put_js = 0;
1728
+ $this->writer->object();
1729
  $n = $this->mpdf->n;
1730
  $this->pdf_acro_array .= $n . ' 0 R ';
1731
  $this->forms[$form['n']]['obj'] = $n;
1732
 
1733
+ $this->writer->write('<<');
1734
+ $this->writer->write('/Type /Annot ');
1735
+ $this->writer->write('/Subtype /Widget ');
1736
 
1737
+ $this->writer->write('/Rect [ ' . $this->_form_rect($form['x'], $form['y'], $form['w'], $form['h'], $hPt) . ' ] ');
1738
+ $form['hidden'] ? $this->writer->write('/F 2 ') : $this->writer->write('/F 4 ');
1739
+ $this->writer->write('/FT /Tx ');
1740
 
1741
+ $this->writer->write('/H /N ');
1742
+ $this->writer->write('/R 0 ');
1743
 
1744
  if (is_array($form['FF']) && count($form['FF']) > 0) {
1745
+ $this->writer->write('/Ff ' . $this->_setflag($form['FF']) . ' ');
1746
  }
1747
  if (isset($form['maxlen']) && $form['maxlen'] > 0) {
1748
+ $this->writer->write('/MaxLen ' . $form['maxlen']);
1749
  }
1750
 
1751
  $temp = '';
1752
  $temp .= '/W ' . $form['BS_W'] . ' ';
1753
  $temp .= '/S /' . $form['BS_S'] . ' ';
1754
+ $this->writer->write("/BS << $temp >>");
1755
 
1756
  $temp = '';
1757
  $temp .= '/BC [ ' . $form['BC_C'] . ' ] ';
1758
  $temp .= '/BG [ ' . $form['BG_C'] . ' ] ';
1759
+ $this->writer->write('/MK <<' . $temp . ' >>');
1760
 
1761
+ $this->writer->write('/T ' . $this->writer->string($form['T']));
1762
+ $this->writer->write('/TU ' . $this->writer->string($form['TU']));
1763
  if ($form['V'] || $form['V'] === '0') {
1764
+ $this->writer->write('/V ' . $this->writer->string($form['V']));
1765
  }
1766
+ $this->writer->write('/DV ' . $this->writer->string($form['DV']));
1767
+ $this->writer->write('/DA (/F' . $this->mpdf->fonts[$form['style']['font']]['i'] . ' ' . $form['style']['fontsize'] . ' Tf ' . $form['style']['fontcolor'] . ')');
1768
  if ($form['Q']) {
1769
+ $this->writer->write('/Q ' . $form['Q'] . '');
1770
  }
1771
 
1772
+ $this->writer->write('/NM ' . $this->writer->string(sprintf('%04u-%04u', $n, 5000 + $form['n'])));
1773
+ $this->writer->write('/M ' . $this->writer->string('D:' . date('YmdHis')));
1774
 
1775
 
1776
  if (isset($this->array_form_text_js[$form['T']])) {
1795
  $js_str .= '/C ' . ($cc + $this->mpdf->n) . ' 0 R ';
1796
  $this->pdf_array_co .= $this->mpdf->n . ' 0 R ';
1797
  }
1798
+ $this->writer->write('/AA << ' . $js_str . ' >>');
1799
  }
1800
 
1801
+ $this->writer->write('>>');
1802
+ $this->writer->write('endobj');
1803
 
1804
  if ($put_js == 1) {
1805
  if (isset($this->array_form_text_js[$form['T']]['F'])) {
vendor/mpdf/mpdf/src/Gradient.php CHANGED
@@ -3,9 +3,11 @@
3
  namespace Mpdf;
4
 
5
  use Mpdf\Color\ColorConverter;
 
6
 
7
  class Gradient
8
  {
 
9
  const TYPE_LINEAR = 2;
10
  const TYPE_RADIAL = 3;
11
 
@@ -24,11 +26,17 @@ class Gradient
24
  */
25
  private $colorConverter;
26
 
27
- public function __construct(Mpdf $mpdf, SizeConverter $sizeConverter, ColorConverter $colorConverter)
 
 
 
 
 
28
  {
29
  $this->mpdf = $mpdf;
30
  $this->sizeConverter = $sizeConverter;
31
  $this->colorConverter = $colorConverter;
 
32
  }
33
 
34
  // mPDF 5.3.A1
@@ -119,7 +127,7 @@ class Gradient
119
  return $s;
120
  }
121
 
122
- $this->mpdf->_out($s);
123
  }
124
 
125
  // type = linear:2; radial: 3;
@@ -585,7 +593,7 @@ class Gradient
585
  return $s;
586
  }
587
 
588
- $this->mpdf->_out($s);
589
  }
590
 
591
  private function parseMozLinearGradient($m, $repeat)
3
  namespace Mpdf;
4
 
5
  use Mpdf\Color\ColorConverter;
6
+ use Mpdf\Writer\BaseWriter;
7
 
8
  class Gradient
9
  {
10
+
11
  const TYPE_LINEAR = 2;
12
  const TYPE_RADIAL = 3;
13
 
26
  */
27
  private $colorConverter;
28
 
29
+ /**
30
+ * @var \Mpdf\Writer\BaseWriter
31
+ */
32
+ private $writer;
33
+
34
+ public function __construct(Mpdf $mpdf, SizeConverter $sizeConverter, ColorConverter $colorConverter, BaseWriter $writer)
35
  {
36
  $this->mpdf = $mpdf;
37
  $this->sizeConverter = $sizeConverter;
38
  $this->colorConverter = $colorConverter;
39
+ $this->writer = $writer;
40
  }
41
 
42
  // mPDF 5.3.A1
127
  return $s;
128
  }
129
 
130
+ $this->writer->write($s);
131
  }
132
 
133
  // type = linear:2; radial: 3;
593
  return $s;
594
  }
595
 
596
+ $this->writer->write($s);
597
  }
598
 
599
  private function parseMozLinearGradient($m, $repeat)
vendor/mpdf/mpdf/src/Image/ImageProcessor.php CHANGED
@@ -3,15 +3,25 @@
3
  namespace Mpdf\Image;
4
 
5
  use Mpdf\Cache;
 
6
  use Mpdf\Color\ColorConverter;
7
  use Mpdf\Color\ColorModeConverter;
 
8
  use Mpdf\CssManager;
 
9
  use Mpdf\Gif\Gif;
 
10
  use Mpdf\Language\LanguageToFontInterface;
11
  use Mpdf\Language\ScriptToLanguageInterface;
 
12
  use Mpdf\Log\Context as LogContext;
 
13
  use Mpdf\Mpdf;
 
14
  use Mpdf\Otl;
 
 
 
15
  use Mpdf\SizeConverter;
16
 
17
  use Psr\Log\LoggerInterface;
@@ -84,6 +94,11 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
84
  */
85
  public $scriptToLanguage;
86
 
 
 
 
 
 
87
  /**
88
  * @var \Psr\Log\LoggerInterface
89
  */
@@ -99,6 +114,7 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
99
  Cache $cache,
100
  LanguageToFontInterface $languageToFont,
101
  ScriptToLanguageInterface $scriptToLanguage,
 
102
  LoggerInterface $logger
103
  ) {
104
 
@@ -111,6 +127,7 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
111
  $this->cache = $cache;
112
  $this->languageToFont = $languageToFont;
113
  $this->scriptToLanguage = $scriptToLanguage;
 
114
 
115
  $this->logger = $logger;
116
 
@@ -122,7 +139,7 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
122
  /**
123
  * @param \Psr\Log\LoggerInterface
124
  *
125
- * @return \Mpdf\Mpdf
126
  */
127
  public function setLogger(LoggerInterface $logger)
128
  {
@@ -136,6 +153,10 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
136
  // mPDF 6
137
  // firsttime i.e. whether to add to this->images - use false when calling iteratively
138
  // Image Data passed directly as var:varname
 
 
 
 
139
  if (preg_match('/var:\s*(.*)/', $file, $v)) {
140
  if (!isset($this->mpdf->imageVars[$v[1]])) {
141
  return $this->imageError($file, $firsttime, 'Unknown image variable');
@@ -151,13 +172,13 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
151
  }
152
 
153
  // mPDF 5.7.4 URLs
154
- if ($firsttime && $file && substr($file, 0, 5) != 'data:') {
155
- $file = str_replace(" ", "%20", $file);
156
  }
157
  if ($firsttime && $orig_srcpath) {
158
  // If orig_srcpath is a relative file path (and not a URL), then it needs to be URL decoded
159
- if (substr($orig_srcpath, 0, 5) != 'data:') {
160
- $orig_srcpath = str_replace(" ", "%20", $orig_srcpath);
161
  }
162
  if (!preg_match('/^(http|ftp)/', $orig_srcpath)) {
163
  $orig_srcpath = $this->urldecodeParts($orig_srcpath);
@@ -172,21 +193,26 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
172
 
173
  if (isset($this->mpdf->images[$file])) {
174
  return $this->mpdf->images[$file];
175
- } elseif ($orig_srcpath && isset($this->mpdf->formobjects[$orig_srcpath])) {
 
 
176
  $file = $orig_srcpath;
177
  return $this->mpdf->formobjects[$file];
178
- } elseif (isset($this->mpdf->formobjects[$file])) {
 
 
179
  return $this->mpdf->formobjects[$file];
180
- } elseif ($firsttime && isset($this->failedImages[$file])) { // Save re-trying image URL's which have already failed
 
 
181
  return $this->imageError($file, $firsttime, '');
182
  }
183
 
184
  if (empty($data)) {
185
 
186
- $type = '';
187
  $data = '';
188
 
189
- if ($orig_srcpath && $this->mpdf->basepathIsLocal && $check = @fopen($orig_srcpath, "rb")) {
190
  fclose($check);
191
  $file = $orig_srcpath;
192
  $this->logger->debug(sprintf('Fetching (file_get_contents) content of file "%s" with local basepath', $file), ['context' => LogContext::REMOTE_CONTENT]);
@@ -194,7 +220,7 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
194
  $type = $this->guesser->guess($data);
195
  }
196
 
197
- if (!$data && $check = @fopen($file, "rb")) {
198
  fclose($check);
199
  $this->logger->debug(sprintf('Fetching (file_get_contents) content of file "%s" with non-local basepath', $file), ['context' => LogContext::REMOTE_CONTENT]);
200
  $data = file_get_contents($file);
@@ -202,14 +228,14 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
202
  }
203
 
204
  if ((!$data || !$type) && function_exists('curl_init')) { // mPDF 5.7.4
205
- $this->mpdf->getFileContentsByCurl($file, $data); // needs full url?? even on local (never needed for local)
206
  if ($data) {
207
  $type = $this->guesser->guess($data);
208
  }
209
  }
210
 
211
  if ((!$data || !$type) && !ini_get('allow_url_fopen')) { // only worth trying if remote file and !ini_get('allow_url_fopen')
212
- $this->mpdf->getFileContentsBySocket($file, $data); // needs full url?? even on local (never needed for local)
213
  if ($data) {
214
  $type = $this->guesser->guess($data);
215
  }
@@ -220,16 +246,16 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
220
  return $this->imageError($file, $firsttime, 'Could not find image file');
221
  }
222
 
223
- if (empty($type)) {
224
  $type = $this->guesser->guess($data);
225
  }
226
 
227
- if (($type == 'wmf' || $type == 'svg') && !$allowvector) {
228
  return $this->imageError($file, $firsttime, 'WMF or SVG image file not supported in this context');
229
  }
230
 
231
  // SVG
232
- if ($type == 'svg') {
233
  $svg = new Svg($this->mpdf, $this->otl, $this->cssManager, $this, $this->sizeConverter, $this->colorConverter, $this->languageToFont, $this->scriptToLanguage);
234
  $family = $this->mpdf->FontFamily;
235
  $style = $this->mpdf->FontStyle;
@@ -250,36 +276,41 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
250
  }
251
 
252
  // JPEG
253
- if ($type == 'jpeg' || $type == 'jpg') {
 
254
  $hdr = $this->jpgHeaderFromString($data);
255
  if (!$hdr) {
256
  return $this->imageError($file, $firsttime, 'Error parsing JPG header');
257
  }
 
258
  $a = $this->jpgDataFromHeader($hdr);
259
- $channels = intval($a[4]);
260
  $j = strpos($data, 'JFIF');
 
261
  if ($j) {
262
- //Read resolution
263
- $unitSp = ord(substr($data, ($j + 7), 1));
264
  if ($unitSp > 0) {
265
- $ppUx = $this->twoBytesToInt(substr($data, ($j + 8), 2)); // horizontal pixels per meter, usually set to zero
266
- if ($unitSp == 2) { // = dots per cm (if == 1 set as dpi)
267
  $ppUx = round($ppUx / 10 * 25.4);
268
  }
269
  }
270
  }
271
- if ($a[2] == 'DeviceCMYK' && (($this->mpdf->PDFA && $this->mpdf->restrictColorSpace != 3) || $this->mpdf->restrictColorSpace == 2)) {
 
272
 
273
  // convert to RGB image
274
- if (!function_exists("gd_info")) {
275
- throw new \Mpdf\MpdfException("JPG image may not use CMYK color space (" . $file . ").");
276
  }
277
 
278
  if ($this->mpdf->PDFA && !$this->mpdf->PDFAauto) {
279
- $this->mpdf->PDFAXwarnings[] = "JPG image may not use CMYK color space - " . $file . " - (Image converted to RGB. NB This will alter the colour profile of the image.)";
280
  }
281
 
282
  $im = @imagecreatefromstring($data);
 
283
  if ($im) {
284
  $tempfile = $this->cache->tempFilename('_tempImgPNG' . md5($file) . random_int(1, 10000) . '.png');
285
  imageinterlace($im, false);
@@ -300,20 +331,22 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
300
  $this->mpdf->images[$file] = $info;
301
  }
302
  return $info;
303
- } else {
304
- return $this->imageError($file, $firsttime, 'Error creating GD image file from JPG(CMYK) image');
305
  }
306
 
307
- } elseif ($a[2] == 'DeviceRGB' && ($this->mpdf->PDFX || $this->mpdf->restrictColorSpace == 3)) {
 
 
 
 
308
  // Convert to CMYK image stream - nominally returned as type='png'
309
- $info = $this->convImage($data, $a[2], 'DeviceCMYK', $a[0], $a[1], $ppUx, false);
310
  if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
311
- $this->mpdf->PDFAXwarnings[] = "JPG image may not use RGB color space - " . $file . " - (Image converted to CMYK. NB This will alter the colour profile of the image.)";
312
  }
313
 
314
- } elseif (($a[2] == 'DeviceRGB' || $a[2] == 'DeviceCMYK') && $this->mpdf->restrictColorSpace == 1) {
315
  // Convert to Grayscale image stream - nominally returned as type='png'
316
- $info = $this->convImage($data, $a[2], 'DeviceGray', $a[0], $a[1], $ppUx, false);
317
 
318
  } else {
319
  // mPDF 6 Detect Adobe APP14 Tag
@@ -325,24 +358,24 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
325
  $icc = [];
326
  while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) {
327
  // get ICC sequence length
328
- $length = $this->twoBytesToInt(substr($data, ($pos - 2), 2)) - 16;
329
- $sn = max(1, ord($data[($pos + 12)]));
330
- $nom = max(1, ord($data[($pos + 13)]));
331
- $icc[($sn - 1)] = substr($data, ($pos + 14), $length);
332
  $offset = ($pos + 14 + $length);
333
  }
334
  // order and compact ICC segments
335
  if (count($icc) > 0) {
336
  ksort($icc);
337
  $icc = implode('', $icc);
338
- if (substr($icc, 36, 4) != 'acsp') {
339
  // invalid ICC profile
340
  $icc = false;
341
  }
342
  $input = substr($icc, 16, 4);
343
  $output = substr($icc, 20, 4);
344
  // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
345
- if ($input != 'RGB ' || $output != 'XYZ ') {
346
  $icc = false;
347
  }
348
  } else {
@@ -366,15 +399,18 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
366
  }
367
 
368
  return $info;
369
- } elseif ($type == 'png') {
 
 
 
370
 
371
  // Check signature
372
- if (substr($data, 0, 8) != chr(137) . 'PNG' . chr(13) . chr(10) . chr(26) . chr(10)) {
373
  return $this->imageError($file, $firsttime, 'Error parsing PNG identifier');
374
  }
375
 
376
  // Read header chunk
377
- if (substr($data, 12, 4) != 'IHDR') {
378
  return $this->imageError($file, $firsttime, 'Incorrect PNG file (no IHDR block found)');
379
  }
380
 
@@ -386,18 +422,18 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
386
  $channels = 0;
387
 
388
  // if($bpc>8) { $errpng = 'not 8-bit depth'; } // mPDF 6 Allow through to be handled as native PNG
389
-
390
  $ct = ord(substr($data, 25, 1));
391
- if ($ct == 0) {
 
392
  $colspace = 'DeviceGray';
393
  $channels = 1;
394
- } elseif ($ct == 2) {
395
  $colspace = 'DeviceRGB';
396
  $channels = 3;
397
- } elseif ($ct == 3) {
398
  $colspace = 'Indexed';
399
  $channels = 1;
400
- } elseif ($ct == 4) {
401
  $colspace = 'DeviceGray';
402
  $channels = 1;
403
  $errpng = 'alpha channel';
@@ -414,28 +450,30 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
414
  $pngalpha = true;
415
  } // mPDF 6
416
 
417
- if ($ct == 3 && strpos($data, 'iCCP') !== false) {
418
  $errpng = 'indexed plus ICC';
419
  } // mPDF 6
 
420
  // $pngalpha is used as a FLAG of any kind of transparency which COULD be tranferred to an alpha channel
421
  // incl. single-color tarnsparency, depending which type of handling occurs later
422
-
423
- if (ord(substr($data, 26, 1)) != 0) {
424
  $errpng = 'compression method';
425
  } // only 0 should be specified
426
- if (ord(substr($data, 27, 1)) != 0) {
 
427
  $errpng = 'filter method';
428
- } // only 0 should be specified
429
- if (ord(substr($data, 28, 1)) != 0) {
 
430
  $errpng = 'interlaced file';
431
  }
432
 
433
  $j = strpos($data, 'pHYs');
434
  if ($j) {
435
  //Read resolution
436
- $unitSp = ord(substr($data, ($j + 12), 1));
437
- if ($unitSp == 1) {
438
- $ppUx = $this->fourBytesToInt(substr($data, ($j + 4), 4)); // horizontal pixels per meter, usually set to zero
439
  $ppUx = round($ppUx / 1000 * 25.4);
440
  }
441
  }
@@ -445,7 +483,7 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
445
  $gAMA = 0;
446
  $j = strpos($data, 'gAMA');
447
  if ($j && strpos($data, 'sRGB') === false) { // sRGB colorspace - overrides gAMA
448
- $gAMA = $this->fourBytesToInt(substr($data, ($j + 4), 4)); // Gamma value times 100000
449
  $gAMA /= 100000;
450
 
451
  // http://www.libpng.org/pub/png/spec/1.2/PNG-Encoders.html
@@ -475,257 +513,263 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
475
  //$j = strpos($data,'cHRM'); // Chromaticity and Whitepoint
476
  // $firsttime added mPDF 6 so when PNG Grayscale with alpha using resrtictcolorspace to CMYK
477
  // the alpha channel is sent through as secondtime as Indexed and should not be converted to CMYK
478
- if ($firsttime && ($colspace == 'DeviceRGB' || $colspace == 'Indexed') && ($this->mpdf->PDFX || $this->mpdf->restrictColorSpace == 3)) {
 
479
  // Convert to CMYK image stream - nominally returned as type='png'
480
- $info = $this->convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
481
  if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
482
- $this->mpdf->PDFAXwarnings[] = "PNG image may not use RGB color space - " . $file . " - (Image converted to CMYK. NB This will alter the colour profile of the image.)";
483
  }
484
- } // $firsttime added mPDF 6 so when PNG Grayscale with alpha using resrtictcolorspace to CMYK
485
- // the alpha channel is sent through as secondtime as Indexed and should not be converted to CMYK
486
- elseif ($firsttime && ($colspace == 'DeviceRGB' || $colspace == 'Indexed') && $this->mpdf->restrictColorSpace == 1) {
 
 
487
  // Convert to Grayscale image stream - nominally returned as type='png'
488
- $info = $this->convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
 
489
  } elseif (($this->mpdf->PDFA || $this->mpdf->PDFX) && $pngalpha) {
 
490
  // Remove alpha channel
491
- if ($this->mpdf->restrictColorSpace == 1) { // Grayscale
492
- $info = $this->convImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
493
- } elseif ($this->mpdf->restrictColorSpace == 3) { // CMYK
494
- $info = $this->convImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
495
  } elseif ($this->mpdf->PDFA) { // RGB
496
- $info = $this->convImage($data, $colspace, 'DeviceRGB', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
497
  }
498
  if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
499
- $this->mpdf->PDFAXwarnings[] = "Transparency (alpha channel) not permitted in PDFA or PDFX files - " . $file . " - (Image converted to one without transparency.)";
500
  }
 
501
  } elseif ($firsttime && ($errpng || $pngalpha || $gamma)) { // mPDF 5.7.2 Gamma correction
502
- if (function_exists('gd_info')) {
503
- $gd = gd_info();
504
- } else {
505
- $gd = [];
506
- }
507
  if (!isset($gd['PNG Support'])) {
508
- return $this->imageError($file, $firsttime, 'GD library required for PNG image (' . $errpng . ')');
509
  }
510
- $im = imagecreatefromstring($data);
511
 
 
512
  if (!$im) {
513
- return $this->imageError($file, $firsttime, 'Error creating GD image from PNG file (' . $errpng . ')');
514
  }
 
515
  $w = imagesx($im);
516
  $h = imagesy($im);
517
- if ($im) {
518
- $tempfile = $this->cache->tempFilename('_tempImgPNG' . md5($file) . random_int(1, 10000) . '.png');
519
 
520
- // Alpha channel set (including using tRNS for Paletted images)
521
- if ($pngalpha) {
522
- if ($this->mpdf->PDFA) {
523
- throw new \Mpdf\MpdfException("PDFA1-b does not permit images with alpha channel transparency (" . $file . ").");
524
- }
525
 
526
- $imgalpha = imagecreate($w, $h);
527
- // generate gray scale pallete
528
- for ($c = 0; $c < 256; ++$c) {
529
- imagecolorallocate($imgalpha, $c, $c, $c);
530
- }
531
 
532
- // mPDF 6
533
- if ($colspace == 'Indexed') { // generate Alpha channel values from tRNS
534
- // Read transparency info
535
- $p = strpos($data, 'tRNS');
536
- if ($p) {
537
- $n = $this->fourBytesToInt(substr($data, ($p - 4), 4));
538
- $transparency = substr($data, ($p + 4), $n);
539
- // ord($transparency{$index}) = the alpha value for that index
540
- // generate alpha channel
541
- for ($ypx = 0; $ypx < $h; ++$ypx) {
542
- for ($xpx = 0; $xpx < $w; ++$xpx) {
543
- $colorindex = imagecolorat($im, $xpx, $ypx);
544
- if ($colorindex >= $n) {
545
- $alpha = 255;
546
- } else {
547
- $alpha = ord($transparency{$colorindex});
548
- } // 0-255
549
- if ($alpha > 0) {
550
- imagesetpixel($imgalpha, $xpx, $ypx, $alpha);
551
- }
552
- }
553
- }
554
- }
555
- } elseif ($ct === 0 || $ct == 2) { // generate Alpha channel values from tRNS
556
- // Get transparency as array of RGB
557
- $p = strpos($data, 'tRNS');
558
- if ($p) {
559
- $trns = '';
560
- $n = $this->fourBytesToInt(substr($data, ($p - 4), 4));
561
- $t = substr($data, ($p + 4), $n);
562
- if ($colspace == 'DeviceGray') { // ct===0
563
- $trns = [$this->translateValue(substr($t, 0, 2), $bpc)];
564
- } else /* $colspace=='DeviceRGB' */ { // ct==2
565
- $trns = [];
566
- $trns[0] = $this->translateValue(substr($t, 0, 2), $bpc);
567
- $trns[1] = $this->translateValue(substr($t, 2, 2), $bpc);
568
- $trns[2] = $this->translateValue(substr($t, 4, 2), $bpc);
569
- }
570
 
571
- // generate alpha channel
572
- for ($ypx = 0; $ypx < $h; ++$ypx) {
573
- for ($xpx = 0; $xpx < $w; ++$xpx) {
574
- $rgb = imagecolorat($im, $xpx, $ypx);
575
- $r = ($rgb >> 16) & 0xFF;
576
- $g = ($rgb >> 8) & 0xFF;
577
- $b = $rgb & 0xFF;
578
- if ($colspace == 'DeviceGray' && $b == $trns[0]) {
579
- $alpha = 0;
580
- } elseif ($r == $trns[0] && $g == $trns[1] && $b == $trns[2]) {
581
- $alpha = 0;
582
- } // ct==2
583
- else {
584
- $alpha = 255;
585
- }
586
- if ($alpha > 0) {
587
- imagesetpixel($imgalpha, $xpx, $ypx, $alpha);
588
- }
 
589
  }
590
  }
591
  }
592
- } else {
593
- // extract alpha channel
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
  for ($ypx = 0; $ypx < $h; ++$ypx) {
595
  for ($xpx = 0; $xpx < $w; ++$xpx) {
596
- $alpha = (imagecolorat($im, $xpx, $ypx) & 0x7F000000) >> 24;
597
- if ($alpha < 127) {
598
- imagesetpixel($imgalpha, $xpx, $ypx, (255 - ($alpha * 2)));
 
 
 
 
 
 
 
 
 
 
599
  }
600
  }
601
  }
602
  }
603
-
604
- // NB This must happen after the Alpha channel is extracted
605
- // imagegammacorrect() removes the alpha channel data in $im - (I think this is a bug in PHP)
606
- if ($gamma) {
607
- imagegammacorrect($im, $gamma, 2.2);
 
 
 
 
608
  }
 
609
 
610
- $tempfile_alpha = $this->cache->tempFilename('_tempMskPNG' . md5($file) . random_int(1, 10000) . '.png');
 
 
 
 
611
 
612
- $check = @imagepng($imgalpha, $tempfile_alpha);
613
 
614
- if (!$check) {
615
- return $this->imageError($file, $firsttime, 'Failed to create temporary image file (' . $tempfile_alpha . ') parsing PNG image with alpha channel (' . $errpng . ')');
616
- }
617
 
618
- imagedestroy($imgalpha);
619
- // extract image without alpha channel
620
- $imgplain = imagecreatetruecolor($w, $h);
621
- imagealphablending($imgplain, false); // mPDF 5.7.2
622
- imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
623
 
624
- // create temp image file
625
- $check = @imagepng($imgplain, $tempfile);
626
- if (!$check) {
627
- return $this->imageError($file, $firsttime, 'Failed to create temporary image file (' . $tempfile . ') parsing PNG image with alpha channel (' . $errpng . ')');
628
- }
629
- imagedestroy($imgplain);
630
- // embed mask image
631
- $minfo = $this->getImage($tempfile_alpha, false);
632
- unlink($tempfile_alpha);
633
 
634
- if (!$minfo) {
635
- return $this->imageError($file, $firsttime, 'Error parsing temporary file (' . $tempfile_alpha . ') created with GD library to parse PNG image');
636
- }
 
 
 
 
 
 
637
 
638
- $imgmask = count($this->mpdf->images) + 1;
639
- $minfo['cs'] = 'DeviceGray';
640
- $minfo['i'] = $imgmask;
641
- $this->mpdf->images[$tempfile_alpha] = $minfo;
642
- // embed image, masked with previously embedded mask
643
- $info = $this->getImage($tempfile, false);
644
- unlink($tempfile);
645
 
646
- if (!$info) {
647
- return $this->imageError($file, $firsttime, 'Error parsing temporary file (' . $tempfile . ') created with GD library to parse PNG image');
648
- }
 
 
 
 
649
 
650
- $info['masked'] = $imgmask;
651
- if ($ppUx) {
652
- $info['set-dpi'] = $ppUx;
653
- }
654
- $info['type'] = 'png';
655
- if ($firsttime) {
656
- $info['i'] = count($this->mpdf->images) + 1;
657
- $info['interpolation'] = $interpolation; // mPDF 6
658
- $this->mpdf->images[$file] = $info;
659
- }
660
 
661
- return $info;
662
- } else { // No alpha/transparency set (but cannot read directly because e.g. bit-depth != 8, interlaced etc)
663
- // ICC profile
664
- $icc = false;
665
- $p = strpos($data, 'iCCP');
666
- if ($p && $colspace == "Indexed") { // Cannot have ICC profile and Indexed together
667
- $p += 4;
668
- $n = $this->fourBytesToInt(substr($data, ($p - 8), 4));
669
- $nullsep = strpos(substr($data, $p, 80), chr(0));
670
- $icc = substr($data, ($p + $nullsep + 2), ($n - ($nullsep + 2)));
671
- $icc = @gzuncompress($icc); // Ignored if fails
672
- if ($icc) {
673
- if (substr($icc, 36, 4) != 'acsp') {
674
- $icc = false;
675
- } // invalid ICC profile
676
- else {
677
- $input = substr($icc, 16, 4);
678
- $output = substr($icc, 20, 4);
679
- // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
680
- if ($input != 'RGB ' || $output != 'XYZ ') {
681
- $icc = false;
682
- }
683
- }
684
- }
685
- // Convert to RGB colorspace so can use ICC Profile
686
- if ($icc) {
687
- imagepalettetotruecolor($im);
688
- $colspace = 'DeviceRGB';
689
- $channels = 3;
 
 
 
 
 
690
  }
691
  }
 
 
 
 
 
 
 
 
692
 
693
- if ($gamma) {
694
- imagegammacorrect($im, $gamma, 2.2);
695
- }
696
 
697
- imagealphablending($im, false);
698
- imagesavealpha($im, false);
699
- imageinterlace($im, false);
700
 
701
- $check = @imagepng($im, $tempfile);
702
- if (!$check) {
703
- return $this->imageError($file, $firsttime, 'Failed to create temporary image file (' . $tempfile . ') parsing PNG image (' . $errpng . ')');
704
- }
705
- imagedestroy($im);
706
- $info = $this->getImage($tempfile, false);
707
- unlink($tempfile);
708
- if (!$info) {
709
- return $this->imageError($file, $firsttime, 'Error parsing temporary file (' . $tempfile . ') created with GD library to parse PNG image');
710
- }
711
 
712
- if ($ppUx) {
713
- $info['set-dpi'] = $ppUx;
714
- }
715
- $info['type'] = 'png';
716
- if ($firsttime) {
717
- $info['i'] = count($this->mpdf->images) + 1;
718
- $info['interpolation'] = $interpolation; // mPDF 6
719
- if ($icc) {
720
- $info['ch'] = $channels;
721
- $info['icc'] = $icc;
722
- }
723
- $this->mpdf->images[$file] = $info;
724
- }
725
- return $info;
726
  }
 
727
  }
 
 
 
728
  } else { // PNG image with no need to convert alph channels, bpc <> 8 etc.
 
729
  $parms = '/DecodeParms <</Predictor 15 /Colors ' . $channels . ' /BitsPerComponent ' . $bpc . ' /Columns ' . $w . '>>';
730
  //Scan chunks looking for palette, transparency and image data
731
  $pal = '';
@@ -733,23 +777,24 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
733
  $pngdata = '';
734
  $icc = false;
735
  $p = 33;
 
736
  do {
737
  $n = $this->fourBytesToInt(substr($data, $p, 4));
738
  $p += 4;
739
  $type = substr($data, $p, 4);
740
  $p += 4;
741
- if ($type == 'PLTE') {
742
  //Read palette
743
  $pal = substr($data, $p, $n);
744
  $p += $n;
745
  $p += 4;
746
- } elseif ($type == 'tRNS') {
747
  //Read transparency info
748
  $t = substr($data, $p, $n);
749
  $p += $n;
750
- if ($ct == 0) {
751
  $trns = [ord(substr($t, 1, 1))];
752
- } elseif ($ct == 2) {
753
  $trns = [ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1))];
754
  } else {
755
  $pos = strpos($t, chr(0));
@@ -758,30 +803,30 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
758
  }
759
  }
760
  $p += 4;
761
- } elseif ($type == 'IDAT') {
762
  $pngdata.=substr($data, $p, $n);
763
  $p += $n;
764
  $p += 4;
765
- } elseif ($type == 'iCCP') {
766
  $nullsep = strpos(substr($data, $p, 80), chr(0));
767
- $icc = substr($data, ($p + $nullsep + 2), ($n - ($nullsep + 2)));
768
  $icc = @gzuncompress($icc); // Ignored if fails
769
  if ($icc) {
770
- if (substr($icc, 36, 4) != 'acsp') {
771
  $icc = false;
772
  } // invalid ICC profile
773
  else {
774
  $input = substr($icc, 16, 4);
775
  $output = substr($icc, 20, 4);
776
  // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
777
- if ($input != 'RGB ' || $output != 'XYZ ') {
778
  $icc = false;
779
  }
780
  }
781
  }
782
  $p += $n;
783
  $p += 4;
784
- } elseif ($type == 'IEND') {
785
  break;
786
  } elseif (preg_match('/[a-zA-Z]{4}/', $type)) {
787
  $p += $n + 4;
@@ -792,11 +837,11 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
792
  if (!$pngdata) {
793
  return $this->imageError($file, $firsttime, 'Error parsing PNG image data - no IDAT data found');
794
  }
795
- if ($colspace == 'Indexed' && empty($pal)) {
796
  return $this->imageError($file, $firsttime, 'Error parsing PNG image data - missing colour palette');
797
  }
798
 
799
- if ($colspace == 'Indexed' && $icc) {
800
  $icc = false;
801
  } // mPDF 6 cannot have ICC profile and Indexed in a PDF document as both use the colorspace tag.
802
 
@@ -819,7 +864,7 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
819
 
820
  return $info;
821
 
822
- } elseif ($type == 'gif') { // GIF
823
 
824
  if (function_exists('gd_info')) {
825
  $gd = gd_info();
@@ -868,48 +913,51 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
868
  $this->mpdf->images[$file] = $info;
869
  }
870
  return $info;
871
- } else {
872
- return $this->imageError($file, $firsttime, 'Error creating GD image file from GIF image');
873
  }
 
 
874
  }
875
 
876
  $gif = new Gif();
877
 
878
  $h = 0;
879
  $w = 0;
 
880
  $gif->loadFile($data, 0);
881
 
 
 
 
 
 
882
  if (isset($gif->m_img->m_gih->m_bLocalClr) && $gif->m_img->m_gih->m_bLocalClr) {
883
  $nColors = $gif->m_img->m_gih->m_nTableSize;
884
  $pal = $gif->m_img->m_gih->m_colorTable->toString();
885
- if ((isset($bgColor)) and $bgColor != -1) { // mPDF 5.7.3
886
  $bgColor = $gif->m_img->m_gih->m_colorTable->colorIndex($bgColor);
887
  }
888
  $colspace = 'Indexed';
889
  } elseif (isset($gif->m_gfh->m_bGlobalClr) && $gif->m_gfh->m_bGlobalClr) {
890
  $nColors = $gif->m_gfh->m_nTableSize;
891
  $pal = $gif->m_gfh->m_colorTable->toString();
892
- if ((isset($bgColor)) and $bgColor != -1) {
893
  $bgColor = $gif->m_gfh->m_colorTable->colorIndex($bgColor);
894
  }
895
  $colspace = 'Indexed';
896
- } else {
897
- $nColors = 0;
898
- $bgColor = -1;
899
- $colspace = 'DeviceGray';
900
- $pal = '';
901
  }
902
 
903
  $trns = '';
 
904
  if (isset($gif->m_img->m_bTrans) && $gif->m_img->m_bTrans && ($nColors > 0)) {
905
  $trns = [$gif->m_img->m_nTrans];
906
  }
 
907
  $gifdata = $gif->m_img->m_data;
908
  $w = $gif->m_gfh->m_nWidth;
909
  $h = $gif->m_gfh->m_nHeight;
910
  $gif->ClearData();
911
 
912
- if ($colspace == 'Indexed' and empty($pal)) {
913
  return $this->imageError($file, $firsttime, 'Error parsing GIF image - missing colour palette');
914
  }
915
 
@@ -929,25 +977,28 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
929
 
930
  return $info;
931
 
932
- } elseif ($type == 'bmp') {
933
 
934
- if (empty($this->bmp)) {
935
  $this->bmp = new Bmp($this->mpdf);
936
  }
 
937
  $info = $this->bmp->_getBMPimage($data, $file);
938
  if (isset($info['error'])) {
939
  return $this->imageError($file, $firsttime, $info['error']);
940
  }
 
941
  if ($firsttime) {
942
  $info['i'] = count($this->mpdf->images) + 1;
943
  $info['interpolation'] = $interpolation; // mPDF 6
944
  $this->mpdf->images[$file] = $info;
945
  }
 
946
  return $info;
947
 
948
- } elseif ($type == 'wmf') {
949
 
950
- if (empty($this->wmf)) {
951
  $this->wmf = new Wmf($this->mpdf, $this->colorConverter);
952
  }
953
 
@@ -1018,7 +1069,7 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1018
  return $this->imageError($file, $firsttime, 'Error parsing image file - image type not recognised');
1019
  }
1020
 
1021
- private function convImage(&$data, $colspace, $targetcs, $w, $h, $dpi, $mask, $gamma_correction = false, $pngcolortype = false)
1022
  {
1023
  if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
1024
  $mask = false;
@@ -1037,13 +1088,13 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1037
  // Need to extract alpha channel info before imagegammacorrect (which loses the data)
1038
  if ($mask) { // i.e. $pngalpha for PNG
1039
  // mPDF 6
1040
- if ($colspace == 'Indexed') { // generate Alpha channel values from tRNS - only from PNG
1041
  //Read transparency info
1042
  $transparency = '';
1043
  $p = strpos($data, 'tRNS');
1044
  if ($p) {
1045
- $n = $this->fourBytesToInt(substr($data, ($p - 4), 4));
1046
- $transparency = substr($data, ($p + 4), $n);
1047
  // ord($transparency{$index}) = the alpha value for that index
1048
  // generate alpha channel
1049
  for ($ypx = 0; $ypx < $h; ++$ypx) {
@@ -1058,14 +1109,14 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1058
  }
1059
  }
1060
  }
1061
- } elseif ($pngcolortype === 0 || $pngcolortype == 2) { // generate Alpha channel values from tRNS
1062
  // Get transparency as array of RGB
1063
  $p = strpos($data, 'tRNS');
1064
  if ($p) {
1065
  $trns = '';
1066
- $n = $this->fourBytesToInt(substr($data, ($p - 4), 4));
1067
- $t = substr($data, ($p + 4), $n);
1068
- if ($colspace == 'DeviceGray') { // ct===0
1069
  $trns = [$this->translateValue(substr($t, 0, 2), $bpc)];
1070
  } else /* $colspace=='DeviceRGB' */ { // ct==2
1071
  $trns = [];
@@ -1081,7 +1132,7 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1081
  $r = ($rgb >> 16) & 0xFF;
1082
  $g = ($rgb >> 8) & 0xFF;
1083
  $b = $rgb & 0xFF;
1084
- if ($colspace == 'DeviceGray' && $b == $trns[0]) {
1085
  $alpha = 0;
1086
  } elseif ($r == $trns[0] && $g == $trns[1] && $b == $trns[2]) {
1087
  $alpha = 0;
@@ -1120,23 +1171,23 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1120
  $p = strpos($data, 'tRNS');
1121
  if ($p) {
1122
  $n = $this->fourBytesToInt(substr($data, ($p - 4), 4));
1123
- $t = substr($data, ($p + 4), $n);
1124
- if ($colspace == 'DeviceGray') { // ct===0
1125
  $trns = [$this->translateValue(substr($t, 0, 2), $bpc)];
1126
- } elseif ($colspace == 'DeviceRGB') { // ct==2
1127
  $trns[0] = $this->translateValue(substr($t, 0, 2), $bpc);
1128
  $trns[1] = $this->translateValue(substr($t, 2, 2), $bpc);
1129
  $trns[2] = $this->translateValue(substr($t, 4, 2), $bpc);
1130
  $trnsrgb = $trns;
1131
- if ($targetcs == 'DeviceCMYK') {
1132
  $col = $this->colorModeConverter->rgb2cmyk([3, $trns[0], $trns[1], $trns[2]]);
1133
- $c1 = intval($col[1] * 2.55);
1134
- $c2 = intval($col[2] * 2.55);
1135
- $c3 = intval($col[3] * 2.55);
1136
- $c4 = intval($col[4] * 2.55);
1137
  $trns = [$c1, $c2, $c3, $c4];
1138
- } elseif ($targetcs == 'DeviceGray') {
1139
- $c = intval(($trns[0] * .21) + ($trns[1] * .71) + ($trns[2] * .07));
1140
  $trns = [$c];
1141
  }
1142
  } else { // Indexed
@@ -1148,15 +1199,15 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1148
  $b = $pal['blue'];
1149
  $trns = [$r, $g, $b]; // ****
1150
  $trnsrgb = $trns;
1151
- if ($targetcs == 'DeviceCMYK') {
1152
  $col = $this->colorModeConverter->rgb2cmyk([3, $r, $g, $b]);
1153
- $c1 = intval($col[1] * 2.55);
1154
- $c2 = intval($col[2] * 2.55);
1155
- $c3 = intval($col[3] * 2.55);
1156
- $c4 = intval($col[4] * 2.55);
1157
  $trns = [$c1, $c2, $c3, $c4];
1158
- } elseif ($targetcs == 'DeviceGray') {
1159
- $c = intval(($r * .21) + ($g * .71) + ($b * .07));
1160
  $trns = [$c];
1161
  }
1162
  }
@@ -1170,23 +1221,23 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1170
  $r = ($rgb >> 16) & 0xFF;
1171
  $g = ($rgb >> 8) & 0xFF;
1172
  $b = $rgb & 0xFF;
1173
- if ($colspace == 'Indexed') {
1174
  $pal = imagecolorsforindex($im, $rgb);
1175
  $r = $pal['red'];
1176
  $g = $pal['green'];
1177
  $b = $pal['blue'];
1178
  }
1179
 
1180
- if ($targetcs == 'DeviceCMYK') {
1181
  $col = $this->colorModeConverter->rgb2cmyk([3, $r, $g, $b]);
1182
- $c1 = intval($col[1] * 2.55);
1183
- $c2 = intval($col[2] * 2.55);
1184
- $c3 = intval($col[3] * 2.55);
1185
- $c4 = intval($col[4] * 2.55);
1186
  if ($trnsrgb) {
1187
  // original pixel was not set as transparent but processed color does match
1188
- if ($trnsrgb != [$r, $g, $b] && $trns == [$c1, $c2, $c3, $c4]) {
1189
- if ($c4 == 0) {
1190
  $c4 = 1;
1191
  } else {
1192
  $c4--;
@@ -1194,12 +1245,12 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1194
  }
1195
  }
1196
  $imgdata .= chr($c1) . chr($c2) . chr($c3) . chr($c4);
1197
- } elseif ($targetcs == 'DeviceGray') {
1198
- $c = intval(($r * .21) + ($g * .71) + ($b * .07));
1199
  if ($trnsrgb) {
1200
  // original pixel was not set as transparent but processed color does match
1201
- if ($trnsrgb != [$r, $g, $b] && $trns == [$c]) {
1202
- if ($c == 0) {
1203
  $c = 1;
1204
  } else {
1205
  $c--;
@@ -1207,17 +1258,17 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1207
  }
1208
  }
1209
  $imgdata .= chr($c);
1210
- } elseif ($targetcs == 'DeviceRGB') {
1211
  $imgdata .= chr($r) . chr($g) . chr($b);
1212
  }
1213
  }
1214
  }
1215
 
1216
- if ($targetcs == 'DeviceGray') {
1217
  $ncols = 1;
1218
- } elseif ($targetcs == 'DeviceRGB') {
1219
  $ncols = 3;
1220
- } elseif ($targetcs == 'DeviceCMYK') {
1221
  $ncols = 4;
1222
  }
1223
 
@@ -1242,6 +1293,7 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1242
  } elseif ($trns) {
1243
  $info['trns'] = $trns;
1244
  }
 
1245
  imagedestroy($im);
1246
  }
1247
  return $info;
@@ -1253,13 +1305,13 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1253
  $p += $this->twoBytesToInt(substr($data, $p, 2)); // Length of initial marker block
1254
  $marker = substr($data, $p, 2);
1255
 
1256
- while ($marker != chr(255) . chr(192) && $marker != chr(255) . chr(194) && $p < strlen($data)) {
1257
  // Start of frame marker (FFC0) or (FFC2) mPDF 4.4.004
1258
- $p += ($this->twoBytesToInt(substr($data, $p + 2, 2))) + 2; // Length of marker block
1259
  $marker = substr($data, $p, 2);
1260
  }
1261
 
1262
- if ($marker != chr(255) . chr(192) && $marker != chr(255) . chr(194)) {
1263
  return false;
1264
  }
1265
  return substr($data, $p + 2, 10);
@@ -1278,9 +1330,9 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
1278
 
1279
  $channels = ord(substr($hdr, 7, 1));
1280
 
1281
- if ($channels == 3) {
1282
  $colspace = 'DeviceRGB';
1283
- } elseif ($channels == 4) {
1284
  $colspace = 'DeviceCMYK';
1285
  } else {
1286
  $colspace = 'DeviceGray';
3
  namespace Mpdf\Image;
4
 
5
  use Mpdf\Cache;
6
+
7
  use Mpdf\Color\ColorConverter;
8
  use Mpdf\Color\ColorModeConverter;
9
+
10
  use Mpdf\CssManager;
11
+
12
  use Mpdf\Gif\Gif;
13
+
14
  use Mpdf\Language\LanguageToFontInterface;
15
  use Mpdf\Language\ScriptToLanguageInterface;
16
+
17
  use Mpdf\Log\Context as LogContext;
18
+
19
  use Mpdf\Mpdf;
20
+
21
  use Mpdf\Otl;
22
+
23
+ use Mpdf\RemoteContentFetcher;
24
+
25
  use Mpdf\SizeConverter;
26
 
27
  use Psr\Log\LoggerInterface;
94
  */
95
  public $scriptToLanguage;
96
 
97
+ /**
98
+ * @var \Mpdf\RemoteContentFetcher
99
+ */
100
+ private $remoteContentFetcher;
101
+
102
  /**
103
  * @var \Psr\Log\LoggerInterface
104
  */
114
  Cache $cache,
115
  LanguageToFontInterface $languageToFont,
116
  ScriptToLanguageInterface $scriptToLanguage,
117
+ RemoteContentFetcher $remoteContentFetcher,
118
  LoggerInterface $logger
119
  ) {
120
 
127
  $this->cache = $cache;
128
  $this->languageToFont = $languageToFont;
129
  $this->scriptToLanguage = $scriptToLanguage;
130
+ $this->remoteContentFetcher = $remoteContentFetcher;
131
 
132
  $this->logger = $logger;
133
 
139
  /**
140
  * @param \Psr\Log\LoggerInterface
141
  *
142
+ * @return self
143
  */
144
  public function setLogger(LoggerInterface $logger)
145
  {
153
  // mPDF 6
154
  // firsttime i.e. whether to add to this->images - use false when calling iteratively
155
  // Image Data passed directly as var:varname
156
+
157
+ $type = null;
158
+ $data = '';
159
+
160
  if (preg_match('/var:\s*(.*)/', $file, $v)) {
161
  if (!isset($this->mpdf->imageVars[$v[1]])) {
162
  return $this->imageError($file, $firsttime, 'Unknown image variable');
172
  }
173
 
174
  // mPDF 5.7.4 URLs
175
+ if ($firsttime && $file && strpos($file, 'data:') !== 0) {
176
+ $file = str_replace(' ', '%20', $file);
177
  }
178
  if ($firsttime && $orig_srcpath) {
179
  // If orig_srcpath is a relative file path (and not a URL), then it needs to be URL decoded
180
+ if (strpos($orig_srcpath, 'data:') !== 0) {
181
+ $orig_srcpath = str_replace(' ', '%20', $orig_srcpath);
182
  }
183
  if (!preg_match('/^(http|ftp)/', $orig_srcpath)) {
184
  $orig_srcpath = $this->urldecodeParts($orig_srcpath);
193
 
194
  if (isset($this->mpdf->images[$file])) {
195
  return $this->mpdf->images[$file];
196
+ }
197
+
198
+ if ($orig_srcpath && isset($this->mpdf->formobjects[$orig_srcpath])) {
199
  $file = $orig_srcpath;
200
  return $this->mpdf->formobjects[$file];
201
+ }
202
+
203
+ if (isset($this->mpdf->formobjects[$file])) {
204
  return $this->mpdf->formobjects[$file];
205
+ }
206
+
207
+ if ($firsttime && isset($this->failedImages[$file])) { // Save re-trying image URL's which have already failed
208
  return $this->imageError($file, $firsttime, '');
209
  }
210
 
211
  if (empty($data)) {
212
 
 
213
  $data = '';
214
 
215
+ if ($orig_srcpath && $this->mpdf->basepathIsLocal && $check = @fopen($orig_srcpath, 'rb')) {
216
  fclose($check);
217
  $file = $orig_srcpath;
218
  $this->logger->debug(sprintf('Fetching (file_get_contents) content of file "%s" with local basepath', $file), ['context' => LogContext::REMOTE_CONTENT]);
220
  $type = $this->guesser->guess($data);
221
  }
222
 
223
+ if (!$data && $check = @fopen($file, 'rb')) {
224
  fclose($check);
225
  $this->logger->debug(sprintf('Fetching (file_get_contents) content of file "%s" with non-local basepath', $file), ['context' => LogContext::REMOTE_CONTENT]);
226
  $data = file_get_contents($file);
228
  }
229
 
230
  if ((!$data || !$type) && function_exists('curl_init')) { // mPDF 5.7.4
231
+ $data = $this->remoteContentFetcher->getFileContentsByCurl($file); // needs full url?? even on local (never needed for local)
232
  if ($data) {
233
  $type = $this->guesser->guess($data);
234
  }
235
  }
236
 
237
  if ((!$data || !$type) && !ini_get('allow_url_fopen')) { // only worth trying if remote file and !ini_get('allow_url_fopen')
238
+ $data = $this->remoteContentFetcher->getFileContentsBySocket($file); // needs full url?? even on local (never needed for local)
239
  if ($data) {
240
  $type = $this->guesser->guess($data);
241
  }
246
  return $this->imageError($file, $firsttime, 'Could not find image file');
247
  }
248
 
249
+ if ($type === null) {
250
  $type = $this->guesser->guess($data);
251
  }
252
 
253
+ if (($type === 'wmf' || $type === 'svg') && !$allowvector) {
254
  return $this->imageError($file, $firsttime, 'WMF or SVG image file not supported in this context');
255
  }
256
 
257
  // SVG
258
+ if ($type === 'svg') {
259
  $svg = new Svg($this->mpdf, $this->otl, $this->cssManager, $this, $this->sizeConverter, $this->colorConverter, $this->languageToFont, $this->scriptToLanguage);
260
  $family = $this->mpdf->FontFamily;
261
  $style = $this->mpdf->FontStyle;
276
  }
277
 
278
  // JPEG
279
+ if ($type === 'jpeg' || $type === 'jpg') {
280
+
281
  $hdr = $this->jpgHeaderFromString($data);
282
  if (!$hdr) {
283
  return $this->imageError($file, $firsttime, 'Error parsing JPG header');
284
  }
285
+
286
  $a = $this->jpgDataFromHeader($hdr);
287
+ $channels = (int) $a[4];
288
  $j = strpos($data, 'JFIF');
289
+
290
  if ($j) {
291
+ // Read resolution
292
+ $unitSp = ord(substr($data, $j + 7, 1));
293
  if ($unitSp > 0) {
294
+ $ppUx = $this->twoBytesToInt(substr($data, $j + 8, 2)); // horizontal pixels per meter, usually set to zero
295
+ if ($unitSp === 2) { // = dots per cm (if == 1 set as dpi)
296
  $ppUx = round($ppUx / 10 * 25.4);
297
  }
298
  }
299
  }
300
+
301
+ if ($a[2] === 'DeviceCMYK' && ($this->mpdf->restrictColorSpace === 2 || ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace !== 3))) {
302
 
303
  // convert to RGB image
304
+ if (!function_exists('gd_info')) {
305
+ throw new \Mpdf\MpdfException(sprintf('JPG image may not use CMYK color space (%s).', $file));
306
  }
307
 
308
  if ($this->mpdf->PDFA && !$this->mpdf->PDFAauto) {
309
+ $this->mpdf->PDFAXwarnings[] = sprintf('JPG image may not use CMYK color space - %s - (Image converted to RGB. NB This will alter the colour profile of the image.)', $file);
310
  }
311
 
312
  $im = @imagecreatefromstring($data);
313
+
314
  if ($im) {
315
  $tempfile = $this->cache->tempFilename('_tempImgPNG' . md5($file) . random_int(1, 10000) . '.png');
316
  imageinterlace($im, false);
331
  $this->mpdf->images[$file] = $info;
332
  }
333
  return $info;
 
 
334
  }
335
 
336
+ return $this->imageError($file, $firsttime, 'Error creating GD image file from JPG(CMYK) image');
337
+
338
+ }
339
+
340
+ if ($a[2] === 'DeviceRGB' && ($this->mpdf->PDFX || $this->mpdf->restrictColorSpace === 3)) {
341
  // Convert to CMYK image stream - nominally returned as type='png'
342
+ $info = $this->convertImage($data, $a[2], 'DeviceCMYK', $a[0], $a[1], $ppUx, false);
343
  if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
344
+ $this->mpdf->PDFAXwarnings[] = sprintf('JPG image may not use RGB color space - %s - (Image converted to CMYK. NB This will alter the colour profile of the image.)', $file);
345
  }
346
 
347
+ } elseif (($a[2] === 'DeviceRGB' || $a[2] === 'DeviceCMYK') && $this->mpdf->restrictColorSpace === 1) {
348
  // Convert to Grayscale image stream - nominally returned as type='png'
349
+ $info = $this->convertImage($data, $a[2], 'DeviceGray', $a[0], $a[1], $ppUx, false);
350
 
351
  } else {
352
  // mPDF 6 Detect Adobe APP14 Tag
358
  $icc = [];
359
  while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) {
360
  // get ICC sequence length
361
+ $length = $this->twoBytesToInt(substr($data, $pos - 2, 2)) - 16;
362
+ $sn = max(1, ord($data[$pos + 12]));
363
+ $nom = max(1, ord($data[$pos + 13]));
364
+ $icc[$sn - 1] = substr($data, $pos + 14, $length);
365
  $offset = ($pos + 14 + $length);
366
  }
367
  // order and compact ICC segments
368
  if (count($icc) > 0) {
369
  ksort($icc);
370
  $icc = implode('', $icc);
371
+ if (substr($icc, 36, 4) !== 'acsp') {
372
  // invalid ICC profile
373
  $icc = false;
374
  }
375
  $input = substr($icc, 16, 4);
376
  $output = substr($icc, 20, 4);
377
  // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
378
+ if ($input !== 'RGB ' || $output !== 'XYZ ') {
379
  $icc = false;
380
  }
381
  } else {
399
  }
400
 
401
  return $info;
402
+
403
+ }
404
+
405
+ if ($type === 'png') {
406
 
407
  // Check signature
408
+ if (strpos($data, chr(137) . 'PNG' . chr(13) . chr(10) . chr(26) . chr(10)) !== 0) {
409
  return $this->imageError($file, $firsttime, 'Error parsing PNG identifier');
410
  }
411
 
412
  // Read header chunk
413
+ if (substr($data, 12, 4) !== 'IHDR') {
414
  return $this->imageError($file, $firsttime, 'Incorrect PNG file (no IHDR block found)');
415
  }
416
 
422
  $channels = 0;
423
 
424
  // if($bpc>8) { $errpng = 'not 8-bit depth'; } // mPDF 6 Allow through to be handled as native PNG
 
425
  $ct = ord(substr($data, 25, 1));
426
+
427
+ if ($ct === 0) {
428
  $colspace = 'DeviceGray';
429
  $channels = 1;
430
+ } elseif ($ct === 2) {
431
  $colspace = 'DeviceRGB';
432
  $channels = 3;
433
+ } elseif ($ct === 3) {
434
  $colspace = 'Indexed';
435
  $channels = 1;
436
+ } elseif ($ct === 4) {
437
  $colspace = 'DeviceGray';
438
  $channels = 1;
439
  $errpng = 'alpha channel';
450
  $pngalpha = true;
451
  } // mPDF 6
452
 
453
+ if ($ct === 3 && strpos($data, 'iCCP') !== false) {
454
  $errpng = 'indexed plus ICC';
455
  } // mPDF 6
456
+
457
  // $pngalpha is used as a FLAG of any kind of transparency which COULD be tranferred to an alpha channel
458
  // incl. single-color tarnsparency, depending which type of handling occurs later
459
+ if (ord(substr($data, 26, 1)) !== 0) {
 
460
  $errpng = 'compression method';
461
  } // only 0 should be specified
462
+
463
+ if (ord(substr($data, 27, 1)) !== 0) {
464
  $errpng = 'filter method';
465
+ } // only 0 should be specified
466
+
467
+ if (ord(substr($data, 28, 1)) !== 0) {
468
  $errpng = 'interlaced file';
469
  }
470
 
471
  $j = strpos($data, 'pHYs');
472
  if ($j) {
473
  //Read resolution
474
+ $unitSp = ord(substr($data, $j + 12, 1));
475
+ if ($unitSp === 1) {
476
+ $ppUx = $this->fourBytesToInt(substr($data, $j + 4, 4)); // horizontal pixels per meter, usually set to zero
477
  $ppUx = round($ppUx / 1000 * 25.4);
478
  }
479
  }
483
  $gAMA = 0;
484
  $j = strpos($data, 'gAMA');
485
  if ($j && strpos($data, 'sRGB') === false) { // sRGB colorspace - overrides gAMA
486
+ $gAMA = $this->fourBytesToInt(substr($data, $j + 4, 4)); // Gamma value times 100000
487
  $gAMA /= 100000;
488
 
489
  // http://www.libpng.org/pub/png/spec/1.2/PNG-Encoders.html
513
  //$j = strpos($data,'cHRM'); // Chromaticity and Whitepoint
514
  // $firsttime added mPDF 6 so when PNG Grayscale with alpha using resrtictcolorspace to CMYK
515
  // the alpha channel is sent through as secondtime as Indexed and should not be converted to CMYK
516
+ if ($firsttime && ($colspace === 'DeviceRGB' || $colspace === 'Indexed') && ($this->mpdf->PDFX || $this->mpdf->restrictColorSpace === 3)) {
517
+
518
  // Convert to CMYK image stream - nominally returned as type='png'
519
+ $info = $this->convertImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
520
  if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
521
+ $this->mpdf->PDFAXwarnings[] = sprintf('PNG image may not use RGB color space - %s - (Image converted to CMYK. NB This will alter the colour profile of the image.)', $file);
522
  }
523
+
524
+ } elseif ($firsttime && ($colspace === 'DeviceRGB' || $colspace === 'Indexed') && $this->mpdf->restrictColorSpace === 1) {
525
+
526
+ // $firsttime added mPDF 6 so when PNG Grayscale with alpha using resrtictcolorspace to CMYK
527
+ // the alpha channel is sent through as secondtime as Indexed and should not be converted to CMYK
528
  // Convert to Grayscale image stream - nominally returned as type='png'
529
+ $info = $this->convertImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
530
+
531
  } elseif (($this->mpdf->PDFA || $this->mpdf->PDFX) && $pngalpha) {
532
+
533
  // Remove alpha channel
534
+ if ($this->mpdf->restrictColorSpace === 1) { // Grayscale
535
+ $info = $this->convertImage($data, $colspace, 'DeviceGray', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
536
+ } elseif ($this->mpdf->restrictColorSpace === 3) { // CMYK
537
+ $info = $this->convertImage($data, $colspace, 'DeviceCMYK', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
538
  } elseif ($this->mpdf->PDFA) { // RGB
539
+ $info = $this->convertImage($data, $colspace, 'DeviceRGB', $w, $h, $ppUx, $pngalpha, $gamma, $ct); // mPDF 5.7.2 Gamma correction
540
  }
541
  if (($this->mpdf->PDFA && !$this->mpdf->PDFAauto) || ($this->mpdf->PDFX && !$this->mpdf->PDFXauto)) {
542
+ $this->mpdf->PDFAXwarnings[] = sprintf('Transparency (alpha channel) not permitted in PDFA or PDFX files - %s - (Image converted to one without transparency.)', $file);
543
  }
544
+
545
  } elseif ($firsttime && ($errpng || $pngalpha || $gamma)) { // mPDF 5.7.2 Gamma correction
546
+
547
+ $gd = function_exists('gd_info') ? gd_info() : [];
 
 
 
548
  if (!isset($gd['PNG Support'])) {
549
+ return $this->imageError($file, $firsttime, sprintf('GD library with PNG support required for image (%s)', $errpng));
550
  }
 
551
 
552
+ $im = imagecreatefromstring($data);
553
  if (!$im) {
554
+ return $this->imageError($file, $firsttime, sprintf('Error creating GD image from PNG file (%s)', $errpng));
555
  }
556
+
557
  $w = imagesx($im);
558
  $h = imagesy($im);
 
 
559
 
560
+ $tempfile = $this->cache->tempFilename('_tempImgPNG' . md5($file) . random_int(1, 10000) . '.png');
 
 
 
 
561
 
562
+ // Alpha channel set (including using tRNS for Paletted images)
563
+ if ($pngalpha) {
564
+ if ($this->mpdf->PDFA) {
565
+ throw new \Mpdf\MpdfException(sprintf('PDFA1-b does not permit images with alpha channel transparency (%s).', $file));
566
+ }
567
 
568
+ $imgalpha = imagecreate($w, $h);
569
+ // generate gray scale pallete
570
+ for ($c = 0; $c < 256; ++$c) {
571
+ imagecolorallocate($imgalpha, $c, $c, $c);
572
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
 
574
+ // mPDF 6
575
+ if ($colspace === 'Indexed') { // generate Alpha channel values from tRNS
576
+ // Read transparency info
577
+ $p = strpos($data, 'tRNS');
578
+ if ($p) {
579
+ $n = $this->fourBytesToInt(substr($data, $p - 4, 4));
580
+ $transparency = substr($data, $p + 4, $n);
581
+ // ord($transparency{$index}) = the alpha value for that index
582
+ // generate alpha channel
583
+ for ($ypx = 0; $ypx < $h; ++$ypx) {
584
+ for ($xpx = 0; $xpx < $w; ++$xpx) {
585
+ $colorindex = imagecolorat($im, $xpx, $ypx);
586
+ if ($colorindex >= $n) {
587
+ $alpha = 255;
588
+ } else {
589
+ $alpha = ord($transparency{$colorindex});
590
+ } // 0-255
591
+ if ($alpha > 0) {
592
+ imagesetpixel($imgalpha, $xpx, $ypx, $alpha);
593
  }
594
  }
595
  }
596
+ }
597
+ } elseif ($ct === 0 || $ct === 2) { // generate Alpha channel values from tRNS
598
+ // Get transparency as array of RGB
599
+ $p = strpos($data, 'tRNS');
600
+ if ($p) {
601
+ $trns = '';
602
+ $n = $this->fourBytesToInt(substr($data, $p - 4, 4));
603
+ $t = substr($data, $p + 4, $n);
604
+ if ($colspace === 'DeviceGray') { // ct===0
605
+ $trns = [$this->translateValue(substr($t, 0, 2), $bpc)];
606
+ } else /* $colspace=='DeviceRGB' */ { // ct==2
607
+ $trns = [];
608
+ $trns[0] = $this->translateValue(substr($t, 0, 2), $bpc);
609
+ $trns[1] = $this->translateValue(substr($t, 2, 2), $bpc);
610
+ $trns[2] = $this->translateValue(substr($t, 4, 2), $bpc);
611
+ }
612
+
613
+ // generate alpha channel
614
  for ($ypx = 0; $ypx < $h; ++$ypx) {
615
  for ($xpx = 0; $xpx < $w; ++$xpx) {
616
+ $rgb = imagecolorat($im, $xpx, $ypx);
617
+ $r = ($rgb >> 16) & 0xFF;
618
+ $g = ($rgb >> 8) & 0xFF;
619
+ $b = $rgb & 0xFF;
620
+ if ($colspace === 'DeviceGray' && $b == $trns[0]) {
621
+ $alpha = 0;
622
+ } elseif ($r == $trns[0] && $g == $trns[1] && $b == $trns[2]) {
623
+ $alpha = 0;
624
+ } else { // ct==2
625
+ $alpha = 255;
626
+ }
627
+ if ($alpha > 0) {
628
+ imagesetpixel($imgalpha, $xpx, $ypx, $alpha);
629
  }
630
  }
631
  }
632
  }
633
+ } else {
634
+ // extract alpha channel
635
+ for ($ypx = 0; $ypx < $h; ++$ypx) {
636
+ for ($xpx = 0; $xpx < $w; ++$xpx) {
637
+ $alpha = (imagecolorat($im, $xpx, $ypx) & 0x7F000000) >> 24;
638
+ if ($alpha < 127) {
639
+ imagesetpixel($imgalpha, $xpx, $ypx, 255 - ($alpha * 2));
640
+ }
641
+ }
642
  }
643
+ }
644
 
645
+ // NB This must happen after the Alpha channel is extracted
646
+ // imagegammacorrect() removes the alpha channel data in $im - (I think this is a bug in PHP)
647
+ if ($gamma) {
648
+ imagegammacorrect($im, $gamma, 2.2);
649
+ }
650
 
651
+ $tempfile_alpha = $this->cache->tempFilename('_tempMskPNG' . md5($file) . random_int(1, 10000) . '.png');
652
 
653
+ $check = @imagepng($imgalpha, $tempfile_alpha);
 
 
654
 
655
+ if (!$check) {
656
+ return $this->imageError($file, $firsttime, 'Failed to create temporary image file (' . $tempfile_alpha . ') parsing PNG image with alpha channel (' . $errpng . ')');
657
+ }
 
 
658
 
659
+ imagedestroy($imgalpha);
660
+ // extract image without alpha channel
661
+ $imgplain = imagecreatetruecolor($w, $h);
662
+ imagealphablending($imgplain, false); // mPDF 5.7.2
663
+ imagecopy($imgplain, $im, 0, 0, 0, 0, $w, $h);
 
 
 
 
664
 
665
+ // create temp image file
666
+ $check = @imagepng($imgplain, $tempfile);
667
+ if (!$check) {
668
+ return $this->imageError($file, $firsttime, 'Failed to create temporary image file (' . $tempfile . ') parsing PNG image with alpha channel (' . $errpng . ')');
669
+ }
670
+ imagedestroy($imgplain);
671
+ // embed mask image
672
+ $minfo = $this->getImage($tempfile_alpha, false);
673
+ unlink($tempfile_alpha);
674
 
675
+ if (!$minfo) {
676
+ return $this->imageError($file, $firsttime, 'Error parsing temporary file (' . $tempfile_alpha . ') created with GD library to parse PNG image');
677
+ }
 
 
 
 
678
 
679
+ $imgmask = count($this->mpdf->images) + 1;
680
+ $minfo['cs'] = 'DeviceGray';
681
+ $minfo['i'] = $imgmask;
682
+ $this->mpdf->images[$tempfile_alpha] = $minfo;
683
+ // embed image, masked with previously embedded mask
684
+ $info = $this->getImage($tempfile, false);
685
+ unlink($tempfile);
686
 
687
+ if (!$info) {
688
+ return $this->imageError($file, $firsttime, 'Error parsing temporary file (' . $tempfile . ') created with GD library to parse PNG image');
689
+ }
 
 
 
 
 
 
 
690
 
691
+ $info['masked'] = $imgmask;
692
+ if ($ppUx) {
693
+ $info['set-dpi'] = $ppUx;
694
+ }
695
+ $info['type'] = 'png';
696
+ if ($firsttime) {
697
+ $info['i'] = count($this->mpdf->images) + 1;
698
+ $info['interpolation'] = $interpolation; // mPDF 6
699
+ $this->mpdf->images[$file] = $info;
700
+ }
701
+
702
+ return $info;
703
+ }
704
+
705
+ // No alpha/transparency set (but cannot read directly because e.g. bit-depth != 8, interlaced etc)
706
+ // ICC profile
707
+ $icc = false;
708
+ $p = strpos($data, 'iCCP');
709
+ if ($p && $colspace === "Indexed") { // Cannot have ICC profile and Indexed together
710
+ $p += 4;
711
+ $n = $this->fourBytesToInt(substr($data, ($p - 8), 4));
712
+ $nullsep = strpos(substr($data, $p, 80), chr(0));
713
+ $icc = substr($data, ($p + $nullsep + 2), ($n - ($nullsep + 2)));
714
+ $icc = @gzuncompress($icc); // Ignored if fails
715
+ if ($icc) {
716
+ if (substr($icc, 36, 4) !== 'acsp') {
717
+ $icc = false;
718
+ } // invalid ICC profile
719
+ else {
720
+ $input = substr($icc, 16, 4);
721
+ $output = substr($icc, 20, 4);
722
+ // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
723
+ if ($input !== 'RGB ' || $output !== 'XYZ ') {
724
+ $icc = false;
725
  }
726
  }
727
+ }
728
+ // Convert to RGB colorspace so can use ICC Profile
729
+ if ($icc) {
730
+ imagepalettetotruecolor($im);
731
+ $colspace = 'DeviceRGB';
732
+ $channels = 3;
733
+ }
734
+ }
735
 
736
+ if ($gamma) {
737
+ imagegammacorrect($im, $gamma, 2.2);
738
+ }
739
 
740
+ imagealphablending($im, false);
741
+ imagesavealpha($im, false);
742
+ imageinterlace($im, false);
743
 
744
+ $check = @imagepng($im, $tempfile);
745
+ if (!$check) {
746
+ return $this->imageError($file, $firsttime, 'Failed to create temporary image file (' . $tempfile . ') parsing PNG image (' . $errpng . ')');
747
+ }
748
+ imagedestroy($im);
749
+ $info = $this->getImage($tempfile, false);
750
+ unlink($tempfile);
751
+ if (!$info) {
752
+ return $this->imageError($file, $firsttime, 'Error parsing temporary file (' . $tempfile . ') created with GD library to parse PNG image');
753
+ }
754
 
755
+ if ($ppUx) {
756
+ $info['set-dpi'] = $ppUx;
757
+ }
758
+ $info['type'] = 'png';
759
+ if ($firsttime) {
760
+ $info['i'] = count($this->mpdf->images) + 1;
761
+ $info['interpolation'] = $interpolation; // mPDF 6
762
+ if ($icc) {
763
+ $info['ch'] = $channels;
764
+ $info['icc'] = $icc;
 
 
 
 
765
  }
766
+ $this->mpdf->images[$file] = $info;
767
  }
768
+
769
+ return $info;
770
+
771
  } else { // PNG image with no need to convert alph channels, bpc <> 8 etc.
772
+
773
  $parms = '/DecodeParms <</Predictor 15 /Colors ' . $channels . ' /BitsPerComponent ' . $bpc . ' /Columns ' . $w . '>>';
774
  //Scan chunks looking for palette, transparency and image data
775
  $pal = '';
777
  $pngdata = '';
778
  $icc = false;
779
  $p = 33;
780
+
781
  do {
782
  $n = $this->fourBytesToInt(substr($data, $p, 4));
783
  $p += 4;
784
  $type = substr($data, $p, 4);
785
  $p += 4;
786
+ if ($type === 'PLTE') {
787
  //Read palette
788
  $pal = substr($data, $p, $n);
789
  $p += $n;
790
  $p += 4;
791
+ } elseif ($type === 'tRNS') {
792
  //Read transparency info
793
  $t = substr($data, $p, $n);
794
  $p += $n;
795
+ if ($ct === 0) {
796
  $trns = [ord(substr($t, 1, 1))];
797
+ } elseif ($ct === 2) {
798
  $trns = [ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1))];
799
  } else {
800
  $pos = strpos($t, chr(0));
803
  }
804
  }
805
  $p += 4;
806
+ } elseif ($type === 'IDAT') {
807
  $pngdata.=substr($data, $p, $n);
808
  $p += $n;
809
  $p += 4;
810
+ } elseif ($type === 'iCCP') {
811
  $nullsep = strpos(substr($data, $p, 80), chr(0));
812
+ $icc = substr($data, $p + $nullsep + 2, $n - ($nullsep + 2));
813
  $icc = @gzuncompress($icc); // Ignored if fails
814
  if ($icc) {
815
+ if (substr($icc, 36, 4) !== 'acsp') {
816
  $icc = false;
817
  } // invalid ICC profile
818
  else {
819
  $input = substr($icc, 16, 4);
820
  $output = substr($icc, 20, 4);
821
  // Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
822
+ if ($input !== 'RGB ' || $output !== 'XYZ ') {
823
  $icc = false;
824
  }
825
  }
826
  }
827
  $p += $n;
828
  $p += 4;
829
+ } elseif ($type === 'IEND') {
830
  break;
831
  } elseif (preg_match('/[a-zA-Z]{4}/', $type)) {
832
  $p += $n + 4;
837
  if (!$pngdata) {
838
  return $this->imageError($file, $firsttime, 'Error parsing PNG image data - no IDAT data found');
839
  }
840
+ if ($colspace === 'Indexed' && empty($pal)) {
841
  return $this->imageError($file, $firsttime, 'Error parsing PNG image data - missing colour palette');
842
  }
843
 
844
+ if ($colspace === 'Indexed' && $icc) {
845
  $icc = false;
846
  } // mPDF 6 cannot have ICC profile and Indexed in a PDF document as both use the colorspace tag.
847
 
864
 
865
  return $info;
866
 
867
+ } elseif ($type === 'gif') { // GIF
868
 
869
  if (function_exists('gd_info')) {
870
  $gd = gd_info();
913
  $this->mpdf->images[$file] = $info;
914
  }
915
  return $info;
 
 
916
  }
917
+
918
+ return $this->imageError($file, $firsttime, 'Error creating GD image file from GIF image');
919
  }
920
 
921
  $gif = new Gif();
922
 
923
  $h = 0;
924
  $w = 0;
925
+
926
  $gif->loadFile($data, 0);
927
 
928
+ $nColors = 0;
929
+ $bgColor = -1;
930
+ $colspace = 'DeviceGray';
931
+ $pal = '';
932
+
933
  if (isset($gif->m_img->m_gih->m_bLocalClr) && $gif->m_img->m_gih->m_bLocalClr) {
934
  $nColors = $gif->m_img->m_gih->m_nTableSize;
935
  $pal = $gif->m_img->m_gih->m_colorTable->toString();
936
+ if ((isset($bgColor)) && $bgColor !== -1) { // mPDF 5.7.3
937
  $bgColor = $gif->m_img->m_gih->m_colorTable->colorIndex($bgColor);
938
  }
939
  $colspace = 'Indexed';
940
  } elseif (isset($gif->m_gfh->m_bGlobalClr) && $gif->m_gfh->m_bGlobalClr) {
941
  $nColors = $gif->m_gfh->m_nTableSize;
942
  $pal = $gif->m_gfh->m_colorTable->toString();
943
+ if ((isset($bgColor)) && $bgColor != -1) {
944
  $bgColor = $gif->m_gfh->m_colorTable->colorIndex($bgColor);
945
  }
946
  $colspace = 'Indexed';
 
 
 
 
 
947
  }
948
 
949
  $trns = '';
950
+
951
  if (isset($gif->m_img->m_bTrans) && $gif->m_img->m_bTrans && ($nColors > 0)) {
952
  $trns = [$gif->m_img->m_nTrans];
953
  }
954
+
955
  $gifdata = $gif->m_img->m_data;
956
  $w = $gif->m_gfh->m_nWidth;
957
  $h = $gif->m_gfh->m_nHeight;
958
  $gif->ClearData();
959
 
960
+ if ($colspace === 'Indexed' && empty($pal)) {
961
  return $this->imageError($file, $firsttime, 'Error parsing GIF image - missing colour palette');
962
  }
963
 
977
 
978
  return $info;
979
 
980
+ } elseif ($type === 'bmp') {
981
 
982
+ if ($this->bmp === null) {
983
  $this->bmp = new Bmp($this->mpdf);
984
  }
985
+
986
  $info = $this->bmp->_getBMPimage($data, $file);
987
  if (isset($info['error'])) {
988
  return $this->imageError($file, $firsttime, $info['error']);
989
  }
990
+
991
  if ($firsttime) {
992
  $info['i'] = count($this->mpdf->images) + 1;
993
  $info['interpolation'] = $interpolation; // mPDF 6
994
  $this->mpdf->images[$file] = $info;
995
  }
996
+
997
  return $info;
998
 
999
+ } elseif ($type === 'wmf') {
1000
 
1001
+ if ($this->wmf === null) {
1002
  $this->wmf = new Wmf($this->mpdf, $this->colorConverter);
1003
  }
1004
 
1069
  return $this->imageError($file, $firsttime, 'Error parsing image file - image type not recognised');
1070
  }
1071
 
1072
+ private function convertImage(&$data, $colspace, $targetcs, $w, $h, $dpi, $mask, $gamma_correction = false, $pngcolortype = false)
1073
  {
1074
  if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
1075
  $mask = false;
1088
  // Need to extract alpha channel info before imagegammacorrect (which loses the data)
1089
  if ($mask) { // i.e. $pngalpha for PNG
1090
  // mPDF 6
1091
+ if ($colspace === 'Indexed') { // generate Alpha channel values from tRNS - only from PNG
1092
  //Read transparency info
1093
  $transparency = '';
1094
  $p = strpos($data, 'tRNS');
1095
  if ($p) {
1096
+ $n = $this->fourBytesToInt(substr($data, $p - 4, 4));
1097
+ $transparency = substr($data, $p + 4, $n);
1098
  // ord($transparency{$index}) = the alpha value for that index
1099
  // generate alpha channel
1100
  for ($ypx = 0; $ypx < $h; ++$ypx) {
1109
  }
1110
  }
1111
  }
1112
+ } elseif ($pngcolortype === 0 || $pngcolortype === 2) { // generate Alpha channel values from tRNS
1113
  // Get transparency as array of RGB
1114
  $p = strpos($data, 'tRNS');
1115
  if ($p) {
1116
  $trns = '';
1117
+ $n = $this->fourBytesToInt(substr($data, $p - 4, 4));
1118
+ $t = substr($data, $p + 4, $n);
1119
+ if ($colspace === 'DeviceGray') { // ct===0
1120
  $trns = [$this->translateValue(substr($t, 0, 2), $bpc)];
1121
  } else /* $colspace=='DeviceRGB' */ { // ct==2
1122
  $trns = [];
1132
  $r = ($rgb >> 16) & 0xFF;
1133
  $g = ($rgb >> 8) & 0xFF;
1134
  $b = $rgb & 0xFF;
1135
+ if ($colspace === 'DeviceGray' && $b == $trns[0]) {
1136
  $alpha = 0;
1137
  } elseif ($r == $trns[0] && $g == $trns[1] && $b == $trns[2]) {
1138
  $alpha = 0;
1171
  $p = strpos($data, 'tRNS');
1172
  if ($p) {
1173
  $n = $this->fourBytesToInt(substr($data, ($p - 4), 4));
1174
+ $t = substr($data, $p + 4, $n);
1175
+ if ($colspace === 'DeviceGray') { // ct===0
1176
  $trns = [$this->translateValue(substr($t, 0, 2), $bpc)];
1177
+ } elseif ($colspace === 'DeviceRGB') { // ct==2
1178
  $trns[0] = $this->translateValue(substr($t, 0, 2), $bpc);
1179
  $trns[1] = $this->translateValue(substr($t, 2, 2), $bpc);
1180
  $trns[2] = $this->translateValue(substr($t, 4, 2), $bpc);
1181
  $trnsrgb = $trns;
1182
+ if ($targetcs === 'DeviceCMYK') {
1183
  $col = $this->colorModeConverter->rgb2cmyk([3, $trns[0], $trns[1], $trns[2]]);
1184
+ $c1 = (int) ($col[1] * 2.55);
1185
+ $c2 = (int) ($col[2] * 2.55);
1186
+ $c3 = (int) ($col[3] * 2.55);
1187
+ $c4 = (int) ($col[4] * 2.55);
1188
  $trns = [$c1, $c2, $c3, $c4];
1189
+ } elseif ($targetcs === 'DeviceGray') {
1190
+ $c = (int) (($trns[0] * .21) + ($trns[1] * .71) + ($trns[2] * .07));
1191
  $trns = [$c];
1192
  }
1193
  } else { // Indexed
1199
  $b = $pal['blue'];
1200
  $trns = [$r, $g, $b]; // ****
1201
  $trnsrgb = $trns;
1202
+ if ($targetcs === 'DeviceCMYK') {
1203
  $col = $this->colorModeConverter->rgb2cmyk([3, $r, $g, $b]);
1204
+ $c1 = (int) ($col[1] * 2.55);
1205
+ $c2 = (int) ($col[2] * 2.55);
1206
+ $c3 = (int) ($col[3] * 2.55);
1207
+ $c4 = (int) ($col[4] * 2.55);
1208
  $trns = [$c1, $c2, $c3, $c4];
1209
+ } elseif ($targetcs === 'DeviceGray') {
1210
+ $c = (int) (($r * .21) + ($g * .71) + ($b * .07));
1211
  $trns = [$c];
1212
  }
1213
  }
1221
  $r = ($rgb >> 16) & 0xFF;
1222
  $g = ($rgb >> 8) & 0xFF;
1223
  $b = $rgb & 0xFF;
1224
+ if ($colspace === 'Indexed') {
1225
  $pal = imagecolorsforindex($im, $rgb);
1226
  $r = $pal['red'];
1227
  $g = $pal['green'];
1228
  $b = $pal['blue'];
1229
  }
1230
 
1231
+ if ($targetcs === 'DeviceCMYK') {
1232
  $col = $this->colorModeConverter->rgb2cmyk([3, $r, $g, $b]);
1233
+ $c1 = (int) ($col[1] * 2.55);
1234
+ $c2 = (int) ($col[2] * 2.55);
1235
+ $c3 = (int) ($col[3] * 2.55);
1236
+ $c4 = (int) ($col[4] * 2.55);
1237
  if ($trnsrgb) {
1238
  // original pixel was not set as transparent but processed color does match
1239
+ if ($trnsrgb !== [$r, $g, $b] && $trns === [$c1, $c2, $c3, $c4]) {
1240
+ if ($c4 === 0) {
1241
  $c4 = 1;
1242
  } else {
1243
  $c4--;
1245
  }
1246
  }
1247
  $imgdata .= chr($c1) . chr($c2) . chr($c3) . chr($c4);
1248
+ } elseif ($targetcs === 'DeviceGray') {
1249
+ $c = (int) (($r * .21) + ($g * .71) + ($b * .07));
1250
  if ($trnsrgb) {
1251
  // original pixel was not set as transparent but processed color does match
1252
+ if ($trnsrgb !== [$r, $g, $b] && $trns === [$c]) {
1253
+ if ($c === 0) {
1254
  $c = 1;
1255
  } else {
1256
  $c--;
1258
  }
1259
  }
1260
  $imgdata .= chr($c);
1261
+ } elseif ($targetcs === 'DeviceRGB') {
1262
  $imgdata .= chr($r) . chr($g) . chr($b);
1263
  }
1264
  }
1265
  }
1266
 
1267
+ if ($targetcs === 'DeviceGray') {
1268
  $ncols = 1;
1269
+ } elseif ($targetcs === 'DeviceRGB') {
1270
  $ncols = 3;
1271
+ } elseif ($targetcs === 'DeviceCMYK') {
1272
  $ncols = 4;
1273
  }
1274
 
1293
  } elseif ($trns) {
1294
  $info['trns'] = $trns;
1295
  }
1296
+
1297
  imagedestroy($im);
1298
  }
1299
  return $info;
1305
  $p += $this->twoBytesToInt(substr($data, $p, 2)); // Length of initial marker block
1306
  $marker = substr($data, $p, 2);
1307
 
1308
+ while ($marker !== chr(255) . chr(192) && $marker !== chr(255) . chr(194) && $p < strlen($data)) {
1309
  // Start of frame marker (FFC0) or (FFC2) mPDF 4.4.004
1310
+ $p += $this->twoBytesToInt(substr($data, $p + 2, 2)) + 2; // Length of marker block
1311
  $marker = substr($data, $p, 2);
1312
  }
1313
 
1314
+ if ($marker !== chr(255) . chr(192) && $marker !== chr(255) . chr(194)) {
1315
  return false;
1316
  }
1317
  return substr($data, $p + 2, 10);
1330
 
1331
  $channels = ord(substr($hdr, 7, 1));
1332
 
1333
+ if ($channels === 3) {
1334
  $colspace = 'DeviceRGB';
1335
+ } elseif ($channels === 4) {
1336
  $colspace = 'DeviceCMYK';
1337
  } else {
1338
  $colspace = 'DeviceGray';
vendor/mpdf/mpdf/src/Image/ImageTypeGuesser.php CHANGED
@@ -5,6 +5,11 @@ namespace Mpdf\Image;
5
  class ImageTypeGuesser
6
  {
7
 
 
 
 
 
 
8
  public function guess($data)
9
  {
10
  if (in_array(substr($data, 6, 4), ['JFIF', 'Exif'], true) || strpos($data, chr(255) . chr(216)) === 0) { // 0xFF 0xD8 // mpDF 5.7.2
5
  class ImageTypeGuesser
6
  {
7
 
8
+ /**
9
+ * @param string $data
10
+ *
11
+ * @return null|string
12
+ */
13
  public function guess($data)
14
  {
15
  if (in_array(substr($data, 6, 4), ['JFIF', 'Exif'], true) || strpos($data, chr(255) . chr(216)) === 0) { // 0xFF 0xD8 // mpDF 5.7.2
vendor/mpdf/mpdf/src/Image/Svg.php CHANGED
@@ -1557,7 +1557,10 @@ class Svg
1557
 
1558
  $start = [$this->xbase, -$this->ybase];
1559
 
1560
- preg_match_all('/[\-^]?[\d.]+(e[\-]?[\d]+){0,1}/i', $arguments, $a, PREG_SET_ORDER);
 
 
 
1561
 
1562
  // if the command is a capital letter, the coords go absolute, otherwise relative
1563
  if (strtolower($command) == $command) {
@@ -1574,8 +1577,8 @@ class Svg
1574
  switch (strtolower($command)) {
1575
  case 'm': // move
1576
  for ($i = 0; $i < $ile_argumentow; $i+=2) {
1577
- $x = $a[$i][0];
1578
- $y = $a[$i + 1][0];
1579
  if ($relative) {
1580
  $pdfx = ($this->xbase + $x);
1581
  $pdfy = ($this->ybase - $y);
@@ -1607,8 +1610,8 @@ class Svg
1607
  break;
1608
  case 'l': // a simple line
1609
  for ($i = 0; $i < $ile_argumentow; $i+=2) {
1610
- $x = ($a[$i][0]);
1611
- $y = ($a[$i + 1][0]);
1612
  if ($relative) {
1613
  $pdfx = ($this->xbase + $x);
1614
  $pdfy = ($this->ybase - $y);
@@ -1630,7 +1633,7 @@ class Svg
1630
  break;
1631
  case 'h': // a very simple horizontal line
1632
  for ($i = 0; $i < $ile_argumentow; $i++) {
1633
- $x = ($a[$i][0]);
1634
  if ($relative) {
1635
  $y = 0;
1636
  $pdfx = ($this->xbase + $x);
@@ -1654,7 +1657,7 @@ class Svg
1654
  break;
1655
  case 'v': // the simplest line, vertical
1656
  for ($i = 0; $i < $ile_argumentow; $i++) {
1657
- $y = ($a[$i][0]);
1658
  if ($relative) {
1659
  $x = 0;
1660
  $pdfx = ($this->xbase + $x);
@@ -1684,10 +1687,10 @@ class Svg
1684
  for ($i = 0; $i < $ile_argumentow; $i += 4) {
1685
  $x1 = $this->lastcontrolpoints[0];
1686
  $y1 = $this->lastcontrolpoints[1];
1687
- $x2 = ($a[$i][0]);
1688
- $y2 = ($a[$i + 1][0]);
1689
- $x = ($a[$i + 2][0]);
1690
- $y = ($a[$i + 3][0]);
1691
  if ($relative) {
1692
  $pdfx1 = ($this->xbase + $x1);
1693
  $pdfy1 = ($this->ybase - $y1);
@@ -1727,12 +1730,12 @@ class Svg
1727
  break;
1728
  case 'c': // bezier with second vertex equal second control
1729
  for ($i = 0; $i < $ile_argumentow; $i += 6) {
1730
- $x1 = ($a[$i][0]);
1731
- $y1 = ($a[$i + 1][0]);
1732
- $x2 = ($a[$i + 2][0]);
1733
- $y2 = ($a[$i + 3][0]);
1734
- $x = ($a[$i + 4][0]);
1735
- $y = ($a[$i + 5][0]);
1736
 
1737
 
1738
  if ($relative) {
@@ -1776,10 +1779,10 @@ class Svg
1776
 
1777
  case 'q': // bezier quadratic avec point de control
1778
  for ($i = 0; $i < $ile_argumentow; $i += 4) {
1779
- $x1 = ($a[$i][0]);
1780
- $y1 = ($a[$i + 1][0]);
1781
- $x = ($a[$i + 2][0]);
1782
- $y = ($a[$i + 3][0]);
1783
  if ($relative) {
1784
  $pdfx = ($this->xbase + $x);
1785
  $pdfy = ($this->ybase - $y);
@@ -1832,8 +1835,8 @@ class Svg
1832
  $this->lastcontrolpoints = [0, 0];
1833
  }
1834
  for ($i = 0; $i < $ile_argumentow; $i += 2) {
1835
- $x = ($a[$i][0]);
1836
- $y = ($a[$i + 1][0]);
1837
 
1838
  $x1 = $this->lastcontrolpoints[0];
1839
  $y1 = $this->lastcontrolpoints[1];
@@ -1879,20 +1882,20 @@ class Svg
1879
  break;
1880
  case 'a': // Elliptical arc
1881
  for ($i = 0; $i < $ile_argumentow; $i += 7) {
1882
- $rx = ($a[$i][0]);
1883
- $ry = ($a[$i + 1][0]);
1884
- $angle = ($a[$i + 2][0]); //x-axis-rotation
1885
- $largeArcFlag = ($a[$i + 3][0]);
1886
- $sweepFlag = ($a[$i + 4][0]);
1887
- $x2 = ($a[$i + 5][0]);
1888
- $y2 = ($a[$i + 6][0]);
1889
  $x1 = $this->xbase;
1890
  $y1 = -$this->ybase;
1891
  if ($relative) {
1892
  $x2 = $this->xbase + $x2;
1893
  $y2 = -$this->ybase + $y2;
1894
- $this->xbase += ($a[$i + 5][0]);
1895
- $this->ybase += -($a[$i + 6][0]);
1896
  } else {
1897
  $this->xbase = $x2;
1898
  $this->ybase = -$y2;
1557
 
1558
  $start = [$this->xbase, -$this->ybase];
1559
 
1560
+ // taken from https://github.com/PhenX/php-svg-lib/blob/master/src/Svg/Tag/Path.php#L47
1561
+ // Handle args like: a5.38022,5.38022,0,0,1-2.4207.72246,4.50524,4.50524,0,0,1-3.12681-1.33942,9.67442,9.67442,0,0,1-2.38273-3.016,1.87506,1.87506,0,0,1,.34979-2.43562
1562
+ preg_match_all('/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/i', $arguments, $a, PREG_PATTERN_ORDER);
1563
+ $a = $a[0];
1564
 
1565
  // if the command is a capital letter, the coords go absolute, otherwise relative
1566
  if (strtolower($command) == $command) {
1577
  switch (strtolower($command)) {
1578
  case 'm': // move
1579
  for ($i = 0; $i < $ile_argumentow; $i+=2) {
1580
+ $x = $a[$i];
1581
+ $y = $a[$i + 1];
1582
  if ($relative) {
1583
  $pdfx = ($this->xbase + $x);
1584
  $pdfy = ($this->ybase - $y);
1610
  break;
1611
  case 'l': // a simple line
1612
  for ($i = 0; $i < $ile_argumentow; $i+=2) {
1613
+ $x = ($a[$i]);
1614
+ $y = ($a[$i + 1]);
1615
  if ($relative) {
1616
  $pdfx = ($this->xbase + $x);
1617
  $pdfy = ($this->ybase - $y);
1633
  break;
1634
  case 'h': // a very simple horizontal line
1635
  for ($i = 0; $i < $ile_argumentow; $i++) {
1636
+ $x = ($a[$i]);
1637
  if ($relative) {
1638
  $y = 0;
1639
  $pdfx = ($this->xbase + $x);
1657
  break;
1658
  case 'v': // the simplest line, vertical
1659
  for ($i = 0; $i < $ile_argumentow; $i++) {
1660
+ $y = ($a[$i]);
1661
  if ($relative) {
1662
  $x = 0;
1663
  $pdfx = ($this->xbase + $x);
1687
  for ($i = 0; $i < $ile_argumentow; $i += 4) {
1688
  $x1 = $this->lastcontrolpoints[0];
1689
  $y1 = $this->lastcontrolpoints[1];
1690
+ $x2 = ($a[$i]);
1691
+ $y2 = ($a[$i + 1]);
1692
+ $x = ($a[$i + 2]);
1693
+ $y = ($a[$i + 3]);
1694
  if ($relative) {
1695
  $pdfx1 = ($this->xbase + $x1);
1696
  $pdfy1 = ($this->ybase - $y1);
1730
  break;
1731
  case 'c': // bezier with second vertex equal second control
1732
  for ($i = 0; $i < $ile_argumentow; $i += 6) {
1733
+ $x1 = ($a[$i]);
1734
+ $y1 = ($a[$i + 1]);
1735
+ $x2 = ($a[$i + 2]);
1736
+ $y2 = ($a[$i + 3]);
1737
+ $x = ($a[$i + 4]);
1738
+ $y = ($a[$i + 5]);
1739
 
1740
 
1741
  if ($relative) {
1779
 
1780
  case 'q': // bezier quadratic avec point de control
1781
  for ($i = 0; $i < $ile_argumentow; $i += 4) {
1782
+ $x1 = ($a[$i]);
1783
+ $y1 = ($a[$i + 1]);
1784
+ $x = ($a[$i + 2]);
1785
+ $y = ($a[$i + 3]);
1786
  if ($relative) {
1787
  $pdfx = ($this->xbase + $x);
1788
  $pdfy = ($this->ybase - $y);
1835
  $this->lastcontrolpoints = [0, 0];
1836
  }
1837
  for ($i = 0; $i < $ile_argumentow; $i += 2) {
1838
+ $x = ($a[$i]);
1839
+ $y = ($a[$i + 1]);
1840
 
1841
  $x1 = $this->lastcontrolpoints[0];
1842
  $y1 = $this->lastcontrolpoints[1];
1882
  break;
1883
  case 'a': // Elliptical arc
1884
  for ($i = 0; $i < $ile_argumentow; $i += 7) {
1885
+ $rx = ($a[$i]);
1886
+ $ry = ($a[$i + 1]);
1887
+ $angle = ($a[$i + 2]); //x-axis-rotation
1888
+ $largeArcFlag = ($a[$i + 3]);
1889
+ $sweepFlag = ($a[$i + 4]);
1890
+ $x2 = ($a[$i + 5]);
1891
+ $y2 = ($a[$i + 6]);
1892
  $x1 = $this->xbase;
1893
  $y1 = -$this->ybase;
1894
  if ($relative) {
1895
  $x2 = $this->xbase + $x2;
1896
  $y2 = -$this->ybase + $y2;
1897
+ $this->xbase += ($a[$i + 5]);
1898
+ $this->ybase += -($a[$i + 6]);
1899
  } else {
1900
  $this->xbase = $x2;
1901
  $this->ybase = -$y2;
vendor/mpdf/mpdf/src/Mpdf.php CHANGED
@@ -5,38 +5,25 @@ namespace Mpdf;
5
  use fpdi_pdf_parser;
6
  use pdf_parser;
7
 
 
 
8
  use Mpdf\Config\ConfigVariables;
9
  use Mpdf\Config\FontVariables;
10
 
11
- use Mpdf\Color\ColorConverter;
12
- use Mpdf\Color\ColorModeConverter;
13
- use Mpdf\Color\ColorSpaceRestrictor;
14
-
15
  use Mpdf\Conversion;
16
 
17
  use Mpdf\Css\Border;
18
  use Mpdf\Css\TextVars;
19
 
20
- use Mpdf\Image\ImageProcessor;
21
-
22
- use Mpdf\Language\LanguageToFont;
23
- use Mpdf\Language\ScriptToLanguage;
24
-
25
  use Mpdf\Log\Context as LogContext;
26
 
27
- use Mpdf\Fonts\FontCache;
28
- use Mpdf\Fonts\FontFileFinder;
29
  use Mpdf\Fonts\MetricsGenerator;
30
 
31
  use Mpdf\Output\Destination;
32
 
33
- use Mpdf\Pdf\Protection;
34
- use Mpdf\Pdf\Protection\UniqidGenerator;
35
-
36
  use Mpdf\QrCode;
37
 
38
  use Mpdf\Utils\Arrays;
39
- use Mpdf\Utils\PdfDate;
40
  use Mpdf\Utils\NumericString;
41
  use Mpdf\Utils\UtfString;
42
 
@@ -49,13 +36,14 @@ use Psr\Log\NullLogger;
49
  * based on FPDF by Olivier Plathey
50
  * and HTML2FPDF by Renato Coelho
51
  *
52
- * @version 7.0
53
  * @license GPL-2.0
54
  */
55
  class Mpdf implements \Psr\Log\LoggerAwareInterface
56
  {
57
 
58
- const VERSION = '7.1.5';
 
 
59
 
60
  const SCALE = 72 / 25.4;
61
 
@@ -174,6 +162,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
174
  var $list_auto_mode; // mPDF 6
175
  var $list_indent_first_level; // mPDF 6
176
  var $list_indent_default; // mPDF 6
 
177
  var $list_marker_offset; // mPDF 6
178
  var $list_symbol_size;
179
 
@@ -246,6 +235,9 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
246
  var $OTLtags; // mPDF 5.7.1
247
  var $OTLdata; // mPDF 5.7.1
248
 
 
 
 
249
  var $writingToC;
250
  var $layers;
251
  var $layerDetails;
@@ -605,6 +597,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
605
  var $enabledtags;
606
 
607
  var $lineheight;
 
608
  var $basepath;
609
  var $textparam;
610
 
@@ -915,6 +908,11 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
915
  */
916
  private $protection;
917
 
 
 
 
 
 
918
  /**
919
  * @var \Mpdf\Image\ImageProcessor
920
  */
@@ -935,6 +933,71 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
935
  */
936
  private $logger;
937
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
938
  /**
939
  * @var string[]
940
  */
@@ -966,80 +1029,26 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
966
  $originalConfig = $config;
967
  $config = $this->initConfig($originalConfig);
968
 
969
- $this->sizeConverter = new SizeConverter($this->dpi, $this->default_font_size, $this, $this->logger);
970
-
971
- $this->colorModeConverter = new ColorModeConverter();
972
- $this->colorSpaceRestrictor = new ColorSpaceRestrictor(
973
- $this,
974
- $this->colorModeConverter,
975
- $this->restrictColorSpace
976
- );
977
- $this->colorConverter = new ColorConverter($this, $this->colorModeConverter, $this->colorSpaceRestrictor);
978
-
979
-
980
- $this->gradient = new Gradient($this, $this->sizeConverter, $this->colorConverter);
981
- $this->tableOfContents = new TableOfContents($this, $this->sizeConverter);
982
-
983
- $this->cache = new Cache($config['tempDir']);
984
- $this->fontCache = new FontCache(new Cache($config['tempDir'] . '/ttfontdata'));
985
-
986
- $this->fontFileFinder = new FontFileFinder($config['fontDir']);
987
-
988
- $this->cssManager = new CssManager($this, $this->cache, $this->sizeConverter, $this->colorConverter);
989
-
990
- $this->otl = new Otl($this, $this->fontCache);
991
-
992
- $this->form = new Form($this, $this->otl, $this->colorConverter);
993
-
994
- $this->hyphenator = new Hyphenator($this);
995
-
996
- $this->imageProcessor = new ImageProcessor(
997
  $this,
998
- $this->otl,
999
- $this->cssManager,
1000
- $this->sizeConverter,
1001
- $this->colorConverter,
1002
- $this->colorModeConverter,
1003
- $this->cache,
1004
  $this->languageToFont,
1005
  $this->scriptToLanguage,
1006
- $this->logger
 
 
 
1007
  );
1008
 
1009
- $this->tag = new Tag(
1010
- $this,
1011
- $this->cache,
1012
- $this->cssManager,
1013
- $this->form,
1014
- $this->otl,
1015
- $this->tableOfContents,
1016
- $this->sizeConverter,
1017
- $this->colorConverter,
1018
- $this->imageProcessor,
1019
- $this->languageToFont
1020
- );
1021
 
1022
- $this->services = [
1023
- 'otl',
1024
- 'bmp',
1025
- 'cache',
1026
- 'cssManager',
1027
- 'directWrite',
1028
- 'fontCache',
1029
- 'fontFileFinder',
1030
- 'form',
1031
- 'gradient',
1032
- 'tableOfContents',
1033
- 'tag',
1034
- 'wmf',
1035
- 'sizeConverter',
1036
- 'colorConverter',
1037
- 'hyphenator',
1038
- 'imageProcessor',
1039
- 'protection',
1040
- 'languageToFont',
1041
- 'scriptToLanguage',
1042
- ];
1043
 
1044
  $this->time0 = microtime(true);
1045
 
@@ -1746,6 +1755,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
1746
  } else {
1747
  throw new \Mpdf\MpdfException('Incorrect zoom display mode: ' . $zoom);
1748
  }
 
1749
  if ($layout == 'single' or $layout == 'continuous' or $layout == 'two' or $layout == 'twoleft' or $layout == 'tworight' or $layout == 'default') {
1750
  $this->LayoutMode = $layout;
1751
  } else {
@@ -1873,7 +1883,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
1873
  if ($return) {
1874
  return sprintf('/GS%d gs', $gs);
1875
  } else {
1876
- $this->_out(sprintf('/GS%d gs', $gs));
1877
  }
1878
  }
1879
 
@@ -1909,17 +1919,17 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
1909
  $this->pdf_version = '1.5';
1910
  }
1911
  if ($this->visibility != 'visible') {
1912
- $this->_out('EMC');
1913
  $this->hasOC = intval($this->hasOC);
1914
  }
1915
  if ($v == 'printonly') {
1916
- $this->_out('/OC /OC1 BDC');
1917
  $this->hasOC = ($this->hasOC | 1);
1918
  } elseif ($v == 'screenonly') {
1919
- $this->_out('/OC /OC2 BDC');
1920
  $this->hasOC = ($this->hasOC | 2);
1921
  } elseif ($v == 'hidden') {
1922
- $this->_out('/OC /OC3 BDC');
1923
  $this->hasOC = ($this->hasOC | 4);
1924
  } elseif ($v != 'visible') {
1925
  throw new \Mpdf\MpdfException('Incorrect visibility: ' . $v);
@@ -1934,8 +1944,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
1934
  // Was is function _begindoc()
1935
  // Start document
1936
  $this->state = 1;
1937
- $this->_out('%PDF-' . $this->pdf_version);
1938
- $this->_out('%' . chr(226) . chr(227) . chr(207) . chr(211)); // 4 chars > 128 to show binary file
1939
  }
1940
  }
1941
 
@@ -2694,7 +2704,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
2694
  }
2695
  }
2696
  $this->current_layer = $id;
2697
- $this->_out('/OCZ-index /ZI' . $id . ' BDC');
2698
 
2699
  $this->pageoutput[$this->page] = [];
2700
  }
@@ -2702,7 +2712,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
2702
  function EndLayer()
2703
  {
2704
  if ($this->current_layer > 0) {
2705
- $this->_out('EMCZ-index');
2706
  $this->current_layer = 0;
2707
  }
2708
  }
@@ -2901,9 +2911,9 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
2901
  $this->x = $this->lMargin;
2902
  $this->y = $this->tMargin;
2903
  $this->FontFamily = '';
2904
- $this->_out('2 J');
2905
  $this->LineWidth = $lw;
2906
- $this->_out(sprintf('%.3F w', $lw * Mpdf::SCALE));
2907
 
2908
  if ($family) {
2909
  $this->SetFont($family, $style, $size, true, true);
@@ -2912,13 +2922,13 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
2912
  $this->DrawColor = $dc;
2913
 
2914
  if ($dc != $this->defDrawColor) {
2915
- $this->_out($dc);
2916
  }
2917
 
2918
  $this->FillColor = $fc;
2919
 
2920
  if ($fc != $this->defFillColor) {
2921
- $this->_out($fc);
2922
  }
2923
 
2924
  $this->TextColor = $tc;
@@ -3125,16 +3135,16 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3125
  }
3126
 
3127
  // Tiling Patterns
3128
- $this->_out('___PAGE___START' . $this->uniqstr);
3129
- $this->_out('___BACKGROUND___PATTERNS' . $this->uniqstr);
3130
- $this->_out('___HEADER___MARKER' . $this->uniqstr);
3131
  $this->pageBackgrounds = [];
3132
 
3133
  // Set line cap style to square
3134
  $this->SetLineCap(2);
3135
  // Set line width
3136
  $this->LineWidth = $lw;
3137
- $this->_out(sprintf('%.3F w', $lw * Mpdf::SCALE));
3138
  // Set font
3139
  if ($family) {
3140
  $this->SetFont($family, $style, $size, true, true); // forces write
@@ -3143,11 +3153,11 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3143
  // Set colors
3144
  $this->DrawColor = $dc;
3145
  if ($dc != $this->defDrawColor) {
3146
- $this->_out($dc);
3147
  }
3148
  $this->FillColor = $fc;
3149
  if ($fc != $this->defFillColor) {
3150
- $this->_out($fc);
3151
  }
3152
  $this->TextColor = $tc;
3153
  $this->ColorFlag = $cf;
@@ -3158,7 +3168,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3158
  // Restore line width
3159
  if ($this->LineWidth != $lw) {
3160
  $this->LineWidth = $lw;
3161
- $this->_out(sprintf('%.3F w', $lw * Mpdf::SCALE));
3162
  }
3163
  // Restore font
3164
  if ($family) {
@@ -3168,11 +3178,11 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3168
  // Restore colors
3169
  if ($this->DrawColor != $dc) {
3170
  $this->DrawColor = $dc;
3171
- $this->_out($dc);
3172
  }
3173
  if ($this->FillColor != $fc) {
3174
  $this->FillColor = $fc;
3175
- $this->_out($fc);
3176
  }
3177
  $this->TextColor = $tc;
3178
  $this->ColorFlag = $cf;
@@ -3295,7 +3305,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3295
  }
3296
  $this->DrawColor = $out;
3297
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['DrawColor']) && $this->pageoutput[$this->page]['DrawColor'] != $this->DrawColor) || !isset($this->pageoutput[$this->page]['DrawColor']))) {
3298
- $this->_out($this->DrawColor);
3299
  }
3300
  $this->pageoutput[$this->page]['DrawColor'] = $this->DrawColor;
3301
  }
@@ -3312,7 +3322,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3312
  $this->FillColor = $out;
3313
  $this->ColorFlag = ($out != $this->TextColor);
3314
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor']))) {
3315
- $this->_out($this->FillColor);
3316
  }
3317
  $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
3318
  }
@@ -3658,7 +3668,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3658
  $this->LineWidth = $width;
3659
  $lwout = (sprintf('%.3F w', $width * Mpdf::SCALE));
3660
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['LineWidth']) && $this->pageoutput[$this->page]['LineWidth'] != $lwout) || !isset($this->pageoutput[$this->page]['LineWidth']))) {
3661
- $this->_out($lwout);
3662
  }
3663
  $this->pageoutput[$this->page]['LineWidth'] = $lwout;
3664
  }
@@ -3666,7 +3676,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3666
  function Line($x1, $y1, $x2, $y2)
3667
  {
3668
  // Draw a line
3669
- $this->_out(sprintf('%.3F %.3F m %.3F %.3F l S', $x1 * Mpdf::SCALE, ($this->h - $y1) * Mpdf::SCALE, $x2 * Mpdf::SCALE, ($this->h - $y2) * Mpdf::SCALE));
3670
  }
3671
 
3672
  function Arrow($x1, $y1, $x2, $y2, $headsize = 3, $fill = 'B', $angle = 25)
@@ -3693,12 +3703,12 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3693
 
3694
  $s = '';
3695
  $s .= sprintf('%.3F %.3F m %.3F %.3F l S', $x1 * Mpdf::SCALE, ($this->h - $y1) * Mpdf::SCALE, $x5 * Mpdf::SCALE, $y5 * Mpdf::SCALE);
3696
- $this->_out($s);
3697
 
3698
  $s = '';
3699
  $s .= sprintf('%.3F %.3F m %.3F %.3F l %.3F %.3F l %.3F %.3F l %.3F %.3F l ', $x5 * Mpdf::SCALE, $y5 * Mpdf::SCALE, $x3 * Mpdf::SCALE, $y3 * Mpdf::SCALE, $x2 * Mpdf::SCALE, ($this->h - $y2) * Mpdf::SCALE, $x4 * Mpdf::SCALE, $y4 * Mpdf::SCALE, $x5 * Mpdf::SCALE, $y5 * Mpdf::SCALE);
3700
  $s .= $fill;
3701
- $this->_out($s);
3702
  }
3703
 
3704
  function Rect($x, $y, $w, $h, $style = '')
@@ -3711,7 +3721,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
3711
  } else {
3712
  $op = 'S';
3713
  }
3714
- $this->_out(sprintf('%.3F %.3F %.3F %.3F re %s', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$h * Mpdf::SCALE, $op));
3715
  }
3716
 
3717
  function AddFontDirectory($directory)
@@ -4140,7 +4150,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
4140
  if ($write) {
4141
  $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
4142
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) {
4143
- $this->_out($fontout);
4144
  }
4145
  $this->pageoutput[$this->page]['Font'] = $fontout;
4146
  }
@@ -4208,7 +4218,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
4208
  if ($write) {
4209
  $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
4210
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) {
4211
- $this->_out($fontout);
4212
  }
4213
  $this->pageoutput[$this->page]['Font'] = $fontout;
4214
  }
@@ -4234,7 +4244,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
4234
  $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
4235
  // Edited mPDF 3.0
4236
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) {
4237
- $this->_out($fontout);
4238
  }
4239
  $this->pageoutput[$this->page]['Font'] = $fontout;
4240
  }
@@ -4335,8 +4345,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
4335
  // IF corefonts AND NOT SmCaps AND NOT Kerning
4336
  // Just output text
4337
  if ($this->usingCoreFont && !($textvar & TextVars::FC_SMALLCAPS) && !($textvar & TextVars::FC_KERNING)) {
4338
- $txt2 = $this->_escape($txt2);
4339
- $s .=sprintf('BT ' . $aix . ' (%s) Tj ET', $px, $py, $txt2);
4340
  } // IF NOT corefonts [AND NO wordspacing] AND NOT SIP/SMP AND NOT SmCaps AND NOT Kerning AND NOT OTL
4341
  // Just output text
4342
  elseif (!$this->usingCoreFont && !($textvar & TextVars::FC_SMALLCAPS) && !($textvar & TextVars::FC_KERNING) && !(isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF) && !empty($OTLdata['GPOSinfo']))) {
@@ -4346,8 +4356,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
4346
  $s .=sprintf('BT ' . $aix . ' %s Tj ET', $px, $py, $txt2);
4347
  } // NOT SIP/SMP
4348
  else {
4349
- $txt2 = $this->UTF8ToUTF16BE($txt2, false);
4350
- $txt2 = $this->_escape($txt2);
4351
  $s .=sprintf('BT ' . $aix . ' (%s) Tj ET', $px, $py, $txt2);
4352
  }
4353
  } // IF NOT corefonts [AND IS wordspacing] AND NOT SIP AND NOT SmCaps AND NOT Kerning AND NOT OTL
@@ -4415,7 +4425,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
4415
  if ($return) {
4416
  return $s . " \n";
4417
  }
4418
- $this->_out($s);
4419
  }
4420
 
4421
  /* -- DIRECTW -- */
@@ -4506,11 +4516,11 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
4506
  function ResetSpacing()
4507
  {
4508
  if ($this->ws != 0) {
4509
- $this->_out('BT 0 Tw ET');
4510
  }
4511
  $this->ws = 0;
4512
  if ($this->charspacing != 0) {
4513
- $this->_out('BT 0 Tc ET');
4514
  }
4515
  $this->charspacing = 0;
4516
  }
@@ -4521,18 +4531,18 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
4521
  $cs = 0;
4522
  }
4523
  if ($cs) {
4524
- $this->_out(sprintf('BT %.3F Tc ET', $cs));
4525
  } elseif ($this->charspacing != 0) {
4526
- $this->_out('BT 0 Tc ET');
4527
  }
4528
  $this->charspacing = $cs;
4529
  if (intval($ws * 1000) == 0) {
4530
  $ws = 0;
4531
  }
4532
  if ($ws) {
4533
- $this->_out(sprintf('BT %.3F Tw ET', $ws));
4534
  } elseif ($this->ws != 0) {
4535
- $this->_out('BT 0 Tw ET');
4536
  }
4537
  $this->ws = $ws;
4538
  }
@@ -5120,7 +5130,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5120
  // IF corefonts AND NOT SmCaps AND NOT Kerning
5121
  // Just output text; charspacing and wordspacing already set by charspacing (Tc) and ws (Tw)
5122
  if ($this->usingCoreFont && !($textvar & TextVars::FC_SMALLCAPS) && !($textvar & TextVars::FC_KERNING)) {
5123
- $txt2 = $this->_escape($txt2);
5124
  $sub .=sprintf('BT ' . $aix . ' (%s) Tj ET', $px, $py, $txt2);
5125
  } // IF NOT corefonts AND NO wordspacing AND NOT SIP/SMP AND NOT SmCaps AND NOT Kerning AND NOT OTL
5126
  // Just output text
@@ -5131,8 +5141,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5131
  $sub .=sprintf('BT ' . $aix . ' %s Tj ET', $px, $py, $txt2);
5132
  } // NOT SIP/SMP
5133
  else {
5134
- $txt2 = $this->UTF8ToUTF16BE($txt2, false);
5135
- $txt2 = $this->_escape($txt2);
5136
  $sub .=sprintf('BT ' . $aix . ' (%s) Tj ET', $px, $py, $txt2);
5137
  }
5138
  } // IF NOT corefonts AND IS wordspacing AND NOT SIP AND NOT SmCaps AND NOT Kerning AND NOT OTL
@@ -5140,15 +5150,15 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5140
  // IF multibyte - Tw has no effect - need to do word spacing using an adjustment before each space
5141
  elseif (!$this->usingCoreFont && $this->ws && !((isset($this->CurrentFont['sip']) && $this->CurrentFont['sip']) || (isset($this->CurrentFont['smp']) && $this->CurrentFont['smp'])) && !($textvar & TextVars::FC_SMALLCAPS) && !($textvar & TextVars::FC_KERNING) && !(isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF) && (!empty($OTLdata['GPOSinfo']) || (strpos($OTLdata['group'], 'M') !== false && $this->charspacing)) )) {
5142
  $space = " ";
5143
- $space = $this->UTF8ToUTF16BE($space, false);
5144
- $space = $this->_escape($space);
5145
  $sub .=sprintf('BT ' . $aix . ' %.3F Tc [', $px, $py, $this->charspacing);
5146
  $t = explode(' ', $txt2);
5147
  $numt = count($t);
5148
  for ($i = 0; $i < $numt; $i++) {
5149
  $tx = $t[$i];
5150
- $tx = $this->UTF8ToUTF16BE($tx, false);
5151
- $tx = $this->_escape($tx);
5152
  $sub .=sprintf('(%s) ', $tx);
5153
  if (($i + 1) < $numt) {
5154
  $adj = -($this->ws) * 1000 / $this->FontSizePt;
@@ -5328,12 +5338,12 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5328
  }
5329
  }
5330
  if ($s) {
5331
- $this->_out($s);
5332
  }
5333
 
5334
  // WORD SPACING
5335
  if ($this->ws && !$this->usingCoreFont) {
5336
- $this->_out(sprintf('BT %.3F Tc ET', $this->charspacing));
5337
  }
5338
  $this->lasth = $h;
5339
  if (strpos($txt, "\n") !== false) {
@@ -5543,9 +5553,9 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5543
  if ($this->usingCoreFont) {
5544
  $tx = utf8_decode($tx);
5545
  } else {
5546
- $tx = $this->UTF8ToUTF16BE($tx, false);
5547
  }
5548
- $tx = $this->_escape($tx);
5549
  }
5550
 
5551
  // If any settings require a new Text Group
@@ -5622,8 +5632,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5622
  }
5623
  } else {
5624
  $tx = UtfString::code2utf($c);
5625
- $tx = $this->UTF8ToUTF16BE($tx, false);
5626
- $tx = $this->_escape($tx);
5627
  }
5628
 
5629
  if ($kashida > $tatw) {
@@ -5710,8 +5720,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5710
  if ($mode == 'MBTw') { // Multibyte requiring word spacing
5711
  $space = ' ';
5712
  // Convert string to UTF-16BE without BOM
5713
- $space = $this->UTF8ToUTF16BE($space, false);
5714
- $space = $this->_escape($space);
5715
  $s = sprintf(' BT ' . $aix, $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE);
5716
  $t = explode(' ', $txt);
5717
  for ($i = 0; $i < count($t); $i++) {
@@ -5725,8 +5735,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5725
  $tj .= sprintf(')%d(', $kern);
5726
  }
5727
  $tc = UtfString::code2utf($unicode[$ti]);
5728
- $tc = $this->UTF8ToUTF16BE($tc, false);
5729
- $tj .= $this->_escape($tc);
5730
  }
5731
  $tj .= ')';
5732
  $s .= sprintf(' %.3F Tc [%s] TJ', $this->charspacing, $tj);
@@ -5747,8 +5757,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5747
  $tj .= sprintf(')%d(', $kern);
5748
  }
5749
  $tx = UtfString::code2utf($unicode[$i]);
5750
- $tx = $this->UTF8ToUTF16BE($tx, false);
5751
- $tj .= $this->_escape($tx);
5752
  }
5753
  $tj .= ')';
5754
  $s .= sprintf(' BT ' . $aix . ' [%s] TJ ET ', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $tj);
@@ -5761,7 +5771,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
5761
  $kern = -$this->CurrentFont['kerninfo'][$txt[($i - 1)]][$txt[$i]];
5762
  $tj .= sprintf(')%d(', $kern);
5763
  }
5764
- $tj .= $this->_escape($txt[$i]);
5765
  }
5766
  $tj .= ')';
5767
  $s .= sprintf(' BT ' . $aix . ' [%s] TJ ET ', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $tj);
@@ -6243,7 +6253,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
6243
  $this->SetFont($saved['family'], $saved['style'], $saved['sizePt'], true, true); // force output
6244
  $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
6245
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) {
6246
- $this->_out($fontout);
6247
  }
6248
  $this->pageoutput[$this->page]['Font'] = $fontout;
6249
  } else {
@@ -7044,7 +7054,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
7044
  if ($objattr['type'] == 'image') {
7045
  // mPDF 5.7.3 TRANSFORMS
7046
  if (isset($objattr['transform'])) {
7047
- $this->_out("\n" . '% BTR'); // Begin Transform
7048
  }
7049
  if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->current_layer == 0) {
7050
  $this->BeginLayer($objattr['z-index']);
@@ -7174,7 +7184,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
7174
  // mPDF 5.7.3 TRANSFORMS / BACKGROUND COLOR
7175
  // Transform also affects image background
7176
  if ($tr2) {
7177
- $this->_out('q ' . $tr2 . ' ');
7178
  }
7179
  if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
7180
  $bgcol = $objattr['bgcolor'];
@@ -7183,7 +7193,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
7183
  $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings));
7184
  }
7185
  if ($tr2) {
7186
- $this->_out('Q');
7187
  }
7188
 
7189
  /* -- BACKGROUNDS -- */
@@ -7205,7 +7215,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
7205
  $outstring = sprintf("q " . $tr . $tr2 . "%.3F 0 0 %.3F %.3F %.3F cm " . $gradmask . "/I%d Do Q", $obiw * Mpdf::SCALE, $obih * Mpdf::SCALE, $objattr['INNER-X'] * Mpdf::SCALE, ($this->h - ($objattr['INNER-Y'] + $obih )) * Mpdf::SCALE, $objattr['ID']); // mPDF 5.7.3 TRANSFORMS
7206
  }
7207
  }
7208
- $this->_out($outstring);
7209
  // LINK
7210
  if (isset($objattr['link'])) {
7211
  $this->Link($objattr['INNER-X'], $objattr['INNER-Y'], $objattr['INNER-WIDTH'], $objattr['INNER-HEIGHT'], $objattr['link']);
@@ -7217,13 +7227,13 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
7217
  // mPDF 5.7.3 TRANSFORMS
7218
  // Transform also affects image borders
7219
  if ($tr2) {
7220
- $this->_out('q ' . $tr2 . ' ');
7221
  }
7222
  if ((isset($objattr['border_top']) && $objattr['border_top'] > 0) || (isset($objattr['border_left']) && $objattr['border_left'] > 0) || (isset($objattr['border_right']) && $objattr['border_right'] > 0) || (isset($objattr['border_bottom']) && $objattr['border_bottom'] > 0)) {
7223
  $this->PaintImgBorder($objattr, $is_table);
7224
  }
7225
  if ($tr2) {
7226
- $this->_out('Q');
7227
  }
7228
 
7229
  if (isset($objattr['visibility']) && $objattr['visibility'] != 'visible' && $objattr['visibility']) {
@@ -7234,7 +7244,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
7234
  }
7235
  // mPDF 5.7.3 TRANSFORMS
7236
  if (isset($objattr['transform'])) {
7237
- $this->_out("\n" . '% ETR'); // End Transform
7238
  }
7239
  }
7240
 
@@ -7512,19 +7522,19 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
7512
  // x and y are the centre of the bullet; size is the width and/or height in mm
7513
  $fcol = $this->SetTColor($color, true);
7514
  $lcol = strtoupper($fcol); // change 0 0 0 rg to 0 0 0 RG
7515
- $this->_out(sprintf('q %s %s', $lcol, $fcol));
7516
- $this->_out('0 j 0 J [] 0 d');
7517
  if ($type == 'square') {
7518
  $size *= 0.85; // Smaller to appear the same size as circle/disc
7519
- $this->_out(sprintf('%.3F %.3F %.3F %.3F re f', ($x - $size / 2) * Mpdf::SCALE, ($this->h - $y + $size / 2) * Mpdf::SCALE, ($size) * Mpdf::SCALE, (-$size) * Mpdf::SCALE));
7520
  } elseif ($type == 'disc') {
7521
  $this->Circle($x, $y, $size / 2, 'F'); // Fill
7522
  } elseif ($type == 'circle') {
7523
  $lw = $size / 12; // Line width
7524
- $this->_out(sprintf('%.3F w ', $lw * Mpdf::SCALE));
7525
  $this->Circle($x, $y, $size / 2 - $lw / 2, 'S'); // Stroke
7526
  }
7527
- $this->_out('Q');
7528
  }
7529
 
7530
  // mPDF 6
@@ -8653,7 +8663,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
8653
  }
8654
  $tr = ($mode . ' Tr');
8655
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']))) {
8656
- $this->_out($tr);
8657
  }
8658
  $this->pageoutput[$this->page]['TextRendering'] = $tr;
8659
  }
@@ -8665,7 +8675,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
8665
  $this->SetDColor($params['outline-COLOR']);
8666
  $tr = ('2 Tr');
8667
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']))) {
8668
- $this->_out($tr);
8669
  }
8670
  $this->pageoutput[$this->page]['TextRendering'] = $tr;
8671
  } else { // Now resets all values
@@ -8674,7 +8684,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
8674
  $this->_SetTextRendering(0);
8675
  $tr = ('0 Tr');
8676
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']))) {
8677
- $this->_out($tr);
8678
  }
8679
  $this->pageoutput[$this->page]['TextRendering'] = $tr;
8680
  }
@@ -8814,7 +8824,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
8814
  $outstring = $this->watermarkImgAlpha . "\n" . $outstring . "\n" . $this->SetAlpha(1, 'Normal', true) . "\n";
8815
  $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS' . $this->uniqstr . ')/', "\n" . $outstring . "\n" . '\\1', $this->pages[$this->page]);
8816
  } else {
8817
- $this->_out($outstring);
8818
  }
8819
 
8820
  return 0;
@@ -8885,7 +8895,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
8885
  }
8886
 
8887
  if ($paint) {
8888
- $this->_out($outstring);
8889
  if ($link) {
8890
  $this->Link($x, $y, $w, $h, $link);
8891
  }
@@ -9156,7 +9166,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
9156
  {
9157
  $s = sprintf('%d j', $mode);
9158
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['LineJoin']) && $this->pageoutput[$this->page]['LineJoin'] != $s) || !isset($this->pageoutput[$this->page]['LineJoin']))) {
9159
- $this->_out($s);
9160
  }
9161
  $this->pageoutput[$this->page]['LineJoin'] = $s;
9162
  }
@@ -9165,7 +9175,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
9165
  {
9166
  $s = sprintf('%d J', $mode);
9167
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['LineCap']) && $this->pageoutput[$this->page]['LineCap'] != $s) || !isset($this->pageoutput[$this->page]['LineCap']))) {
9168
- $this->_out($s);
9169
  }
9170
  $this->pageoutput[$this->page]['LineCap'] = $s;
9171
  }
@@ -9178,7 +9188,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
9178
  $s = '[] 0 d';
9179
  }
9180
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Dash']) && $this->pageoutput[$this->page]['Dash'] != $s) || !isset($this->pageoutput[$this->page]['Dash']))) {
9181
- $this->_out($s);
9182
  }
9183
  $this->pageoutput[$this->page]['Dash'] = $s;
9184
  }
@@ -9694,508 +9704,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
9694
  $this->state = 1;
9695
  }
9696
 
9697
- function _putpages()
9698
- {
9699
- $nb = $this->page;
9700
- $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
9701
-
9702
- if ($this->DefOrientation == 'P') {
9703
- $defwPt = $this->fwPt;
9704
- $defhPt = $this->fhPt;
9705
- } else {
9706
- $defwPt = $this->fhPt;
9707
- $defhPt = $this->fwPt;
9708
- }
9709
- $annotid = (3 + 2 * $nb);
9710
-
9711
- // Active Forms
9712
- $totaladdnum = 0;
9713
- for ($n = 1; $n <= $nb; $n++) {
9714
- if (isset($this->PageLinks[$n])) {
9715
- $totaladdnum += count($this->PageLinks[$n]);
9716
- }
9717
- /* -- ANNOTATIONS -- */
9718
- if (isset($this->PageAnnots[$n])) {
9719
- foreach ($this->PageAnnots[$n] as $k => $pl) {
9720
- if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) {
9721
- $totaladdnum += 2;
9722
- } else {
9723
- $totaladdnum++;
9724
- }
9725
- }
9726
- }
9727
- /* -- END ANNOTATIONS -- */
9728
-
9729
- /* -- FORMS -- */
9730
- if (count($this->form->forms) > 0) {
9731
- $this->form->countPageForms($n, $totaladdnum);
9732
- }
9733
- /* -- END FORMS -- */
9734
- }
9735
- /* -- FORMS -- */
9736
- // Make a note in the radio button group of the obj_id it will have
9737
- $ctr = 0;
9738
- if (count($this->form->form_radio_groups)) {
9739
- foreach ($this->form->form_radio_groups as $name => $frg) {
9740
- $this->form->form_radio_groups[$name]['obj_id'] = $annotid + $totaladdnum + $ctr;
9741
- $ctr++;
9742
- }
9743
- }
9744
- /* -- END FORMS -- */
9745
-
9746
- // Select unused fonts (usually default font)
9747
- $unused = [];
9748
- foreach ($this->fonts as $fk => $font) {
9749
- if (isset($font['type']) && $font['type'] == 'TTF' && !$font['used']) {
9750
- $unused[] = $fk;
9751
- }
9752
- }
9753
-
9754
-
9755
- for ($n = 1; $n <= $nb; $n++) {
9756
- $thispage = $this->pages[$n];
9757
- if (isset($this->OrientationChanges[$n])) {
9758
- $hPt = $this->pageDim[$n]['w'] * Mpdf::SCALE;
9759
- $wPt = $this->pageDim[$n]['h'] * Mpdf::SCALE;
9760
- $owidthPt_LR = $this->pageDim[$n]['outer_width_TB'] * Mpdf::SCALE;
9761
- $owidthPt_TB = $this->pageDim[$n]['outer_width_LR'] * Mpdf::SCALE;
9762
- } else {
9763
- $wPt = $this->pageDim[$n]['w'] * Mpdf::SCALE;
9764
- $hPt = $this->pageDim[$n]['h'] * Mpdf::SCALE;
9765
- $owidthPt_LR = $this->pageDim[$n]['outer_width_LR'] * Mpdf::SCALE;
9766
- $owidthPt_TB = $this->pageDim[$n]['outer_width_TB'] * Mpdf::SCALE;
9767
- }
9768
- // Remove references to unused fonts (usually default font)
9769
- foreach ($unused as $fk) {
9770
- if ($this->fonts[$fk]['sip'] || $this->fonts[$fk]['smp']) {
9771
- foreach ($this->fonts[$fk]['subsetfontids'] as $k => $fid) {
9772
- $thispage = preg_replace('/\s\/F' . $fid . ' \d[\d.]* Tf\s/is', ' ', $thispage);
9773
- }
9774
- } else {
9775
- $thispage = preg_replace('/\s\/F' . $this->fonts[$fk]['i'] . ' \d[\d.]* Tf\s/is', ' ', $thispage);
9776
- }
9777
- }
9778
- // Clean up repeated /GS1 gs statements
9779
- // For some reason using + for repetition instead of {2,20} crashes PHP Script Interpreter ???
9780
- $thispage = preg_replace('/(\/GS1 gs\n){2,20}/', "/GS1 gs\n", $thispage);
9781
-
9782
- $thispage = preg_replace('/(\s*___BACKGROUND___PATTERNS' . $this->uniqstr . '\s*)/', " ", $thispage);
9783
- $thispage = preg_replace('/(\s*___HEADER___MARKER' . $this->uniqstr . '\s*)/', " ", $thispage);
9784
- $thispage = preg_replace('/(\s*___PAGE___START' . $this->uniqstr . '\s*)/', " ", $thispage);
9785
- $thispage = preg_replace('/(\s*___TABLE___BACKGROUNDS' . $this->uniqstr . '\s*)/', " ", $thispage);
9786
- // mPDF 5.7.3 TRANSFORMS
9787
- while (preg_match('/(\% BTR(.*?)\% ETR)/is', $thispage, $m)) {
9788
- $thispage = preg_replace('/(\% BTR.*?\% ETR)/is', '', $thispage, 1) . "\n" . $m[2];
9789
- }
9790
-
9791
- // Page
9792
- $this->_newobj();
9793
- $this->_out('<</Type /Page');
9794
- $this->_out('/Parent 1 0 R');
9795
- if (isset($this->OrientationChanges[$n])) {
9796
- $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]', $hPt, $wPt));
9797
- // If BleedBox is defined, it must be larger than the TrimBox, but smaller than the MediaBox
9798
- $bleedMargin = $this->pageDim[$n]['bleedMargin'] * Mpdf::SCALE;
9799
- if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
9800
- $x0 = $owidthPt_TB - $bleedMargin;
9801
- $y0 = $owidthPt_LR - $bleedMargin;
9802
- $x1 = $hPt - $owidthPt_TB + $bleedMargin;
9803
- $y1 = $wPt - $owidthPt_LR + $bleedMargin;
9804
- $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
9805
- }
9806
- $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_TB, $owidthPt_LR, ($hPt - $owidthPt_TB), ($wPt - $owidthPt_LR)));
9807
- if (isset($this->OrientationChanges[$n]) && $this->displayDefaultOrientation) {
9808
- if ($this->DefOrientation == 'P') {
9809
- $this->_out('/Rotate 270');
9810
- } else {
9811
- $this->_out('/Rotate 90');
9812
- }
9813
- }
9814
- } // elseif($wPt != $defwPt || $hPt != $defhPt) {
9815
- else {
9816
- $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]', $wPt, $hPt));
9817
- $bleedMargin = $this->pageDim[$n]['bleedMargin'] * Mpdf::SCALE;
9818
- if ($bleedMargin && ($owidthPt_TB || $owidthPt_LR)) {
9819
- $x0 = $owidthPt_LR - $bleedMargin;
9820
- $y0 = $owidthPt_TB - $bleedMargin;
9821
- $x1 = $wPt - $owidthPt_LR + $bleedMargin;
9822
- $y1 = $hPt - $owidthPt_TB + $bleedMargin;
9823
- $this->_out(sprintf('/BleedBox [%.3F %.3F %.3F %.3F]', $x0, $y0, $x1, $y1));
9824
- }
9825
- $this->_out(sprintf('/TrimBox [%.3F %.3F %.3F %.3F]', $owidthPt_LR, $owidthPt_TB, ($wPt - $owidthPt_LR), ($hPt - $owidthPt_TB)));
9826
- }
9827
- $this->_out('/Resources 2 0 R');
9828
-
9829
- // Important to keep in RGB colorSpace when using transparency
9830
- if (!$this->PDFA && !$this->PDFX) {
9831
- if ($this->restrictColorSpace == 3) {
9832
- $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceCMYK >> ');
9833
- } elseif ($this->restrictColorSpace == 1) {
9834
- $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceGray >> ');
9835
- } else {
9836
- $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceRGB >> ');
9837
- }
9838
- }
9839
-
9840
- $annotsnum = 0;
9841
- $embeddedfiles = []; // mPDF 5.7.2 /EmbeddedFiles
9842
-
9843
- if (isset($this->PageLinks[$n])) {
9844
- $annotsnum += count($this->PageLinks[$n]);
9845
- }
9846
- /* -- ANNOTATIONS -- */
9847
- if (isset($this->PageAnnots[$n])) {
9848
- foreach ($this->PageAnnots[$n] as $k => $pl) {
9849
- if (!empty($pl['opt']['file'])) {
9850
- $embeddedfiles[$annotsnum + 1] = true;
9851
- } // mPDF 5.7.2 /EmbeddedFiles
9852
- if (!empty($pl['opt']['popup']) || !empty($pl['opt']['file'])) {
9853
- $annotsnum += 2;
9854
- } else {
9855
- $annotsnum++;
9856
- }
9857
- $this->PageAnnots[$n][$k]['pageobj'] = $this->n;
9858
- }
9859
- }
9860
- /* -- END ANNOTATIONS -- */
9861
-
9862
- /* -- FORMS -- */
9863
- // Active Forms
9864
- $formsnum = 0;
9865
- if (count($this->form->forms) > 0) {
9866
- foreach ($this->form->forms as $val) {
9867
- if ($val['page'] == $n) {
9868
- $formsnum++;
9869
- }
9870
- }
9871
- }
9872
- /* -- END FORMS -- */
9873
- if ($annotsnum || $formsnum) {
9874
- $s = '/Annots [ ';
9875
- for ($i = 0; $i < $annotsnum; $i++) {
9876
- if (!isset($embeddedfiles[$i])) {
9877
- $s .= ($annotid + $i) . ' 0 R ';
9878
- } // mPDF 5.7.2 /EmbeddedFiles
9879
- }
9880
- $annotid += $annotsnum;
9881
- /* -- FORMS -- */
9882
- if (count($this->form->forms) > 0) {
9883
- $this->form->addFormIds($n, $s, $annotid);
9884
- }
9885
- /* -- END FORMS -- */
9886
- $s .= '] ';
9887
- $this->_out($s);
9888
- }
9889
-
9890
- $this->_out('/Contents ' . ($this->n + 1) . ' 0 R>>');
9891
- $this->_out('endobj');
9892
-
9893
- // Page content
9894
- $this->_newobj();
9895
- $p = ($this->compress) ? gzcompress($thispage) : $thispage;
9896
- $this->_out('<<' . $filter . '/Length ' . strlen($p) . '>>');
9897
- $this->_putstream($p);
9898
- $this->_out('endobj');
9899
- }
9900
- $this->_putannots(); // mPDF 5.7.2
9901
- // Pages root
9902
- $this->offsets[1] = strlen($this->buffer);
9903
- $this->_out('1 0 obj');
9904
- $this->_out('<</Type /Pages');
9905
- $kids = '/Kids [';
9906
- for ($i = 0; $i < $nb; $i++) {
9907
- $kids .= (3 + 2 * $i) . ' 0 R ';
9908
- }
9909
- $this->_out($kids . ']');
9910
- $this->_out('/Count ' . $nb);
9911
- $this->_out(sprintf('/MediaBox [0 0 %.3F %.3F]', $defwPt, $defhPt));
9912
- $this->_out('>>');
9913
- $this->_out('endobj');
9914
- }
9915
-
9916
- /**
9917
- * @since 5.7.2
9918
- */
9919
- function _putannots()
9920
- {
9921
- $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
9922
-
9923
- $nb = $this->page;
9924
-
9925
- for ($n = 1; $n <= $nb; $n++) {
9926
-
9927
- $annotobjs = [];
9928
-
9929
- if (isset($this->PageLinks[$n]) || isset($this->PageAnnots[$n]) || count($this->form->forms) > 0) {
9930
-
9931
- $wPt = $this->pageDim[$n]['w'] * Mpdf::SCALE;
9932
- $hPt = $this->pageDim[$n]['h'] * Mpdf::SCALE;
9933
-
9934
- // Links
9935
- if (isset($this->PageLinks[$n])) {
9936
-
9937
- foreach ($this->PageLinks[$n] as $key => $pl) {
9938
-
9939
- $this->_newobj();
9940
- $annot = '';
9941
-
9942
- $rect = sprintf('%.3F %.3F %.3F %.3F', $pl[0], $pl[1], $pl[0] + $pl[2], $pl[1] - $pl[3]);
9943
-
9944
- $annot .= '<</Type /Annot /Subtype /Link /Rect [' . $rect . ']';
9945
- // Removed as causing undesired effects in Chrome PDF viewer https://github.com/mpdf/mpdf/issues/283
9946
- // $annot .= ' /Contents ' . $this->_UTF16BEtextstring($pl[4]);
9947
- $annot .= ' /NM ' . $this->_textstring(sprintf('%04u-%04u', $n, $key));
9948
- $annot .= ' /M ' . $this->_textstring('D:' . date('YmdHis'));
9949
-
9950
- $annot .= ' /Border [0 0 0]';
9951
-
9952
- // Use this (instead of /Border) to specify border around link
9953
-
9954
- // $annot .= ' /BS <</W 1'; // Width on points; 0 = no line
9955
- // $annot .= ' /S /D'; // style - [S]olid, [D]ashed, [B]eveled, [I]nset, [U]nderline
9956
- // $annot .= ' /D [3 2]'; // Dash array - if dashed
9957
- // $annot .= ' >>';
9958
- // $annot .= ' /C [1 0 0]'; // Color RGB
9959
-
9960
- if ($this->PDFA || $this->PDFX) {
9961
- $annot .= ' /F 28';
9962
- }
9963
-
9964
- if (strpos($pl[4], '@') === 0) {
9965
-
9966
- $p = substr($pl[4], 1);
9967
- // $h=isset($this->OrientationChanges[$p]) ? $wPt : $hPt;
9968
- $htarg = $this->pageDim[$p]['h'] * Mpdf::SCALE;
9969
- $annot .= sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>', 1 + 2 * $p, $htarg);
9970
-
9971
- } elseif (is_string($pl[4])) {
9972
-
9973
- $annot .= ' /A <</S /URI /URI ' . $this->_textstring($pl[4]) . '>> >>';
9974
-
9975
- } else {
9976
-
9977
- $l = $this->links[$pl[4]];
9978
- // may not be set if #link points to non-existent target
9979
- if (isset($this->pageDim[$l[0]]['h'])) {
9980
- $htarg = $this->pageDim[$l[0]]['h'] * Mpdf::SCALE;
9981
- } else {
9982
- $htarg = $this->h * Mpdf::SCALE;
9983
- } // doesn't really matter
9984
-
9985
- $annot .= sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>', 1 + 2 * $l[0], $htarg - $l[1] * Mpdf::SCALE);
9986
- }
9987
-
9988
- $this->_out($annot);
9989
- $this->_out('endobj');
9990
-
9991
- }
9992
- }
9993
-
9994
- /* -- ANNOTATIONS -- */
9995
- if (isset($this->PageAnnots[$n])) {
9996
-
9997
- foreach ($this->PageAnnots[$n] as $key => $pl) {
9998
-
9999
- $fileAttachment = (bool) $pl['opt']['file'];
10000
-
10001
- if ($fileAttachment && !$this->allowAnnotationFiles) {
10002
- $this->logger->warning('Embedded files for annotations have to be allowed explicitly with "allowAnnotationFiles" config key');
10003
- $fileAttachment = false;
10004
- }
10005
-
10006
- $this->_newobj();
10007
- $annot = '';
10008
- $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER);
10009
- $x = $pl['x'];
10010
-
10011
- if ($this->annotMargin <> 0 || $x == 0 || $x < 0) { // Odd page
10012
- $x = ($wPt / Mpdf::SCALE) - $this->annotMargin;
10013
- }
10014
-
10015
- $w = $h = 0;
10016
- $a = $x * Mpdf::SCALE;
10017
- $b = $hPt - ($pl['y'] * Mpdf::SCALE);
10018
-
10019
- $annot .= '<</Type /Annot ';
10020
-
10021
- if ($fileAttachment) {
10022
- $annot .= '/Subtype /FileAttachment ';
10023
- // Need to set a size for FileAttachment icons
10024
- if ($pl['opt']['icon'] == 'Paperclip') {
10025
- $w = 8.235;
10026
- $h = 20;
10027
- } elseif ($pl['opt']['icon'] == 'Tag') {
10028
- $w = 20;
10029
- $h = 16;
10030
- } elseif ($pl['opt']['icon'] == 'Graph') {
10031
- $w = 20;
10032
- $h = 20;
10033
- } else {
10034
- $w = 14;
10035
- $h = 20;
10036
- }
10037
-
10038
- // PushPin
10039
- $f = $pl['opt']['file'];
10040
- $f = preg_replace('/^.*\//', '', $f);
10041
- $f = preg_replace('/[^a-zA-Z0-9._]/', '', $f);
10042
-
10043
- $annot .= '/FS <</Type /Filespec /F (' . $f . ')';
10044
- $annot .= '/EF <</F ' . ($this->n + 1) . ' 0 R>>';
10045
- $annot .= '>>';
10046
-
10047
- } else {
10048
- $annot .= '/Subtype /Text';
10049
- $w = 20;
10050
- $h = 20; // mPDF 6
10051
- }
10052
-
10053
- $rect = sprintf('%.3F %.3F %.3F %.3F', $a, $b - $h, $a + $w, $b);
10054
- $annot .= ' /Rect [' . $rect . ']';
10055
-
10056
- // contents = description of file in free text
10057
- $annot .= ' /Contents ' . $this->_UTF16BEtextstring($pl['txt']);
10058
-
10059
- $annot .= ' /NM ' . $this->_textstring(sprintf('%04u-%04u', $n, (2000 + $key)));
10060
- $annot .= ' /M ' . $this->_textstring('D:' . date('YmdHis'));
10061
- $annot .= ' /CreationDate ' . $this->_textstring('D:' . date('YmdHis'));
10062
- $annot .= ' /Border [0 0 0]';
10063
-
10064
- if ($this->PDFA || $this->PDFX) {
10065
- $annot .= ' /F 28';
10066
- $annot .= ' /CA 1';
10067
- } elseif ($pl['opt']['ca'] > 0) {
10068
- $annot .= ' /CA ' . $pl['opt']['ca'];
10069
- }
10070
-
10071
- $annotcolor = ' /C [';
10072
- if (isset($pl['opt']['c']) and $pl['opt']['c']) {
10073
- $col = $pl['opt']['c'];
10074
- if ($col{0} == 3 || $col{0} == 5) {
10075
- $annotcolor .= sprintf("%.3F %.3F %.3F", ord($col{1}) / 255, ord($col{2}) / 255, ord($col{3}) / 255);
10076
- } elseif ($col{0} == 1) {
10077
- $annotcolor .= sprintf("%.3F", ord($col{1}) / 255);
10078
- } elseif ($col{0} == 4 || $col{0} == 6) {
10079
- $annotcolor .= sprintf("%.3F %.3F %.3F %.3F", ord($col{1}) / 100, ord($col{2}) / 100, ord($col{3}) / 100, ord($col{4}) / 100);
10080
- } else {
10081
- $annotcolor .= '1 1 0';
10082
- }
10083
- } else {
10084
- $annotcolor .= '1 1 0';
10085
- }
10086
- $annotcolor .= ']';
10087
- $annot .= $annotcolor;
10088
-
10089
- // Usually Author
10090
- // Use as Title for fileattachment
10091
- if (isset($pl['opt']['t']) and is_string($pl['opt']['t'])) {
10092
- $annot .= ' /T ' . $this->_UTF16BEtextstring($pl['opt']['t']);
10093
- }
10094
-
10095
- if ($fileAttachment) {
10096
- $iconsapp = ['Paperclip', 'Graph', 'PushPin', 'Tag'];
10097
- } else {
10098
- $iconsapp = ['Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph'];
10099
- }
10100
-
10101
- if (isset($pl['opt']['icon']) and in_array($pl['opt']['icon'], $iconsapp)) {
10102
- $annot .= ' /Name /' . $pl['opt']['icon'];
10103
- } elseif ($fileAttachment) {
10104
- $annot .= ' /Name /PushPin';
10105
- } else {
10106
- $annot .= ' /Name /Note';
10107
- }
10108
-
10109
- if (!$fileAttachment) {
10110
- ///Subj is PDF 1.5 spec.
10111
- if (isset($pl['opt']['subj']) && !$this->PDFA && !$this->PDFX) {
10112
- $annot .= ' /Subj ' . $this->_UTF16BEtextstring($pl['opt']['subj']);
10113
- }
10114
- if (!empty($pl['opt']['popup'])) {
10115
- $annot .= ' /Open true';
10116
- $annot .= ' /Popup ' . ($this->n + 1) . ' 0 R';
10117
- } else {
10118
- $annot .= ' /Open false';
10119
- }
10120
- }
10121
-
10122
- $annot .= ' /P ' . $pl['pageobj'] . ' 0 R';
10123
- $annot .= '>>';
10124
- $this->_out($annot);
10125
- $this->_out('endobj');
10126
-
10127
- if ($fileAttachment) {
10128
- $file = @file_get_contents($pl['opt']['file']);
10129
- if (!$file) {
10130
- throw new \Mpdf\MpdfException('mPDF Error: Cannot access file attachment - ' . $pl['opt']['file']);
10131
- }
10132
- $filestream = gzcompress($file);
10133
- $this->_newobj();
10134
- $this->_out('<</Type /EmbeddedFile');
10135
- $this->_out('/Length ' . strlen($filestream));
10136
- $this->_out('/Filter /FlateDecode');
10137
- $this->_out('>>');
10138
- $this->_putstream($filestream);
10139
- $this->_out('endobj');
10140
- } elseif (!empty($pl['opt']['popup'])) {
10141
- $this->_newobj();
10142
- $annot = '';
10143
- if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][0])) {
10144
- $x = $pl['opt']['popup'][0] * Mpdf::SCALE;
10145
- } else {
10146
- $x = $pl['x'] * Mpdf::SCALE;
10147
- }
10148
- if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][1])) {
10149
- $y = $hPt - ($pl['opt']['popup'][1] * Mpdf::SCALE);
10150
- } else {
10151
- $y = $hPt - ($pl['y'] * Mpdf::SCALE);
10152
- }
10153
- if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][2])) {
10154
- $w = $pl['opt']['popup'][2] * Mpdf::SCALE;
10155
- } else {
10156
- $w = 180;
10157
- }
10158
- if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][3])) {
10159
- $h = $pl['opt']['popup'][3] * Mpdf::SCALE;
10160
- } else {
10161
- $h = 120;
10162
- }
10163
- $rect = sprintf('%.3F %.3F %.3F %.3F', $x, $y - $h, $x + $w, $y);
10164
- $annot .= '<</Type /Annot /Subtype /Popup /Rect [' . $rect . ']';
10165
- $annot .= ' /M ' . $this->_textstring('D:' . date('YmdHis'));
10166
- if ($this->PDFA || $this->PDFX) {
10167
- $annot .= ' /F 28';
10168
- }
10169
- $annot .= ' /Parent ' . ($this->n - 1) . ' 0 R';
10170
- $annot .= '>>';
10171
- $this->_out($annot);
10172
- $this->_out('endobj');
10173
- }
10174
- }
10175
- }
10176
-
10177
- /* -- END ANNOTATIONS -- */
10178
-
10179
- /* -- FORMS -- */
10180
- // Active Forms
10181
- if (count($this->form->forms) > 0) {
10182
- $this->form->_putFormItems($n, $hPt);
10183
- }
10184
- /* -- END FORMS -- */
10185
- }
10186
- }
10187
-
10188
- /* -- FORMS -- */
10189
- // Active Forms - Radio Button Group entries
10190
- // Output Radio Button Group form entries (radio_on_obj_id already determined)
10191
- if (count($this->form->form_radio_groups)) {
10192
- $this->form->_putRadioItems($n);
10193
- }
10194
- /* -- END FORMS -- */
10195
- }
10196
-
10197
  /* -- ANNOTATIONS -- */
10198
-
10199
  function Annotation($text, $x = 0, $y = 0, $icon = 'Note', $author = '', $subject = '', $opacity = 0, $colarray = false, $popup = '', $file = '')
10200
  {
10201
  if (is_array($colarray) && count($colarray) == 3) {
@@ -10266,3943 +9775,2541 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
10266
 
10267
  /* -- END ANNOTATIONS -- */
10268
 
10269
- function _putfonts()
10270
- {
10271
- $nf = $this->n;
10272
- foreach ($this->FontFiles as $fontkey => $info) {
10273
- // TrueType embedded
10274
- if (isset($info['type']) && $info['type'] == 'TTF' && !$info['sip'] && !$info['smp']) {
10275
- $used = true;
10276
- $asSubset = false;
10277
- foreach ($this->fonts as $k => $f) {
10278
- if (isset($f['fontkey']) && $f['fontkey'] == $fontkey && $f['type'] == 'TTF') {
10279
- $used = $f['used'];
10280
- if ($used) {
10281
- $nChars = (ord($f['cw'][0]) << 8) + ord($f['cw'][1]);
10282
- $usage = intval(count($f['subset']) * 100 / $nChars);
10283
- $fsize = $info['length1'];
10284
- // Always subset the very large TTF files
10285
- if ($fsize > ($this->maxTTFFilesize * 1024)) {
10286
- $asSubset = true;
10287
- } elseif ($usage < $this->percentSubset) {
10288
- $asSubset = true;
10289
- }
10290
- }
10291
- if ($this->PDFA || $this->PDFX) {
10292
- $asSubset = false;
10293
- }
10294
- $this->fonts[$k]['asSubset'] = $asSubset;
10295
- break;
10296
- }
10297
- }
10298
- if ($used && !$asSubset) {
10299
- // Font file embedding
10300
- $this->_newobj();
10301
- $this->FontFiles[$fontkey]['n'] = $this->n;
10302
- $originalsize = $info['length1'];
10303
- if ($this->repackageTTF || $this->fonts[$fontkey]['TTCfontID'] > 0 || $this->fonts[$fontkey]['useOTL'] > 0) { // mPDF 5.7.1
10304
- // First see if there is a cached compressed file
10305
- if ($this->fontCache->has($fontkey . '.ps.z')) {
10306
- $font = $this->fontCache->load($fontkey . '.ps.z');
10307
- include $this->fontCache->tempFilename($fontkey . '.ps.php'); // sets $originalsize (of repackaged font)
10308
- } else {
10309
- $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor);
10310
- $font = $ttf->repackageTTF($this->FontFiles[$fontkey]['ttffile'], $this->fonts[$fontkey]['TTCfontID'], $this->debugfonts, $this->fonts[$fontkey]['useOTL']); // mPDF 5.7.1
10311
 
10312
- $originalsize = strlen($font);
10313
- $font = gzcompress($font);
10314
- unset($ttf);
10315
 
10316
- $len = "<?php \n";
10317
- $len .= '$originalsize=' . $originalsize . ";\n";
10318
 
10319
- $this->fontCache->binaryWrite($fontkey . '.ps.z', $font);
10320
- $this->fontCache->write($fontkey . '.ps.php', $len);
10321
- }
10322
- } else {
10323
- // First see if there is a cached compressed file
10324
- if ($this->fontCache->has($fontkey . '.z')) {
10325
- $font = $this->fontCache->load($fontkey . '.z', 'rb');
10326
- } else {
10327
- $font = file_get_contents($this->FontFiles[$fontkey]['ttffile']);
10328
- $font = gzcompress($font);
10329
- $this->fontCache->binaryWrite($fontkey . '.z', $font);
10330
  }
10331
  }
10332
-
10333
- $this->_out('<</Length ' . strlen($font));
10334
- $this->_out('/Filter /FlateDecode');
10335
- $this->_out('/Length1 ' . $originalsize);
10336
- $this->_out('>>');
10337
- $this->_putstream($font);
10338
- $this->_out('endobj');
10339
  }
10340
  }
10341
  }
10342
 
10343
- $nfonts = count($this->fonts);
10344
- $fctr = 1;
10345
- foreach ($this->fonts as $k => $font) {
10346
- // Font objects
10347
- $type = $font['type'];
10348
- $name = $font['name'];
10349
- if ((!isset($font['used']) || !$font['used']) && $type == 'TTF') {
10350
- continue;
10351
- }
10352
-
10353
- // @log Writing fonts
10354
-
10355
- if (isset($font['asSubset'])) {
10356
- $asSubset = $font['asSubset'];
10357
- } else {
10358
- $asSubset = '';
10359
- }
10360
- /* -- CJK-FONTS -- */
10361
- if ($type == 'Type0') { // = Adobe CJK Fonts
10362
- $this->fonts[$k]['n'] = $this->n + 1;
10363
- $this->_newobj();
10364
- $this->_out('<</Type /Font');
10365
- $this->_putType0($font);
10366
- } else { /* -- END CJK-FONTS -- */
10367
- if ($type == 'core') {
10368
- // Standard font
10369
- $this->fonts[$k]['n'] = $this->n + 1;
10370
- if ($this->PDFA || $this->PDFX) {
10371
- throw new \Mpdf\MpdfException('Core fonts are not allowed in PDF/A1-b or PDFX/1-a files (Times, Helvetica, Courier etc.)');
10372
- }
10373
- $this->_newobj();
10374
- $this->_out('<</Type /Font');
10375
- $this->_out('/BaseFont /' . $name);
10376
- $this->_out('/Subtype /Type1');
10377
- if ($name != 'Symbol' && $name != 'ZapfDingbats') {
10378
- $this->_out('/Encoding /WinAnsiEncoding');
10379
- }
10380
- $this->_out('>>');
10381
- $this->_out('endobj');
10382
- } // TrueType embedded SUBSETS for SIP (CJK extB containing Supplementary Ideographic Plane 2)
10383
- // Or Unicode Plane 1 - Supplementary Multilingual Plane
10384
- elseif ($type == 'TTF' && ($font['sip'] || $font['smp'])) {
10385
- if (!$font['used']) {
10386
- continue;
10387
- }
10388
- $ssfaid = "AA";
10389
- $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor);
10390
- for ($sfid = 0; $sfid < count($font['subsetfontids']); $sfid++) {
10391
- $this->fonts[$k]['n'][$sfid] = $this->n + 1; // NB an array for subset
10392
- $subsetname = 'MPDF' . $ssfaid . '+' . $font['name'];
10393
- $ssfaid++;
10394
-
10395
- /* For some strange reason a subset ($sfid > 0) containing less than 97 characters causes an error
10396
- so fill up the array */
10397
- for ($j = count($font['subsets'][$sfid]); $j < 98; $j++) {
10398
- $font['subsets'][$sfid][$j] = 0;
10399
- }
10400
-
10401
- $subset = $font['subsets'][$sfid];
10402
- unset($subset[0]);
10403
- $ttfontstream = $ttf->makeSubsetSIP($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts, $font['useOTL']); // mPDF 5.7.1
10404
- $ttfontsize = strlen($ttfontstream);
10405
- $fontstream = gzcompress($ttfontstream);
10406
- $widthstring = '';
10407
- $toUnistring = '';
10408
-
10409
-
10410
- foreach ($font['subsets'][$sfid] as $cp => $u) {
10411
- $w = $this->_getCharWidth($font['cw'], $u);
10412
- if ($w !== false) {
10413
- $widthstring .= $w . ' ';
10414
- } else {
10415
- $widthstring .= round($ttf->defaultWidth) . ' ';
10416
- }
10417
- if ($u > 65535) {
10418
- $utf8 = chr(($u >> 18) + 240) . chr((($u >> 12) & 63) + 128) . chr((($u >> 6) & 63) + 128) . chr(($u & 63) + 128);
10419
- $utf16 = mb_convert_encoding($utf8, 'UTF-16BE', 'UTF-8');
10420
- $l1 = ord($utf16[0]);
10421
- $h1 = ord($utf16[1]);
10422
- $l2 = ord($utf16[2]);
10423
- $h2 = ord($utf16[3]);
10424
- $toUnistring .= sprintf("<%02s> <%02s%02s%02s%02s>\n", strtoupper(dechex($cp)), strtoupper(dechex($l1)), strtoupper(dechex($h1)), strtoupper(dechex($l2)), strtoupper(dechex($h2)));
10425
- } else {
10426
- $toUnistring .= sprintf("<%02s> <%04s>\n", strtoupper(dechex($cp)), strtoupper(dechex($u)));
10427
- }
10428
- }
10429
-
10430
- // Additional Type1 or TrueType font
10431
- $this->_newobj();
10432
- $this->_out('<</Type /Font');
10433
- $this->_out('/BaseFont /' . $subsetname);
10434
- $this->_out('/Subtype /TrueType');
10435
- $this->_out('/FirstChar 0 /LastChar ' . (count($font['subsets'][$sfid]) - 1));
10436
- $this->_out('/Widths ' . ($this->n + 1) . ' 0 R');
10437
- $this->_out('/FontDescriptor ' . ($this->n + 2) . ' 0 R');
10438
- $this->_out('/ToUnicode ' . ($this->n + 3) . ' 0 R');
10439
- $this->_out('>>');
10440
- $this->_out('endobj');
10441
-
10442
- // Widths
10443
- $this->_newobj();
10444
- $this->_out('[' . $widthstring . ']');
10445
- $this->_out('endobj');
10446
-
10447
- // Descriptor
10448
- $this->_newobj();
10449
- $s = '<</Type /FontDescriptor /FontName /' . $subsetname . "\n";
10450
- foreach ($font['desc'] as $kd => $v) {
10451
- if ($kd == 'Flags') {
10452
- $v = $v | 4;
10453
- $v = $v & ~32;
10454
- } // SYMBOLIC font flag
10455
- $s .= ' /' . $kd . ' ' . $v . "\n";
10456
- }
10457
- $s .= '/FontFile2 ' . ($this->n + 2) . ' 0 R';
10458
- $this->_out($s . '>>');
10459
- $this->_out('endobj');
10460
-
10461
- // ToUnicode
10462
- $this->_newobj();
10463
- $toUni = "/CIDInit /ProcSet findresource begin\n";
10464
- $toUni .= "12 dict begin\n";
10465
- $toUni .= "begincmap\n";
10466
- $toUni .= "/CIDSystemInfo\n";
10467
- $toUni .= "<</Registry (Adobe)\n";
10468
- $toUni .= "/Ordering (UCS)\n";
10469
- $toUni .= "/Supplement 0\n";
10470
- $toUni .= ">> def\n";
10471
- $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
10472
- $toUni .= "/CMapType 2 def\n";
10473
- $toUni .= "1 begincodespacerange\n";
10474
- $toUni .= "<00> <FF>\n";
10475
- // $toUni .= sprintf("<00> <%02s>\n", strtoupper(dechex(count($font['subsets'][$sfid])-1)));
10476
- $toUni .= "endcodespacerange\n";
10477
- $toUni .= count($font['subsets'][$sfid]) . " beginbfchar\n";
10478
- $toUni .= $toUnistring;
10479
- $toUni .= "endbfchar\n";
10480
- $toUni .= "endcmap\n";
10481
- $toUni .= "CMapName currentdict /CMap defineresource pop\n";
10482
- $toUni .= "end\n";
10483
- $toUni .= "end\n";
10484
- $this->_out('<</Length ' . (strlen($toUni)) . '>>');
10485
- $this->_putstream($toUni);
10486
- $this->_out('endobj');
10487
-
10488
- // Font file
10489
- $this->_newobj();
10490
- $this->_out('<</Length ' . strlen($fontstream));
10491
- $this->_out('/Filter /FlateDecode');
10492
- $this->_out('/Length1 ' . $ttfontsize);
10493
- $this->_out('>>');
10494
- $this->_putstream($fontstream);
10495
- $this->_out('endobj');
10496
- } // foreach subset
10497
- unset($ttf);
10498
- } // TrueType embedded SUBSETS or FULL
10499
- elseif ($type == 'TTF') {
10500
- $this->fonts[$k]['n'] = $this->n + 1;
10501
- if ($asSubset) {
10502
- $ssfaid = "A";
10503
- $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor);
10504
- $fontname = 'MPDFA' . $ssfaid . '+' . $font['name'];
10505
- $subset = $font['subset'];
10506
- unset($subset[0]);
10507
- $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset, $font['TTCfontID'], $this->debugfonts, $font['useOTL']);
10508
- $ttfontsize = strlen($ttfontstream);
10509
- $fontstream = gzcompress($ttfontstream);
10510
- $codeToGlyph = $ttf->codeToGlyph;
10511
- unset($codeToGlyph[0]);
10512
- } else {
10513
- $fontname = $font['name'];
10514
- }
10515
- // Type0 Font
10516
- // A composite font - a font composed of other fonts, organized hierarchically
10517
- $this->_newobj();
10518
- $this->_out('<</Type /Font');
10519
- $this->_out('/Subtype /Type0');
10520
- $this->_out('/BaseFont /' . $fontname . '');
10521
- $this->_out('/Encoding /Identity-H');
10522
- $this->_out('/DescendantFonts [' . ($this->n + 1) . ' 0 R]');
10523
- $this->_out('/ToUnicode ' . ($this->n + 2) . ' 0 R');
10524
- $this->_out('>>');
10525
- $this->_out('endobj');
10526
-
10527
- // CIDFontType2
10528
- // A CIDFont whose glyph descriptions are based on TrueType font technology
10529
- $this->_newobj();
10530
- $this->_out('<</Type /Font');
10531
- $this->_out('/Subtype /CIDFontType2');
10532
- $this->_out('/BaseFont /' . $fontname . '');
10533
- $this->_out('/CIDSystemInfo ' . ($this->n + 2) . ' 0 R');
10534
- $this->_out('/FontDescriptor ' . ($this->n + 3) . ' 0 R');
10535
- if (isset($font['desc']['MissingWidth'])) {
10536
- $this->_out('/DW ' . $font['desc']['MissingWidth'] . '');
10537
- }
10538
-
10539
- if (!$asSubset && $this->fontCache->has($font['fontkey'] . '.cw')) {
10540
- $w = $this->fontCache->load($font['fontkey'] . '.cw');
10541
- $this->_out($w);
10542
- } else {
10543
- $this->_putTTfontwidths($font, $asSubset, ($asSubset ? $ttf->maxUni : 0));
10544
- }
10545
-
10546
- $this->_out('/CIDToGIDMap ' . ($this->n + 4) . ' 0 R');
10547
- $this->_out('>>');
10548
- $this->_out('endobj');
10549
-
10550
- // ToUnicode
10551
- $this->_newobj();
10552
- $toUni = "/CIDInit /ProcSet findresource begin\n";
10553
- $toUni .= "12 dict begin\n";
10554
- $toUni .= "begincmap\n";
10555
- $toUni .= "/CIDSystemInfo\n";
10556
- $toUni .= "<</Registry (Adobe)\n";
10557
- $toUni .= "/Ordering (UCS)\n";
10558
- $toUni .= "/Supplement 0\n";
10559
- $toUni .= ">> def\n";
10560
- $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
10561
- $toUni .= "/CMapType 2 def\n";
10562
- $toUni .= "1 begincodespacerange\n";
10563
- $toUni .= "<0000> <FFFF>\n";
10564
- $toUni .= "endcodespacerange\n";
10565
- $toUni .= "1 beginbfrange\n";
10566
- $toUni .= "<0000> <FFFF> <0000>\n";
10567
- $toUni .= "endbfrange\n";
10568
- $toUni .= "endcmap\n";
10569
- $toUni .= "CMapName currentdict /CMap defineresource pop\n";
10570
- $toUni .= "end\n";
10571
- $toUni .= "end\n";
10572
- $this->_out('<</Length ' . (strlen($toUni)) . '>>');
10573
- $this->_putstream($toUni);
10574
- $this->_out('endobj');
10575
-
10576
-
10577
- // CIDSystemInfo dictionary
10578
- $this->_newobj();
10579
- $this->_out('<</Registry (Adobe)');
10580
- $this->_out('/Ordering (UCS)');
10581
- $this->_out('/Supplement 0');
10582
- $this->_out('>>');
10583
- $this->_out('endobj');
10584
-
10585
- // Font descriptor
10586
- $this->_newobj();
10587
- $this->_out('<</Type /FontDescriptor');
10588
- $this->_out('/FontName /' . $fontname);
10589
- foreach ($font['desc'] as $kd => $v) {
10590
- if ($asSubset && $kd == 'Flags') {
10591
- $v = $v | 4;
10592
- $v = $v & ~32;
10593
- } // SYMBOLIC font flag
10594
- $this->_out(' /' . $kd . ' ' . $v);
10595
- }
10596
- if ($font['panose']) {
10597
- $this->_out(' /Style << /Panose <' . $font['panose'] . '> >>');
10598
- }
10599
- if ($asSubset) {
10600
- $this->_out('/FontFile2 ' . ($this->n + 2) . ' 0 R');
10601
- } elseif ($font['fontkey']) {
10602
- // obj ID of a stream containing a TrueType font program
10603
- $this->_out('/FontFile2 ' . $this->FontFiles[$font['fontkey']]['n'] . ' 0 R');
10604
- }
10605
- $this->_out('>>');
10606
- $this->_out('endobj');
10607
-
10608
- // Embed CIDToGIDMap
10609
- // A specification of the mapping from CIDs to glyph indices
10610
- if ($asSubset) {
10611
- $cidtogidmap = '';
10612
- $cidtogidmap = str_pad('', 256 * 256 * 2, "\x00");
10613
- foreach ($codeToGlyph as $cc => $glyph) {
10614
- $cidtogidmap[$cc * 2] = chr($glyph >> 8);
10615
- $cidtogidmap[$cc * 2 + 1] = chr($glyph & 0xFF);
10616
- }
10617
- $cidtogidmap = gzcompress($cidtogidmap);
10618
- } else {
10619
- // First see if there is a cached CIDToGIDMapfile
10620
- $cidtogidmap = '';
10621
- if ($this->fontCache->has($font['fontkey'] . '.cgm')) {
10622
- $cidtogidmap = $this->fontCache->load($font['fontkey'] . '.cgm');
10623
- } else {
10624
- $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor);
10625
- $charToGlyph = $ttf->getCTG($font['ttffile'], $font['TTCfontID'], $this->debugfonts, $font['useOTL']);
10626
- $cidtogidmap = str_pad('', 256 * 256 * 2, "\x00");
10627
- foreach ($charToGlyph as $cc => $glyph) {
10628
- $cidtogidmap[$cc * 2] = chr($glyph >> 8);
10629
- $cidtogidmap[$cc * 2 + 1] = chr($glyph & 0xFF);
10630
- }
10631
- unset($ttf);
10632
- $cidtogidmap = gzcompress($cidtogidmap);
10633
- $this->fontCache->binaryWrite($font['fontkey'] . '.cgm', $cidtogidmap);
10634
- }
10635
- }
10636
- $this->_newobj();
10637
- $this->_out('<</Length ' . strlen($cidtogidmap) . '');
10638
- $this->_out('/Filter /FlateDecode');
10639
- $this->_out('>>');
10640
- $this->_putstream($cidtogidmap);
10641
- $this->_out('endobj');
10642
-
10643
- // Font file
10644
- if ($asSubset) {
10645
- $this->_newobj();
10646
- $this->_out('<</Length ' . strlen($fontstream));
10647
- $this->_out('/Filter /FlateDecode');
10648
- $this->_out('/Length1 ' . $ttfontsize);
10649
- $this->_out('>>');
10650
- $this->_putstream($fontstream);
10651
- $this->_out('endobj');
10652
- unset($ttf);
10653
- }
10654
- } else {
10655
- throw new \Mpdf\MpdfException('Unsupported font type: ' . $type . ' (' . $name . ')');
10656
- }
10657
- }
10658
- }
10659
- }
10660
-
10661
- function _putTTfontwidths(&$font, $asSubset, $maxUni)
10662
- {
10663
- if ($asSubset && $this->fontCache->has($font['fontkey'] . '.cw127.php')) {
10664
- include $this->fontCache->tempFilename($font['fontkey'] . '.cw127.php');
10665
- $startcid = 128;
10666
- } else {
10667
- $rangeid = 0;
10668
- $range = [];
10669
- $prevcid = -2;
10670
- $prevwidth = -1;
10671
- $interval = false;
10672
- $startcid = 1;
10673
- }
10674
- if ($asSubset) {
10675
- $cwlen = $maxUni + 1;
10676
- } else {
10677
- $cwlen = (strlen($font['cw']) / 2);
10678
- }
10679
-
10680
- // for each character
10681
- for ($cid = $startcid; $cid < $cwlen; $cid++) {
10682
- if ($cid == 128 && $asSubset && (!$this->fontCache->has($font['fontkey'] . '.cw127.php'))) {
10683
- $cw127 = '<?php' . "\n";
10684
- $cw127 .= '$rangeid=' . $rangeid . ";\n";
10685
- $cw127 .= '$prevcid=' . $prevcid . ";\n";
10686
- $cw127 .= '$prevwidth=' . $prevwidth . ";\n";
10687
- if ($interval) {
10688
- $cw127 .= '$interval=true' . ";\n";
10689
- } else {
10690
- $cw127 .= '$interval=false' . ";\n";
10691
  }
10692
- $cw127 .= '$range=' . var_export($range, true) . ";\n";
10693
- $this->fontCache->write($font['fontkey'] . '.cw127.php', $cw127);
10694
- }
10695
-
10696
- $character1 = isset($font['cw'][$cid * 2]) ? $font['cw'][$cid * 2] : '';
10697
- $character2 = isset($font['cw'][$cid * 2 + 1]) ? $font['cw'][$cid * 2 + 1] : '';
10698
-
10699
- if ($character1 == "\00" && $character2 == "\00") {
10700
- continue;
10701
- }
10702
-
10703
- $width = (ord($character1) << 8) + ord($character2);
10704
-
10705
- if ($width == 65535) {
10706
- $width = 0;
10707
- }
10708
-
10709
- if ($asSubset && $cid > 255 && (!isset($font['subset'][$cid]) || !$font['subset'][$cid])) {
10710
- continue;
10711
- }
10712
-
10713
- if ($asSubset && $cid > 0xFFFF) {
10714
- continue;
10715
- } // mPDF 6
10716
-
10717
- if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
10718
- if ($cid == ($prevcid + 1)) {
10719
- // consecutive CID
10720
- if ($width == $prevwidth) {
10721
- if ($width == $range[$rangeid][0]) {
10722
- $range[$rangeid][] = $width;
10723
- } else {
10724
- array_pop($range[$rangeid]);
10725
- // new range
10726
- $rangeid = $prevcid;
10727
- $range[$rangeid] = [];
10728
- $range[$rangeid][] = $prevwidth;
10729
- $range[$rangeid][] = $width;
10730
- }
10731
- $interval = true;
10732
- $range[$rangeid]['interval'] = true;
10733
- } else {
10734
- if ($interval) {
10735
- // new range
10736
- $rangeid = $cid;
10737
- $range[$rangeid] = [];
10738
- $range[$rangeid][] = $width;
10739
- } else {
10740
- $range[$rangeid][] = $width;
10741
  }
10742
- $interval = false;
10743
  }
10744
- } else {
10745
- // new range
10746
- $rangeid = $cid;
10747
- $range[$rangeid] = [];
10748
- $range[$rangeid][] = $width;
10749
- $interval = false;
10750
- }
10751
- $prevcid = $cid;
10752
- $prevwidth = $width;
10753
- }
10754
- }
10755
- $w = $this->_putfontranges($range);
10756
- $this->_out($w);
10757
- if (!$asSubset) {
10758
- $this->fontCache->binaryWrite($font['fontkey'] . '.cw', $w);
10759
- }
10760
- }
10761
-
10762
- function _putfontranges(&$range)
10763
- {
10764
- // optimize ranges
10765
- $prevk = -1;
10766
- $nextk = -1;
10767
- $prevint = false;
10768
- foreach ($range as $k => $ws) {
10769
- $cws = count($ws);
10770
- if (($k == $nextk) and ( !$prevint) and ( (!isset($ws['interval'])) or ( $cws < 4))) {
10771
- if (isset($range[$k]['interval'])) {
10772
- unset($range[$k]['interval']);
10773
- }
10774
- $range[$prevk] = array_merge($range[$prevk], $range[$k]);
10775
- unset($range[$k]);
10776
- } else {
10777
- $prevk = $k;
10778
- }
10779
- $nextk = $k + $cws;
10780
- if (isset($ws['interval'])) {
10781
- if ($cws > 3) {
10782
- $prevint = true;
10783
- } else {
10784
- $prevint = false;
10785
- }
10786
- unset($range[$k]['interval']);
10787
- --$nextk;
10788
- } else {
10789
- $prevint = false;
10790
- }
10791
- }
10792
- // output data
10793
- $w = '';
10794
- foreach ($range as $k => $ws) {
10795
- if (count(array_count_values($ws)) == 1) {
10796
- // interval mode is more compact
10797
- $w .= ' ' . $k . ' ' . ($k + count($ws) - 1) . ' ' . $ws[0];
10798
- } else {
10799
- // range mode
10800
- $w .= ' ' . $k . ' [ ' . implode(' ', $ws) . ' ]' . "\n";
10801
- }
10802
- }
10803
- return '/W [' . $w . ' ]';
10804
- }
10805
-
10806
- function _putfontwidths(&$font, $cidoffset = 0)
10807
- {
10808
- ksort($font['cw']);
10809
- unset($font['cw'][65535]);
10810
- $rangeid = 0;
10811
- $range = [];
10812
- $prevcid = -2;
10813
- $prevwidth = -1;
10814
- $interval = false;
10815
- // for each character
10816
- foreach ($font['cw'] as $cid => $width) {
10817
- $cid -= $cidoffset;
10818
- if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
10819
- if ($cid == ($prevcid + 1)) {
10820
- // consecutive CID
10821
- if ($width == $prevwidth) {
10822
- if ($width == $range[$rangeid][0]) {
10823
- $range[$rangeid][] = $width;
10824
- } else {
10825
- array_pop($range[$rangeid]);
10826
- // new range
10827
- $rangeid = $prevcid;
10828
- $range[$rangeid] = [];
10829
- $range[$rangeid][] = $prevwidth;
10830
- $range[$rangeid][] = $width;
10831
- }
10832
- $interval = true;
10833
- $range[$rangeid]['interval'] = true;
10834
- } else {
10835
- if ($interval) {
10836
- // new range
10837
- $rangeid = $cid;
10838
- $range[$rangeid] = [];
10839
- $range[$rangeid][] = $width;
10840
- } else {
10841
- $range[$rangeid][] = $width;
10842
- }
10843
- $interval = false;
10844
  }
10845
- } else {
10846
- // new range
10847
- $rangeid = $cid;
10848
- $range[$rangeid] = [];
10849
- $range[$rangeid][] = $width;
10850
- $interval = false;
10851
  }
10852
- $prevcid = $cid;
10853
- $prevwidth = $width;
10854
  }
10855
  }
10856
- $this->_out($this->_putfontranges($range));
10857
- }
10858
 
10859
- /* -- CJK-FONTS -- */
10860
 
10861
- // from class PDF_Chinese CJK EXTENSIONS
10862
- function _putType0(&$font)
10863
- {
10864
- // Type0
10865
- $this->_out('/Subtype /Type0');
10866
- $this->_out('/BaseFont /' . $font['name'] . '-' . $font['CMap']);
10867
- $this->_out('/Encoding /' . $font['CMap']);
10868
- $this->_out('/DescendantFonts [' . ($this->n + 1) . ' 0 R]');
10869
- $this->_out('>>');
10870
- $this->_out('endobj');
10871
- // CIDFont
10872
- $this->_newobj();
10873
- $this->_out('<</Type /Font');
10874
- $this->_out('/Subtype /CIDFontType0');
10875
- $this->_out('/BaseFont /' . $font['name']);
10876
-
10877
- $cidinfo = '/Registry ' . $this->_textstring('Adobe');
10878
- $cidinfo .= ' /Ordering ' . $this->_textstring($font['registry']['ordering']);
10879
- $cidinfo .= ' /Supplement ' . $font['registry']['supplement'];
10880
- $this->_out('/CIDSystemInfo <<' . $cidinfo . '>>');
10881
-
10882
- $this->_out('/FontDescriptor ' . ($this->n + 1) . ' 0 R');
10883
- if (isset($font['MissingWidth'])) {
10884
- $this->_out('/DW ' . $font['MissingWidth'] . '');
10885
- }
10886
- $this->_putfontwidths($font, 31);
10887
- $this->_out('>>');
10888
- $this->_out('endobj');
10889
-
10890
- // Font descriptor
10891
- $this->_newobj();
10892
- $s = '<</Type /FontDescriptor /FontName /' . $font['name'];
10893
- foreach ($font['desc'] as $k => $v) {
10894
- if ($k != 'Style') {
10895
- $s .= ' /' . $k . ' ' . $v . '';
10896
- }
10897
- }
10898
- $this->_out($s . '>>');
10899
- $this->_out('endobj');
10900
- }
10901
 
10902
- /* -- END CJK-FONTS -- */
10903
 
10904
- function _putimages()
10905
- {
10906
- $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
 
10907
 
10908
- foreach ($this->images as $file => $info) {
 
10909
 
10910
- $this->_newobj();
 
10911
 
10912
- $this->images[$file]['n'] = $this->n;
 
 
 
10913
 
10914
- $this->_out('<</Type /XObject');
10915
- $this->_out('/Subtype /Image');
10916
- $this->_out('/Width ' . $info['w']);
10917
- $this->_out('/Height ' . $info['h']);
10918
 
10919
- if (isset($info['interpolation']) && $info['interpolation']) {
10920
- $this->_out('/Interpolate true'); // mPDF 6 - image interpolation shall be performed by a conforming reader
10921
- }
 
10922
 
10923
- if (isset($info['masked'])) {
10924
- $this->_out('/SMask ' . ($this->n - 1) . ' 0 R');
10925
- }
10926
 
10927
- // set color space
10928
- $icc = false;
10929
- if (isset($info['icc']) and ( $info['icc'] !== false)) {
10930
- // ICC Colour Space
10931
- $icc = true;
10932
- $this->_out('/ColorSpace [/ICCBased ' . ($this->n + 1) . ' 0 R]');
10933
- } elseif ($info['cs'] == 'Indexed') {
10934
- if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace == 3)) {
10935
- throw new \Mpdf\MpdfException("PDFA1-b and PDFX/1-a files do not permit using mixed colour space (" . $file . ").");
10936
- }
10937
- $this->_out('/ColorSpace [/Indexed /DeviceRGB ' . (strlen($info['pal']) / 3 - 1) . ' ' . ($this->n + 1) . ' 0 R]');
10938
- } else {
10939
- $this->_out('/ColorSpace /' . $info['cs']);
10940
- if ($info['cs'] == 'DeviceCMYK') {
10941
- if ($this->PDFA && $this->restrictColorSpace != 3) {
10942
- throw new \Mpdf\MpdfException("PDFA1-b does not permit Images using mixed colour space (" . $file . ").");
10943
- }
10944
- if ($info['type'] == 'jpg') {
10945
- $this->_out('/Decode [1 0 1 0 1 0 1 0]');
10946
- }
10947
- } elseif ($info['cs'] == 'DeviceRGB' && ($this->PDFX || ($this->PDFA && $this->restrictColorSpace == 3))) {
10948
- throw new \Mpdf\MpdfException("PDFA1-b and PDFX/1-a files do not permit using mixed colour space (" . $file . ").");
10949
- }
10950
- }
10951
 
10952
- $this->_out('/BitsPerComponent ' . $info['bpc']);
10953
 
10954
- if (isset($info['f']) && $info['f']) {
10955
- $this->_out('/Filter /' . $info['f']);
10956
- }
10957
 
10958
- if (isset($info['parms'])) {
10959
- $this->_out($info['parms']);
10960
- }
 
 
10961
 
10962
- if (isset($info['trns']) and is_array($info['trns'])) {
10963
- $trns = '';
10964
- for ($i = 0; $i < count($info['trns']); $i++) {
10965
- $trns .= $info['trns'][$i] . ' ' . $info['trns'][$i] . ' ';
10966
- }
10967
- $this->_out('/Mask [' . $trns . ']');
10968
- }
10969
 
10970
- $this->_out('/Length ' . strlen($info['data']) . '>>');
10971
- $this->_putstream($info['data']);
 
10972
 
10973
- unset($this->images[$file]['data']);
10974
 
10975
- $this->_out('endobj');
 
 
10976
 
10977
- if ($icc) { // ICC colour profile
10978
- $this->_newobj();
10979
- $icc = ($this->compress) ? gzcompress($info['icc']) : $info['icc'];
10980
- $this->_out('<</N ' . $info['ch'] . ' ' . $filter . '/Length ' . strlen($icc) . '>>');
10981
- $this->_putstream($icc);
10982
- $this->_out('endobj');
10983
- } elseif ($info['cs'] == 'Indexed') { // Palette
10984
- $this->_newobj();
10985
- $pal = ($this->compress) ? gzcompress($info['pal']) : $info['pal'];
10986
- $this->_out('<<' . $filter . '/Length ' . strlen($pal) . '>>');
10987
- $this->_putstream($pal);
10988
- $this->_out('endobj');
10989
- }
10990
- }
10991
- }
10992
 
10993
- private function getVersionString()
10994
- {
10995
- $return = self::VERSION;
10996
- $headFile = __DIR__ . '/../.git/HEAD';
10997
- if (file_exists($headFile)) {
10998
- $ref = file($headFile);
10999
- $path = explode('/', $ref[0], 3);
11000
- $branch = isset($path[2]) ? trim($path[2]) : '';
11001
- $revFile = __DIR__ . '/../.git/refs/heads/' . $branch;
11002
- if ($branch && file_exists($revFile)) {
11003
- $rev = file($revFile);
11004
- $rev = substr($rev[0], 0, 7);
11005
- $return .= ' (' . $rev . ')';
11006
  }
11007
  }
11008
-
11009
- return $return;
11010
- }
11011
-
11012
- function _putinfo()
11013
- {
11014
- $this->_out('/Producer ' . $this->_UTF16BEtextstring('mPDF ' . $this->getVersionString()));
11015
- if (!empty($this->title)) {
11016
- $this->_out('/Title ' . $this->_UTF16BEtextstring($this->title));
11017
- }
11018
- if (!empty($this->subject)) {
11019
- $this->_out('/Subject ' . $this->_UTF16BEtextstring($this->subject));
11020
- }
11021
- if (!empty($this->author)) {
11022
- $this->_out('/Author ' . $this->_UTF16BEtextstring($this->author));
11023
- }
11024
- if (!empty($this->keywords)) {
11025
- $this->_out('/Keywords ' . $this->_UTF16BEtextstring($this->keywords));
11026
- }
11027
- if (!empty($this->creator)) {
11028
- $this->_out('/Creator ' . $this->_UTF16BEtextstring($this->creator));
11029
- }
11030
- foreach ($this->customProperties as $key => $value) {
11031
- $this->_out('/' . $key . ' ' . $this->_UTF16BEtextstring($value));
11032
- }
11033
-
11034
- $z = date('O'); // +0200
11035
- $offset = substr($z, 0, 3) . "'" . substr($z, 3, 2) . "'";
11036
- $this->_out('/CreationDate ' . $this->_textstring(date('YmdHis') . $offset));
11037
- $this->_out('/ModDate ' . $this->_textstring(date('YmdHis') . $offset));
11038
- if ($this->PDFX) {
11039
- $this->_out('/Trapped/False');
11040
- $this->_out('/GTS_PDFXVersion(PDF/X-1a:2003)');
11041
- }
11042
  }
11043
 
11044
- function _putmetadata()
11045
- {
11046
- $this->_newobj();
11047
- $this->MetadataRoot = $this->n;
11048
- $Producer = 'mPDF ' . self::VERSION;
11049
- $z = date('O'); // +0200
11050
- $offset = substr($z, 0, 3) . ':' . substr($z, 3, 2);
11051
- $CreationDate = date('Y-m-d\TH:i:s') . $offset; // 2006-03-10T10:47:26-05:00 2006-06-19T09:05:17Z
11052
- $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0x0fff) | 0x4000, random_int(0, 0x3fff) | 0x8000, random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff));
11053
-
11054
-
11055
- $m = '<?xpacket begin="' . chr(239) . chr(187) . chr(191) . '" id="W5M0MpCehiHzreSzNTczkc9d"?>' . "\n"; // begin = FEFF BOM
11056
- $m .= ' <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="3.1-701">' . "\n";
11057
- $m .= ' <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">' . "\n";
11058
- $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">' . "\n";
11059
- $m .= ' <pdf:Producer>' . $Producer . '</pdf:Producer>' . "\n";
11060
- if (!empty($this->keywords)) {
11061
- $m .= ' <pdf:Keywords>' . $this->keywords . '</pdf:Keywords>' . "\n";
11062
- }
11063
- $m .= ' </rdf:Description>' . "\n";
11064
-
11065
- $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:xmp="http://ns.adobe.com/xap/1.0/">' . "\n";
11066
- $m .= ' <xmp:CreateDate>' . $CreationDate . '</xmp:CreateDate>' . "\n";
11067
- $m .= ' <xmp:ModifyDate>' . $CreationDate . '</xmp:ModifyDate>' . "\n";
11068
- $m .= ' <xmp:MetadataDate>' . $CreationDate . '</xmp:MetadataDate>' . "\n";
11069
- if (!empty($this->creator)) {
11070
- $m .= ' <xmp:CreatorTool>' . $this->creator . '</xmp:CreatorTool>' . "\n";
11071
- }
11072
- $m .= ' </rdf:Description>' . "\n";
11073
-
11074
- // DC elements
11075
- $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:dc="http://purl.org/dc/elements/1.1/">' . "\n";
11076
- $m .= ' <dc:format>application/pdf</dc:format>' . "\n";
11077
- if (!empty($this->title)) {
11078
- $m .= ' <dc:title>
11079
- <rdf:Alt>
11080
- <rdf:li xml:lang="x-default">' . $this->title . '</rdf:li>
11081
- </rdf:Alt>
11082
- </dc:title>' . "\n";
11083
- }
11084
- if (!empty($this->keywords)) {
11085
- $m .= ' <dc:subject>
11086
- <rdf:Bag>
11087
- <rdf:li>' . $this->keywords . '</rdf:li>
11088
- </rdf:Bag>
11089
- </dc:subject>' . "\n";
11090
- }
11091
- if (!empty($this->subject)) {
11092
- $m .= ' <dc:description>
11093
- <rdf:Alt>
11094
- <rdf:li xml:lang="x-default">' . $this->subject . '</rdf:li>
11095
- </rdf:Alt>
11096
- </dc:description>' . "\n";
11097
- }
11098
- if (!empty($this->author)) {
11099
- $m .= ' <dc:creator>
11100
- <rdf:Seq>
11101
- <rdf:li>' . $this->author . '</rdf:li>
11102
- </rdf:Seq>
11103
- </dc:creator>' . "\n";
11104
  }
11105
- $m .= ' </rdf:Description>' . "\n";
 
11106
 
11107
- if (!empty($this->additionalXmpRdf)) {
11108
- $m .= $this->additionalXmpRdf;
11109
  }
11110
 
11111
- // This bit is specific to PDFX-1a
11112
- if ($this->PDFX) {
11113
- $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/" pdfx:Apag_PDFX_Checkup="1.3" pdfx:GTS_PDFXConformance="PDF/X-1a:2003" pdfx:GTS_PDFXVersion="PDF/X-1:2003"/>' . "\n";
11114
- } // This bit is specific to PDFA-1b
11115
- elseif ($this->PDFA) {
11116
 
11117
- if (strpos($this->PDFAversion, '-') === false) {
11118
- throw new \Mpdf\MpdfException(sprintf('PDFA version (%s) is not valid. (Use: 1-B, 3-B, etc.)', $this->PDFAversion));
 
 
11119
  }
11120
 
11121
- list($part, $conformance) = explode('-', strtoupper($this->PDFAversion));
11122
- $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" >' . "\n";
11123
- $m .= ' <pdfaid:part>' . $part . '</pdfaid:part>' . "\n";
11124
- $m .= ' <pdfaid:conformance>' . $conformance . '</pdfaid:conformance>' . "\n";
11125
- if ($part === '1' && $conformance === 'B') {
11126
- $m .= ' <pdfaid:amd>2005</pdfaid:amd>' . "\n";
11127
- }
11128
- $m .= ' </rdf:Description>' . "\n";
11129
- }
11130
-
11131
- $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">' . "\n";
11132
- $m .= ' <xmpMM:DocumentID>uuid:' . $uuid . '</xmpMM:DocumentID>' . "\n";
11133
- $m .= ' </rdf:Description>' . "\n";
11134
- $m .= ' </rdf:RDF>' . "\n";
11135
- $m .= ' </x:xmpmeta>' . "\n";
11136
- $m .= str_repeat(str_repeat(' ', 100) . "\n", 20); // 2-4kB whitespace padding required
11137
- $m .= '<?xpacket end="w"?>'; // "r" read only
11138
- $this->_out('<</Type/Metadata/Subtype/XML/Length ' . strlen($m) . '>>');
11139
- $this->_putstream($m);
11140
- $this->_out('endobj');
11141
- }
11142
-
11143
- function _putoutputintent()
11144
- {
11145
- $this->_newobj();
11146
- $this->OutputIntentRoot = $this->n;
11147
- $this->_out('<</Type /OutputIntent');
11148
-
11149
- $ICCProfile = preg_replace('/_/', ' ', basename($this->ICCProfile, '.icc'));
11150
-
11151
- if ($this->PDFA) {
11152
- $this->_out('/S /GTS_PDFA1');
11153
- if ($this->ICCProfile) {
11154
- $this->_out('/Info (' . $ICCProfile . ')');
11155
- $this->_out('/OutputConditionIdentifier (Custom)');
11156
- $this->_out('/OutputCondition ()');
11157
- } else {
11158
- $this->_out('/Info (sRGB IEC61966-2.1)');
11159
- $this->_out('/OutputConditionIdentifier (sRGB IEC61966-2.1)');
11160
- $this->_out('/OutputCondition ()');
11161
- }
11162
- $this->_out('/DestOutputProfile ' . ($this->n + 1) . ' 0 R');
11163
- } elseif ($this->PDFX) { // always a CMYK profile
11164
- $this->_out('/S /GTS_PDFX');
11165
- if ($this->ICCProfile) {
11166
- $this->_out('/Info (' . $ICCProfile . ')');
11167
- $this->_out('/OutputConditionIdentifier (Custom)');
11168
- $this->_out('/OutputCondition ()');
11169
- $this->_out('/DestOutputProfile ' . ($this->n + 1) . ' 0 R');
11170
  } else {
11171
- $this->_out('/Info (CGATS TR 001)');
11172
- $this->_out('/OutputConditionIdentifier (CGATS TR 001)');
11173
- $this->_out('/OutputCondition (CGATS TR 001 (SWOP))');
11174
- $this->_out('/RegistryName (http://www.color.org)');
11175
  }
11176
- }
11177
- $this->_out('>>');
11178
- $this->_out('endobj');
11179
-
11180
- if ($this->PDFX && !$this->ICCProfile) {
11181
- return;
11182
- }
11183
-
11184
- $this->_newobj();
11185
 
11186
- if ($this->ICCProfile) {
11187
- if (!file_exists($this->ICCProfile)) {
11188
- throw new \Mpdf\MpdfException(sprintf('Unable to find ICC profile "%s"', $this->ICCProfile));
 
 
 
11189
  }
11190
- $s = file_get_contents($this->ICCProfile);
11191
- } else {
11192
- $s = file_get_contents(__DIR__ . '/../data/iccprofiles/sRGB_IEC61966-2-1.icc');
11193
- }
11194
 
11195
- if ($this->compress) {
11196
- $s = gzcompress($s);
11197
- }
11198
 
11199
- $this->_out('<<');
11200
 
11201
- if ($this->PDFX || ($this->PDFA && $this->restrictColorSpace == 3)) {
11202
- $this->_out('/N 4');
11203
- } else {
11204
- $this->_out('/N 3');
11205
- }
 
11206
 
11207
- if ($this->compress) {
11208
- $this->_out('/Filter /FlateDecode ');
11209
- }
 
 
 
11210
 
11211
- $this->_out('/Length ' . strlen($s) . '>>');
11212
- $this->_putstream($s);
11213
- $this->_out('endobj');
11214
- }
11215
 
11216
- function _putAssociatedFiles()
11217
- {
11218
- if (!function_exists('gzcompress')) {
11219
- throw new \Mpdf\MpdfException('ext-zlib is required for compression of associated files');
11220
- }
 
11221
 
11222
- // for each file, we create the spec object + the stream object
11223
- foreach ($this->associatedFiles as $k => $file) {
11224
- // spec
11225
- $this->_newobj();
11226
- $this->associatedFiles[$k]['_root'] = $this->n; // we store the root ref of object for future reference (e.g. /EmbeddedFiles catalog)
11227
- $this->_out('<</F ' . $this->_textstring($file['name']));
11228
- if ($file['description']) {
11229
- $this->_out('/Desc ' . $this->_textstring($file['description']));
11230
- }
11231
- $this->_out('/Type /Filespec');
11232
- $this->_out('/EF <<');
11233
- $this->_out('/F ' . ($this->n + 1) . ' 0 R');
11234
- $this->_out('/UF ' . ($this->n + 1) . ' 0 R');
11235
- $this->_out('>>');
11236
- if ($file['AFRelationship']) {
11237
- $this->_out('/AFRelationship /' . $file['AFRelationship']);
11238
  }
11239
- $this->_out('/UF ' . $this->_textstring($file['name']));
11240
- $this->_out('>>');
11241
- $this->_out('endobj');
11242
 
11243
- $fileContent = null;
11244
- if (isset($file['path'])) {
11245
- $fileContent = @file_get_contents($file['path']);
11246
- } elseif (isset($file['content'])) {
11247
- $fileContent = $file['content'];
11248
  }
11249
 
11250
- if (!$fileContent) {
11251
- throw new \Mpdf\MpdfException(sprintf('Cannot access associated file - %s', $file['path']));
11252
- }
11253
 
11254
- $filestream = gzcompress($fileContent);
11255
- $this->_newobj();
11256
- $this->_out('<</Type /EmbeddedFile');
11257
- if ($file['mime']) {
11258
- $this->_out('/Subtype /' . $this->_escapeName($file['mime']));
 
 
 
11259
  }
11260
- $this->_out('/Length '.strlen($filestream));
11261
- $this->_out('/Filter /FlateDecode');
11262
- if (isset($file['path'])) {
11263
- $this->_out('/Params <</ModDate '.$this->_textstring('D:'.PdfDate::format(filemtime($file['path']))).' >>');
11264
  } else {
11265
- $this->_out('/Params <</ModDate '.$this->_textstring('D:'.PdfDate::format(time())).' >>');
11266
  }
11267
 
11268
- $this->_out('>>');
11269
- $this->_putstream($filestream);
11270
- $this->_out('endobj');
11271
- }
 
 
 
 
 
 
11272
 
11273
- // AF array
11274
- $this->_newobj();
11275
- $refs = [];
11276
- foreach ($this->associatedFiles as $file) {
11277
- array_push($refs, '' . $file['_root'] . ' 0 R');
11278
  }
11279
- $this->_out('[' . join(' ', $refs) . ']');
11280
- $this->_out('endobj');
11281
- $this->associatedFilesRoot = $this->n;
11282
- }
11283
 
11284
- function _putcatalog()
11285
- {
11286
- $this->_out('/Type /Catalog');
11287
- $this->_out('/Pages 1 0 R');
11288
- if ($this->ZoomMode == 'fullpage') {
11289
- $this->_out('/OpenAction [3 0 R /Fit]');
11290
- } elseif ($this->ZoomMode == 'fullwidth') {
11291
- $this->_out('/OpenAction [3 0 R /FitH null]');
11292
- } elseif ($this->ZoomMode == 'real') {
11293
- $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
11294
- } elseif (!is_string($this->ZoomMode)) {
11295
- $this->_out('/OpenAction [3 0 R /XYZ null null ' . ($this->ZoomMode / 100) . ']');
11296
  } else {
11297
- $this->_out('/OpenAction [3 0 R /XYZ null null null]');
11298
- }
11299
- if ($this->LayoutMode == 'single') {
11300
- $this->_out('/PageLayout /SinglePage');
11301
- } elseif ($this->LayoutMode == 'continuous') {
11302
- $this->_out('/PageLayout /OneColumn');
11303
- } elseif ($this->LayoutMode == 'twoleft') {
11304
- $this->_out('/PageLayout /TwoColumnLeft');
11305
- } elseif ($this->LayoutMode == 'tworight') {
11306
- $this->_out('/PageLayout /TwoColumnRight');
11307
- } elseif ($this->LayoutMode == 'two') {
11308
- if ($this->mirrorMargins) {
11309
- $this->_out('/PageLayout /TwoColumnRight');
11310
- } else {
11311
- $this->_out('/PageLayout /TwoColumnLeft');
11312
  }
11313
  }
11314
 
11315
- // Bookmarks
11316
- if (count($this->BMoutlines) > 0) {
11317
- $this->_out('/Outlines ' . $this->OutlineRoot . ' 0 R');
11318
- $this->_out('/PageMode /UseOutlines');
11319
- }
11320
 
11321
- // Fullscreen
11322
- if (is_int(strpos($this->DisplayPreferences, 'FullScreen'))) {
11323
- $this->_out('/PageMode /FullScreen');
11324
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11325
 
11326
- // Metadata
11327
- if ($this->PDFA || $this->PDFX) {
11328
- $this->_out('/Metadata ' . $this->MetadataRoot . ' 0 R');
11329
- }
 
 
 
 
 
 
 
11330
 
11331
- // OutputIntents
11332
- if ($this->PDFA || $this->PDFX || $this->ICCProfile) {
11333
- $this->_out('/OutputIntents [' . $this->OutputIntentRoot . ' 0 R]');
 
11334
  }
11335
 
11336
- // Associated files
11337
- if ($this->associatedFilesRoot) {
11338
- $this->_out('/AF '. $this->associatedFilesRoot .' 0 R');
11339
 
11340
- $names = [];
11341
- foreach ($this->associatedFiles as $file) {
11342
- array_push($names, $this->_textstring($file['name']) . ' ' . $file['_root'] . ' 0 R');
11343
- }
11344
- $this->_out('/Names << /EmbeddedFiles << /Names [' . join(' ', $names) . '] >> >>');
11345
- }
11346
 
11347
- // Forms
11348
- if (count($this->form->forms) > 0) {
11349
- $this->form->_putFormsCatalog();
 
 
 
11350
  }
11351
 
11352
- if (isset($this->js)) {
11353
- $this->_out('/Names << /JavaScript ' . ($this->n_js) . ' 0 R >> ');
11354
- }
11355
 
11356
- if ($this->DisplayPreferences || $this->directionality == 'rtl' || $this->mirrorMargins) {
11357
- $this->_out('/ViewerPreferences<<');
11358
- if (is_int(strpos($this->DisplayPreferences, 'HideMenubar'))) {
11359
- $this->_out('/HideMenubar true');
11360
- }
11361
- if (is_int(strpos($this->DisplayPreferences, 'HideToolbar'))) {
11362
- $this->_out('/HideToolbar true');
11363
  }
11364
- if (is_int(strpos($this->DisplayPreferences, 'HideWindowUI'))) {
11365
- $this->_out('/HideWindowUI true');
 
11366
  }
11367
- if (is_int(strpos($this->DisplayPreferences, 'DisplayDocTitle'))) {
11368
- $this->_out('/DisplayDocTitle true');
 
11369
  }
11370
- if (is_int(strpos($this->DisplayPreferences, 'CenterWindow'))) {
11371
- $this->_out('/CenterWindow true');
 
11372
  }
11373
- if (is_int(strpos($this->DisplayPreferences, 'FitWindow'))) {
11374
- $this->_out('/FitWindow true');
 
11375
  }
11376
- ///PrintScaling is PDF 1.6 spec.
11377
- if (is_int(strpos($this->DisplayPreferences, 'NoPrintScaling')) && !$this->PDFA && !$this->PDFX) {
11378
- $this->_out('/PrintScaling /None');
11379
  }
11380
- if ($this->directionality == 'rtl') {
11381
- $this->_out('/Direction /R2L');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11382
  }
11383
- ///Duplex is PDF 1.7 spec.
11384
- if ($this->mirrorMargins && !$this->PDFA && !$this->PDFX) {
11385
- // if ($this->DefOrientation=='P') $this->_out('/Duplex /DuplexFlipShortEdge');
11386
- $this->_out('/Duplex /DuplexFlipLongEdge'); // PDF v1.7+
11387
  }
11388
- $this->_out('>>');
11389
  }
11390
 
11391
- if ($this->open_layer_pane && ($this->hasOC || count($this->layers))) {
11392
- $this->_out('/PageMode /UseOC');
 
 
 
 
 
 
 
 
 
 
 
 
 
11393
  }
11394
 
11395
- if ($this->hasOC || count($this->layers)) {
11396
- $p = $v = $h = $l = $loff = $lall = $as = '';
11397
- if ($this->hasOC) {
11398
- if (($this->hasOC & 1) == 1) {
11399
- $p = $this->n_ocg_print . ' 0 R';
11400
- }
11401
- if (($this->hasOC & 2) == 2) {
11402
- $v = $this->n_ocg_view . ' 0 R';
11403
- }
11404
- if (($this->hasOC & 4) == 4) {
11405
- $h = $this->n_ocg_hidden . ' 0 R';
11406
- }
11407
- $as = "<</Event /Print /OCGs [$p $v $h] /Category [/Print]>> <</Event /View /OCGs [$p $v $h] /Category [/View]>>";
11408
  }
 
 
 
 
 
 
 
11409
 
11410
- if (count($this->layers)) {
11411
- foreach ($this->layers as $k => $layer) {
11412
- if (strtolower($this->layerDetails[$k]['state']) == 'hidden') {
11413
- $loff .= $layer['n'] . ' 0 R ';
11414
- } else {
11415
- $l .= $layer['n'] . ' 0 R ';
11416
- }
11417
- $lall .= $layer['n'] . ' 0 R ';
11418
- }
11419
  }
11420
- $this->_out("/OCProperties <</OCGs [$p $v $h $lall] /D <</ON [$p $l] /OFF [$v $h $loff] ");
11421
- $this->_out("/Order [$v $p $h $lall] ");
11422
- if ($as) {
11423
- $this->_out("/AS [$as] ");
11424
  }
11425
- $this->_out(">>>>");
11426
  }
11427
- }
11428
 
11429
- function _enddoc()
11430
- {
11431
- // @log Writing Headers & Footers
 
 
 
11432
 
11433
- $this->_puthtmlheaders();
11434
 
11435
- // @log Writing Pages
 
 
 
 
 
 
11436
 
11437
- // Remove references to unused fonts (usually default font)
11438
- foreach ($this->fonts as $fk => $font) {
11439
- if (isset($font['type']) && $font['type'] == 'TTF' && !$font['used']) {
11440
- if ($font['sip'] || $font['smp']) {
11441
- foreach ($font['subsetfontids'] as $k => $fid) {
11442
- foreach ($this->pages as $pn => $page) {
11443
- $this->pages[$pn] = preg_replace('/\s\/F' . $fid . ' \d[\d.]* Tf\s/is', ' ', $this->pages[$pn]);
11444
- }
11445
- }
11446
- } else {
11447
- foreach ($this->pages as $pn => $page) {
11448
- $this->pages[$pn] = preg_replace('/\s\/F' . $font['i'] . ' \d[\d.]* Tf\s/is', ' ', $this->pages[$pn]);
11449
- }
11450
- }
11451
- }
11452
  }
11453
 
11454
- if (count($this->layers)) {
11455
- foreach ($this->pages as $pn => $page) {
11456
- preg_match_all('/\/OCZ-index \/ZI(\d+) BDC(.*?)(EMCZ)-index/is', $this->pages[$pn], $m1);
11457
- preg_match_all('/\/OCBZ-index \/ZI(\d+) BDC(.*?)(EMCBZ)-index/is', $this->pages[$pn], $m2);
11458
- preg_match_all('/\/OCGZ-index \/ZI(\d+) BDC(.*?)(EMCGZ)-index/is', $this->pages[$pn], $m3);
11459
- $m = [];
11460
- for ($i = 0; $i < 4; $i++) {
11461
- $m[$i] = array_merge($m1[$i], $m2[$i], $m3[$i]);
11462
- }
11463
- if (count($m[0])) {
11464
- $sortarr = [];
11465
- for ($i = 0; $i < count($m[0]); $i++) {
11466
- $key = $m[1][$i] * 2;
11467
- if ($m[3][$i] == 'EMCZ') {
11468
- $key +=2; // background first then gradient then normal
11469
- } elseif ($m[3][$i] == 'EMCGZ') {
11470
- $key +=1;
11471
- }
11472
- $sortarr[$i] = $key;
11473
- }
11474
- asort($sortarr);
11475
- foreach ($sortarr as $i => $k) {
11476
- $this->pages[$pn] = str_replace($m[0][$i], '', $this->pages[$pn]);
11477
- $this->pages[$pn] .= "\n" . $m[0][$i] . "\n";
11478
- }
11479
- $this->pages[$pn] = preg_replace('/\/OC[BG]{0,1}Z-index \/ZI(\d+) BDC/is', '/OC /ZI\\1 BDC ', $this->pages[$pn]);
11480
- $this->pages[$pn] = preg_replace('/EMC[BG]{0,1}Z-index/is', 'EMC', $this->pages[$pn]);
11481
- }
11482
  }
 
11483
  }
 
11484
 
11485
- $this->_putpages();
11486
-
11487
- // @log Writing document resources
11488
-
11489
- $this->_putresources();
11490
- // Info
11491
- $this->_newobj();
11492
- $this->InfoRoot = $this->n;
11493
- $this->_out('<<');
11494
-
11495
- // @log Writing document info
11496
-
11497
- $this->_putinfo();
11498
- $this->_out('>>');
11499
- $this->_out('endobj');
11500
-
11501
- // METADATA
11502
- if ($this->PDFA || $this->PDFX) {
11503
- $this->_putmetadata();
11504
  }
11505
 
11506
- // OUTPUTINTENT
11507
- if ($this->PDFA || $this->PDFX || $this->ICCProfile) {
11508
- $this->_putoutputintent();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11509
  }
 
11510
 
11511
- // Associated files
11512
- if ($this->associatedFiles) {
11513
- $this->_putAssociatedFiles();
 
 
 
 
 
11514
  }
 
 
 
 
11515
 
11516
- // Catalog
11517
- $this->_newobj();
11518
- $this->_out('<<');
 
 
 
 
 
11519
 
11520
- // @log Writing document catalog
11521
 
11522
- $this->_putcatalog();
11523
- $this->_out('>>');
11524
- $this->_out('endobj');
11525
 
11526
- // Cross-ref
11527
- $o = strlen($this->buffer);
11528
- $this->_out('xref');
11529
- $this->_out('0 ' . ($this->n + 1));
11530
- $this->_out('0000000000 65535 f ');
11531
 
11532
- for ($i = 1; $i <= $this->n; $i++) {
11533
- $this->_out(sprintf('%010d 00000 n ', $this->offsets[$i]));
 
 
 
11534
  }
11535
 
11536
- // Trailer
11537
- $this->_out('trailer');
11538
- $this->_out('<<');
11539
- $this->_puttrailer();
11540
- $this->_out('>>');
11541
- $this->_out('startxref');
11542
- $this->_out($o);
11543
-
11544
- $this->buffer .= '%%EOF';
11545
- $this->state = 3;
11546
-
11547
- // Imports
11548
- if ($this->enableImports && count($this->parsers) > 0) {
11549
- foreach ($this->parsers as $k => $_) {
11550
- $this->parsers[$k]->closeFile();
11551
- $this->parsers[$k] = null;
11552
- unset($this->parsers[$k]);
11553
- }
11554
  }
11555
- }
11556
 
11557
- function _beginpage(
11558
- $orientation,
11559
- $mgl = '',
11560
- $mgr = '',
11561
- $mgt = '',
11562
- $mgb = '',
11563
- $mgh = '',
11564
- $mgf = '',
11565
- $ohname = '',
11566
- $ehname = '',
11567
- $ofname = '',
11568
- $efname = '',
11569
- $ohvalue = 0,
11570
- $ehvalue = 0,
11571
- $ofvalue = 0,
11572
- $efvalue = 0,
11573
- $pagesel = '',
11574
- $newformat = ''
11575
- ) {
11576
- if (!($pagesel && $this->page == 1 && (sprintf("%0.4f", $this->y) == sprintf("%0.4f", $this->tMargin)))) {
11577
- $this->page++;
11578
- $this->pages[$this->page] = '';
11579
  }
11580
- $this->state = 2;
11581
- $resetHTMLHeadersrequired = false;
11582
 
11583
- if ($newformat) {
11584
- $this->_setPageSize($newformat, $orientation);
11585
  }
11586
 
11587
- /* -- CSS-PAGE -- */
11588
- // Paged media (page-box)
11589
- if ($pagesel || (isset($this->page_box['using']) && $this->page_box['using'])) {
 
11590
 
11591
- if ($pagesel || $this->page == 1) {
11592
- $first = true;
 
 
 
 
11593
  } else {
11594
- $first = false;
11595
  }
 
11596
 
11597
- if ($this->mirrorMargins && ($this->page % 2 == 0)) {
11598
- $oddEven = 'E';
11599
- } else {
11600
- $oddEven = 'O';
11601
- }
 
 
 
11602
 
11603
- if ($pagesel) {
11604
- $psel = $pagesel;
11605
- } elseif ($this->page_box['current']) {
11606
- $psel = $this->page_box['current'];
11607
- } else {
11608
- $psel = '';
11609
- }
11610
 
11611
- list($orientation, $mgl, $mgr, $mgt, $mgb, $mgh, $mgf, $hname, $fname, $bg, $resetpagenum, $pagenumstyle, $suppress, $marks, $newformat) = $this->SetPagedMediaCSS($psel, $first, $oddEven);
11612
 
11613
- if ($this->mirrorMargins && ($this->page % 2 == 0)) {
11614
 
11615
- if ($hname) {
11616
- $ehvalue = 1;
11617
- $ehname = $hname;
11618
- } else {
11619
- $ehvalue = -1;
11620
- }
11621
 
11622
- if ($fname) {
11623
- $efvalue = 1;
11624
- $efname = $fname;
11625
- } else {
11626
- $efvalue = -1;
11627
- }
11628
 
 
 
 
11629
  } else {
11630
-
11631
- if ($hname) {
11632
- $ohvalue = 1;
11633
- $ohname = $hname;
11634
- } else {
11635
- $ohvalue = -1;
11636
- }
11637
-
11638
- if ($fname) {
11639
- $ofvalue = 1;
11640
- $ofname = $fname;
11641
- } else {
11642
- $ofvalue = -1;
11643
- }
11644
  }
 
11645
 
11646
- if ($resetpagenum || $pagenumstyle || $suppress) {
11647
- $this->PageNumSubstitutions[] = ['from' => ($this->page), 'reset' => $resetpagenum, 'type' => $pagenumstyle, 'suppress' => $suppress];
11648
- }
11649
 
11650
- // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
11651
- $this->show_marks = $marks;
 
11652
 
11653
- // Background color
11654
- if (isset($bg['BACKGROUND-COLOR'])) {
11655
- $cor = $this->colorConverter->convert($bg['BACKGROUND-COLOR'], $this->PDFAXwarnings);
11656
- if ($cor) {
11657
- $this->bodyBackgroundColor = $cor;
11658
- }
11659
- } else {
11660
- $this->bodyBackgroundColor = false;
11661
- }
11662
 
11663
- /* -- BACKGROUNDS -- */
11664
- if (isset($bg['BACKGROUND-GRADIENT'])) {
11665
- $this->bodyBackgroundGradient = $bg['BACKGROUND-GRADIENT'];
11666
- } else {
11667
- $this->bodyBackgroundGradient = false;
11668
- }
11669
 
11670
- // Tiling Patterns
11671
- if (isset($bg['BACKGROUND-IMAGE']) && $bg['BACKGROUND-IMAGE']) {
11672
- $ret = $this->SetBackground($bg, $this->pgwidth);
11673
- if ($ret) {
11674
- $this->bodyBackgroundImage = $ret;
11675
- }
11676
- } else {
11677
- $this->bodyBackgroundImage = false;
11678
- }
11679
- /* -- END BACKGROUNDS -- */
11680
 
11681
- $this->page_box['current'] = $psel;
11682
- $this->page_box['using'] = true;
 
 
11683
  }
11684
- /* -- END CSS-PAGE -- */
11685
 
11686
- // Page orientation
11687
- if (!$orientation) {
11688
- $orientation = $this->DefOrientation;
11689
  } else {
11690
- $orientation = strtoupper(substr($orientation, 0, 1));
11691
- if ($orientation != $this->DefOrientation) {
11692
- $this->OrientationChanges[$this->page] = true;
11693
- }
11694
  }
11695
 
11696
- if ($orientation != $this->CurOrientation || $newformat) {
11697
-
11698
- // Change orientation
11699
- if ($orientation == 'P') {
11700
- $this->wPt = $this->fwPt;
11701
- $this->hPt = $this->fhPt;
11702
- $this->w = $this->fw;
11703
- $this->h = $this->fh;
11704
- if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation == 'P') {
11705
- $this->tMargin = $this->orig_tMargin;
11706
- $this->bMargin = $this->orig_bMargin;
11707
- $this->DeflMargin = $this->orig_lMargin;
11708
- $this->DefrMargin = $this->orig_rMargin;
11709
- $this->margin_header = $this->orig_hMargin;
11710
- $this->margin_footer = $this->orig_fMargin;
11711
- } else {
11712
- $resetHTMLHeadersrequired = true;
11713
- }
11714
- } else {
11715
- $this->wPt = $this->fhPt;
11716
- $this->hPt = $this->fwPt;
11717
- $this->w = $this->fh;
11718
- $this->h = $this->fw;
11719
-
11720
- if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation == 'P') {
11721
- $this->tMargin = $this->orig_lMargin;
11722
- $this->bMargin = $this->orig_rMargin;
11723
- $this->DeflMargin = $this->orig_bMargin;
11724
- $this->DefrMargin = $this->orig_tMargin;
11725
- $this->margin_header = $this->orig_hMargin;
11726
- $this->margin_footer = $this->orig_fMargin;
11727
- } else {
11728
- $resetHTMLHeadersrequired = true;
11729
- }
11730
- }
11731
 
11732
- $this->CurOrientation = $orientation;
11733
- $this->ResetMargins();
11734
- $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
11735
- $this->PageBreakTrigger = $this->h - $this->bMargin;
11736
  }
 
11737
 
11738
- $this->pageDim[$this->page]['w'] = $this->w;
11739
- $this->pageDim[$this->page]['h'] = $this->h;
11740
 
11741
- $this->pageDim[$this->page]['outer_width_LR'] = isset($this->page_box['outer_width_LR']) ? $this->page_box['outer_width_LR'] : 0;
11742
- $this->pageDim[$this->page]['outer_width_TB'] = isset($this->page_box['outer_width_TB']) ? $this->page_box['outer_width_TB'] : 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11743
 
11744
- if (!isset($this->page_box['outer_width_LR']) && !isset($this->page_box['outer_width_TB'])) {
11745
- $this->pageDim[$this->page]['bleedMargin'] = 0;
11746
- } elseif ($this->bleedMargin <= $this->page_box['outer_width_LR'] && $this->bleedMargin <= $this->page_box['outer_width_TB']) {
11747
- $this->pageDim[$this->page]['bleedMargin'] = $this->bleedMargin;
11748
- } else {
11749
- $this->pageDim[$this->page]['bleedMargin'] = min($this->page_box['outer_width_LR'], $this->page_box['outer_width_TB']) - 0.01;
11750
  }
11751
 
11752
- // If Page Margins are re-defined
11753
- // strlen()>0 is used to pick up (integer) 0, (string) '0', or set value
11754
- if ((strlen($mgl) > 0 && $this->DeflMargin != $mgl) || (strlen($mgr) > 0 && $this->DefrMargin != $mgr) || (strlen($mgt) > 0 && $this->tMargin != $mgt) || (strlen($mgb) > 0 && $this->bMargin != $mgb) || (strlen($mgh) > 0 && $this->margin_header != $mgh) || (strlen($mgf) > 0 && $this->margin_footer != $mgf)) {
11755
 
11756
- if (strlen($mgl) > 0) {
11757
- $this->DeflMargin = $mgl;
11758
- }
 
11759
 
11760
- if (strlen($mgr) > 0) {
11761
- $this->DefrMargin = $mgr;
11762
- }
 
 
 
 
11763
 
11764
- if (strlen($mgt) > 0) {
11765
- $this->tMargin = $mgt;
11766
- }
 
 
11767
 
11768
- if (strlen($mgb) > 0) {
11769
- $this->bMargin = $mgb;
11770
- }
 
11771
 
11772
- if (strlen($mgh) > 0) {
11773
- $this->margin_header = $mgh;
11774
- }
 
11775
 
11776
- if (strlen($mgf) > 0) {
11777
- $this->margin_footer = $mgf;
11778
- }
 
11779
 
11780
- $this->ResetMargins();
11781
- $this->SetAutoPageBreak($this->autoPageBreak, $this->bMargin);
 
11782
 
11783
- $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
11784
- $resetHTMLHeadersrequired = true;
11785
- }
 
 
11786
 
11787
- $this->ResetMargins();
11788
- $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
11789
- $this->SetAutoPageBreak($this->autoPageBreak, $this->bMargin);
11790
 
11791
- // Reset column top margin
11792
- $this->y0 = $this->tMargin;
11793
 
11794
- $this->x = $this->lMargin;
11795
- $this->y = $this->tMargin;
11796
- $this->FontFamily = '';
11797
 
11798
- // HEADERS AND FOOTERS // mPDF 6
11799
- if ($ohvalue < 0 || strtoupper($ohvalue) == 'OFF') {
11800
- $this->HTMLHeader = '';
11801
- $resetHTMLHeadersrequired = true;
11802
- } elseif ($ohname && $ohvalue > 0) {
11803
- if (preg_match('/^html_(.*)$/i', $ohname, $n)) {
11804
- $name = $n[1];
11805
- } else {
11806
- $name = $ohname;
11807
- }
11808
- if (isset($this->pageHTMLheaders[$name])) {
11809
- $this->HTMLHeader = $this->pageHTMLheaders[$name];
11810
- } else {
11811
- $this->HTMLHeader = '';
11812
- }
11813
- $resetHTMLHeadersrequired = true;
11814
  }
 
 
11815
 
11816
- if ($ehvalue < 0 || strtoupper($ehvalue) == 'OFF') {
11817
- $this->HTMLHeaderE = '';
11818
- $resetHTMLHeadersrequired = true;
11819
- } elseif ($ehname && $ehvalue > 0) {
11820
- if (preg_match('/^html_(.*)$/i', $ehname, $n)) {
11821
- $name = $n[1];
11822
- } else {
11823
- $name = $ehname;
11824
- }
11825
- if (isset($this->pageHTMLheaders[$name])) {
11826
- $this->HTMLHeaderE = $this->pageHTMLheaders[$name];
11827
- } else {
11828
- $this->HTMLHeaderE = '';
11829
- }
11830
- $resetHTMLHeadersrequired = true;
11831
- }
11832
 
11833
- if ($ofvalue < 0 || strtoupper($ofvalue) == 'OFF') {
11834
- $this->HTMLFooter = '';
11835
- $resetHTMLHeadersrequired = true;
11836
- } elseif ($ofname && $ofvalue > 0) {
11837
- if (preg_match('/^html_(.*)$/i', $ofname, $n)) {
11838
- $name = $n[1];
11839
- } else {
11840
- $name = $ofname;
 
 
 
 
 
 
 
 
 
11841
  }
11842
- if (isset($this->pageHTMLfooters[$name])) {
11843
- $this->HTMLFooter = $this->pageHTMLfooters[$name];
11844
- } else {
11845
- $this->HTMLFooter = '';
 
11846
  }
11847
- $resetHTMLHeadersrequired = true;
11848
  }
11849
-
11850
- if ($efvalue < 0 || strtoupper($efvalue) == 'OFF') {
11851
- $this->HTMLFooterE = '';
11852
- $resetHTMLHeadersrequired = true;
11853
- } elseif ($efname && $efvalue > 0) {
11854
- if (preg_match('/^html_(.*)$/i', $efname, $n)) {
11855
- $name = $n[1];
11856
- } else {
11857
- $name = $efname;
11858
- }
11859
- if (isset($this->pageHTMLfooters[$name])) {
11860
- $this->HTMLFooterE = $this->pageHTMLfooters[$name];
11861
- } else {
11862
- $this->HTMLFooterE = '';
11863
- }
11864
- $resetHTMLHeadersrequired = true;
11865
- }
11866
-
11867
- if ($resetHTMLHeadersrequired) {
11868
- $this->SetHTMLHeader($this->HTMLHeader);
11869
- $this->SetHTMLHeader($this->HTMLHeaderE, 'E');
11870
- $this->SetHTMLFooter($this->HTMLFooter);
11871
- $this->SetHTMLFooter($this->HTMLFooterE, 'E');
11872
- }
11873
-
11874
-
11875
- if (($this->mirrorMargins) && (($this->page) % 2 == 0)) { // EVEN
11876
- $this->_setAutoHeaderHeight($this->HTMLHeaderE);
11877
- $this->_setAutoFooterHeight($this->HTMLFooterE);
11878
- } else { // ODD or DEFAULT
11879
- $this->_setAutoHeaderHeight($this->HTMLHeader);
11880
- $this->_setAutoFooterHeight($this->HTMLFooter);
11881
- }
11882
-
11883
- // Reset column top margin
11884
- $this->y0 = $this->tMargin;
11885
-
11886
- $this->x = $this->lMargin;
11887
- $this->y = $this->tMargin;
11888
  }
11889
 
11890
- // mPDF 6
11891
- function _setAutoHeaderHeight(&$htmlh)
11892
  {
11893
- /* When the setAutoTopMargin option is set to pad/stretch, only apply auto header height when a header exists */
11894
- if ($this->HTMLHeader === '' && $this->HTMLHeaderE === '') {
11895
- return;
11896
- }
11897
-
11898
- if ($this->setAutoTopMargin == 'pad') {
11899
- if (isset($htmlh['h']) && $htmlh['h']) {
11900
- $h = $htmlh['h'];
11901
- } // 5.7.3
11902
- else {
11903
- $h = 0;
11904
- }
11905
- $this->tMargin = $this->margin_header + $h + $this->orig_tMargin;
11906
- } elseif ($this->setAutoTopMargin == 'stretch') {
11907
- if (isset($htmlh['h']) && $htmlh['h']) {
11908
- $h = $htmlh['h'];
11909
- } // 5.7.3
11910
- else {
11911
- $h = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11912
  }
11913
- $this->tMargin = max($this->orig_tMargin, $this->margin_header + $h + $this->autoMarginPadding);
11914
  }
 
 
 
 
 
11915
  }
11916
 
11917
- // mPDF 6
11918
- function _setAutoFooterHeight(&$htmlf)
 
 
11919
  {
11920
- /* When the setAutoTopMargin option is set to pad/stretch, only apply auto footer height when a footer exists */
11921
- if ($this->HTMLFooter === '' && $this->HTMLFooterE === '') {
11922
- return;
11923
  }
11924
-
11925
- if ($this->setAutoBottomMargin == 'pad') {
11926
- if (isset($htmlf['h']) && $htmlf['h']) {
11927
- $h = $htmlf['h'];
11928
- } // 5.7.3
11929
- else {
11930
- $h = 0;
11931
- }
11932
- $this->bMargin = $this->margin_footer + $h + $this->orig_bMargin;
11933
- $this->PageBreakTrigger = $this->h - $this->bMargin;
11934
- } elseif ($this->setAutoBottomMargin == 'stretch') {
11935
- if (isset($htmlf['h']) && $htmlf['h']) {
11936
- $h = $htmlf['h'];
11937
- } // 5.7.3
11938
- else {
11939
- $h = 0;
11940
- }
11941
- $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $h + $this->autoMarginPadding);
11942
- $this->PageBreakTrigger = $this->h - $this->bMargin;
11943
  }
 
 
11944
  }
11945
 
11946
- function _endpage()
11947
  {
11948
- /* -- CSS-IMAGE-FLOAT -- */
11949
- $this->printfloatbuffer();
11950
- /* -- END CSS-IMAGE-FLOAT -- */
11951
 
11952
- if ($this->visibility != 'visible') {
11953
- $this->SetVisibility('visible');
 
 
 
 
 
 
 
 
 
11954
  }
11955
- $this->EndLayer();
11956
- // End of page contents
11957
- $this->state = 1;
11958
  }
11959
 
11960
- function _newobj($obj_id = false, $onlynewobj = false)
11961
  {
11962
- if (!$obj_id) {
11963
- $obj_id = ++$this->n;
11964
- }
11965
- // Begin a new object
11966
- if (!$onlynewobj) {
11967
- $this->offsets[$obj_id] = strlen($this->buffer);
11968
- $this->_out($obj_id . ' 0 obj');
11969
- $this->_current_obj_id = $obj_id; // for later use with encryption
11970
- }
 
 
 
 
 
 
 
 
 
 
11971
  }
11972
 
11973
- function _dounderline($x, $y, $txt, $OTLdata = false, $textvar = 0)
11974
  {
11975
- // Now print line exactly where $y secifies - called from Text() and Cell() - adjust position there
11976
- // WORD SPACING
11977
- $w = ($this->GetStringWidth($txt, false, $OTLdata, $textvar) * Mpdf::SCALE) + ($this->charspacing * mb_strlen($txt, $this->mb_enc)) + ( $this->ws * mb_substr_count($txt, ' ', $this->mb_enc));
11978
- // Draw a line
11979
- return sprintf('%.3F %.3F m %.3F %.3F l S', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, ($x * Mpdf::SCALE) + $w, ($this->h - $y) * Mpdf::SCALE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11980
  }
11981
 
11982
- function getFileContentsByCurl($url, &$data)
11983
  {
11984
- $this->logger->debug(sprintf('Fetching (cURL) content of remote URL "%s"', $url), ['context' => LogContext::REMOTE_CONTENT]);
11985
-
11986
- $ch = curl_init($url);
11987
-
11988
- curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1'); // mPDF 5.7.4
11989
- curl_setopt($ch, CURLOPT_HEADER, 0);
11990
- curl_setopt($ch, CURLOPT_NOBODY, 0);
11991
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
11992
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->curlTimeout);
11993
-
11994
- if ($this->curlFollowLocation) {
11995
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
11996
- }
11997
-
11998
- if ($this->curlAllowUnsafeSslRequests) {
11999
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
12000
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
12001
- }
12002
-
12003
- $data = curl_exec($ch);
12004
- curl_close($ch);
12005
  }
12006
 
12007
- function getFileContentsBySocket($url, &$data)
12008
  {
12009
- $this->logger->debug(sprintf('Fetching (socket) content of remote URL "%s"', $url), ['context' => LogContext::REMOTE_CONTENT]);
12010
- // mPDF 5.7.3
12011
-
12012
- $timeout = 1;
12013
- $p = parse_url($url);
12014
- $file = $p['path'];
12015
- if ($p['scheme'] == 'https') {
12016
- $prefix = 'ssl://';
12017
- $port = ($p['port'] ? $p['port'] : 443);
12018
- } else {
12019
- $prefix = '';
12020
- $port = ($p['port'] ? $p['port'] : 80);
12021
- }
12022
- if ($p['query']) {
12023
- $file .= '?' . $p['query'];
12024
- }
12025
- if (!($fh = @fsockopen($prefix . $p['host'], $port, $errno, $errstr, $timeout))) {
12026
- return false;
12027
- }
12028
-
12029
- $getstring = "GET " . $file . " HTTP/1.0 \r\n" .
12030
- "Host: " . $p['host'] . " \r\n" .
12031
- "Connection: close\r\n\r\n";
12032
-
12033
- fwrite($fh, $getstring);
12034
-
12035
- // Get rid of HTTP header
12036
- $s = fgets($fh, 1024);
12037
- if (!$s) {
12038
- return false;
12039
- }
12040
- while (!feof($fh)) {
12041
- $s = fgets($fh, 1024);
12042
- if ($s == "\r\n") {
12043
- break;
12044
- }
12045
- }
12046
- $data = '';
12047
-
12048
- while (!feof($fh)) {
12049
- $data .= fgets($fh, 1024);
12050
- }
12051
-
12052
- fclose($fh);
12053
  }
12054
 
12055
- // ==============================================================
12056
- // Moved outside WMF as also needed for SVG
12057
- function _putformobjects()
12058
- {
12059
- foreach ($this->formobjects as $file => $info) {
12060
-
12061
- $this->_newobj();
12062
-
12063
- $this->formobjects[$file]['n'] = $this->n;
12064
 
12065
- $this->_out('<</Type /XObject');
12066
- $this->_out('/Subtype /Form');
12067
- $this->_out('/Group ' . ($this->n + 1) . ' 0 R');
12068
- $this->_out('/BBox [' . $info['x'] . ' ' . $info['y'] . ' ' . ($info['w'] + $info['x']) . ' ' . ($info['h'] + $info['y']) . ']');
 
 
 
12069
 
12070
- if ($this->compress) {
12071
- $this->_out('/Filter /FlateDecode');
 
 
 
 
 
 
 
 
 
 
12072
  }
12073
-
12074
- $data = ($this->compress) ? gzcompress($info['data']) : $info['data'];
12075
- $this->_out('/Length ' . strlen($data) . '>>');
12076
- $this->_putstream($data);
12077
-
12078
- unset($this->formobjects[$file]['data']);
12079
-
12080
- $this->_out('endobj');
12081
-
12082
- // Required for SVG transparency (opacity) to work
12083
- $this->_newobj();
12084
- $this->_out('<</Type /Group');
12085
- $this->_out('/S /Transparency');
12086
- $this->_out('>>');
12087
- $this->_out('endobj');
12088
  }
 
 
 
 
 
 
 
 
12089
  }
12090
 
12091
- function _freadint($f)
12092
  {
12093
- $i = ord(fread($f, 1)) << 24;
12094
- $i += ord(fread($f, 1)) << 16;
12095
- $i += ord(fread($f, 1)) << 8;
12096
- $i += ord(fread($f, 1));
12097
-
12098
- return $i;
12099
  }
12100
 
12101
- function _UTF16BEtextstring($s)
12102
  {
12103
- $s = $this->UTF8ToUTF16BE($s, true);
12104
- if ($this->encrypted) {
12105
- $s = $this->protection->rc4($this->protection->objectKey($this->_current_obj_id), $s);
12106
  }
12107
-
12108
- return '(' . $this->_escape($s) . ')';
12109
  }
12110
 
12111
- function _textstring($s)
12112
  {
12113
- if ($this->encrypted) {
12114
- $s = $this->protection->rc4($this->protection->objectKey($this->_current_obj_id), $s);
12115
- }
 
 
 
 
 
 
12116
 
12117
- return '(' . $this->_escape($s) . ')';
 
 
 
 
 
 
 
 
 
 
 
12118
  }
12119
 
12120
- function _escape($s)
 
12121
  {
12122
- return strtr($s, [')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r']);
 
 
 
 
 
 
 
 
 
 
 
12123
  }
12124
 
12125
- function _escapeName($s)
12126
  {
12127
- return strtr($s, array('/' => '#2F'));
 
 
 
 
 
 
 
 
 
 
 
 
 
12128
  }
12129
 
12130
- function _putstream($s)
 
12131
  {
12132
- if ($this->encrypted) {
12133
- $s = $this->protection->rc4($this->protection->objectKey($this->_current_obj_id), $s);
12134
  }
12135
-
12136
- $this->_out('stream');
12137
- $this->_out($s);
12138
- $this->_out('endstream');
12139
  }
12140
 
12141
- function _out($s, $ln = true)
12142
  {
12143
- if ($this->state == 2) {
12144
- if ($this->bufferoutput) {
12145
- $this->headerbuffer.= $s . "\n";
12146
- } /* -- COLUMNS -- */ elseif (($this->ColActive) && !$this->processingHeader && !$this->processingFooter) {
12147
- // Captures everything in buffer for columns; Almost everything is sent from fn. Cell() except:
12148
- // Images sent from Image() or
12149
- // later sent as _out($textto) in printbuffer
12150
- // Line()
12151
- if (preg_match('/q \d+\.\d\d+ 0 0 (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ cm \/(I|FO)\d+ Do Q/', $s, $m)) { // Image data
12152
- $h = ($m[1] / Mpdf::SCALE);
12153
- // Update/overwrite the lowest bottom of printing y value for a column
12154
- $this->ColDetails[$this->CurrCol]['bottom_margin'] = $this->y + $h;
12155
- } /* -- TABLES -- */ elseif (preg_match('/\d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ ([\-]{0,1}\d+\.\d\d+) re/', $s, $m) && $this->tableLevel > 0) { // Rect in table
12156
- $h = ($m[1] / Mpdf::SCALE);
12157
- // Update/overwrite the lowest bottom of printing y value for a column
12158
- $this->ColDetails[$this->CurrCol]['bottom_margin'] = max($this->ColDetails[$this->CurrCol]['bottom_margin'], ($this->y + $h));
12159
- } /* -- END TABLES -- */ else { // Td Text Set in Cell()
12160
- if (isset($this->ColDetails[$this->CurrCol]['bottom_margin'])) {
12161
- $h = $this->ColDetails[$this->CurrCol]['bottom_margin'] - $this->y;
12162
- } else {
12163
- $h = 0;
12164
- }
12165
- }
12166
- if ($h < 0) {
12167
- $h = -$h;
12168
- }
12169
- $this->columnbuffer[] = [
12170
- 's' => $s, // Text string to output
12171
- 'col' => $this->CurrCol, // Column when printed
12172
- 'x' => $this->x, // x when printed
12173
- 'y' => $this->y, // this->y when printed (after column break)
12174
- 'h' => $h // actual y at bottom when printed = y+h
12175
- ];
12176
- } /* -- END COLUMNS -- */
12177
- /* -- TABLES -- */ elseif ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
12178
- // Captures eveything in buffer for rotated tables;
12179
- $this->tablebuffer .= $s . "\n";
12180
- } /* -- END TABLES -- */ elseif ($this->kwt && !$this->processingHeader && !$this->processingFooter) {
12181
- // Captures eveything in buffer for keep-with-table (h1-6);
12182
- $this->kwt_buffer[] = [
12183
- 's' => $s, // Text string to output
12184
- 'x' => $this->x, // x when printed
12185
- 'y' => $this->y, // y when printed
12186
- ];
12187
- } elseif (($this->keep_block_together) && !$this->processingHeader && !$this->processingFooter) {
12188
- // do nothing
12189
- } else {
12190
- $this->pages[$this->page] .= $s . ($ln == true ? "\n" : '');
12191
- }
12192
  } else {
12193
- $this->buffer .= $s . ($ln == true ? "\n" : '');
 
 
 
 
 
 
 
 
 
 
 
12194
  }
 
12195
  }
12196
 
12197
- /* -- WATERMARK -- */
12198
-
12199
- // add a watermark
12200
- function watermark($texte, $angle = 45, $fontsize = 96, $alpha = 0.2)
12201
  {
12202
- if ($this->PDFA || $this->PDFX) {
12203
- throw new \Mpdf\MpdfException('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!');
12204
- }
 
12205
 
12206
- if (!$this->watermark_font) {
12207
- $this->watermark_font = $this->default_font;
 
 
 
 
 
 
 
 
 
12208
  }
 
12209
 
12210
- $this->SetFont($this->watermark_font, "B", $fontsize, false); // Don't output
12211
- $texte = $this->purify_utf8_text($texte);
12212
-
12213
- if ($this->text_input_as_HTML) {
12214
- $texte = $this->all_entities_to_utf8($texte);
12215
  }
12216
 
12217
- if ($this->usingCoreFont) {
12218
- $texte = mb_convert_encoding($texte, $this->mb_enc, 'UTF-8');
 
 
 
 
 
 
 
 
 
 
 
12219
  }
12220
 
12221
- // DIRECTIONALITY
12222
- if (preg_match("/([" . $this->pregRTLchars . "])/u", $texte)) {
12223
- $this->biDirectional = true;
12224
- } // *OTL*
12225
-
12226
- $textvar = 0;
12227
- $save_OTLtags = $this->OTLtags;
12228
- $this->OTLtags = [];
12229
- if ($this->useKerning) {
12230
- if ($this->CurrentFont['haskernGPOS']) {
12231
- $this->OTLtags['Plus'] .= ' kern';
12232
- } else {
12233
- $textvar = ($textvar | TextVars::FC_KERNING);
12234
- }
12235
- }
12236
 
12237
- /* -- OTL -- */
12238
- // Use OTL OpenType Table Layout - GSUB & GPOS
12239
- if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
12240
- $texte = $this->otl->applyOTL($texte, $this->CurrentFont['useOTL']);
12241
- $OTLdata = $this->otl->OTLdata;
12242
  }
12243
- /* -- END OTL -- */
12244
- $this->OTLtags = $save_OTLtags;
12245
 
12246
- $this->magic_reverse_dir($texte, $this->directionality, $OTLdata);
12247
 
12248
- $this->SetAlpha($alpha);
 
 
 
12249
 
12250
- $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings));
 
12251
 
12252
- $szfont = $fontsize;
12253
- $loop = 0;
12254
- $maxlen = (min($this->w, $this->h) ); // sets max length of text as 7/8 width/height of page
12255
 
12256
- while ($loop == 0) {
12257
- $this->SetFont($this->watermark_font, "B", $szfont, false); // Don't output
12258
- $offset = ((sin(deg2rad($angle))) * ($szfont / Mpdf::SCALE));
 
 
 
 
12259
 
12260
- $strlen = $this->GetStringWidth($texte, true, $OTLdata, $textvar);
12261
- if ($strlen > $maxlen - $offset) {
12262
- $szfont --;
12263
- } else {
12264
- $loop ++;
12265
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12266
  }
 
12267
 
12268
- $this->SetFont($this->watermark_font, "B", $szfont - 0.1, true, true); // Output The -0.1 is because SetFont above is not written to PDF
12269
 
12270
- // Repeating it will not output anything as mPDF thinks it is set
12271
- $adj = ((cos(deg2rad($angle))) * ($strlen / 2));
12272
- $opp = ((sin(deg2rad($angle))) * ($strlen / 2));
12273
 
12274
- $wx = ($this->w / 2) - $adj + $offset / 3;
12275
- $wy = ($this->h / 2) + $opp;
 
 
 
 
 
 
12276
 
12277
- $this->Rotate($angle, $wx, $wy);
12278
- $this->Text($wx, $wy, $texte, $OTLdata, $textvar);
12279
- $this->Rotate(0);
12280
- $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings));
12281
 
12282
- $this->SetAlpha(1);
12283
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12284
 
12285
- function watermarkImg($src, $alpha = 0.2)
12286
- {
12287
- if ($this->PDFA || $this->PDFX) {
12288
- throw new \Mpdf\MpdfException('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!');
12289
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12290
 
12291
- if ($this->watermarkImgBehind) {
12292
- $this->watermarkImgAlpha = $this->SetAlpha($alpha, 'Normal', true);
12293
- } else {
12294
- $this->SetAlpha($alpha, $this->watermarkImgAlphaBlend);
12295
- }
12296
 
12297
- $this->Image($src, 0, 0, 0, 0, '', '', true, true, true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12298
 
12299
- if (!$this->watermarkImgBehind) {
12300
- $this->SetAlpha(1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12301
  }
12302
- }
12303
 
12304
- /* -- END WATERMARK -- */
12305
 
12306
- function Rotate($angle, $x = -1, $y = -1)
12307
- {
12308
- if ($x == -1) {
12309
- $x = $this->x;
12310
- }
12311
- if ($y == -1) {
12312
- $y = $this->y;
12313
- }
12314
- if ($this->angle != 0) {
12315
- $this->_out('Q');
12316
  }
12317
- $this->angle = $angle;
12318
- if ($angle != 0) {
12319
- $angle*=M_PI / 180;
12320
- $c = cos($angle);
12321
- $s = sin($angle);
12322
- $cx = $x * Mpdf::SCALE;
12323
- $cy = ($this->h - $y) * Mpdf::SCALE;
12324
- $this->_out(sprintf('q %.5F %.5F %.5F %.5F %.3F %.3F cm 1 0 0 1 %.3F %.3F cm', $c, $s, -$s, $c, $cx, $cy, -$cx, -$cy));
12325
  }
12326
- }
12327
 
12328
- function CircularText($x, $y, $r, $text, $align = 'top', $fontfamily = '', $fontsize = 0, $fontstyle = '', $kerning = 120, $fontwidth = 100, $divider = '')
12329
- {
12330
- if (empty($this->directWrite)) {
12331
- $this->directWrite = new DirectWrite($this, $this->otl, $this->sizeConverter, $this->colorConverter);
12332
  }
12333
 
12334
- $this->directWrite->CircularText($x, $y, $r, $text, $align, $fontfamily, $fontsize, $fontstyle, $kerning, $fontwidth, $divider);
12335
- }
12336
-
12337
- // From Invoice
12338
- function RoundedRect($x, $y, $w, $h, $r, $style = '')
12339
- {
12340
- $hp = $this->h;
12341
 
12342
- if ($style == 'F') {
12343
- $op = 'f';
12344
- } elseif ($style == 'FD' or $style == 'DF') {
12345
- $op = 'B';
12346
- } else {
12347
- $op = 'S';
 
 
 
 
 
 
 
 
 
 
 
12348
  }
12349
 
12350
- $MyArc = 4 / 3 * (sqrt(2) - 1);
12351
- $this->_out(sprintf('%.3F %.3F m', ($x + $r) * Mpdf::SCALE, ($hp - $y) * Mpdf::SCALE));
12352
- $xc = $x + $w - $r;
12353
- $yc = $y + $r;
12354
- $this->_out(sprintf('%.3F %.3F l', $xc * Mpdf::SCALE, ($hp - $y) * Mpdf::SCALE));
12355
-
12356
- $this->_Arc($xc + $r * $MyArc, $yc - $r, $xc + $r, $yc - $r * $MyArc, $xc + $r, $yc);
12357
- $xc = $x + $w - $r;
12358
- $yc = $y + $h - $r;
12359
- $this->_out(sprintf('%.3F %.3F l', ($x + $w) * Mpdf::SCALE, ($hp - $yc) * Mpdf::SCALE));
12360
-
12361
- $this->_Arc($xc + $r, $yc + $r * $MyArc, $xc + $r * $MyArc, $yc + $r, $xc, $yc + $r);
12362
- $xc = $x + $r;
12363
- $yc = $y + $h - $r;
12364
- $this->_out(sprintf('%.3F %.3F l', $xc * Mpdf::SCALE, ($hp - ($y + $h)) * Mpdf::SCALE));
12365
-
12366
- $this->_Arc($xc - $r * $MyArc, $yc + $r, $xc - $r, $yc + $r * $MyArc, $xc - $r, $yc);
12367
- $xc = $x + $r;
12368
- $yc = $y + $r;
12369
- $this->_out(sprintf('%.3F %.3F l', ($x) * Mpdf::SCALE, ($hp - $yc) * Mpdf::SCALE));
12370
-
12371
- $this->_Arc($xc - $r, $yc - $r * $MyArc, $xc - $r * $MyArc, $yc - $r, $xc, $yc - $r);
12372
- $this->_out($op);
12373
- }
12374
-
12375
- function _Arc($x1, $y1, $x2, $y2, $x3, $y3)
12376
- {
12377
- $h = $this->h;
12378
- $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x1 * Mpdf::SCALE, ($h - $y1) * Mpdf::SCALE, $x2 * Mpdf::SCALE, ($h - $y2) * Mpdf::SCALE, $x3 * Mpdf::SCALE, ($h - $y3) * Mpdf::SCALE));
12379
- }
12380
-
12381
- // ====================================================
12382
-
12383
 
 
 
 
 
 
 
 
 
12384
 
12385
- /* -- DIRECTW -- */
12386
- function Shaded_box($text, $font = '', $fontstyle = 'B', $szfont = '', $width = '70%', $style = 'DF', $radius = 2.5, $fill = '#FFFFFF', $color = '#000000', $pad = 2)
12387
- {
12388
- // F (shading - no line),S (line, no shading),DF (both)
12389
- if (empty($this->directWrite)) {
12390
- $this->directWrite = new DirectWrite($this, $this->otl, $this->sizeConverter, $this->colorConverter);
12391
- }
12392
- $this->directWrite->Shaded_box($text, $font, $fontstyle, $szfont, $width, $style, $radius, $fill, $color, $pad);
12393
- }
12394
 
12395
- /* -- END DIRECTW -- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12396
 
12397
- function UTF8StringToArray($str, $addSubset = true)
12398
- {
12399
- $out = [];
12400
- $len = strlen($str);
12401
- for ($i = 0; $i < $len; $i++) {
12402
- $uni = -1;
12403
- $h = ord($str[$i]);
12404
- if ($h <= 0x7F) {
12405
- $uni = $h;
12406
- } elseif ($h >= 0xC2) {
12407
- if (($h <= 0xDF) && ($i < $len - 1)) {
12408
- $uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
12409
- } elseif (($h <= 0xEF) && ($i < $len - 2)) {
12410
- $uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
12411
- } elseif (($h <= 0xF4) && ($i < $len - 3)) {
12412
- $uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
12413
  }
12414
- }
12415
- if ($uni >= 0) {
12416
- $out[] = $uni;
12417
- if ($addSubset && isset($this->CurrentFont['subset'])) {
12418
- $this->CurrentFont['subset'][$uni] = $uni;
 
 
 
 
 
 
 
 
 
 
 
12419
  }
12420
  }
12421
  }
12422
- return $out;
12423
  }
12424
 
12425
- // Convert utf-8 string to <HHHHHH> for Font Subsets
12426
- function UTF8toSubset($str)
12427
  {
12428
- $ret = '<';
12429
- // $str = preg_replace('/'.preg_quote($this->aliasNbPg,'/').'/', chr(7), $str ); // mPDF 6 deleted
12430
- // $str = preg_replace('/'.preg_quote($this->aliasNbPgGp,'/').'/', chr(8), $str ); // mPDF 6 deleted
12431
- $unicode = $this->UTF8StringToArray($str);
12432
- $orig_fid = $this->CurrentFont['subsetfontids'][0];
12433
- $last_fid = $this->CurrentFont['subsetfontids'][0];
12434
- foreach ($unicode as $c) {
12435
- /* // mPDF 6 deleted
12436
- if ($c == 7 || $c == 8) {
12437
- if ($orig_fid != $last_fid) {
12438
- $ret .= '> Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <';
12439
- $last_fid = $orig_fid;
12440
- }
12441
- if ($c == 7) { $ret .= $this->aliasNbPgHex; }
12442
- else { $ret .= $this->aliasNbPgGpHex; }
12443
- continue;
12444
- }
12445
- */
12446
- if (!$this->_charDefined($this->CurrentFont['cw'], $c)) {
12447
- $c = 0;
12448
- } // mPDF 6
12449
- for ($i = 0; $i < 99; $i++) {
12450
- // return c as decimal char
12451
- $init = array_search($c, $this->CurrentFont['subsets'][$i]);
12452
- if ($init !== false) {
12453
- if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
12454
- $ret .= '> Tj /F' . $this->CurrentFont['subsetfontids'][$i] . ' ' . $this->FontSizePt . ' Tf <';
12455
- $last_fid = $this->CurrentFont['subsetfontids'][$i];
12456
- }
12457
- $ret .= sprintf("%02s", strtoupper(dechex($init)));
12458
- break;
12459
- } // TrueType embedded SUBSETS
12460
- elseif (count($this->CurrentFont['subsets'][$i]) < 255) {
12461
- $n = count($this->CurrentFont['subsets'][$i]);
12462
- $this->CurrentFont['subsets'][$i][$n] = $c;
12463
- if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
12464
- $ret .= '> Tj /F' . $this->CurrentFont['subsetfontids'][$i] . ' ' . $this->FontSizePt . ' Tf <';
12465
- $last_fid = $this->CurrentFont['subsetfontids'][$i];
12466
- }
12467
- $ret .= sprintf("%02s", strtoupper(dechex($n)));
12468
- break;
12469
- } elseif (!isset($this->CurrentFont['subsets'][($i + 1)])) {
12470
- // TrueType embedded SUBSETS
12471
- $this->CurrentFont['subsets'][($i + 1)] = [0 => 0];
12472
- $new_fid = count($this->fonts) + $this->extraFontSubsets + 1;
12473
- $this->CurrentFont['subsetfontids'][($i + 1)] = $new_fid;
12474
- $this->extraFontSubsets++;
12475
  }
 
 
12476
  }
 
 
 
12477
  }
12478
- $ret .= '>';
12479
- if ($last_fid != $orig_fid) {
12480
- $ret .= ' Tj /F' . $orig_fid . ' ' . $this->FontSizePt . ' Tf <> ';
 
 
 
 
 
 
 
 
 
12481
  }
12482
- return $ret;
12483
  }
12484
 
12485
- // Converts UTF-8 strings to UTF16-BE.
12486
- function UTF8ToUTF16BE($str, $setbom = true)
12487
  {
12488
- if ($this->checkSIP && preg_match("/([\x{20000}-\x{2FFFF}])/u", $str)) {
12489
- if (!in_array($this->currentfontfamily, ['gb', 'big5', 'sjis', 'uhc', 'gbB', 'big5B', 'sjisB', 'uhcB', 'gbI', 'big5I', 'sjisI', 'uhcI',
12490
- 'gbBI', 'big5BI', 'sjisBI', 'uhcBI'])) {
12491
- $str = preg_replace("/[\x{20000}-\x{2FFFF}]/u", chr(0), $str);
12492
- }
12493
- }
12494
- if ($this->checkSMP && preg_match("/([\x{10000}-\x{1FFFF}])/u", $str)) {
12495
- $str = preg_replace("/[\x{10000}-\x{1FFFF}]/u", chr(0), $str);
12496
  }
12497
- $outstr = ""; // string to be returned
12498
- if ($setbom) {
12499
- $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM)
 
 
 
 
 
 
12500
  }
12501
- $outstr .= mb_convert_encoding($str, 'UTF-16BE', 'UTF-8');
12502
- return $outstr;
12503
- }
12504
 
12505
- /* -- CJK-FONTS -- */
12506
 
12507
- // from class PDF_Chinese CJK EXTENSIONS
12508
- function AddCIDFont($family, $style, $name, &$cw, $CMap, $registry, $desc)
12509
- {
12510
- $fontkey = strtolower($family) . strtoupper($style);
12511
- if (isset($this->fonts[$fontkey])) {
12512
- throw new \Mpdf\MpdfException("Font already added: $family $style");
12513
  }
12514
- $i = count($this->fonts) + $this->extraFontSubsets + 1;
12515
- $name = str_replace(' ', '', $name);
12516
- if ($family == 'sjis') {
12517
- $up = -120;
12518
- } else {
12519
- $up = -130;
12520
  }
12521
- // ? 'up' and 'ut' do not seem to be referenced anywhere
12522
- $this->fonts[$fontkey] = ['i' => $i, 'type' => 'Type0', 'name' => $name, 'up' => $up, 'ut' => 40, 'cw' => $cw, 'CMap' => $CMap, 'registry' => $registry, 'MissingWidth' => 1000, 'desc' => $desc];
12523
- }
12524
 
12525
- function AddCJKFont($family)
12526
- {
12527
 
12528
- if ($this->PDFA || $this->PDFX) {
12529
- throw new \Mpdf\MpdfException("Adobe CJK fonts cannot be embedded in mPDF (required for PDFA1-b and PDFX/1-a).");
12530
- }
12531
- if ($family == 'big5') {
12532
- $this->AddBig5Font();
12533
- } elseif ($family == 'gb') {
12534
- $this->AddGBFont();
12535
- } elseif ($family == 'sjis') {
12536
- $this->AddSJISFont();
12537
- } elseif ($family == 'uhc') {
12538
- $this->AddUHCFont();
12539
- }
12540
- }
12541
 
12542
- function AddBig5Font()
12543
- {
12544
- // Add Big5 font with proportional Latin
12545
- $family = 'big5';
12546
- $name = 'MSungStd-Light-Acro';
12547
- $cw = $this->Big5_widths;
12548
- $CMap = 'UniCNS-UTF16-H';
12549
- $registry = ['ordering' => 'CNS1', 'supplement' => 4];
12550
- $desc = [
12551
- 'Ascent' => 880,
12552
- 'Descent' => -120,
12553
- 'CapHeight' => 880,
12554
- 'Flags' => 6,
12555
- 'FontBBox' => '[-160 -249 1015 1071]',
12556
- 'ItalicAngle' => 0,
12557
- 'StemV' => 93,
12558
- ];
12559
- $this->AddCIDFont($family, '', $name, $cw, $CMap, $registry, $desc);
12560
- $this->AddCIDFont($family, 'B', $name . ',Bold', $cw, $CMap, $registry, $desc);
12561
- $this->AddCIDFont($family, 'I', $name . ',Italic', $cw, $CMap, $registry, $desc);
12562
- $this->AddCIDFont($family, 'BI', $name . ',BoldItalic', $cw, $CMap, $registry, $desc);
12563
- }
12564
 
12565
- function AddGBFont()
12566
- {
12567
- // Add GB font with proportional Latin
12568
- $family = 'gb';
12569
- $name = 'STSongStd-Light-Acro';
12570
- $cw = $this->GB_widths;
12571
- $CMap = 'UniGB-UTF16-H';
12572
- $registry = ['ordering' => 'GB1', 'supplement' => 4];
12573
- $desc = [
12574
- 'Ascent' => 880,
12575
- 'Descent' => -120,
12576
- 'CapHeight' => 737,
12577
- 'Flags' => 6,
12578
- 'FontBBox' => '[-25 -254 1000 880]',
12579
- 'ItalicAngle' => 0,
12580
- 'StemV' => 58,
12581
- 'Style' => '<< /Panose <000000000400000000000000> >>',
12582
- ];
12583
- $this->AddCIDFont($family, '', $name, $cw, $CMap, $registry, $desc);
12584
- $this->AddCIDFont($family, 'B', $name . ',Bold', $cw, $CMap, $registry, $desc);
12585
- $this->AddCIDFont($family, 'I', $name . ',Italic', $cw, $CMap, $registry, $desc);
12586
- $this->AddCIDFont($family, 'BI', $name . ',BoldItalic', $cw, $CMap, $registry, $desc);
12587
- }
12588
 
12589
- function AddSJISFont()
12590
- {
12591
- // Add SJIS font with proportional Latin
12592
- $family = 'sjis';
12593
- $name = 'KozMinPro-Regular-Acro';
12594
- $cw = $this->SJIS_widths;
12595
- $CMap = 'UniJIS-UTF16-H';
12596
- $registry = ['ordering' => 'Japan1', 'supplement' => 5];
12597
- $desc = [
12598
- 'Ascent' => 880,
12599
- 'Descent' => -120,
12600
- 'CapHeight' => 740,
12601
- 'Flags' => 6,
12602
- 'FontBBox' => '[-195 -272 1110 1075]',
12603
- 'ItalicAngle' => 0,
12604
- 'StemV' => 86,
12605
- 'XHeight' => 502,
12606
- ];
12607
- $this->AddCIDFont($family, '', $name, $cw, $CMap, $registry, $desc);
12608
- $this->AddCIDFont($family, 'B', $name . ',Bold', $cw, $CMap, $registry, $desc);
12609
- $this->AddCIDFont($family, 'I', $name . ',Italic', $cw, $CMap, $registry, $desc);
12610
- $this->AddCIDFont($family, 'BI', $name . ',BoldItalic', $cw, $CMap, $registry, $desc);
12611
- }
12612
 
12613
- function AddUHCFont()
12614
- {
12615
- // Add UHC font with proportional Latin
12616
- $family = 'uhc';
12617
- $name = 'HYSMyeongJoStd-Medium-Acro';
12618
- $cw = $this->UHC_widths;
12619
- $CMap = 'UniKS-UTF16-H';
12620
- $registry = ['ordering' => 'Korea1', 'supplement' => 2];
12621
- $desc = [
12622
- 'Ascent' => 880,
12623
- 'Descent' => -120,
12624
- 'CapHeight' => 720,
12625
- 'Flags' => 6,
12626
- 'FontBBox' => '[-28 -148 1001 880]',
12627
- 'ItalicAngle' => 0,
12628
- 'StemV' => 60,
12629
- 'Style' => '<< /Panose <000000000600000000000000> >>',
12630
- ];
12631
- $this->AddCIDFont($family, '', $name, $cw, $CMap, $registry, $desc);
12632
- $this->AddCIDFont($family, 'B', $name . ',Bold', $cw, $CMap, $registry, $desc);
12633
- $this->AddCIDFont($family, 'I', $name . ',Italic', $cw, $CMap, $registry, $desc);
12634
- $this->AddCIDFont($family, 'BI', $name . ',BoldItalic', $cw, $CMap, $registry, $desc);
12635
- }
12636
 
12637
- /* -- END CJK-FONTS -- */
12638
 
12639
- //////////////////////////////////////////////////////////////////////////////
12640
- //////////////////////////////////////////////////////////////////////////////
12641
- //////////////////////////////////////////////////////////////////////////////
12642
- //////////////////////////////////////////////////////////////////////////////
12643
- //////////////////////////////////////////////////////////////////////////////
12644
- //////////////////////////////////////////////////////////////////////////////
12645
- //////////////////////////////////////////////////////////////////////////////
12646
 
12647
- function SetDefaultFont($font)
12648
- {
12649
- // Disallow embedded fonts to be used as defaults in PDFA
12650
- if ($this->PDFA || $this->PDFX) {
12651
- if (strtolower($font) == 'ctimes') {
12652
- $font = 'serif';
12653
- }
12654
- if (strtolower($font) == 'ccourier') {
12655
- $font = 'monospace';
12656
- }
12657
- if (strtolower($font) == 'chelvetica') {
12658
- $font = 'sans-serif';
 
12659
  }
12660
  }
12661
- $font = $this->SetFont($font); // returns substituted font if necessary
12662
- $this->default_font = $font;
12663
- $this->original_default_font = $font;
12664
- if (!$this->watermark_font) {
12665
- $this->watermark_font = $font;
12666
- } // *WATERMARK*
12667
- $this->defaultCSS['BODY']['FONT-FAMILY'] = $font;
12668
- $this->cssManager->CSS['BODY']['FONT-FAMILY'] = $font;
12669
- }
12670
-
12671
- function SetDefaultFontSize($fontsize)
12672
- {
12673
- $this->default_font_size = $fontsize;
12674
- $this->original_default_font_size = $fontsize;
12675
- $this->SetFontSize($fontsize);
12676
- $this->defaultCSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
12677
- $this->cssManager->CSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
12678
  }
12679
 
12680
- function SetDefaultBodyCSS($prop, $val)
12681
  {
12682
- if ($prop) {
12683
- $this->defaultCSS['BODY'][strtoupper($prop)] = $val;
12684
- $this->cssManager->CSS['BODY'][strtoupper($prop)] = $val;
12685
  }
12686
- }
12687
 
12688
- function SetDirectionality($dir = 'ltr')
12689
- {
12690
- /* -- OTL -- */
12691
- if (strtolower($dir) == 'rtl') {
12692
- if ($this->directionality != 'rtl') {
12693
- // Swop L/R Margins so page 1 RTL is an 'even' page
12694
- $tmp = $this->DeflMargin;
12695
- $this->DeflMargin = $this->DefrMargin;
12696
- $this->DefrMargin = $tmp;
12697
- $this->orig_lMargin = $this->DeflMargin;
12698
- $this->orig_rMargin = $this->DefrMargin;
12699
 
12700
- $this->SetMargins($this->DeflMargin, $this->DefrMargin, $this->tMargin);
12701
- }
12702
- $this->directionality = 'rtl';
12703
- $this->defaultAlign = 'R';
12704
- $this->defaultTableAlign = 'R';
12705
- } else {
12706
- /* -- END OTL -- */
12707
- $this->directionality = 'ltr';
12708
- $this->defaultAlign = 'L';
12709
- $this->defaultTableAlign = 'L';
12710
- } // *OTL*
12711
- $this->cssManager->CSS['BODY']['DIRECTION'] = $this->directionality;
12712
- }
12713
 
12714
- // Return either a number (factor) - based on current set fontsize (if % or em) - or exact lineheight (with 'mm' after it)
12715
- function fixLineheight($v)
12716
- {
12717
- $lh = false;
12718
- if (preg_match('/^[0-9\.,]*$/', $v) && $v >= 0) {
12719
- return ($v + 0);
12720
- } elseif (strtoupper($v) == 'NORMAL' || $v == 'N') {
12721
- return 'N'; // mPDF 6
12722
- } else {
12723
- $tlh = $this->sizeConverter->convert($v, $this->FontSize, $this->FontSize, true);
12724
- if ($tlh) {
12725
- return ($tlh . 'mm');
 
 
 
 
 
 
 
12726
  }
12727
  }
12728
- return $this->normalLineheight;
12729
- }
12730
 
12731
- function _getNormalLineheight($desc = false)
12732
- {
12733
- if (!$desc) {
12734
- $desc = $this->CurrentFont['desc'];
12735
- }
12736
- if (!isset($desc['Leading'])) {
12737
- $desc['Leading'] = 0;
12738
- }
12739
- if ($this->useFixedNormalLineHeight) {
12740
- $lh = $this->normalLineheight;
12741
- } elseif (isset($desc['Ascent']) && $desc['Ascent']) {
12742
- $lh = ($this->adjustFontDescLineheight * ($desc['Ascent'] - $desc['Descent'] + $desc['Leading']) / 1000);
12743
- } else {
12744
- $lh = $this->normalLineheight;
12745
  }
12746
- return $lh;
12747
- }
12748
 
12749
- // Set a (fixed) lineheight to an actual value - either to named fontsize(pts) or default
12750
- function SetLineHeight($FontPt = '', $lh = '')
12751
- {
12752
- if (!$FontPt) {
12753
- $FontPt = $this->FontSizePt;
12754
  }
12755
- $fs = $FontPt / Mpdf::SCALE;
12756
- $this->lineheight = $this->_computeLineheight($lh, $fs);
12757
  }
12758
 
12759
- function _computeLineheight($lh, $fs = '')
12760
  {
12761
- if ($this->shrin_k > 1) {
12762
- $k = $this->shrin_k;
12763
- } else {
12764
- $k = 1;
12765
- }
12766
- if (!$fs) {
12767
- $fs = $this->FontSize;
12768
- }
12769
- if ($lh == 'N') {
12770
- $lh = $this->_getNormalLineheight();
12771
- }
12772
- if (preg_match('/mm/', $lh)) {
12773
- return (((float) $lh) / $k); // convert to number
12774
- } elseif ($lh > 0) {
12775
- return ($fs * $lh);
12776
  }
12777
- return ($fs * $this->normalLineheight);
12778
- }
12779
 
12780
- function _setLineYpos(&$fontsize, &$fontdesc, &$CSSlineheight, $blockYpos = false)
12781
- {
12782
- $ypos['glyphYorigin'] = 0;
12783
- $ypos['baseline-shift'] = 0;
12784
- $linegap = 0;
12785
- $leading = 0;
12786
 
12787
- if (isset($fontdesc['Ascent']) && $fontdesc['Ascent'] && !$this->useFixedTextBaseline) {
12788
- // Fontsize uses font metrics - this method seems to produce results compatible with browsers (except IE9)
12789
- $ypos['boxtop'] = $fontdesc['Ascent'] / 1000 * $fontsize;
12790
- $ypos['boxbottom'] = $fontdesc['Descent'] / 1000 * $fontsize;
12791
- if (isset($fontdesc['Leading'])) {
12792
- $linegap = $fontdesc['Leading'] / 1000 * $fontsize;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12793
  }
12794
- } // Default if not set - uses baselineC
12795
- else {
12796
- $ypos['boxtop'] = (0.5 + $this->baselineC) * $fontsize;
12797
- $ypos['boxbottom'] = -(0.5 - $this->baselineC) * $fontsize;
12798
  }
12799
- $fontheight = $ypos['boxtop'] - $ypos['boxbottom'];
12800
 
12801
- if ($this->shrin_k > 1) {
12802
- $shrin_k = $this->shrin_k;
12803
- } else {
12804
- $shrin_k = 1;
12805
  }
12806
 
12807
- $leading = 0;
12808
- if ($CSSlineheight == 'N') {
12809
- $lh = $this->_getNormalLineheight($fontdesc);
12810
- $lineheight = ($fontsize * $lh);
12811
- $leading += $linegap; // specified in hhea or sTypo in OpenType tables
12812
- } elseif (preg_match('/mm/', $CSSlineheight)) {
12813
- $lineheight = (((float) $CSSlineheight) / $shrin_k); // convert to number
12814
- } // ??? If lineheight is a factor e.g. 1.3 ?? use factor x 1em or ? use 'normal' lineheight * factor
12815
- // Could depend on value for $text_height - a draft CSS value as set above for now
12816
- elseif ($CSSlineheight > 0) {
12817
- $lineheight = ($fontsize * $CSSlineheight);
12818
- } else {
12819
- $lineheight = ($fontsize * $this->normalLineheight);
12820
  }
12821
 
12822
- // In general, calculate the "leading" - the difference between the fontheight and the lineheight
12823
- // and add half to the top and half to the bottom. BUT
12824
- // If an inline element has a font-size less than the block element, and the line-height is set as an em or % value
12825
- // it will add too much leading below the font and expand the height of the line - so just use the block element exttop/extbottom:
12826
- if (preg_match('/mm/', $CSSlineheight) && $ypos['boxtop'] < $blockYpos['boxtop'] && $ypos['boxbottom'] > $blockYpos['boxbottom']) {
12827
- $ypos['exttop'] = $blockYpos['exttop'];
12828
- $ypos['extbottom'] = $blockYpos['extbottom'];
12829
- } else {
12830
- $leading += ($lineheight - $fontheight);
12831
 
12832
- $ypos['exttop'] = $ypos['boxtop'] + $leading / 2;
12833
- $ypos['extbottom'] = $ypos['boxbottom'] - $leading / 2;
 
 
 
 
 
 
 
12834
  }
12835
 
 
 
 
 
 
12836
 
12837
- // TEMP ONLY FOR DEBUGGING *********************************
12838
- // $ypos['lineheight'] = $lineheight;
12839
- // $ypos['fontheight'] = $fontheight;
12840
- // $ypos['leading'] = $leading;
12841
 
12842
- return $ypos;
12843
- }
12844
 
12845
- /* Called from WriteFlowingBlock() and finishFlowingBlock()
12846
- Determines the line hieght and glyph/writing position
12847
- for each element in the line to be written */
12848
 
12849
- function _setInlineBlockHeights(&$lineBox, &$stackHeight, &$content, &$font, $is_table)
12850
- {
12851
- if ($this->shrin_k > 1) {
12852
- $shrin_k = $this->shrin_k;
12853
- } else {
12854
- $shrin_k = 1;
12855
- }
12856
 
12857
- $ypos = [];
12858
- $bordypos = [];
12859
- $bgypos = [];
12860
 
12861
- if ($is_table) {
12862
- // FOR TABLE
12863
- $fontsize = $this->FontSize;
12864
- $fontkey = $this->FontFamily . $this->FontStyle;
12865
- $fontdesc = $this->fonts[$fontkey]['desc'];
12866
- $CSSlineheight = $this->cellLineHeight;
12867
- $line_stacking_strategy = $this->cellLineStackingStrategy; // inline-line-height [default] | block-line-height | max-height | grid-height
12868
- $line_stacking_shift = $this->cellLineStackingShift; // consider-shifts [default] | disregard-shifts
12869
- } else {
12870
- // FOR BLOCK FONT
12871
- $fontsize = $this->blk[$this->blklvl]['InlineProperties']['size'];
12872
- $fontkey = $this->blk[$this->blklvl]['InlineProperties']['family'] . $this->blk[$this->blklvl]['InlineProperties']['style'];
12873
- $fontdesc = $this->fonts[$fontkey]['desc'];
12874
- $CSSlineheight = $this->blk[$this->blklvl]['line_height'];
12875
- // inline-line-height | block-line-height | max-height | grid-height
12876
- $line_stacking_strategy = (isset($this->blk[$this->blklvl]['line_stacking_strategy']) ? $this->blk[$this->blklvl]['line_stacking_strategy'] : 'inline-line-height');
12877
- // consider-shifts | disregard-shifts
12878
- $line_stacking_shift = (isset($this->blk[$this->blklvl]['line_stacking_shift']) ? $this->blk[$this->blklvl]['line_stacking_shift'] : 'consider-shifts');
12879
- }
12880
- $boxLineHeight = $this->_computeLineheight($CSSlineheight, $fontsize);
12881
 
 
12882
 
12883
- // First, set a "strut" using block font at index $lineBox[-1]
12884
- $ypos[-1] = $this->_setLineYpos($fontsize, $fontdesc, $CSSlineheight);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12885
 
12886
- // for the block element - always taking the block EXTENDED progression including leading - which may be negative
12887
- if ($line_stacking_strategy == 'block-line-height') {
12888
- $topy = $ypos[-1]['exttop'];
12889
- $bottomy = $ypos[-1]['extbottom'];
12890
- } else {
12891
- $topy = 0;
12892
- $bottomy = 0;
12893
  }
12894
 
12895
- // Get text-middle for aligning images/objects
12896
- $midpoint = $ypos[-1]['boxtop'] - (($ypos[-1]['boxtop'] - $ypos[-1]['boxbottom']) / 2);
12897
 
12898
- // for images / inline objects / replaced elements
12899
- $mta = 0; // Maximum top-aligned
12900
- $mba = 0; // Maximum bottom-aligned
12901
- foreach ($content as $k => $chunk) {
12902
- if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]['type'] == 'listmarker') {
12903
- $ypos[$k] = $ypos[-1];
12904
- // UPDATE Maximums
12905
- if ($line_stacking_strategy == 'block-line-height' || $line_stacking_strategy == 'grid-height' || $line_stacking_strategy == 'max-height') { // don't include extended block progression of all inline elements
12906
- if ($ypos[$k]['boxtop'] > $topy) {
12907
- $topy = $ypos[$k]['boxtop'];
12908
- }
12909
- if ($ypos[$k]['boxbottom'] < $bottomy) {
12910
- $bottomy = $ypos[$k]['boxbottom'];
12911
- }
12912
- } else {
12913
- if ($ypos[$k]['exttop'] > $topy) {
12914
- $topy = $ypos[$k]['exttop'];
12915
- }
12916
- if ($ypos[$k]['extbottom'] < $bottomy) {
12917
- $bottomy = $ypos[$k]['extbottom'];
12918
- }
12919
- }
12920
- } elseif (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]['type'] == 'dottab') { // mPDF 6 DOTTAB
12921
- $fontsize = $font[$k]['size'];
12922
- $fontdesc = $font[$k]['curr']['desc'];
12923
- $lh = 1;
12924
- $ypos[$k] = $this->_setLineYpos($fontsize, $fontdesc, $lh, $ypos[-1]); // Lineheight=1 fixed
12925
- } elseif (isset($this->objectbuffer[$k])) {
12926
- $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
12927
- $va = $this->objectbuffer[$k]['vertical-align'];
12928
-
12929
- if ($va == 'BS') { // (BASELINE default)
12930
- if ($oh > $topy) {
12931
- $topy = $oh;
12932
- }
12933
- } elseif ($va == 'M') {
12934
- if (($midpoint + $oh / 2) > $topy) {
12935
- $topy = $midpoint + $oh / 2;
12936
- }
12937
- if (($midpoint - $oh / 2) < $bottomy) {
12938
- $bottomy = $midpoint - $oh / 2;
12939
- }
12940
- } elseif ($va == 'TT') {
12941
- if (($ypos[-1]['boxtop'] - $oh) < $bottomy) {
12942
- $bottomy = $ypos[-1]['boxtop'] - $oh;
12943
- $topy = max($topy, $ypos[-1]['boxtop']);
12944
- }
12945
- } elseif ($va == 'TB') {
12946
- if (($ypos[-1]['boxbottom'] + $oh) > $topy) {
12947
- $topy = $ypos[-1]['boxbottom'] + $oh;
12948
- $bottomy = min($bottomy, $ypos[-1]['boxbottom']);
12949
- }
12950
- } elseif ($va == 'T') {
12951
- if ($oh > $mta) {
12952
- $mta = $oh;
12953
- }
12954
- } elseif ($va == 'B') {
12955
- if ($oh > $mba) {
12956
- $mba = $oh;
12957
- }
12958
- }
12959
- } elseif ($content[$k] || $content[$k] === '0') {
12960
- // FOR FLOWING BLOCK
12961
- $fontsize = $font[$k]['size'];
12962
- $fontdesc = $font[$k]['curr']['desc'];
12963
- // In future could set CSS line-height from inline elements; for now, use block level:
12964
- $ypos[$k] = $this->_setLineYpos($fontsize, $fontdesc, $CSSlineheight, $ypos[-1]);
12965
-
12966
- if (isset($font[$k]['textparam']['text-baseline']) && $font[$k]['textparam']['text-baseline'] != 0) {
12967
- $ypos[$k]['baseline-shift'] = $font[$k]['textparam']['text-baseline'];
12968
- }
12969
-
12970
- // DO ALIGNMENT FOR BASELINES *******************
12971
- // Until most fonts have OpenType BASE tables, this won't work
12972
- // $ypos[$k] compared to $ypos[-1] or $ypos[$k-1] using $dominant_baseline and $baseline_table
12973
- // UPDATE Maximums
12974
- if ($line_stacking_strategy == 'block-line-height' || $line_stacking_strategy == 'grid-height' || $line_stacking_strategy == 'max-height') { // don't include extended block progression of all inline elements
12975
- if ($line_stacking_shift == 'disregard-shifts') {
12976
- if ($ypos[$k]['boxtop'] > $topy) {
12977
- $topy = $ypos[$k]['boxtop'];
12978
- }
12979
- if ($ypos[$k]['boxbottom'] < $bottomy) {
12980
- $bottomy = $ypos[$k]['boxbottom'];
12981
- }
12982
- } else {
12983
- if (($ypos[$k]['boxtop'] + $ypos[$k]['baseline-shift']) > $topy) {
12984
- $topy = $ypos[$k]['boxtop'] + $ypos[$k]['baseline-shift'];
12985
- }
12986
- if (($ypos[$k]['boxbottom'] + $ypos[$k]['baseline-shift']) < $bottomy) {
12987
- $bottomy = $ypos[$k]['boxbottom'] + $ypos[$k]['baseline-shift'];
12988
- }
12989
- }
12990
- } else {
12991
- if ($line_stacking_shift == 'disregard-shifts') {
12992
- if ($ypos[$k]['exttop'] > $topy) {
12993
- $topy = $ypos[$k]['exttop'];
12994
- }
12995
- if ($ypos[$k]['extbottom'] < $bottomy) {
12996
- $bottomy = $ypos[$k]['extbottom'];
12997
- }
12998
- } else {
12999
- if (($ypos[$k]['exttop'] + $ypos[$k]['baseline-shift']) > $topy) {
13000
- $topy = $ypos[$k]['exttop'] + $ypos[$k]['baseline-shift'];
13001
- }
13002
- if (($ypos[$k]['extbottom'] + $ypos[$k]['baseline-shift']) < $bottomy) {
13003
- $bottomy = $ypos[$k]['extbottom'] + $ypos[$k]['baseline-shift'];
13004
- }
13005
  }
 
13006
  }
13007
-
13008
- // If BORDER set on inline element
13009
- if (isset($font[$k]['bord']) && $font[$k]['bord']) {
13010
- $bordfontsize = $font[$k]['textparam']['bord-decoration']['fontsize'] / $shrin_k;
13011
- $bordfontkey = $font[$k]['textparam']['bord-decoration']['fontkey'];
13012
- if ($bordfontkey != $fontkey || $bordfontsize != $fontsize || isset($font[$k]['textparam']['bord-decoration']['baseline'])) {
13013
- $bordfontdesc = $this->fonts[$bordfontkey]['desc'];
13014
- $bordypos[$k] = $this->_setLineYpos($bordfontsize, $bordfontdesc, $CSSlineheight, $ypos[-1]);
13015
- if (isset($font[$k]['textparam']['bord-decoration']['baseline']) && $font[$k]['textparam']['bord-decoration']['baseline'] != 0) {
13016
- $bordypos[$k]['baseline-shift'] = $font[$k]['textparam']['bord-decoration']['baseline'] / $shrin_k;
13017
- }
13018
- }
13019
  }
13020
- // If BACKGROUND set on inline element
13021
- if (isset($font[$k]['spanbgcolor']) && $font[$k]['spanbgcolor']) {
13022
- $bgfontsize = $font[$k]['textparam']['bg-decoration']['fontsize'] / $shrin_k;
13023
- $bgfontkey = $font[$k]['textparam']['bg-decoration']['fontkey'];
13024
- if ($bgfontkey != $fontkey || $bgfontsize != $fontsize || isset($font[$k]['textparam']['bg-decoration']['baseline'])) {
13025
- $bgfontdesc = $this->fonts[$bgfontkey]['desc'];
13026
- $bgypos[$k] = $this->_setLineYpos($bgfontsize, $bgfontdesc, $CSSlineheight, $ypos[-1]);
13027
- if (isset($font[$k]['textparam']['bg-decoration']['baseline']) && $font[$k]['textparam']['bg-decoration']['baseline'] != 0) {
13028
- $bgypos[$k]['baseline-shift'] = $font[$k]['textparam']['bg-decoration']['baseline'] / $shrin_k;
13029
- }
13030
- }
13031
  }
13032
  }
13033
- }
13034
-
13035
-
13036
- // TOP or BOTTOM aligned images
13037
- if ($mta > ($topy - $bottomy)) {
13038
- if (($topy - $mta) < $bottomy) {
13039
- $bottomy = $topy - $mta;
13040
- }
13041
- }
13042
- if ($mba > ($topy - $bottomy)) {
13043
- if (($bottomy + $mba) > $topy) {
13044
- $topy = $bottomy + $mba;
13045
  }
13046
  }
13047
 
13048
- if ($line_stacking_strategy == 'block-line-height') { // fixed height set by block element (whether present or not)
13049
- $topy = $ypos[-1]['exttop'];
13050
- $bottomy = $ypos[-1]['extbottom'];
 
13051
  }
13052
 
13053
- $inclusiveHeight = $topy - $bottomy;
13054
-
13055
- // SET $stackHeight taking note of line_stacking_strategy
13056
- // NB inclusive height already takes account of need to consider block progression height (excludes leading set by lineheight)
13057
- // or extended block progression height (includes leading set by lineheight)
13058
- if ($line_stacking_strategy == 'block-line-height') { // fixed = extended block progression height of block element
13059
- $stackHeight = $boxLineHeight;
13060
- } elseif ($line_stacking_strategy == 'max-height') { // smallest height which includes extended block progression height of block element
13061
- // and block progression heights of inline elements (NOT extended)
13062
- $stackHeight = $inclusiveHeight;
13063
- } elseif ($line_stacking_strategy == 'grid-height') { // smallest multiple of block element lineheight to include
13064
- // block progression heights of inline elements (NOT extended)
13065
- $stackHeight = $boxLineHeight;
13066
- while ($stackHeight < $inclusiveHeight) {
13067
- $stackHeight += $boxLineHeight;
13068
- }
13069
- } else { // 'inline-line-height' = default // smallest height which includes extended block progression height of block element
13070
- // AND extended block progression heights of inline elements
13071
- $stackHeight = $inclusiveHeight;
13072
- }
13073
 
13074
- $diff = $stackHeight - $inclusiveHeight;
13075
- $topy += $diff / 2;
13076
- $bottomy -= $diff / 2;
 
13077
 
13078
- // ADJUST $ypos => lineBox using $stackHeight; lineBox are all offsets from the top of stackHeight in mm
13079
- // and SET IMAGE OFFSETS
13080
- $lineBox[-1]['boxtop'] = $topy - $ypos[-1]['boxtop'];
13081
- $lineBox[-1]['boxbottom'] = $topy - $ypos[-1]['boxbottom'];
13082
- // $lineBox[-1]['exttop'] = $topy - $ypos[-1]['exttop'];
13083
- // $lineBox[-1]['extbottom'] = $topy - $ypos[-1]['extbottom'];
13084
- $lineBox[-1]['glyphYorigin'] = $topy - $ypos[-1]['glyphYorigin'];
13085
- $lineBox[-1]['baseline-shift'] = $ypos[-1]['baseline-shift'];
13086
 
13087
- $midpoint = $lineBox[-1]['boxbottom'] - (($lineBox[-1]['boxbottom'] - $lineBox[-1]['boxtop']) / 2);
 
13088
 
13089
- foreach ($content as $k => $chunk) {
13090
- if (isset($this->objectbuffer[$k])) {
13091
- $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
13092
- // LIST MARKERS
13093
- if ($this->objectbuffer[$k]['type'] == 'listmarker') {
13094
- $oh = $fontsize;
13095
- } elseif ($this->objectbuffer[$k]['type'] == 'dottab') { // mPDF 6 DOTTAB
13096
- $oh = $font[$k]['size']; // == $this->objectbuffer[$k]['fontsize']/Mpdf::SCALE;
13097
- $lineBox[$k]['boxtop'] = $topy - $ypos[$k]['boxtop'];
13098
- $lineBox[$k]['boxbottom'] = $topy - $ypos[$k]['boxbottom'];
13099
- $lineBox[$k]['glyphYorigin'] = $topy - $ypos[$k]['glyphYorigin'];
13100
- $lineBox[$k]['baseline-shift'] = 0;
13101
- // continue;
13102
- }
13103
- $va = $this->objectbuffer[$k]['vertical-align']; // = $objattr['vertical-align'] = set as M,T,B,S
13104
 
13105
- if ($va == 'BS') { // (BASELINE default)
13106
- $lineBox[$k]['top'] = $lineBox[-1]['glyphYorigin'] - $oh;
13107
- } elseif ($va == 'M') {
13108
- $lineBox[$k]['top'] = $midpoint - $oh / 2;
13109
- } elseif ($va == 'TT') {
13110
- $lineBox[$k]['top'] = $lineBox[-1]['boxtop'];
13111
- } elseif ($va == 'TB') {
13112
- $lineBox[$k]['top'] = $lineBox[-1]['boxbottom'] - $oh;
13113
- } elseif ($va == 'T') {
13114
- $lineBox[$k]['top'] = 0;
13115
- } elseif ($va == 'B') {
13116
- $lineBox[$k]['top'] = $stackHeight - $oh;
13117
- }
13118
- } elseif ($content[$k] || $content[$k] === '0') {
13119
- $lineBox[$k]['boxtop'] = $topy - $ypos[$k]['boxtop'];
13120
- $lineBox[$k]['boxbottom'] = $topy - $ypos[$k]['boxbottom'];
13121
- // $lineBox[$k]['exttop'] = $topy - $ypos[$k]['exttop'];
13122
- // $lineBox[$k]['extbottom'] = $topy - $ypos[$k]['extbottom'];
13123
- $lineBox[$k]['glyphYorigin'] = $topy - $ypos[$k]['glyphYorigin'];
13124
- $lineBox[$k]['baseline-shift'] = $ypos[$k]['baseline-shift'];
13125
- if (isset($bordypos[$k]['boxtop'])) {
13126
- $lineBox[$k]['border-boxtop'] = $topy - $bordypos[$k]['boxtop'];
13127
- $lineBox[$k]['border-boxbottom'] = $topy - $bordypos[$k]['boxbottom'];
13128
- $lineBox[$k]['border-baseline-shift'] = $bordypos[$k]['baseline-shift'];
13129
- }
13130
- if (isset($bgypos[$k]['boxtop'])) {
13131
- $lineBox[$k]['background-boxtop'] = $topy - $bgypos[$k]['boxtop'];
13132
- $lineBox[$k]['background-boxbottom'] = $topy - $bgypos[$k]['boxbottom'];
13133
- $lineBox[$k]['background-baseline-shift'] = $bgypos[$k]['baseline-shift'];
13134
- }
13135
- }
13136
  }
13137
  }
13138
 
13139
- function SetBasePath($str = '')
 
13140
  {
13141
- if (isset($_SERVER['HTTP_HOST'])) {
13142
- $host = $_SERVER['HTTP_HOST'];
13143
- } elseif (isset($_SERVER['SERVER_NAME'])) {
13144
- $host = $_SERVER['SERVER_NAME'];
13145
- } else {
13146
- $host = '';
13147
- }
13148
- if (!$str) {
13149
- if ($_SERVER['SCRIPT_NAME']) {
13150
- $currentPath = dirname($_SERVER['SCRIPT_NAME']);
13151
- } else {
13152
- $currentPath = dirname($_SERVER['PHP_SELF']);
13153
- }
13154
- $currentPath = str_replace("\\", "/", $currentPath);
13155
- if ($currentPath == '/') {
13156
- $currentPath = '';
13157
- }
13158
- if ($host) { // mPDF 6
13159
- if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && $_SERVER['HTTPS'] !== 'off') {
13160
- $currpath = 'https://' . $host . $currentPath . '/';
13161
  } else {
13162
- $currpath = 'http://' . $host . $currentPath . '/';
13163
  }
13164
- } else {
13165
- $currpath = '';
13166
  }
13167
- $this->basepath = $currpath;
13168
- $this->basepathIsLocal = true;
13169
- return;
13170
- }
13171
- $str = preg_replace('/\?.*/', '', $str);
13172
- if (!preg_match('/(http|https|ftp):\/\/.*\//i', $str)) {
13173
- $str .= '/';
13174
- }
13175
- $str .= 'xxx'; // in case $str ends in / e.g. http://www.bbc.co.uk/
13176
- $this->basepath = dirname($str) . "/"; // returns e.g. e.g. http://www.google.com/dir1/dir2/dir3/
13177
- $this->basepath = str_replace("\\", "/", $this->basepath); // If on Windows
13178
- $tr = parse_url($this->basepath);
13179
- if (isset($tr['host']) && ($tr['host'] == $host)) {
13180
- $this->basepathIsLocal = true;
13181
- } else {
13182
- $this->basepathIsLocal = false;
13183
- }
13184
- }
13185
-
13186
- public function GetFullPath(&$path, $basepath = '')
13187
- {
13188
- // When parsing CSS need to pass temporary basepath - so links are relative to current stylesheet
13189
- if (!$basepath) {
13190
- $basepath = $this->basepath;
13191
- }
13192
-
13193
- // Fix path value
13194
- $path = str_replace("\\", '/', $path); // If on Windows
13195
-
13196
- // mPDF 5.7.2
13197
- if (substr($path, 0, 2) === '//') {
13198
- $scheme = parse_url($basepath, PHP_URL_SCHEME);
13199
- $scheme = $scheme ?: 'http';
13200
- $path = $scheme . ':' . $path;
13201
- }
13202
-
13203
- $path = preg_replace('|^./|', '', $path); // Inadvertently corrects "./path/etc" and "//www.domain.com/etc"
13204
-
13205
- if (substr($path, 0, 1) == '#') {
13206
- return;
13207
- }
13208
-
13209
- if (preg_match('@^(mailto|tel|fax):.*@i', $path)) {
13210
- return;
13211
- }
13212
-
13213
- if (substr($path, 0, 3) == "../") { // It is a relative link
13214
 
13215
- $backtrackamount = substr_count($path, "../");
13216
- $maxbacktrack = substr_count($basepath, "/") - 3;
13217
- $filepath = str_replace("../", '', $path);
13218
- $path = $basepath;
13219
 
13220
- // If it is an invalid relative link, then make it go to directory root
13221
- if ($backtrackamount > $maxbacktrack) {
13222
- $backtrackamount = $maxbacktrack;
 
 
 
 
 
 
 
 
 
 
 
13223
  }
13224
 
13225
- // Backtrack some directories
13226
- for ($i = 0; $i < $backtrackamount + 1; $i++) {
13227
- $path = substr($path, 0, strrpos($path, "/"));
13228
- }
13229
 
13230
- $path = $path . "/" . $filepath; // Make it an absolute path
 
13231
 
13232
- } elseif ((strpos($path, ":/") === false || strpos($path, ":/") > 10) && !is_file($path)) { // It is a local link
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13233
 
13234
- if (substr($path, 0, 1) == "/") {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13235
 
13236
- $tr = parse_url($basepath);
 
 
13237
 
13238
- // mPDF 5.7.2
13239
- $root = '';
13240
- if (!empty($tr['scheme'])) {
13241
- $root .= $tr['scheme'] . '://';
13242
- }
 
 
 
 
 
 
 
 
 
13243
 
13244
- $root .= isset($tr['host']) ? $tr['host'] : '';
13245
- $root .= ((isset($tr['port']) && $tr['port']) ? (':' . $tr['port']) : ''); // mPDF 5.7.3
 
 
 
 
 
 
 
 
13246
 
13247
- $path = $root . $path;
13248
 
13249
- } else {
13250
- $path = $basepath . $path;
13251
- }
13252
- }
13253
- // Do nothing if it is an Absolute Link
13254
- }
13255
 
13256
- function docPageNum($num = 0, $extras = false)
13257
- {
13258
- if ($num < 1) {
13259
- $num = $this->page;
13260
- }
13261
 
13262
- $type = $this->defaultPageNumStyle; // set default Page Number Style
13263
- $ppgno = $num;
13264
- $suppress = 0;
13265
- $offset = 0;
13266
- $lastreset = 0;
13267
 
13268
- foreach ($this->PageNumSubstitutions as $psarr) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13269
 
13270
- if ($num >= $psarr['from']) {
 
 
 
 
13271
 
13272
- if ($psarr['reset']) {
13273
- if ($psarr['reset'] > 1) {
13274
- $offset = $psarr['reset'] - 1;
13275
  }
13276
- $ppgno = $num - $psarr['from'] + 1 + $offset;
13277
- $lastreset = $psarr['from'];
13278
- }
13279
 
13280
- if ($psarr['type']) {
13281
- $type = $psarr['type'];
13282
- }
 
 
13283
 
13284
- if (strtoupper($psarr['suppress']) == 'ON' || $psarr['suppress'] == 1) {
13285
- $suppress = 1;
13286
- } elseif (strtoupper($psarr['suppress']) == 'OFF') {
13287
- $suppress = 0;
13288
- }
13289
- }
13290
- }
13291
-
13292
- if ($suppress) {
13293
- return '';
13294
- }
13295
-
13296
- $ppgno = $this->_getStyledNumber($ppgno, $type);
13297
-
13298
- if ($extras) {
13299
- $ppgno = $this->pagenumPrefix . $ppgno . $this->pagenumSuffix;
13300
- }
13301
-
13302
- return $ppgno;
13303
- }
13304
-
13305
- function docPageNumTotal($num = 0, $extras = false)
13306
- {
13307
- if ($num < 1) {
13308
- $num = $this->page;
13309
- }
13310
-
13311
- $type = $this->defaultPageNumStyle; // set default Page Number Style
13312
- $ppgstart = 1;
13313
- $ppgend = count($this->pages) + 1;
13314
- $suppress = 0;
13315
- $offset = 0;
13316
 
13317
- foreach ($this->PageNumSubstitutions as $psarr) {
13318
- if ($num >= $psarr['from']) {
13319
- if ($psarr['reset']) {
13320
- if ($psarr['reset'] > 1) {
13321
- $offset = $psarr['reset'] - 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13322
  }
13323
- $ppgstart = $psarr['from'] + $offset;
13324
- $ppgend = count($this->pages) + 1 + $offset;
13325
- }
13326
- if ($psarr['type']) {
13327
- $type = $psarr['type'];
13328
- }
13329
- if (strtoupper($psarr['suppress']) == 'ON' || $psarr['suppress'] == 1) {
13330
- $suppress = 1;
13331
- } elseif (strtoupper($psarr['suppress']) == 'OFF') {
13332
- $suppress = 0;
13333
- }
13334
- }
13335
- if ($num < $psarr['from']) {
13336
- if ($psarr['reset']) {
13337
- $ppgend = $psarr['from'] + $offset;
13338
- break;
13339
- }
13340
- }
13341
- }
13342
-
13343
- if ($suppress) {
13344
- return '';
13345
- }
13346
 
13347
- $ppgno = $ppgend - $ppgstart + $offset;
13348
- $ppgno = $this->_getStyledNumber($ppgno, $type);
13349
 
13350
- if ($extras) {
13351
- $ppgno = $this->pagenumPrefix . $ppgno . $this->pagenumSuffix;
13352
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13353
 
13354
- return $ppgno;
13355
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13356
 
13357
- // mPDF 6
13358
- function _getStyledNumber($ppgno, $type, $listmarker = false)
13359
- {
13360
- if ($listmarker) {
13361
- $reverse = true; // Reverse RTL numerals (Hebrew) when using for list
13362
- $checkfont = true; // Using list - font is set, so check if character is available
13363
- } else {
13364
- $reverse = false; // For pagenumbers, RTL numerals (Hebrew) will get reversed later by bidi
13365
- $checkfont = false; // For pagenumbers - font is not set, so no check
13366
- }
13367
 
13368
- $decToAlpha = new Conversion\DecToAlpha();
13369
- $decToCjk = new Conversion\DecToCjk();
13370
- $decToHebrew = new Conversion\DecToHebrew();
13371
- $decToRoman = new Conversion\DecToRoman();
13372
- $decToOther = new Conversion\DecToOther($this);
 
13373
 
13374
- $lowertype = strtolower($type);
 
 
 
 
 
 
 
 
13375
 
13376
- if ($lowertype == 'upper-latin' || $lowertype == 'upper-alpha' || $type == 'A') {
 
 
 
 
 
 
 
 
 
13377
 
13378
- $ppgno = $decToAlpha->convert($ppgno, true);
 
 
 
 
 
 
 
 
 
 
 
 
13379
 
13380
- } elseif ($lowertype == 'lower-latin' || $lowertype == 'lower-alpha' || $type == 'a') {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13381
 
13382
- $ppgno = $decToAlpha->convert($ppgno, false);
 
 
 
 
 
 
 
 
13383
 
13384
- } elseif ($lowertype == 'upper-roman' || $type == 'I') {
13385
-
13386
- $ppgno = $decToRoman->convert($ppgno, true);
13387
-
13388
- } elseif ($lowertype == 'lower-roman' || $type == 'i') {
13389
-
13390
- $ppgno = $decToRoman->convert($ppgno, false);
13391
-
13392
- } elseif ($lowertype == 'hebrew') {
13393
-
13394
- $ppgno = $decToHebrew->convert($ppgno, $reverse);
 
 
 
 
 
 
13395
 
13396
- } elseif (preg_match('/(arabic-indic|bengali|devanagari|gujarati|gurmukhi|kannada|malayalam|oriya|persian|tamil|telugu|thai|urdu|cambodian|khmer|lao)/i', $lowertype, $m)) {
 
 
 
 
 
 
13397
 
13398
- $cp = $decToOther->getCodePage($m[1]);
13399
- $ppgno = $decToOther->convert($ppgno, $cp, $checkfont);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13400
 
13401
- } elseif ($lowertype == 'cjk-decimal') {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13402
 
13403
- $ppgno = $decToCjk->convert($ppgno);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13405
  }
13406
-
13407
- return $ppgno;
13408
  }
13409
 
13410
- function docPageSettings($num = 0)
13411
- {
13412
- // Returns current type (numberstyle), suppression state for this page number;
13413
- // reset is only returned if set for this page number
13414
- if ($num < 1) {
13415
- $num = $this->page;
13416
- }
13417
 
13418
- $type = $this->defaultPageNumStyle; // set default Page Number Style
13419
- $ppgno = $num;
13420
- $suppress = 0;
13421
- $offset = 0;
13422
- $reset = '';
13423
 
13424
- foreach ($this->PageNumSubstitutions as $psarr) {
13425
- if ($num >= $psarr['from']) {
13426
- if ($psarr['reset']) {
13427
- if ($psarr['reset'] > 1) {
13428
- $offset = $psarr['reset'] - 1;
13429
- }
13430
- $ppgno = $num - $psarr['from'] + 1 + $offset;
13431
- }
13432
- if ($psarr['type']) {
13433
- $type = $psarr['type'];
13434
- }
13435
- if (strtoupper($psarr['suppress']) == 'ON' || $psarr['suppress'] == 1) {
13436
- $suppress = 1;
13437
- } elseif (strtoupper($psarr['suppress']) == 'OFF') {
13438
- $suppress = 0;
13439
  }
13440
  }
13441
- if ($num == $psarr['from']) {
13442
- $reset = $psarr['reset'];
 
 
13443
  }
 
 
13444
  }
13445
 
13446
- if ($suppress) {
13447
- $suppress = 'on';
 
 
 
 
 
 
 
 
 
 
13448
  } else {
13449
- $suppress = 'off';
 
 
 
 
 
 
13450
  }
13451
 
13452
- return [$type, $suppress, $reset];
13453
- }
 
 
 
 
13454
 
13455
- function RestartDocTemplate()
13456
- {
13457
- $this->docTemplateStart = $this->page;
 
 
 
 
 
 
 
 
 
 
 
13458
  }
13459
 
13460
- // Page header
13461
- function Header($content = '')
13462
  {
13463
-
13464
- $this->cMarginL = 0;
13465
- $this->cMarginR = 0;
13466
-
13467
-
13468
- if (($this->mirrorMargins && ($this->page % 2 == 0) && $this->HTMLHeaderE) || ($this->mirrorMargins && ($this->page % 2 == 1) && $this->HTMLHeader) || (!$this->mirrorMargins && $this->HTMLHeader)) {
13469
- $this->writeHTMLHeaders();
13470
- return;
13471
- }
13472
- }
13473
-
13474
- /* -- TABLES -- */
13475
- function TableHeaderFooter($content = '', $tablestartpage = '', $tablestartcolumn = '', $horf = 'H', $level = 0, $firstSpread = true, $finalSpread = true)
13476
- {
13477
- if (($horf == 'H' || $horf == 'F') && !empty($content)) { // mPDF 5.7.2
13478
- $table = &$this->table[1][1];
13479
-
13480
- // mPDF 5.7.2
13481
- if ($horf == 'F') { // Table Footer
13482
- $firstrow = count($table['cells']) - $table['footernrows'];
13483
- $lastrow = count($table['cells']) - 1;
13484
- } else { // Table Header
13485
- $firstrow = 0;
13486
- $lastrow = $table['headernrows'] - 1;
13487
- }
13488
- if (empty($content[$firstrow])) {
13489
- if ($this->debug) {
13490
- throw new \Mpdf\MpdfException("<tfoot> must precede <tbody> in a table");
13491
  } else {
13492
- return;
13493
  }
13494
  }
 
 
 
 
 
 
 
 
13495
 
 
 
 
13496
 
13497
- // Advance down page by half width of top border
13498
- if ($horf == 'H') { // Only if header
13499
- if ($table['borders_separate']) {
13500
- $adv = $table['border_spacing_V'] / 2 + $table['border_details']['T']['w'] + $table['padding']['T'];
13501
- } else {
13502
- $adv = $table['max_cell_border_width']['T'] / 2;
13503
- }
13504
- if ($adv) {
13505
- if ($this->table_rotate) {
13506
- $this->y += ($adv);
13507
- } else {
13508
- $this->DivLn($adv, $this->blklvl, true);
13509
- }
13510
- }
 
13511
  }
 
13512
 
13513
- $topy = $content[$firstrow][0]['y'] - $this->y;
 
 
13514
 
13515
- for ($i = $firstrow; $i <= $lastrow; $i++) {
13516
- $y = $this->y;
 
13517
 
13518
- /* -- COLUMNS -- */
13519
- // If outside columns, this is done in PaintDivBB
13520
- if ($this->ColActive) {
13521
- // OUTER FILL BGCOLOR of DIVS
13522
- if ($this->blklvl > 0) {
13523
- $firstblockfill = $this->GetFirstBlockFill();
13524
- if ($firstblockfill && $this->blklvl >= $firstblockfill) {
13525
- $divh = $content[$i][0]['h'];
13526
- $bak_x = $this->x;
13527
- $this->DivLn($divh, -3, false);
13528
- // Reset current block fill
13529
- $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
13530
- $this->SetFColor($bcor);
13531
- $this->x = $bak_x;
13532
- }
13533
- }
13534
- }
13535
- /* -- END COLUMNS -- */
13536
 
13537
- $colctr = 0;
13538
- foreach ($content[$i] as $tablehf) {
13539
- $colctr++;
13540
- $y = Arrays::get($tablehf, 'y', null) - $topy;
13541
- $this->y = $y;
13542
- // Set some cell values
13543
- $x = Arrays::get($tablehf, 'x', null);
13544
- if (($this->mirrorMargins) && ($tablestartpage == 'ODD') && (($this->page) % 2 == 0)) { // EVEN
13545
- $x = $x + $this->MarginCorrection;
13546
- } elseif (($this->mirrorMargins) && ($tablestartpage == 'EVEN') && (($this->page) % 2 == 1)) { // ODD
13547
- $x = $x + $this->MarginCorrection;
13548
- }
13549
- /* -- COLUMNS -- */
13550
- // Added to correct for Columns
13551
- if ($this->ColActive) {
13552
- if ($this->directionality == 'rtl') { // *OTL*
13553
- $x -= ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth + $this->ColGap); // *OTL*
13554
- } // *OTL*
13555
- else { // *OTL*
13556
- $x += ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth + $this->ColGap);
13557
- } // *OTL*
13558
- }
13559
- /* -- END COLUMNS -- */
 
 
 
 
 
 
13560
 
13561
- if ($colctr == 1) {
13562
- $x0 = $x;
13563
- }
 
 
 
 
 
 
 
 
 
13564
 
13565
- // mPDF ITERATION
13566
- if ($this->iterationCounter) {
13567
- foreach ($tablehf['textbuffer'] as $k => $t) {
13568
- if (!is_array($t[0]) && preg_match('/{iteration ([a-zA-Z0-9_]+)}/', $t[0], $m)) {
13569
- $vname = '__' . $m[1] . '_';
13570
- if (!isset($this->$vname)) {
13571
- $this->$vname = 1;
13572
- } else {
13573
- $this->$vname++;
13574
- }
13575
- $tablehf['textbuffer'][$k][0] = preg_replace('/{iteration ' . $m[1] . '}/', $this->$vname, $tablehf['textbuffer'][$k][0]);
13576
- }
13577
- }
13578
- }
13579
 
13580
- $w = Arrays::get($tablehf, 'w', null);
13581
- $h = Arrays::get($tablehf, 'h', null);
13582
- $va = Arrays::get($tablehf, 'va', null);
13583
- $R = Arrays::get($tablehf, 'R', null);
13584
- $direction = Arrays::get($tablehf, 'direction', null);
13585
- $mih = Arrays::get($tablehf, 'mih', null);
13586
- $border = Arrays::get($tablehf, 'border', null);
13587
- $border_details = Arrays::get($tablehf, 'border_details', null);
13588
- $padding = Arrays::get($tablehf, 'padding', null);
13589
- $this->tabletheadjustfinished = true;
13590
 
13591
- $textbuffer = Arrays::get($tablehf, 'textbuffer', null);
 
 
 
 
13592
 
13593
- // Align
13594
- $align = Arrays::get($tablehf, 'a', null);
13595
- $this->cellTextAlign = $align;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13596
 
13597
- $this->cellLineHeight = Arrays::get($tablehf, 'cellLineHeight', null);
13598
- $this->cellLineStackingStrategy = Arrays::get($tablehf, 'cellLineStackingStrategy', null);
13599
- $this->cellLineStackingShift = Arrays::get($tablehf, 'cellLineStackingShift', null);
13600
 
13601
- $this->x = $x;
13602
-
13603
- if ($this->ColActive) {
13604
- if ($table['borders_separate']) {
13605
- $tablefill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
13606
- if ($tablefill) {
13607
- $color = $this->colorConverter->convert($tablefill, $this->PDFAXwarnings);
13608
- if ($color) {
13609
- $xadj = ($table['border_spacing_H'] / 2);
13610
- $yadj = ($table['border_spacing_V'] / 2);
13611
- $wadj = $table['border_spacing_H'];
13612
- $hadj = $table['border_spacing_V'];
13613
- if ($i == $firstrow && $horf == 'H') { // Top
13614
- $yadj += $table['padding']['T'] + $table['border_details']['T']['w'];
13615
- $hadj += $table['padding']['T'] + $table['border_details']['T']['w'];
13616
- }
13617
- if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i + $tablehf['rowspan']) == ($lastrow + 1)) || (!isset($tablehf['rowspan']) && ($i + 1) == ($lastrow + 1))) && $horf == 'F') { // Bottom
13618
- $hadj += $table['padding']['B'] + $table['border_details']['B']['w'];
13619
- }
13620
- if ($colctr == 1) { // Left
13621
- $xadj += $table['padding']['L'] + $table['border_details']['L']['w'];
13622
- $wadj += $table['padding']['L'] + $table['border_details']['L']['w'];
13623
- }
13624
- if ($colctr == count($content[$i])) { // Right
13625
- $wadj += $table['padding']['R'] + $table['border_details']['R']['w'];
13626
- }
13627
- $this->SetFColor($color);
13628
- $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
13629
- }
13630
- }
13631
- }
13632
- }
13633
-
13634
- if ($table['empty_cells'] != 'hide' || !empty($textbuffer) || !$table['borders_separate']) {
13635
- $paintcell = true;
13636
- } else {
13637
- $paintcell = false;
13638
- }
13639
-
13640
- // Vertical align
13641
- if ($R && intval($R) > 0 && isset($va) && $va != 'B') {
13642
- $va = 'B';
13643
- }
13644
-
13645
- if (!isset($va) || empty($va) || $va == 'M') {
13646
- $this->y += ($h - $mih) / 2;
13647
- } elseif (isset($va) && $va == 'B') {
13648
- $this->y += $h - $mih;
13649
- }
13650
-
13651
-
13652
- // TABLE ROW OR CELL FILL BGCOLOR
13653
- $fill = 0;
13654
- if (isset($tablehf['bgcolor']) && $tablehf['bgcolor'] && $tablehf['bgcolor'] != 'transparent') {
13655
- $fill = $tablehf['bgcolor'];
13656
- $leveladj = 6;
13657
- } elseif (isset($content[$i][0]['trbgcolor']) && $content[$i][0]['trbgcolor'] && $content[$i][0]['trbgcolor'] != 'transparent') { // Row color
13658
- $fill = $content[$i][0]['trbgcolor'];
13659
- $leveladj = 3;
13660
- }
13661
- if ($fill && $paintcell) {
13662
- $color = $this->colorConverter->convert($fill, $this->PDFAXwarnings);
13663
- if ($color) {
13664
- if ($table['borders_separate']) {
13665
- if ($this->ColActive) {
13666
- $this->SetFColor($color);
13667
- $this->Rect($x + ($table['border_spacing_H'] / 2), $y + ($table['border_spacing_V'] / 2), $w - $table['border_spacing_H'], $h - $table['border_spacing_V'], 'F');
13668
- } else {
13669
- $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => ($x + ($table['border_spacing_H'] / 2)), 'y' => ($y + ($table['border_spacing_V'] / 2)), 'w' => ($w - $table['border_spacing_H']), 'h' => ($h - $table['border_spacing_V']), 'col' => $color];
13670
- }
13671
- } else {
13672
- if ($this->ColActive) {
13673
- $this->SetFColor($color);
13674
- $this->Rect($x, $y, $w, $h, 'F');
13675
- } else {
13676
- $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'col' => $color];
13677
- }
13678
- }
13679
- }
13680
- }
13681
-
13682
-
13683
- /* -- BACKGROUNDS -- */
13684
- if (isset($tablehf['gradient']) && $tablehf['gradient'] && $paintcell) {
13685
- $g = $this->gradient->parseBackgroundGradient($tablehf['gradient']);
13686
- if ($g) {
13687
- if ($table['borders_separate']) {
13688
- $px = $x + ($table['border_spacing_H'] / 2);
13689
- $py = $y + ($table['border_spacing_V'] / 2);
13690
- $pw = $w - $table['border_spacing_H'];
13691
- $ph = $h - $table['border_spacing_V'];
13692
- } else {
13693
- $px = $x;
13694
- $py = $y;
13695
- $pw = $w;
13696
- $ph = $h;
13697
- }
13698
- if ($this->ColActive) {
13699
- $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
13700
- } else {
13701
- $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
13702
- }
13703
- }
13704
- }
13705
-
13706
- if (isset($tablehf['background-image']) && $paintcell) {
13707
- if ($tablehf['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $tablehf['background-image']['gradient'])) {
13708
- $g = $this->gradient->parseMozGradient($tablehf['background-image']['gradient']);
13709
- if ($g) {
13710
- if ($table['borders_separate']) {
13711
- $px = $x + ($table['border_spacing_H'] / 2);
13712
- $py = $y + ($table['border_spacing_V'] / 2);
13713
- $pw = $w - $table['border_spacing_H'];
13714
- $ph = $h - $table['border_spacing_V'];
13715
- } else {
13716
- $px = $x;
13717
- $py = $y;
13718
- $pw = $w;
13719
- $ph = $h;
13720
- }
13721
- if ($this->ColActive) {
13722
- $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
13723
- } else {
13724
- $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
13725
- }
13726
- }
13727
- } elseif ($tablehf['background-image']['image_id']) { // Background pattern
13728
- $n = count($this->patterns) + 1;
13729
- if ($table['borders_separate']) {
13730
- $px = $x + ($table['border_spacing_H'] / 2);
13731
- $py = $y + ($table['border_spacing_V'] / 2);
13732
- $pw = $w - $table['border_spacing_H'];
13733
- $ph = $h - $table['border_spacing_V'];
13734
- } else {
13735
- $px = $x;
13736
- $py = $y;
13737
- $pw = $w;
13738
- $ph = $h;
13739
- }
13740
- if ($this->ColActive) {
13741
- list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($tablehf['background-image']['orig_w'], $tablehf['background-image']['orig_h'], $pw, $ph, $tablehf['background-image']['resize'], $tablehf['background-image']['x_repeat'], $tablehf['background-image']['y_repeat']);
13742
- $this->patterns[$n] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'pgh' => $this->h, 'image_id' => $tablehf['background-image']['image_id'], 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $tablehf['background-image']['x_pos'], 'y_pos' => $tablehf['background-image']['y_pos'], 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'itype' => $tablehf['background-image']['itype']];
13743
- if ($tablehf['background-image']['opacity'] > 0 && $tablehf['background-image']['opacity'] < 1) {
13744
- $opac = $this->SetAlpha($tablehf['background-image']['opacity'], 'Normal', true);
13745
- } else {
13746
- $opac = '';
13747
- }
13748
- $this->_out(sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $px * Mpdf::SCALE, ($this->h - $py) * Mpdf::SCALE, $pw * Mpdf::SCALE, -$ph * Mpdf::SCALE));
13749
- } else {
13750
- $this->tableBackgrounds[$level * 9 + 8][] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'image_id' => $tablehf['background-image']['image_id'], 'orig_w' => $tablehf['background-image']['orig_w'], 'orig_h' => $tablehf['background-image']['orig_h'], 'x_pos' => $tablehf['background-image']['x_pos'], 'y_pos' => $tablehf['background-image']['y_pos'], 'x_repeat' => $tablehf['background-image']['x_repeat'], 'y_repeat' => $tablehf['background-image']['y_repeat'], 'clippath' => '', 'resize' => $tablehf['background-image']['resize'], 'opacity' => $tablehf['background-image']['opacity'], 'itype' => $tablehf['background-image']['itype']];
13751
- }
13752
- }
13753
- }
13754
- /* -- END BACKGROUNDS -- */
13755
-
13756
- // Cell Border
13757
- if ($table['borders_separate'] && $paintcell && $border) {
13758
- $this->_tableRect($x + ($table['border_spacing_H'] / 2) + ($border_details['L']['w'] / 2), $y + ($table['border_spacing_V'] / 2) + ($border_details['T']['w'] / 2), $w - $table['border_spacing_H'] - ($border_details['L']['w'] / 2) - ($border_details['R']['w'] / 2), $h - $table['border_spacing_V'] - ($border_details['T']['w'] / 2) - ($border_details['B']['w'] / 2), $border, $border_details, false, $table['borders_separate']);
13759
- } elseif ($paintcell && $border) {
13760
- $this->_tableRect($x, $y, $w, $h, $border, $border_details, true, $table['borders_separate']); // true causes buffer
13761
- }
13762
-
13763
- // Print cell content
13764
- if (!empty($textbuffer)) {
13765
- if ($horf == 'F' && preg_match('/{colsum([0-9]*)[_]*}/', $textbuffer[0][0], $m)) {
13766
- $rep = sprintf("%01." . intval($m[1]) . "f", $this->colsums[$colctr - 1]);
13767
- $textbuffer[0][0] = preg_replace('/{colsum[0-9_]*}/', $rep, $textbuffer[0][0]);
13768
- }
13769
-
13770
- if ($R) {
13771
- $cellPtSize = $textbuffer[0][11] / $this->shrin_k;
13772
- if (!$cellPtSize) {
13773
- $cellPtSize = $this->default_font_size;
13774
- }
13775
- $cellFontHeight = ($cellPtSize / Mpdf::SCALE);
13776
- $opx = $this->x;
13777
- $opy = $this->y;
13778
- $angle = intval($R);
13779
-
13780
- // Only allow 45 - 90 degrees (when bottom-aligned) or -90
13781
- if ($angle > 90) {
13782
- $angle = 90;
13783
- } elseif ($angle > 0 && (isset($va) && $va != 'B')) {
13784
- $angle = 90;
13785
- } elseif ($angle > 0 && $angle < 45) {
13786
- $angle = 45;
13787
- } elseif ($angle < 0) {
13788
- $angle = -90;
13789
- }
13790
-
13791
- $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
13792
- if (isset($align) && $align == 'R') {
13793
- $this->x += ($w) + ($offset) - ($cellFontHeight / 3) - ($padding['R'] + $border_details['R']['w']);
13794
- } elseif (!isset($align) || $align == 'C') {
13795
- $this->x += ($w / 2) + ($offset);
13796
- } else {
13797
- $this->x += ($offset) + ($cellFontHeight / 3) + ($padding['L'] + $border_details['L']['w']);
13798
- }
13799
- $str = '';
13800
- foreach ($tablehf['textbuffer'] as $t) {
13801
- $str .= $t[0] . ' ';
13802
- }
13803
- $str = rtrim($str);
13804
-
13805
- if (!isset($va) || $va == 'M') {
13806
- $this->y -= ($h - $mih) / 2; // Undo what was added earlier VERTICAL ALIGN
13807
- if ($angle > 0) {
13808
- $this->y += (($h - $mih) / 2) + ($padding['T'] + $border_details['T']['w']) + ($mih - ($padding['T'] + $border_details['T']['w'] + $border_details['B']['w'] + $padding['B']));
13809
- } elseif ($angle < 0) {
13810
- $this->y += (($h - $mih) / 2) + ($padding['T'] + $border_details['T']['w']);
13811
- }
13812
- } elseif (isset($va) && $va == 'B') {
13813
- $this->y -= $h - $mih; // Undo what was added earlier VERTICAL ALIGN
13814
- if ($angle > 0) {
13815
- $this->y += $h - ($border_details['B']['w'] + $padding['B']);
13816
- } elseif ($angle < 0) {
13817
- $this->y += $h - $mih + ($padding['T'] + $border_details['T']['w']);
13818
- }
13819
- } elseif (isset($va) && $va == 'T') {
13820
- if ($angle > 0) {
13821
- $this->y += $mih - ($border_details['B']['w'] + $padding['B']);
13822
- } elseif ($angle < 0) {
13823
- $this->y += ($padding['T'] + $border_details['T']['w']);
13824
- }
13825
- }
13826
-
13827
- $this->Rotate($angle, $this->x, $this->y);
13828
- $s_fs = $this->FontSizePt;
13829
- $s_f = $this->FontFamily;
13830
- $s_st = $this->FontStyle;
13831
- if (!empty($textbuffer[0][3])) { // Font Color
13832
- $cor = $textbuffer[0][3];
13833
- $this->SetTColor($cor);
13834
- }
13835
- $this->SetFont($textbuffer[0][4], $textbuffer[0][2], $cellPtSize, true, true);
13836
-
13837
- $this->magic_reverse_dir($str, $this->directionality, $textbuffer[0][18]);
13838
- $this->Text($this->x, $this->y, $str, $textbuffer[0][18], $textbuffer[0][8]); // textvar
13839
- $this->Rotate(0);
13840
- $this->SetFont($s_f, $s_st, $s_fs, true, true);
13841
- $this->SetTColor(0);
13842
- $this->x = $opx;
13843
- $this->y = $opy;
13844
- } else {
13845
- if ($table['borders_separate']) { // NB twice border width
13846
- $xadj = $border_details['L']['w'] + $padding['L'] + ($table['border_spacing_H'] / 2);
13847
- $wadj = $border_details['L']['w'] + $border_details['R']['w'] + $padding['L'] + $padding['R'] + $table['border_spacing_H'];
13848
- $yadj = $border_details['T']['w'] + $padding['T'] + ($table['border_spacing_H'] / 2);
13849
- } else {
13850
- $xadj = $border_details['L']['w'] / 2 + $padding['L'];
13851
- $wadj = ($border_details['L']['w'] + $border_details['R']['w']) / 2 + $padding['L'] + $padding['R'];
13852
- $yadj = $border_details['T']['w'] / 2 + $padding['T'];
13853
- }
13854
-
13855
- $this->divwidth = $w - ($wadj);
13856
- $this->x += $xadj;
13857
- $this->y += $yadj;
13858
- $this->printbuffer($textbuffer, '', true, false, $direction);
13859
- }
13860
- }
13861
- $textbuffer = [];
13862
-
13863
- /* -- BACKGROUNDS -- */
13864
- if (!$this->ColActive) {
13865
- if (isset($content[$i][0]['trgradients']) && ($colctr == 1 || $table['borders_separate'])) {
13866
- $g = $this->gradient->parseBackgroundGradient($content[$i][0]['trgradients']);
13867
- if ($g) {
13868
- $gx = $x0;
13869
- $gy = $y;
13870
- $gh = $h;
13871
- $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
13872
- if ($table['borders_separate']) {
13873
- $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
13874
- $clx = $x + ($table['border_spacing_H'] / 2);
13875
- $cly = $y + ($table['border_spacing_V'] / 2);
13876
- $clw = $w - $table['border_spacing_H'];
13877
- $clh = $h - $table['border_spacing_V'];
13878
- // Set clipping path
13879
- $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
13880
- $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s];
13881
- } else {
13882
- $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
13883
- }
13884
- }
13885
- }
13886
-
13887
- if (isset($content[$i][0]['trbackground-images']) && ($colctr == 1 || $table['borders_separate'])) {
13888
- if ($content[$i][0]['trbackground-images']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $content[$i][0]['trbackground-images']['gradient'])) {
13889
- $g = $this->gradient->parseMozGradient($content[$i][0]['trbackground-images']['gradient']);
13890
- if ($g) {
13891
- $gx = $x0;
13892
- $gy = $y;
13893
- $gh = $h;
13894
- $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
13895
- if ($table['borders_separate']) {
13896
- $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
13897
- $clx = $x + ($table['border_spacing_H'] / 2);
13898
- $cly = $y + ($table['border_spacing_V'] / 2);
13899
- $clw = $w - $table['border_spacing_H'];
13900
- $clh = $h - $table['border_spacing_V'];
13901
- // Set clipping path
13902
- $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
13903
- $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s];
13904
- } else {
13905
- $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
13906
- }
13907
- }
13908
- } else {
13909
- $image_id = $content[$i][0]['trbackground-images']['image_id'];
13910
- $orig_w = $content[$i][0]['trbackground-images']['orig_w'];
13911
- $orig_h = $content[$i][0]['trbackground-images']['orig_h'];
13912
- $x_pos = $content[$i][0]['trbackground-images']['x_pos'];
13913
- $y_pos = $content[$i][0]['trbackground-images']['y_pos'];
13914
- $x_repeat = $content[$i][0]['trbackground-images']['x_repeat'];
13915
- $y_repeat = $content[$i][0]['trbackground-images']['y_repeat'];
13916
- $resize = $content[$i][0]['trbackground-images']['resize'];
13917
- $opacity = $content[$i][0]['trbackground-images']['opacity'];
13918
- $itype = $content[$i][0]['trbackground-images']['itype'];
13919
-
13920
- $clippath = '';
13921
- $gx = $x0;
13922
- $gy = $y;
13923
- $gh = $h;
13924
- $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
13925
- if ($table['borders_separate']) {
13926
- $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
13927
- $clx = $x + ($table['border_spacing_H'] / 2);
13928
- $cly = $y + ($table['border_spacing_V'] / 2);
13929
- $clw = $w - $table['border_spacing_H'];
13930
- $clh = $h - $table['border_spacing_V'];
13931
- // Set clipping path
13932
- $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
13933
- $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => $s, 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
13934
- } else {
13935
- $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
13936
- }
13937
- }
13938
- }
13939
- }
13940
- /* -- END BACKGROUNDS -- */
13941
-
13942
- // TABLE BORDER - if separate OR collapsed and only table border
13943
- if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
13944
- $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H'] / 2);
13945
- $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H'] / 2);
13946
- $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V'] / 2);
13947
- $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V'] / 2);
13948
- $tbx = $x;
13949
- $tby = $y;
13950
- $tbw = $w;
13951
- $tbh = $h;
13952
- $tab_bord = 0;
13953
- $corner = '';
13954
- if ($i == $firstrow && $horf == 'H') { // Top
13955
- $tby -= $halfspaceT + ($table['border_details']['T']['w'] / 2);
13956
- $tbh += $halfspaceT + ($table['border_details']['T']['w'] / 2);
13957
- $this->setBorder($tab_bord, Border::TOP);
13958
- $corner .= 'T';
13959
- }
13960
- if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i + $tablehf['rowspan']) == ($lastrow + 1))) && $horf == 'F') { // Bottom
13961
- $tbh += $halfspaceB + ($table['border_details']['B']['w'] / 2);
13962
- $this->setBorder($tab_bord, Border::BOTTOM);
13963
- $corner .= 'B';
13964
- }
13965
- if ($colctr == 1 && $firstSpread) { // Left
13966
- $tbx -= $halfspaceL + ($table['border_details']['L']['w'] / 2);
13967
- $tbw += $halfspaceL + ($table['border_details']['L']['w'] / 2);
13968
- $this->setBorder($tab_bord, Border::LEFT);
13969
- $corner .= 'L';
13970
- }
13971
- if ($colctr == count($content[$i]) && $finalSpread) { // Right
13972
- $tbw += $halfspaceR + ($table['border_details']['R']['w'] / 2);
13973
- $this->setBorder($tab_bord, Border::RIGHT);
13974
- $corner .= 'R';
13975
- }
13976
- $this->_tableRect($tbx, $tby, $tbw, $tbh, $tab_bord, $table['border_details'], false, $table['borders_separate'], 'table', $corner, $table['border_spacing_V'], $table['border_spacing_H']);
13977
- }
13978
- }// end column $content
13979
- $this->y = $y + $h; // Update y coordinate
13980
- }// end row $i
13981
- unset($table);
13982
- $this->colsums = [];
13983
- }
13984
- }
13985
-
13986
- /* -- END TABLES -- */
13987
-
13988
- function SetHTMLHeader($header = '', $OE = '', $write = false)
13989
- {
13990
-
13991
- $height = 0;
13992
- if (is_array($header) && isset($header['html']) && $header['html']) {
13993
- $Hhtml = $header['html'];
13994
- if ($this->setAutoTopMargin) {
13995
- if (isset($header['h'])) {
13996
- $height = $header['h'];
13997
- } else {
13998
- $height = $this->_getHtmlHeight($Hhtml);
13999
- }
14000
- }
14001
- } elseif (!is_array($header) && $header) {
14002
- $Hhtml = $header;
14003
- if ($this->setAutoTopMargin) {
14004
- $height = $this->_getHtmlHeight($Hhtml);
14005
- }
14006
- } else {
14007
- $Hhtml = '';
14008
- }
14009
-
14010
- if ($OE !== 'E') {
14011
- $OE = 'O';
14012
- }
14013
-
14014
- if ($OE === 'E') {
14015
- if ($Hhtml) {
14016
- $this->HTMLHeaderE = [];
14017
- $this->HTMLHeaderE['html'] = $Hhtml;
14018
- $this->HTMLHeaderE['h'] = $height;
14019
- } else {
14020
- $this->HTMLHeaderE = '';
14021
- }
14022
- } else {
14023
- if ($Hhtml) {
14024
- $this->HTMLHeader = [];
14025
- $this->HTMLHeader['html'] = $Hhtml;
14026
- $this->HTMLHeader['h'] = $height;
14027
- } else {
14028
- $this->HTMLHeader = '';
14029
- }
14030
- }
14031
-
14032
- if (!$this->mirrorMargins && $OE == 'E') {
14033
- return;
14034
- }
14035
- if ($Hhtml == '') {
14036
- return;
14037
- }
14038
-
14039
- if ($this->setAutoTopMargin == 'pad') {
14040
- $this->tMargin = $this->margin_header + $height + $this->orig_tMargin;
14041
- if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) {
14042
- $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin;
14043
- }
14044
- } elseif ($this->setAutoTopMargin == 'stretch') {
14045
- $this->tMargin = max($this->orig_tMargin, $this->margin_header + $height + $this->autoMarginPadding);
14046
- if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) {
14047
- $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin;
14048
- }
14049
- }
14050
- if ($write && $this->state != 0 && (($this->mirrorMargins && $OE == 'E' && ($this->page) % 2 == 0) || ($this->mirrorMargins && $OE != 'E' && ($this->page) % 2 == 1) || !$this->mirrorMargins)) {
14051
- $this->writeHTMLHeaders();
14052
- }
14053
- }
14054
-
14055
- function SetHTMLFooter($footer = '', $OE = '')
14056
- {
14057
- $height = 0;
14058
- if (is_array($footer) && isset($footer['html']) && $footer['html']) {
14059
- $Fhtml = $footer['html'];
14060
- if ($this->setAutoBottomMargin) {
14061
- if (isset($footer['h'])) {
14062
- $height = $footer['h'];
14063
- } else {
14064
- $height = $this->_getHtmlHeight($Fhtml);
14065
- }
14066
- }
14067
- } elseif (!is_array($footer) && $footer) {
14068
- $Fhtml = $footer;
14069
- if ($this->setAutoBottomMargin) {
14070
- $height = $this->_getHtmlHeight($Fhtml);
14071
- }
14072
- } else {
14073
- $Fhtml = '';
14074
- }
14075
-
14076
- if ($OE !== 'E') {
14077
- $OE = 'O';
14078
- }
14079
-
14080
- if ($OE === 'E') {
14081
- if ($Fhtml) {
14082
- $this->HTMLFooterE = [];
14083
- $this->HTMLFooterE['html'] = $Fhtml;
14084
- $this->HTMLFooterE['h'] = $height;
14085
- } else {
14086
- $this->HTMLFooterE = '';
14087
- }
14088
- } else {
14089
- if ($Fhtml) {
14090
- $this->HTMLFooter = [];
14091
- $this->HTMLFooter['html'] = $Fhtml;
14092
- $this->HTMLFooter['h'] = $height;
14093
- } else {
14094
- $this->HTMLFooter = '';
14095
- }
14096
- }
14097
-
14098
- if (!$this->mirrorMargins && $OE == 'E') {
14099
- return;
14100
- }
14101
-
14102
- if ($Fhtml == '') {
14103
- return false;
14104
- }
14105
-
14106
- if ($this->setAutoBottomMargin == 'pad') {
14107
- $this->bMargin = $this->margin_footer + $height + $this->orig_bMargin;
14108
- $this->PageBreakTrigger = $this->h - $this->bMargin;
14109
- if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) {
14110
- $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin;
14111
- }
14112
- } elseif ($this->setAutoBottomMargin == 'stretch') {
14113
- $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $height + $this->autoMarginPadding);
14114
- $this->PageBreakTrigger = $this->h - $this->bMargin;
14115
- if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) {
14116
- $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin;
14117
- }
14118
- }
14119
- }
14120
-
14121
- function _getHtmlHeight($html)
14122
- {
14123
- $save_state = $this->state;
14124
- if ($this->state == 0) {
14125
- $this->AddPage($this->CurOrientation);
14126
- }
14127
- $this->state = 2;
14128
- $this->Reset();
14129
- $this->pageoutput[$this->page] = [];
14130
- $save_x = $this->x;
14131
- $save_y = $this->y;
14132
- $this->x = $this->lMargin;
14133
- $this->y = $this->margin_header;
14134
- $html = str_replace('{PAGENO}', $this->pagenumPrefix . $this->docPageNum($this->page) . $this->pagenumSuffix, $html);
14135
- $html = str_replace($this->aliasNbPgGp, $this->nbpgPrefix . $this->docPageNumTotal($this->page) . $this->nbpgSuffix, $html);
14136
- $html = str_replace($this->aliasNbPg, $this->page, $html);
14137
- $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', [$this, 'date_callback'], $html); // mPDF 5.7
14138
- $this->HTMLheaderPageLinks = [];
14139
- $this->HTMLheaderPageAnnots = [];
14140
- $this->HTMLheaderPageForms = [];
14141
- $savepb = $this->pageBackgrounds;
14142
- $this->writingHTMLheader = true;
14143
- $this->WriteHTML($html, 4); // parameter 4 saves output to $this->headerbuffer
14144
- $this->writingHTMLheader = false;
14145
- $h = ($this->y - $this->margin_header);
14146
- $this->Reset();
14147
- // mPDF 5.7.2 - Clear in case Float used in Header/Footer
14148
- $this->blk[0]['blockContext'] = 0;
14149
- $this->blk[0]['float_endpos'] = 0;
14150
-
14151
- $this->pageoutput[$this->page] = [];
14152
- $this->headerbuffer = '';
14153
- $this->pageBackgrounds = $savepb;
14154
- $this->x = $save_x;
14155
- $this->y = $save_y;
14156
- $this->state = $save_state;
14157
- if ($save_state == 0) {
14158
- unset($this->pages[1]);
14159
- $this->page = 0;
14160
- }
14161
- return $h;
14162
- }
14163
-
14164
- // Called internally from Header
14165
- function writeHTMLHeaders()
14166
- {
14167
-
14168
- if ($this->mirrorMargins && ($this->page) % 2 == 0) {
14169
- $OE = 'E';
14170
- } else {
14171
- $OE = 'O';
14172
- }
14173
-
14174
- if ($OE === 'E') {
14175
- $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeaderE['html'];
14176
- } else {
14177
- $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeader['html'];
14178
- }
14179
-
14180
- if ($this->forcePortraitHeaders && $this->CurOrientation == 'L' && $this->CurOrientation != $this->DefOrientation) {
14181
- $this->saveHTMLHeader[$this->page][$OE]['rotate'] = true;
14182
- $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->tMargin;
14183
- $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->bMargin;
14184
- $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
14185
- $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
14186
- $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->h;
14187
- $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->w;
14188
- } else {
14189
- $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->lMargin;
14190
- $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->rMargin;
14191
- $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
14192
- $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
14193
- $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->w;
14194
- $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->h;
14195
- }
14196
- }
14197
-
14198
- function writeHTMLFooters()
14199
- {
14200
-
14201
- if ($this->mirrorMargins && ($this->page) % 2 == 0) {
14202
- $OE = 'E';
14203
- } else {
14204
- $OE = 'O';
14205
- }
14206
 
14207
  if ($OE === 'E') {
14208
  $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooterE['html'];
@@ -14415,28 +12522,40 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
14415
  {
14416
  $oddhtml = '';
14417
  $evenhtml = '';
 
14418
  if (is_string($Harray)) {
14419
- if (strlen($Harray) == 0) {
 
 
14420
  $oddhtml = '';
14421
  $evenhtml = '';
 
14422
  } elseif (strpos($Harray, '|') !== false) {
 
14423
  $hdet = explode('|', $Harray);
 
14424
  list($lw, $cw, $rw) = $this->_shareHeaderFooterWidth($hdet[0], $hdet[1], $hdet[2]);
14425
  $oddhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: bottom; color: #000000; ';
 
14426
  if ($this->defaultheaderfontsize) {
14427
  $oddhtml .= ' font-size: ' . $this->defaultheaderfontsize . 'pt;';
14428
  }
 
14429
  if ($this->defaultheaderfontstyle) {
 
14430
  if ($this->defaultheaderfontstyle == 'B' || $this->defaultheaderfontstyle == 'BI') {
14431
  $oddhtml .= ' font-weight: bold;';
14432
  }
 
14433
  if ($this->defaultheaderfontstyle == 'I' || $this->defaultheaderfontstyle == 'BI') {
14434
  $oddhtml .= ' font-style: italic;';
14435
  }
14436
  }
 
14437
  if ($this->defaultheaderline) {
14438
  $oddhtml .= ' border-bottom: 0.1mm solid #000000;';
14439
  }
 
14440
  $oddhtml .= '">';
14441
  $oddhtml .= '<tr>';
14442
  $oddhtml .= '<td width="' . $lw . '%" style="padding: 0 0 ' . $this->header_line_spacing . 'em 0; text-align: left; ">' . $hdet[0] . '</td>';
@@ -14445,9 +12564,11 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
14445
  $oddhtml .= '</tr></table>';
14446
 
14447
  $evenhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: bottom; color: #000000; ';
 
14448
  if ($this->defaultheaderfontsize) {
14449
  $evenhtml .= ' font-size: ' . $this->defaultheaderfontsize . 'pt;';
14450
  }
 
14451
  if ($this->defaultheaderfontstyle) {
14452
  if ($this->defaultheaderfontstyle == 'B' || $this->defaultheaderfontstyle == 'BI') {
14453
  $evenhtml .= ' font-weight: bold;';
@@ -14456,67 +12577,87 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
14456
  $evenhtml .= ' font-style: italic;';
14457
  }
14458
  }
 
14459
  if ($this->defaultheaderline) {
14460
  $evenhtml .= ' border-bottom: 0.1mm solid #000000;';
14461
  }
 
14462
  $evenhtml .= '">';
14463
  $evenhtml .= '<tr>';
14464
  $evenhtml .= '<td width="' . $rw . '%" style="padding: 0 0 ' . $this->header_line_spacing . 'em 0; text-align: left; ">' . $hdet[2] . '</td>';
14465
  $evenhtml .= '<td width="' . $cw . '%" style="padding: 0 0 ' . $this->header_line_spacing . 'em 0; text-align: center; ">' . $hdet[1] . '</td>';
14466
  $evenhtml .= '<td width="' . $lw . '%" style="padding: 0 0 ' . $this->header_line_spacing . 'em 0; text-align: right; ">' . $hdet[0] . '</td>';
14467
  $evenhtml .= '</tr></table>';
 
14468
  } else {
 
14469
  $oddhtml = '<div style="margin: 0; color: #000000; ';
 
14470
  if ($this->defaultheaderfontsize) {
14471
  $oddhtml .= ' font-size: ' . $this->defaultheaderfontsize . 'pt;';
14472
  }
 
14473
  if ($this->defaultheaderfontstyle) {
 
14474
  if ($this->defaultheaderfontstyle == 'B' || $this->defaultheaderfontstyle == 'BI') {
14475
  $oddhtml .= ' font-weight: bold;';
14476
  }
 
14477
  if ($this->defaultheaderfontstyle == 'I' || $this->defaultheaderfontstyle == 'BI') {
14478
  $oddhtml .= ' font-style: italic;';
14479
  }
14480
  }
 
14481
  if ($this->defaultheaderline) {
14482
  $oddhtml .= ' border-bottom: 0.1mm solid #000000;';
14483
  }
14484
- $oddhtml .= 'text-align: right; ">' . $Harray . '</div>';
14485
 
 
14486
  $evenhtml = '<div style="margin: 0; color: #000000; ';
 
14487
  if ($this->defaultheaderfontsize) {
14488
  $evenhtml .= ' font-size: ' . $this->defaultheaderfontsize . 'pt;';
14489
  }
 
14490
  if ($this->defaultheaderfontstyle) {
 
14491
  if ($this->defaultheaderfontstyle == 'B' || $this->defaultheaderfontstyle == 'BI') {
14492
  $evenhtml .= ' font-weight: bold;';
14493
  }
 
14494
  if ($this->defaultheaderfontstyle == 'I' || $this->defaultheaderfontstyle == 'BI') {
14495
  $evenhtml .= ' font-style: italic;';
14496
  }
14497
  }
 
14498
  if ($this->defaultheaderline) {
14499
  $evenhtml .= ' border-bottom: 0.1mm solid #000000;';
14500
  }
 
14501
  $evenhtml .= 'text-align: left; ">' . $Harray . '</div>';
14502
  }
 
14503
  } elseif (is_array($Harray) && !empty($Harray)) {
14504
- if ($side == 'O') {
 
 
 
 
14505
  $odd = $Harray;
14506
- } elseif ($side == 'E') {
14507
  $even = $Harray;
14508
  } else {
14509
- $odd = $Harray['odd'];
14510
- $even = $Harray['even'];
14511
  }
14512
- $oddhtml = $this->_createHTMLheaderFooter($odd, 'H');
14513
 
 
14514
  $evenhtml = $this->_createHTMLheaderFooter($even, 'H');
14515
  }
14516
 
14517
- if ($side == 'E') {
14518
  $this->SetHTMLHeader($evenhtml, 'E', $write);
14519
- } elseif ($side == 'O') {
14520
  $this->SetHTMLHeader($oddhtml, 'O', $write);
14521
  } else {
14522
  $this->SetHTMLHeader($oddhtml, 'O', $write);
@@ -14528,16 +12669,23 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
14528
  {
14529
  $oddhtml = '';
14530
  $evenhtml = '';
 
14531
  if (is_string($Farray)) {
 
14532
  if (strlen($Farray) == 0) {
 
14533
  $oddhtml = '';
14534
  $evenhtml = '';
 
14535
  } elseif (strpos($Farray, '|') !== false) {
 
14536
  $hdet = explode('|', $Farray);
14537
  $oddhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: top; color: #000000; ';
 
14538
  if ($this->defaultfooterfontsize) {
14539
  $oddhtml .= ' font-size: ' . $this->defaultfooterfontsize . 'pt;';
14540
  }
 
14541
  if ($this->defaultfooterfontstyle) {
14542
  if ($this->defaultfooterfontstyle == 'B' || $this->defaultfooterfontstyle == 'BI') {
14543
  $oddhtml .= ' font-weight: bold;';
@@ -14546,9 +12694,11 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
14546
  $oddhtml .= ' font-style: italic;';
14547
  }
14548
  }
 
14549
  if ($this->defaultfooterline) {
14550
  $oddhtml .= ' border-top: 0.1mm solid #000000;';
14551
  }
 
14552
  $oddhtml .= '">';
14553
  $oddhtml .= '<tr>';
14554
  $oddhtml .= '<td width="33%" style="padding: ' . $this->footer_line_spacing . 'em 0 0 0; text-align: left; ">' . $hdet[0] . '</td>';
@@ -14557,93 +12707,108 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
14557
  $oddhtml .= '</tr></table>';
14558
 
14559
  $evenhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: top; color: #000000; ';
 
14560
  if ($this->defaultfooterfontsize) {
14561
  $evenhtml .= ' font-size: ' . $this->defaultfooterfontsize . 'pt;';
14562
  }
 
14563
  if ($this->defaultfooterfontstyle) {
 
14564
  if ($this->defaultfooterfontstyle == 'B' || $this->defaultfooterfontstyle == 'BI') {
14565
  $evenhtml .= ' font-weight: bold;';
14566
  }
 
14567
  if ($this->defaultfooterfontstyle == 'I' || $this->defaultfooterfontstyle == 'BI') {
14568
  $evenhtml .= ' font-style: italic;';
14569
  }
14570
  }
 
14571
  if ($this->defaultfooterline) {
14572
  $evenhtml .= ' border-top: 0.1mm solid #000000;';
14573
  }
 
14574
  $evenhtml .= '">';
14575
  $evenhtml .= '<tr>';
14576
  $evenhtml .= '<td width="33%" style="padding: ' . $this->footer_line_spacing . 'em 0 0 0; text-align: left; ">' . $hdet[2] . '</td>';
14577
  $evenhtml .= '<td width="33%" style="padding: ' . $this->footer_line_spacing . 'em 0 0 0; text-align: center; ">' . $hdet[1] . '</td>';
14578
  $evenhtml .= '<td width="33%" style="padding: ' . $this->footer_line_spacing . 'em 0 0 0; text-align: right; ">' . $hdet[0] . '</td>';
14579
  $evenhtml .= '</tr></table>';
 
14580
  } else {
 
14581
  $oddhtml = '<div style="margin: 0; color: #000000; ';
 
14582
  if ($this->defaultfooterfontsize) {
14583
  $oddhtml .= ' font-size: ' . $this->defaultfooterfontsize . 'pt;';
14584
  }
 
14585
  if ($this->defaultfooterfontstyle) {
 
14586
  if ($this->defaultfooterfontstyle == 'B' || $this->defaultfooterfontstyle == 'BI') {
14587
  $oddhtml .= ' font-weight: bold;';
14588
  }
 
14589
  if ($this->defaultfooterfontstyle == 'I' || $this->defaultfooterfontstyle == 'BI') {
14590
  $oddhtml .= ' font-style: italic;';
14591
  }
14592
  }
 
14593
  if ($this->defaultfooterline) {
14594
  $oddhtml .= ' border-top: 0.1mm solid #000000;';
14595
  }
 
14596
  $oddhtml .= 'text-align: right; ">' . $Farray . '</div>';
14597
 
14598
  $evenhtml = '<div style="margin: 0; color: #000000; ';
 
14599
  if ($this->defaultfooterfontsize) {
14600
  $evenhtml .= ' font-size: ' . $this->defaultfooterfontsize . 'pt;';
14601
  }
 
14602
  if ($this->defaultfooterfontstyle) {
 
14603
  if ($this->defaultfooterfontstyle == 'B' || $this->defaultfooterfontstyle == 'BI') {
14604
  $evenhtml .= ' font-weight: bold;';
14605
  }
 
14606
  if ($this->defaultfooterfontstyle == 'I' || $this->defaultfooterfontstyle == 'BI') {
14607
  $evenhtml .= ' font-style: italic;';
14608
  }
14609
  }
 
14610
  if ($this->defaultfooterline) {
14611
  $evenhtml .= ' border-top: 0.1mm solid #000000;';
14612
  }
 
14613
  $evenhtml .= 'text-align: left; ">' . $Farray . '</div>';
14614
  }
 
14615
  } elseif (is_array($Farray)) {
14616
- if ($side == 'O') {
 
 
 
 
14617
  $odd = $Farray;
14618
  } elseif ($side == 'E') {
14619
  $even = $Farray;
14620
  } else {
14621
- if (isset($Farray['odd'])) {
14622
- $odd = $Farray['odd'];
14623
- }
14624
- if (isset($Farray['even'])) {
14625
- $even = $Farray['even'];
14626
- }
14627
- }
14628
-
14629
- if (isset($odd)) {
14630
- $oddhtml = $this->_createHTMLheaderFooter($odd, 'F');
14631
  }
14632
 
14633
- if (isset($even)) {
14634
- $evenhtml = $this->_createHTMLheaderFooter($even, 'F');
14635
- }
14636
  }
14637
- /* -- HTMLfooterS-FOOTERS -- */
14638
- if ($side == 'E') {
14639
  $this->SetHTMLFooter($evenhtml, 'E');
14640
- } elseif ($side == 'O') {
14641
  $this->SetHTMLFooter($oddhtml, 'O');
14642
  } else {
14643
  $this->SetHTMLFooter($oddhtml, 'O');
14644
  $this->SetHTMLFooter($evenhtml, 'E');
14645
  }
14646
- /* -- END HTMLfooterS-FOOTERS -- */
14647
  }
14648
 
14649
  /* -- WATERMARK -- */
@@ -16226,9 +14391,9 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
16226
  $this->blk[1]['y0'] = $bbox_y;
16227
  $this->blk[1]['startpage'] = $this->page;
16228
  $this->blk[1]['y1'] = $bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb;
16229
- $this->_out($rot_start);
16230
  $this->PaintDivBB('', 0, 1); // Prints borders and sets backgrounds in $this->pageBackgrounds
16231
- $this->_out($rot_end);
16232
  }
16233
 
16234
  $s = $this->PrintPageBackgrounds();
@@ -16236,7 +14401,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
16236
  $this->pages[$this->page] = preg_replace('/___BEFORE_BORDERS___/', "\n" . $s . "\n", $this->pages[$this->page]);
16237
  $this->pageBackgrounds = [];
16238
 
16239
- $this->_out($rot_start);
16240
 
16241
  // Clipping Output
16242
  if ($overflow == 'hidden') {
@@ -16247,9 +14412,9 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
16247
  }
16248
  // $op = 'W* n'; // Clipping
16249
  $op = 'W n'; // Clipping alternative mode
16250
- $this->_out("q");
16251
  $ch = $clip_y1 - $y;
16252
- $this->_out(sprintf('%.3F %.3F %.3F %.3F re %s', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$ch * Mpdf::SCALE, $op));
16253
  if (!empty($block_s)) {
16254
  $tmp = "q\n" . sprintf('%.3F %.3F %.3F %.3F re %s', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$ch * Mpdf::SCALE, $op);
16255
  $tmp .= "\n" . $block_s . "\nQ";
@@ -16264,7 +14429,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
16264
  $tmp .= "\n" . $block_s . "\nQ";
16265
  $block_s = $tmp;
16266
  }
16267
- $this->_out($block_s);
16268
  }
16269
 
16270
 
@@ -16274,7 +14439,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
16274
  $this->transformScale(($shrink_f * 100), ($shrink_f * 100), $x, $y);
16275
  }
16276
 
16277
- $this->_out($this->headerbuffer);
16278
 
16279
  if ($shrink_f != 1) { // i.e. autofit has resized the box
16280
  $this->StopTransform();
@@ -16282,10 +14447,10 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
16282
 
16283
  if ($overflow == 'hidden') {
16284
  // End clipping
16285
- $this->_out("Q");
16286
  }
16287
 
16288
- $this->_out($rot_end);
16289
 
16290
 
16291
  // Page Links
@@ -17381,35 +15546,6 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
17381
  return ($blt_width + $markeroffset);
17382
  }
17383
 
17384
- /* -- TABLES -- */
17385
-
17386
- // This function determines the shrink factor when resizing tables
17387
- // val is the table_height / page_height_available
17388
- // returns a scaling factor used as $shrin_k to resize the table
17389
- // Overcompensating will be quicker but may unnecessarily shrink table too much
17390
- // Undercompensating means it will reiterate more times (taking more processing time)
17391
- function tbsqrt($val, $iteration = 3)
17392
- {
17393
- $k = 4; // Alters number of iterations until it returns $val itself - Must be > 2
17394
- // Probably best guess and most accurate
17395
- if ($iteration == 1) {
17396
- return sqrt($val);
17397
- }
17398
- // Faster than using sqrt (because it won't undercompensate), and gives reasonable results
17399
- // return 1+(($val-1)/2);
17400
- $x = 2 - (($iteration - 2) / ($k - 2));
17401
- if ($x == 0) {
17402
- $ret = $val + 0.00001;
17403
- } elseif ($x < 0) {
17404
- $ret = 1 + ( pow(2, ($iteration - 2 - $k)) / 1000 );
17405
- } else {
17406
- $ret = 1 + (($val - 1) / $x);
17407
- }
17408
- return $ret;
17409
- }
17410
-
17411
- /* -- END TABLES -- */
17412
-
17413
  function _saveTextBuffer($t, $link = '', $intlink = '', $return = false)
17414
  {
17415
  // mPDF 6 Lists
@@ -18486,13 +16622,13 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
18486
 
18487
  if (isset($tbd['s']) && $tbd['s']) {
18488
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
18489
- $this->_out('q');
18490
  $this->SetLineWidth(0);
18491
- $this->_out(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE));
18492
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE));
18493
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE));
18494
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE));
18495
- $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
18496
  }
18497
 
18498
  $this->_setBorderLine($tbd);
@@ -18557,15 +16693,15 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
18557
  }
18558
  /* -- END BORDER-RADIUS -- */
18559
  $s .= 'S' . "\n";
18560
- $this->_out($s);
18561
 
18562
  if ($tbd['style'] == 'double') {
18563
  $this->SetLineWidth($tbd['w'] / 3);
18564
  $this->SetDColor($tbcol);
18565
- $this->_out($s);
18566
  }
18567
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
18568
- $this->_out('Q');
18569
  }
18570
 
18571
  // Reset Corners and Dash off
@@ -18583,13 +16719,13 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
18583
  $tbd = $this->blk[$blvl]['border_bottom'];
18584
  if (isset($tbd['s']) && $tbd['s']) {
18585
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
18586
- $this->_out('q');
18587
  $this->SetLineWidth(0);
18588
- $this->_out(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE));
18589
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE));
18590
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE));
18591
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE));
18592
- $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
18593
  }
18594
 
18595
  $this->_setBorderLine($tbd);
@@ -18621,15 +16757,15 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
18621
  }
18622
  }
18623
  $s .= 'S' . "\n";
18624
- $this->_out($s);
18625
 
18626
  if ($tbd['style'] == 'double') {
18627
  $this->SetLineWidth($tbd['w'] / 3);
18628
  $this->SetDColor($tbcol);
18629
- $this->_out($s);
18630
  }
18631
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
18632
- $this->_out('Q');
18633
  }
18634
 
18635
  // Reset Corners and Dash off
@@ -18647,13 +16783,13 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
18647
  $tbd = $this->blk[$blvl]['border_left'];
18648
  if (isset($tbd['s']) && $tbd['s']) {
18649
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
18650
- $this->_out('q');
18651
  $this->SetLineWidth(0);
18652
- $this->_out(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE));
18653
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE));
18654
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE));
18655
- $this->_out(sprintf('%.3F %.3F l ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE));
18656
- $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
18657
  }
18658
 
18659
  $this->_setBorderLine($tbd);
@@ -18685,15 +16821,15 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
18685
  }
18686
  }
18687
  $s .= 'S' . "\n";
18688
- $this->_out($s);
18689
 
18690
  if ($tbd['style'] == 'double') {
18691
  $this->SetLineWidth($tbd['w'] / 3);
18692
  $this->SetDColor($tbcol);
18693
- $this->_out($s);
18694
  }
18695
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
18696
- $this->_out('Q');
18697
  }
18698
 
18699
  // Reset Corners and Dash off
@@ -18708,13 +16844,13 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
18708
  $tbd = $this->blk[$blvl]['border_right'];
18709
  if (isset($tbd['s']) && $tbd['s']) {
18710
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
18711
- $this->_out('q');
18712
  $this->SetLineWidth(0);
18713
- $this->_out(sprintf('%.3F %.3F m ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE));
18714
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE));
18715
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE));
18716
- $this->_out(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE));
18717
- $this->_out(' h W n '); // Ends path no-op & Sets the clipping path
18718
  }
18719
 
18720
  $this->_setBorderLine($tbd);
@@ -18746,15 +16882,15 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
18746
  }
18747
  }
18748
  $s .= 'S' . "\n";
18749
- $this->_out($s);
18750
 
18751
  if ($tbd['style'] == 'double') {
18752
  $this->SetLineWidth($tbd['w'] / 3);
18753
  $this->SetDColor($tbcol);
18754
- $this->_out($s);
18755
  }
18756
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
18757
- $this->_out('Q');
18758
  }
18759
 
18760
  // Reset Corners and Dash off
@@ -23430,7 +21566,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
23430
  if ($table['overflow'] == 'hidden' && $level == 1 && !$this->table_rotate && !$this->ColActive) {
23431
  // Bounding rectangle to clip
23432
  $this->tableClipPath = sprintf('q %.3F %.3F %.3F %.3F re W n', $x0 * Mpdf::SCALE, $this->h * Mpdf::SCALE, $this->blk[$this->blklvl]['inner_width'] * Mpdf::SCALE, -$this->h * Mpdf::SCALE);
23433
- $this->_out($this->tableClipPath);
23434
  } else {
23435
  $this->tableClipPath = '';
23436
  }
@@ -23550,7 +21686,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
23550
  }
23551
 
23552
  if ($level == 1) {
23553
- $this->_out('___TABLE___BACKGROUNDS' . $this->uniqstr);
23554
  }
23555
  $tableheaderadj = 0;
23556
  $tablefooteradj = 0;
@@ -23698,7 +21834,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
23698
  }
23699
 
23700
  if ($this->tableClipPath) {
23701
- $this->_out("Q");
23702
  }
23703
 
23704
  $bx = $x0;
@@ -23763,7 +21899,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
23763
  }
23764
  $this->Line($blx, $this->y + ($this->splitTableBorderWidth / 2), $blx + $blw, $this->y + ($this->splitTableBorderWidth / 2));
23765
  $this->DrawColor = $prevDrawColor;
23766
- $this->_out($this->DrawColor);
23767
  $this->SetLineWidth($lw);
23768
  $this->SetLineJoin(2);
23769
  $this->SetLineCap(2);
@@ -23841,11 +21977,11 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
23841
 
23842
  $this->AddPage($this->CurOrientation);
23843
 
23844
- $this->_out('___TABLE___BACKGROUNDS' . $this->uniqstr);
23845
 
23846
 
23847
  if ($this->tableClipPath) {
23848
- $this->_out($this->tableClipPath);
23849
  }
23850
 
23851
  // Added to correct for OddEven Margins
@@ -23862,7 +21998,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
23862
  $blx += $this->MarginCorrection;
23863
  $this->Line($blx, $this->y - ($this->splitTableBorderWidth / 2), $blx + $blw, $this->y - ($this->splitTableBorderWidth / 2));
23864
  $this->DrawColor = $prevDrawColor;
23865
- $this->_out($this->DrawColor);
23866
  $this->SetLineWidth($lw);
23867
  $this->SetLineJoin(2);
23868
  $this->SetLineCap(2);
@@ -23929,1629 +22065,878 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
23929
  }
23930
  if ($adv) {
23931
  if ($this->table_rotate) {
23932
- $this->y += ($adv);
23933
- } else {
23934
- $this->DivLn($adv, $this->blklvl, true);
23935
- }
23936
- }
23937
- }
23938
-
23939
- $outerfilled = 0;
23940
- $y = $y0 = $this->y;
23941
- }
23942
-
23943
- /* -- COLUMNS -- */
23944
- // COLS
23945
- // COLUMN CHANGE
23946
- if ($this->CurrCol != $oldcolumn) {
23947
- // Added to correct for Columns
23948
- $x += $this->ChangeColumn * ($this->ColWidth + $this->ColGap);
23949
- $x0 += $this->ChangeColumn * ($this->ColWidth + $this->ColGap);
23950
- if ($this->CurrCol == 0) { // just added a page - possibly with tableheader
23951
- $y0 = $this->y; // this->y0 is global used by Columns - $y0 is internal to tablewrite
23952
- } else {
23953
- $y0 = $this->y0; // this->y0 is global used by Columns - $y0 is internal to tablewrite
23954
- }
23955
- $y = $y0;
23956
- $outerfilled = 0;
23957
- if ($this->CurrCol != 0 && ($this->keepColumns && $this->ColActive) && !empty($tableheader) && $i > 0) {
23958
- $this->x = $x;
23959
- $this->y = $y;
23960
- $this->TableHeaderFooter($tableheader, $tablestartpage, $tablestartcolumn, 'H', $level);
23961
- $y0 = $y = $this->y;
23962
- }
23963
- }
23964
- /* -- END COLUMNS -- */
23965
- }
23966
- $skippage = true;
23967
- }
23968
-
23969
- $this->x = $x;
23970
- $this->y = $y;
23971
-
23972
- if ($this->kwt_saved && $level == 1) {
23973
- $this->printkwtbuffer();
23974
- $x0 = $x = $this->x;
23975
- $y0 = $y = $this->y;
23976
- $this->kwt_moved = false;
23977
- $this->kwt_saved = false;
23978
- }
23979
-
23980
-
23981
- // Set the Page & Column where table actually starts
23982
- if ($i == 0 && $j == 0 && $level == 1) {
23983
- if (($this->mirrorMargins) && (($this->page) % 2 == 0)) { // EVEN
23984
- $tablestartpage = 'EVEN';
23985
- } elseif (($this->mirrorMargins) && (($this->page) % 2 == 1)) { // ODD
23986
- $tablestartpage = 'ODD';
23987
- } else {
23988
- $tablestartpage = '';
23989
- }
23990
- $tablestartpageno = $this->page;
23991
- if ($this->ColActive) {
23992
- $tablestartcolumn = $this->CurrCol;
23993
- } // *COLUMNS*
23994
- }
23995
-
23996
- // ALIGN
23997
- $align = $cell['a'];
23998
-
23999
- /* -- COLUMNS -- */
24000
- // If outside columns, this is done in PaintDivBB
24001
- if ($this->ColActive) {
24002
- // OUTER FILL BGCOLOR of DIVS
24003
- if ($this->blklvl > 0 && ($j == 0) && !$this->table_rotate && $level == 1) {
24004
- $firstblockfill = $this->GetFirstBlockFill();
24005
- if ($firstblockfill && $this->blklvl >= $firstblockfill) {
24006
- $divh = $maxrowheight;
24007
- // Last row
24008
- if ((!isset($cell['rowspan']) && $i == $numrows - 1) || (isset($cell['rowspan']) && (($i == $numrows - 1 && $cell['rowspan'] < 2) || ($cell['rowspan'] > 1 && ($i + $cell['rowspan'] - 1) == $numrows - 1)))) {
24009
- if ($table['borders_separate']) {
24010
- $adv = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2;
24011
- } else {
24012
- $adv = $table['margin']['B'] + $table['max_cell_border_width']['B'] / 2;
24013
- }
24014
- $divh += $adv; // last row: fill bottom half of bottom border (y advanced at end)
24015
- }
24016
-
24017
- if (($this->y + $divh) > $outerfilled) { // if not already painted by previous rowspan
24018
- $bak_x = $this->x;
24019
- $bak_y = $this->y;
24020
- if ($outerfilled > $this->y) {
24021
- $divh = ($this->y + $divh) - $outerfilled;
24022
- $this->y = $outerfilled;
24023
- }
24024
-
24025
- $this->DivLn($divh, -3, false);
24026
- $outerfilled = $this->y + $divh;
24027
- // Reset current block fill
24028
- $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
24029
- if ($bcor) {
24030
- $this->SetFColor($bcor);
24031
- }
24032
- $this->x = $bak_x;
24033
- $this->y = $bak_y;
24034
- }
24035
- }
24036
- }
24037
- }
24038
-
24039
- // TABLE BACKGROUND FILL BGCOLOR - for cellSpacing
24040
- if ($this->ColActive) {
24041
- if ($table['borders_separate']) {
24042
- $fill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
24043
- if ($fill) {
24044
- $color = $this->colorConverter->convert($fill, $this->PDFAXwarnings);
24045
- if ($color) {
24046
- $xadj = ($table['border_spacing_H'] / 2);
24047
- $yadj = ($table['border_spacing_V'] / 2);
24048
- $wadj = $table['border_spacing_H'];
24049
- $hadj = $table['border_spacing_V'];
24050
- if ($i == 0) { // Top
24051
- $yadj += $table['padding']['T'] + $table['border_details']['T']['w'];
24052
- $hadj += $table['padding']['T'] + $table['border_details']['T']['w'];
24053
- }
24054
- if ($j == 0) { // Left
24055
- $xadj += $table['padding']['L'] + $table['border_details']['L']['w'];
24056
- $wadj += $table['padding']['L'] + $table['border_details']['L']['w'];
24057
- }
24058
- if ($i == ($numrows - 1) || (isset($cell['rowspan']) && ($i + $cell['rowspan']) == $numrows) || (!isset($cell['rowspan']) && ($i + 1) == $numrows)) { // Bottom
24059
- $hadj += $table['padding']['B'] + $table['border_details']['B']['w'];
24060
- }
24061
- if ($j == ($numcols - 1) || (isset($cell['colspan']) && ($j + $cell['colspan']) == $numcols) || (!isset($cell['colspan']) && ($j + 1) == $numcols)) { // Right
24062
- $wadj += $table['padding']['R'] + $table['border_details']['R']['w'];
24063
- }
24064
- $this->SetFColor($color);
24065
- $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
24066
- }
24067
- }
24068
- }
24069
- }
24070
- /* -- END COLUMNS -- */
24071
-
24072
- if ($table['empty_cells'] != 'hide' || !empty($cell['textbuffer']) || (isset($cell['nestedcontent']) && $cell['nestedcontent']) || !$table['borders_separate']) {
24073
- $paintcell = true;
24074
- } else {
24075
- $paintcell = false;
24076
- }
24077
-
24078
- // Set Borders
24079
- $bord = 0;
24080
- $bord_det = [];
24081
-
24082
- if (!$this->simpleTables) {
24083
- if ($this->packTableData) {
24084
- $c = $this->_unpackCellBorder($cell['borderbin']);
24085
- $bord = $c['border'];
24086
- $bord_det = $c['border_details'];
24087
- } else {
24088
- $bord = $cell['border'];
24089
- $bord_det = $cell['border_details'];
24090
- }
24091
- } elseif ($this->simpleTables) {
24092
- $bord = $table['simple']['border'];
24093
- $bord_det = $table['simple']['border_details'];
24094
- }
24095
-
24096
- // TABLE ROW OR CELL FILL BGCOLOR
24097
- $fill = 0;
24098
- if (isset($cell['bgcolor']) && $cell['bgcolor'] && $cell['bgcolor'] != 'transparent') {
24099
- $fill = $cell['bgcolor'];
24100
- $leveladj = 6;
24101
- } elseif (isset($table['bgcolor'][$i]) && $table['bgcolor'][$i] && $table['bgcolor'][$i] != 'transparent') { // Row color
24102
- $fill = $table['bgcolor'][$i];
24103
- $leveladj = 3;
24104
- }
24105
- if ($fill && $paintcell) {
24106
- $color = $this->colorConverter->convert($fill, $this->PDFAXwarnings);
24107
- if ($color) {
24108
- if ($table['borders_separate']) {
24109
- if ($this->ColActive) {
24110
- $this->SetFColor($color);
24111
- $this->Rect($x + ($table['border_spacing_H'] / 2), $y + ($table['border_spacing_V'] / 2), $w - $table['border_spacing_H'], $h - $table['border_spacing_V'], 'F');
24112
- } else {
24113
- $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => ($x + ($table['border_spacing_H'] / 2)), 'y' => ($y + ($table['border_spacing_V'] / 2)), 'w' => ($w - $table['border_spacing_H']), 'h' => ($h - $table['border_spacing_V']), 'col' => $color];
24114
- }
24115
- } else {
24116
- if ($this->ColActive) {
24117
- $this->SetFColor($color);
24118
- $this->Rect($x, $y, $w, $h, 'F');
24119
- } else {
24120
- $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'col' => $color];
24121
- }
24122
- }
24123
- }
24124
- }
24125
-
24126
- /* -- BACKGROUNDS -- */
24127
- if (isset($cell['gradient']) && $cell['gradient'] && $paintcell) {
24128
- $g = $this->gradient->parseBackgroundGradient($cell['gradient']);
24129
- if ($g) {
24130
- if ($table['borders_separate']) {
24131
- $px = $x + ($table['border_spacing_H'] / 2);
24132
- $py = $y + ($table['border_spacing_V'] / 2);
24133
- $pw = $w - $table['border_spacing_H'];
24134
- $ph = $h - $table['border_spacing_V'];
24135
- } else {
24136
- $px = $x;
24137
- $py = $y;
24138
- $pw = $w;
24139
- $ph = $h;
24140
- }
24141
- if ($this->ColActive) {
24142
- $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
24143
- } else {
24144
- $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
24145
- }
24146
- }
24147
- }
24148
-
24149
- if (isset($cell['background-image']) && $paintcell) {
24150
- if (isset($cell['background-image']['gradient']) && $cell['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $cell['background-image']['gradient'])) {
24151
- $g = $this->gradient->parseMozGradient($cell['background-image']['gradient']);
24152
- if ($g) {
24153
- if ($table['borders_separate']) {
24154
- $px = $x + ($table['border_spacing_H'] / 2);
24155
- $py = $y + ($table['border_spacing_V'] / 2);
24156
- $pw = $w - $table['border_spacing_H'];
24157
- $ph = $h - $table['border_spacing_V'];
24158
- } else {
24159
- $px = $x;
24160
- $py = $y;
24161
- $pw = $w;
24162
- $ph = $h;
24163
- }
24164
- if ($this->ColActive) {
24165
- $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
24166
- } else {
24167
- $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
24168
  }
 
 
 
24169
  }
24170
- } elseif (isset($cell['background-image']['image_id']) && $cell['background-image']['image_id']) { // Background pattern
24171
- $n = count($this->patterns) + 1;
24172
- if ($table['borders_separate']) {
24173
- $px = $x + ($table['border_spacing_H'] / 2);
24174
- $py = $y + ($table['border_spacing_V'] / 2);
24175
- $pw = $w - $table['border_spacing_H'];
24176
- $ph = $h - $table['border_spacing_V'];
24177
- } else {
24178
- $px = $x;
24179
- $py = $y;
24180
- $pw = $w;
24181
- $ph = $h;
24182
- }
24183
- if ($this->ColActive) {
24184
- list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($cell['background-image']['orig_w'], $cell['background-image']['orig_h'], $pw, $ph, $cell['background-image']['resize'], $cell['background-image']['x_repeat'], $cell['background-image']['y_repeat']);
24185
- $this->patterns[$n] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'pgh' => $this->h, 'image_id' => $cell['background-image']['image_id'], 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $cell['background-image']['x_pos'], 'y_pos' => $cell['background-image']['y_pos'], 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat];
24186
- if ($cell['background-image']['opacity'] > 0 && $cell['background-image']['opacity'] < 1) {
24187
- $opac = $this->SetAlpha($cell['background-image']['opacity'], 'Normal', true);
24188
  } else {
24189
- $opac = '';
 
 
 
 
 
 
 
 
24190
  }
24191
- $this->_out(sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $px * Mpdf::SCALE, ($this->h - $py) * Mpdf::SCALE, $pw * Mpdf::SCALE, -$ph * Mpdf::SCALE));
24192
- } else {
24193
- $image_id = $cell['background-image']['image_id'];
24194
- $orig_w = $cell['background-image']['orig_w'];
24195
- $orig_h = $cell['background-image']['orig_h'];
24196
- $x_pos = $cell['background-image']['x_pos'];
24197
- $y_pos = $cell['background-image']['y_pos'];
24198
- $x_repeat = $cell['background-image']['x_repeat'];
24199
- $y_repeat = $cell['background-image']['y_repeat'];
24200
- $resize = $cell['background-image']['resize'];
24201
- $opacity = $cell['background-image']['opacity'];
24202
- $itype = $cell['background-image']['itype'];
24203
- $this->tableBackgrounds[$level * 9 + 8][] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
24204
  }
 
24205
  }
24206
- }
24207
- /* -- END BACKGROUNDS -- */
24208
-
24209
- if (isset($cell['colspan']) && $cell['colspan'] > 1) {
24210
- $ccolsp = $cell['colspan'];
24211
- } else {
24212
- $ccolsp = 1;
24213
- }
24214
- if (isset($cell['rowspan']) && $cell['rowspan'] > 1) {
24215
- $crowsp = $cell['rowspan'];
24216
- } else {
24217
- $crowsp = 1;
24218
  }
24219
 
 
 
24220
 
24221
- // but still need to do this for repeated headers...
24222
- if (!$table['borders_separate'] && $this->tabletheadjustfinished && !$this->simpleTables) {
24223
- if (isset($table['topntail']) && $table['topntail']) {
24224
- $bord_det['T'] = $this->border_details($table['topntail']);
24225
- $bord_det['T']['w'] /= $this->shrin_k;
24226
- $this->setBorder($bord, Border::TOP);
24227
- }
24228
- if (isset($table['thead-underline']) && $table['thead-underline']) {
24229
- $bord_det['T'] = $this->border_details($table['thead-underline']);
24230
- $bord_det['T']['w'] /= $this->shrin_k;
24231
- $this->setBorder($bord, Border::TOP);
24232
- }
24233
  }
24234
 
24235
 
24236
- // Get info of first row ==>> table header
24237
- // Use > 1 row if THEAD
24238
- if (isset($table['is_thead'][$i]) && $table['is_thead'][$i] && $level == 1) {
24239
- if ($j == 0) {
24240
- $tableheaderrowheight += $table['hr'][$i];
24241
- }
24242
- $tableheader[$i][0]['trbackground-images'] = (isset($table['trbackground-images'][$i]) ? $table['trbackground-images'][$i] : null);
24243
- $tableheader[$i][0]['trgradients'] = (isset($table['trgradients'][$i]) ? $table['trgradients'][$i] : null);
24244
- $tableheader[$i][0]['trbgcolor'] = (isset($table['bgcolor'][$i]) ? $table['bgcolor'][$i] : null);
24245
- $tableheader[$i][$j]['x'] = $x;
24246
- $tableheader[$i][$j]['y'] = $y;
24247
- $tableheader[$i][$j]['h'] = $h;
24248
- $tableheader[$i][$j]['w'] = $w;
24249
- if (isset($cell['textbuffer'])) {
24250
- $tableheader[$i][$j]['textbuffer'] = $cell['textbuffer'];
24251
  } else {
24252
- $tableheader[$i][$j]['textbuffer'] = '';
24253
- }
24254
- $tableheader[$i][$j]['a'] = $cell['a'];
24255
- $tableheader[$i][$j]['R'] = $cell['R'];
24256
-
24257
- $tableheader[$i][$j]['va'] = $cell['va'];
24258
- $tableheader[$i][$j]['mih'] = $cell['mih'];
24259
- $tableheader[$i][$j]['gradient'] = (isset($cell['gradient']) ? $cell['gradient'] : null); // *BACKGROUNDS*
24260
- $tableheader[$i][$j]['background-image'] = (isset($cell['background-image']) ? $cell['background-image'] : null); // *BACKGROUNDS*
24261
- $tableheader[$i][$j]['rowspan'] = (isset($cell['rowspan']) ? $cell['rowspan'] : null);
24262
- $tableheader[$i][$j]['colspan'] = (isset($cell['colspan']) ? $cell['colspan'] : null);
24263
- $tableheader[$i][$j]['bgcolor'] = $cell['bgcolor'];
24264
-
24265
- if (!$this->simpleTables) {
24266
- $tableheader[$i][$j]['border'] = $bord;
24267
- $tableheader[$i][$j]['border_details'] = $bord_det;
24268
- } elseif ($this->simpleTables) {
24269
- $tableheader[$i][$j]['border'] = $table['simple']['border'];
24270
- $tableheader[$i][$j]['border_details'] = $table['simple']['border_details'];
24271
- }
24272
- $tableheader[$i][$j]['padding'] = $cell['padding'];
24273
- if (isset($cell['direction'])) {
24274
- $tableheader[$i][$j]['direction'] = $cell['direction'];
24275
- }
24276
- if (isset($cell['cellLineHeight'])) {
24277
- $tableheader[$i][$j]['cellLineHeight'] = $cell['cellLineHeight'];
24278
- }
24279
- if (isset($cell['cellLineStackingStrategy'])) {
24280
- $tableheader[$i][$j]['cellLineStackingStrategy'] = $cell['cellLineStackingStrategy'];
24281
- }
24282
- if (isset($cell['cellLineStackingShift'])) {
24283
- $tableheader[$i][$j]['cellLineStackingShift'] = $cell['cellLineStackingShift'];
24284
  }
 
 
 
 
24285
  }
24286
 
24287
- // CELL BORDER
24288
- if ($bord) {
24289
- if ($table['borders_separate'] && $paintcell) {
24290
- $this->_tableRect($x + ($table['border_spacing_H'] / 2) + ($bord_det['L']['w'] / 2), $y + ($table['border_spacing_V'] / 2) + ($bord_det['T']['w'] / 2), $w - $table['border_spacing_H'] - ($bord_det['L']['w'] / 2) - ($bord_det['R']['w'] / 2), $h - $table['border_spacing_V'] - ($bord_det['T']['w'] / 2) - ($bord_det['B']['w'] / 2), $bord, $bord_det, false, $table['borders_separate']);
24291
- } elseif (!$table['borders_separate']) {
24292
- $this->_tableRect($x, $y, $w, $h, $bord, $bord_det, true, $table['borders_separate']); // true causes buffer
24293
- }
24294
- }
24295
 
24296
- // VERTICAL ALIGN
24297
- if ($cell['R'] && intval($cell['R']) > 0 && intval($cell['R']) < 90 && isset($cell['va']) && $cell['va'] != 'B') {
24298
- $cell['va'] = 'B';
24299
- }
24300
- if (!isset($cell['va']) || $cell['va'] == 'M') {
24301
- $this->y += ($h - $cell['mih']) / 2;
24302
- } elseif (isset($cell['va']) && $cell['va'] == 'B') {
24303
- $this->y += $h - $cell['mih'];
24304
- }
 
 
 
 
 
 
 
 
24305
 
24306
- // NESTED CONTENT
24307
- // TEXT (and nested tables)
 
 
 
 
 
24308
 
24309
- $this->divwidth = $w;
24310
- if (!empty($cell['textbuffer'])) {
24311
- $this->cellTextAlign = $align;
24312
- $this->cellLineHeight = $cell['cellLineHeight'];
24313
- $this->cellLineStackingStrategy = $cell['cellLineStackingStrategy'];
24314
- $this->cellLineStackingShift = $cell['cellLineStackingShift'];
24315
- if ($level == 1) {
24316
- if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i]) {
24317
- if (preg_match('/{colsum([0-9]*)[_]*}/', $cell['textbuffer'][0][0], $m)) {
24318
- $rep = sprintf("%01." . intval($m[1]) . "f", $this->colsums[$j]);
24319
- $cell['textbuffer'][0][0] = preg_replace('/{colsum[0-9_]*}/', $rep, $cell['textbuffer'][0][0]);
24320
- }
24321
- } elseif (!isset($table['is_thead'][$i])) {
24322
- if (isset($this->colsums[$j])) {
24323
- $this->colsums[$j] += $this->toFloat($cell['textbuffer'][0][0]);
24324
- } else {
24325
- $this->colsums[$j] = $this->toFloat($cell['textbuffer'][0][0]);
24326
  }
24327
  }
24328
  }
24329
- $opy = $this->y;
24330
- // mPDF ITERATION
24331
- if ($this->iterationCounter) {
24332
- foreach ($cell['textbuffer'] as $k => $t) {
24333
- if (preg_match('/{iteration ([a-zA-Z0-9_]+)}/', $t[0], $m)) {
24334
- $vname = '__' . $m[1] . '_';
24335
- if (!isset($this->$vname)) {
24336
- $this->$vname = 1;
24337
- } else {
24338
- $this->$vname++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24339
  }
24340
- $cell['textbuffer'][$k][0] = preg_replace('/{iteration ' . $m[1] . '}/', $this->$vname, $cell['textbuffer'][$k][0]);
 
24341
  }
24342
  }
24343
  }
 
 
24344
 
 
 
 
 
 
24345
 
24346
- if ($cell['R']) {
24347
- $cellPtSize = $cell['textbuffer'][0][11] / $this->shrin_k;
24348
- if (!$cellPtSize) {
24349
- $cellPtSize = $this->default_font_size;
24350
- }
24351
- $cellFontHeight = ($cellPtSize / Mpdf::SCALE);
24352
- $opx = $this->x;
24353
- $angle = intval($cell['R']);
24354
- // Only allow 45 to 89 degrees (when bottom-aligned) or exactly 90 or -90
24355
- if ($angle > 90) {
24356
- $angle = 90;
24357
- } elseif ($angle > 0 && $angle < 45) {
24358
- $angle = 45;
24359
- } elseif ($angle < 0) {
24360
- $angle = -90;
24361
- }
24362
- $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
24363
- if (isset($cell['a']) && $cell['a'] == 'R') {
24364
- $this->x += ($w) + ($offset) - ($cellFontHeight / 3) - ($cell['padding']['R'] + ($table['border_spacing_H'] / 2));
24365
- } elseif (!isset($cell['a']) || $cell['a'] == 'C') {
24366
- $this->x += ($w / 2) + ($offset);
24367
- } else {
24368
- $this->x += ($offset) + ($cellFontHeight / 3) + ($cell['padding']['L'] + ($table['border_spacing_H'] / 2));
24369
- }
24370
- $str = '';
24371
- foreach ($cell['textbuffer'] as $t) {
24372
- $str .= $t[0] . ' ';
24373
- }
24374
- $str = rtrim($str);
24375
- if (!isset($cell['va']) || $cell['va'] == 'M') {
24376
- $this->y -= ($h - $cell['mih']) / 2; // Undo what was added earlier VERTICAL ALIGN
24377
- if ($angle > 0) {
24378
- $this->y += (($h - $cell['mih']) / 2) + $cell['padding']['T'] + ($cell['mih'] - ($cell['padding']['T'] + $cell['padding']['B']));
24379
- } elseif ($angle < 0) {
24380
- $this->y += (($h - $cell['mih']) / 2) + ($cell['padding']['T'] + ($table['border_spacing_V'] / 2));
24381
- }
24382
- } elseif (isset($cell['va']) && $cell['va'] == 'B') {
24383
- $this->y -= $h - $cell['mih']; // Undo what was added earlier VERTICAL ALIGN
24384
- if ($angle > 0) {
24385
- $this->y += $h - ($cell['padding']['B'] + ($table['border_spacing_V'] / 2));
24386
- } elseif ($angle < 0) {
24387
- $this->y += $h - $cell['mih'] + ($cell['padding']['T'] + ($table['border_spacing_V'] / 2));
24388
- }
24389
- } elseif (isset($cell['va']) && $cell['va'] == 'T') {
24390
- if ($angle > 0) {
24391
- $this->y += $cell['mih'] - ($cell['padding']['B'] + ($table['border_spacing_V'] / 2));
24392
- } elseif ($angle < 0) {
24393
- $this->y += ($cell['padding']['T'] + ($table['border_spacing_V'] / 2));
24394
- }
24395
- }
24396
- $this->Rotate($angle, $this->x, $this->y);
24397
- $s_fs = $this->FontSizePt;
24398
- $s_f = $this->FontFamily;
24399
- $s_st = $this->FontStyle;
24400
- if (!empty($cell['textbuffer'][0][3])) { // Font Color
24401
- $cor = $cell['textbuffer'][0][3];
24402
- $this->SetTColor($cor);
24403
- }
24404
- $this->SetFont($cell['textbuffer'][0][4], $cell['textbuffer'][0][2], $cellPtSize, true, true);
24405
 
24406
- $this->magic_reverse_dir($str, $this->directionality, $cell['textbuffer'][0][18]);
24407
- $this->Text($this->x, $this->y, $str, $cell['textbuffer'][0][18], $cell['textbuffer'][0][8]); // textvar
24408
- $this->Rotate(0);
24409
- $this->SetFont($s_f, $s_st, $s_fs, true, true);
24410
- $this->SetTColor(0);
24411
- $this->x = $opx;
24412
  } else {
24413
- if (!$this->simpleTables) {
24414
- if ($bord_det) {
24415
- $btlw = $bord_det['L']['w'];
24416
- $btrw = $bord_det['R']['w'];
24417
- $bttw = $bord_det['T']['w'];
24418
- } else {
24419
- $btlw = 0;
24420
- $btrw = 0;
24421
- $bttw = 0;
24422
- }
24423
- if ($table['borders_separate']) {
24424
- $xadj = $btlw + $cell['padding']['L'] + ($table['border_spacing_H'] / 2);
24425
- $wadj = $btlw + $btrw + $cell['padding']['L'] + $cell['padding']['R'] + $table['border_spacing_H'];
24426
- $yadj = $bttw + $cell['padding']['T'] + ($table['border_spacing_H'] / 2);
24427
- } else {
24428
- $xadj = $btlw / 2 + $cell['padding']['L'];
24429
- $wadj = ($btlw + $btrw) / 2 + $cell['padding']['L'] + $cell['padding']['R'];
24430
- $yadj = $bttw / 2 + $cell['padding']['T'];
24431
- }
24432
- } elseif ($this->simpleTables) {
24433
- if ($table['borders_separate']) { // NB twice border width
24434
- $xadj = $table['simple']['border_details']['L']['w'] + $cell['padding']['L'] + ($table['border_spacing_H'] / 2);
24435
- $wadj = $table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'] + $cell['padding']['L'] + $cell['padding']['R'] + $table['border_spacing_H'];
24436
- $yadj = $table['simple']['border_details']['T']['w'] + $cell['padding']['T'] + ($table['border_spacing_H'] / 2);
24437
  } else {
24438
- $xadj = $table['simple']['border_details']['L']['w'] / 2 + $cell['padding']['L'];
24439
- $wadj = ($table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w']) / 2 + $cell['padding']['L'] + $cell['padding']['R'];
24440
- $yadj = $table['simple']['border_details']['T']['w'] / 2 + $cell['padding']['T'];
24441
  }
24442
- }
24443
- $this->decimal_offset = 0;
24444
- if (substr($cell['a'], 0, 1) == 'D') {
24445
- if (isset($cell['colspan']) && $cell['colspan'] > 1) {
24446
- $this->cellTextAlign = $c['a'] = substr($cell['a'], 2, 1);
24447
  } else {
24448
- $smax = $table['decimal_align'][$j]['maxs0'];
24449
- $d_content = $table['decimal_align'][$j]['maxs0'] + $table['decimal_align'][$j]['maxs1'];
24450
- $this->decimal_offset = $smax;
24451
- $extra = ($w - $d_content - $wadj);
24452
- if ($extra > 0) {
24453
- if (substr($cell['a'], 2, 1) == 'R') {
24454
- $this->decimal_offset += $extra;
24455
- } elseif (substr($cell['a'], 2, 1) == 'C') {
24456
- $this->decimal_offset += ($extra) / 2;
24457
- }
24458
- }
24459
  }
24460
  }
24461
- $this->divwidth = $w - $wadj;
24462
- if ($this->divwidth == 0) {
24463
- $this->divwidth = 0.0001;
24464
- }
24465
- $this->x += $xadj;
24466
- $this->y += $yadj;
24467
- $this->printbuffer($cell['textbuffer'], '', true, false, $cell['direction']);
24468
  }
24469
- $this->y = $opy;
24470
  }
24471
 
24472
  /* -- BACKGROUNDS -- */
24473
- if (!$this->ColActive) {
24474
- if (isset($table['trgradients'][$i]) && ($j == 0 || $table['borders_separate'])) {
24475
- $g = $this->gradient->parseBackgroundGradient($table['trgradients'][$i]);
24476
- if ($g) {
24477
- $gx = $x0;
24478
- $gy = $y;
24479
- $gh = $h;
24480
- $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
24481
- if ($table['borders_separate']) {
24482
- $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
24483
- $clx = $x + ($table['border_spacing_H'] / 2);
24484
- $cly = $y + ($table['border_spacing_V'] / 2);
24485
- $clw = $w - $table['border_spacing_H'];
24486
- $clh = $h - $table['border_spacing_V'];
24487
- // Set clipping path
24488
- $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
24489
- $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s];
24490
- } else {
24491
- $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
24492
- }
24493
  }
24494
- }
24495
- if (isset($table['trbackground-images'][$i]) && ($j == 0 || $table['borders_separate'])) {
24496
- if (isset($table['trbackground-images'][$i]['gradient']) && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['trbackground-images'][$i]['gradient'])) {
24497
- $g = $this->gradient->parseMozGradient($table['trbackground-images'][$i]['gradient']);
24498
- if ($g) {
24499
- $gx = $x0;
24500
- $gy = $y;
24501
- $gh = $h;
24502
- $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
24503
- if ($table['borders_separate']) {
24504
- $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
24505
- $clx = $x + ($table['border_spacing_H'] / 2);
24506
- $cly = $y + ($table['border_spacing_V'] / 2);
24507
- $clw = $w - $table['border_spacing_H'];
24508
- $clh = $h - $table['border_spacing_V'];
24509
- // Set clipping path
24510
- $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
24511
- $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s];
24512
- } else {
24513
- $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
24514
- }
24515
- }
24516
  } else {
24517
- $image_id = $table['trbackground-images'][$i]['image_id'];
24518
- $orig_w = $table['trbackground-images'][$i]['orig_w'];
24519
- $orig_h = $table['trbackground-images'][$i]['orig_h'];
24520
- $x_pos = $table['trbackground-images'][$i]['x_pos'];
24521
- $y_pos = $table['trbackground-images'][$i]['y_pos'];
24522
- $x_repeat = $table['trbackground-images'][$i]['x_repeat'];
24523
- $y_repeat = $table['trbackground-images'][$i]['y_repeat'];
24524
- $resize = $table['trbackground-images'][$i]['resize'];
24525
- $opacity = $table['trbackground-images'][$i]['opacity'];
24526
- $itype = $table['trbackground-images'][$i]['itype'];
24527
- $clippath = '';
24528
- $gx = $x0;
24529
- $gy = $y;
24530
- $gh = $h;
24531
- $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
24532
  if ($table['borders_separate']) {
24533
- $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
24534
- $clx = $x + ($table['border_spacing_H'] / 2);
24535
- $cly = $y + ($table['border_spacing_V'] / 2);
24536
- $clw = $w - $table['border_spacing_H'];
24537
- $clh = $h - $table['border_spacing_V'];
24538
- // Set clipping path
24539
- $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
24540
- $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => $s, 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
24541
  } else {
24542
- $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24543
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
24544
  }
24545
  }
24546
  }
24547
-
24548
  /* -- END BACKGROUNDS -- */
24549
 
24550
- // TABLE BORDER - if separate
24551
- if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
24552
- $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H'] / 2);
24553
- $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H'] / 2);
24554
- $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V'] / 2);
24555
- $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V'] / 2);
24556
- $tbx = $x;
24557
- $tby = $y;
24558
- $tbw = $w;
24559
- $tbh = $h;
24560
- $tab_bord = 0;
24561
-
24562
- $corner = '';
24563
- if ($i == 0) { // Top
24564
- $tby -= $halfspaceT + ($table['border_details']['T']['w'] / 2);
24565
- $tbh += $halfspaceT + ($table['border_details']['T']['w'] / 2);
24566
- $this->setBorder($tab_bord, Border::TOP);
24567
- $corner .= 'T';
24568
- }
24569
- if ($i == ($numrows - 1) || (isset($cell['rowspan']) && ($i + $cell['rowspan']) == $numrows)) { // Bottom
24570
- $tbh += $halfspaceB + ($table['border_details']['B']['w'] / 2);
24571
- $this->setBorder($tab_bord, Border::BOTTOM);
24572
- $corner .= 'B';
24573
- }
24574
- if ($j == 0) { // Left
24575
- $tbx -= $halfspaceL + ($table['border_details']['L']['w'] / 2);
24576
- $tbw += $halfspaceL + ($table['border_details']['L']['w'] / 2);
24577
- $this->setBorder($tab_bord, Border::LEFT);
24578
- $corner .= 'L';
24579
- }
24580
- if ($j == ($numcols - 1) || (isset($cell['colspan']) && ($j + $cell['colspan']) == $numcols)) { // Right
24581
- $tbw += $halfspaceR + ($table['border_details']['R']['w'] / 2);
24582
- $this->setBorder($tab_bord, Border::RIGHT);
24583
- $corner .= 'R';
24584
- }
24585
- $this->_tableRect($tbx, $tby, $tbw, $tbh, $tab_bord, $table['border_details'], false, $table['borders_separate'], 'table', $corner, $table['border_spacing_V'], $table['border_spacing_H']);
24586
  }
24587
-
24588
- unset($cell);
24589
- // Reset values
24590
- $this->Reset();
24591
- }//end of (if isset(cells)...)
24592
- }// end of columns
24593
-
24594
- $newpagestarted = false;
24595
- $this->tabletheadjustfinished = false;
24596
-
24597
- /* -- COLUMNS -- */
24598
- if ($this->ColActive) {
24599
- if (!$this->table_keep_together && $i < $numrows - 1 && $level == 1) {
24600
- $this->breakpoints[$this->CurrCol][] = $y + $h;
24601
- } // mPDF 6
24602
- if (count($this->cellBorderBuffer)) {
24603
- $this->printcellbuffer();
24604
- }
24605
- }
24606
- /* -- END COLUMNS -- */
24607
-
24608
- if ($i == $numrows - 1) {
24609
- $this->y = $y + $h;
24610
- } // last row jump (update this->y position)
24611
- if ($this->table_rotate && $level == 1) {
24612
- $this->tbrot_h += $h;
24613
- }
24614
- } // end of rows
24615
-
24616
- if (count($this->cellBorderBuffer)) {
24617
- $this->printcellbuffer();
24618
- }
24619
-
24620
-
24621
- if ($this->tableClipPath) {
24622
- $this->_out("Q");
24623
- }
24624
- $this->tableClipPath = '';
24625
-
24626
- // Advance down page by half width of bottom border
24627
- if ($table['borders_separate']) {
24628
- $this->y += $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2;
24629
- } else {
24630
- $this->y += $table['max_cell_border_width']['B'] / 2;
24631
- }
24632
-
24633
- if ($table['borders_separate'] && $level == 1) {
24634
- $this->tbrot_h += $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2;
24635
- } elseif ($level == 1) {
24636
- $this->tbrot_h += $table['margin']['B'] + $table['max_cell_border_width']['B'] / 2;
24637
- }
24638
-
24639
- $bx = $x0;
24640
- $by = $y0;
24641
- if ($table['borders_separate']) {
24642
- $bx -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H'] / 2);
24643
- if ($tablestartpageno != $this->page) { // IF broken across page
24644
- $by += $table['max_cell_border_width']['T'] / 2;
24645
- if (empty($tableheader)) {
24646
- $by -= ($table['border_spacing_V'] / 2);
24647
- }
24648
- } elseif ($split && $startrow > 0 && empty($tableheader)) {
24649
- $by -= ($table['border_spacing_V'] / 2);
24650
- } else {
24651
- $by -= ($table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V'] / 2);
24652
- }
24653
- } elseif ($tablestartpageno != $this->page && !empty($tableheader)) {
24654
- $by += $maxbwtop / 2;
24655
- }
24656
- $by -= $tableheaderadj;
24657
- $bh = $this->y - $by;
24658
- if (!$table['borders_separate']) {
24659
- $bh -= $table['max_cell_border_width']['B'] / 2;
24660
- }
24661
-
24662
- if ($split) {
24663
- $bw = 0;
24664
- $finalSpread = true;
24665
- for ($t = $startcol; $t < $numcols; $t++) {
24666
- if ($table['colPg'][$t] == $splitpg) {
24667
- $bw += $table['wc'][$t];
24668
- }
24669
- if ($table['colPg'][$t] > $splitpg) {
24670
- $finalSpread = false;
24671
- break;
24672
- }
24673
- }
24674
- if ($startcol == 0) {
24675
- $firstSpread = true;
24676
- } else {
24677
- $firstSpread = false;
24678
- }
24679
- if ($table['borders_separate']) {
24680
- $bw += $table['border_spacing_H'];
24681
- if ($firstSpread) {
24682
- $bw += $table['padding']['L'] + $table['border_details']['L']['w'];
24683
- } else {
24684
- $bx += ($table['padding']['L'] + $table['border_details']['L']['w']);
24685
- }
24686
- if ($finalSpread) {
24687
- $bw += $table['padding']['R'] + $table['border_details']['R']['w'];
24688
- }
24689
- }
24690
- } else {
24691
- $bw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
24692
- }
24693
-
24694
- if (!$this->ColActive) {
24695
- if (isset($table['bgcolor'][-1])) {
24696
- $color = $this->colorConverter->convert($table['bgcolor'][-1], $this->PDFAXwarnings);
24697
- if ($color) {
24698
- $this->tableBackgrounds[$level * 9][] = ['gradient' => false, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'col' => $color];
24699
- }
24700
- }
24701
-
24702
- /* -- BACKGROUNDS -- */
24703
- if (isset($table['gradient'])) {
24704
- $g = $this->gradient->parseBackgroundGradient($table['gradient']);
24705
- if ($g) {
24706
- $this->tableBackgrounds[$level * 9 + 1][] = ['gradient' => true, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
24707
- }
24708
- }
24709
-
24710
- if (isset($table['background-image'])) {
24711
- if (isset($table['background-image']['gradient']) && $table['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['background-image']['gradient'])) {
24712
- $g = $this->gradient->parseMozGradient($table['background-image']['gradient']);
24713
- if ($g) {
24714
- $this->tableBackgrounds[$level * 9 + 1][] = ['gradient' => true, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
24715
  }
24716
- } else {
24717
- $image_id = $table['background-image']['image_id'];
24718
- $orig_w = $table['background-image']['orig_w'];
24719
- $orig_h = $table['background-image']['orig_h'];
24720
- $x_pos = $table['background-image']['x_pos'];
24721
- $y_pos = $table['background-image']['y_pos'];
24722
- $x_repeat = $table['background-image']['x_repeat'];
24723
- $y_repeat = $table['background-image']['y_repeat'];
24724
- $resize = $table['background-image']['resize'];
24725
- $opacity = $table['background-image']['opacity'];
24726
- $itype = $table['background-image']['itype'];
24727
- $this->tableBackgrounds[$level * 9 + 2][] = ['x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
24728
- }
24729
- }
24730
- /* -- END BACKGROUNDS -- */
24731
- }
24732
 
24733
- if ($this->tableBackgrounds && $level == 1) {
24734
- $s = $this->PrintTableBackgrounds();
24735
- if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
24736
- $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->tablebuffer);
24737
- if ($level == 1) {
24738
- $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->tablebuffer);
24739
- }
24740
- } elseif ($this->bufferoutput) {
24741
- $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->headerbuffer);
24742
- if ($level == 1) {
24743
- $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->headerbuffer);
24744
- }
24745
- } else {
24746
- $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->pages[$this->page]);
24747
- if ($level == 1) {
24748
- $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->pages[$this->page]);
24749
- }
24750
- }
24751
- $this->tableBackgrounds = [];
24752
- }
24753
 
24754
 
24755
- // TABLE BOTTOM MARGIN
24756
- if ($table['margin']['B']) {
24757
- if (!$this->table_rotate && $level == 1) {
24758
- $this->DivLn($table['margin']['B'], $this->blklvl, true); // collapsible
24759
- } else {
24760
- $this->y += ($table['margin']['B']);
24761
- }
24762
- }
 
 
 
 
 
 
 
 
 
 
 
 
24763
 
24764
- if ($this->ColActive && $level == 1) {
24765
- $this->breakpoints[$this->CurrCol][] = $this->y;
24766
- } // *COLUMNS*
 
 
 
 
24767
 
24768
- if ($split) {
24769
- // Are there more columns to print on a next page?
24770
- if ($lastCol < $numcols - 1) {
24771
- $splitpg++;
24772
- $startcol = $lastCol + 1;
24773
- return [false, $startrow, $startcol, $splitpg, $returny, $y0];
24774
- } else {
24775
- return [true, 0, 0, 0, false, false];
24776
- }
24777
- }
24778
- }
 
 
 
 
 
 
 
 
 
 
24779
 
24780
- // END OF FUNCTION _tableWrite()
24781
- /////////////////////////END OF TABLE CODE//////////////////////////////////
24782
- /* -- END TABLES -- */
 
 
 
 
 
24783
 
24784
- function _putextgstates()
24785
- {
24786
- for ($i = 1; $i <= count($this->extgstates); $i++) {
24787
- $this->_newobj();
24788
- $this->extgstates[$i]['n'] = $this->n;
24789
- $this->_out('<</Type /ExtGState');
24790
- foreach ($this->extgstates[$i]['parms'] as $k => $v) {
24791
- $this->_out('/' . $k . ' ' . $v);
24792
- }
24793
- $this->_out('>>');
24794
- $this->_out('endobj');
24795
- }
24796
- }
24797
 
24798
- function _putocg()
24799
- {
24800
- if ($this->hasOC) {
24801
- $this->_newobj();
24802
- $this->n_ocg_print = $this->n;
24803
- $this->_out('<</Type /OCG /Name ' . $this->_textstring('Print only'));
24804
- $this->_out('/Usage <</Print <</PrintState /ON>> /View <</ViewState /OFF>>>>>>');
24805
- $this->_out('endobj');
24806
- $this->_newobj();
24807
- $this->n_ocg_view = $this->n;
24808
- $this->_out('<</Type /OCG /Name ' . $this->_textstring('Screen only'));
24809
- $this->_out('/Usage <</Print <</PrintState /OFF>> /View <</ViewState /ON>>>>>>');
24810
- $this->_out('endobj');
24811
- $this->_newobj();
24812
- $this->n_ocg_hidden = $this->n;
24813
- $this->_out('<</Type /OCG /Name ' . $this->_textstring('Hidden'));
24814
- $this->_out('/Usage <</Print <</PrintState /OFF>> /View <</ViewState /OFF>>>>>>');
24815
- $this->_out('endobj');
24816
- }
24817
- if (count($this->layers)) {
24818
- ksort($this->layers);
24819
- foreach ($this->layers as $id => $layer) {
24820
- $this->_newobj();
24821
- $this->layers[$id]['n'] = $this->n;
24822
- if (isset($this->layerDetails[$id]['name']) && $this->layerDetails[$id]['name']) {
24823
- $name = $this->layerDetails[$id]['name'];
24824
- } else {
24825
- $name = $layer['name'];
24826
- }
24827
- $this->_out('<</Type /OCG /Name ' . $this->_UTF16BEtextstring($name) . '>>');
24828
- $this->_out('endobj');
24829
- }
24830
- }
24831
- }
24832
 
24833
- /* -- IMPORTS -- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24834
 
24835
- // from mPDFI
24836
- function _putimportedobjects()
24837
- {
24838
- if (is_array($this->parsers) && count($this->parsers) > 0) {
24839
- foreach ($this->parsers as $filename => $p) {
24840
- $this->current_parser = $this->parsers[$filename];
24841
- if (is_array($this->_obj_stack[$filename])) {
24842
- while ($n = key($this->_obj_stack[$filename])) {
24843
- $nObj = $this->current_parser->resolveObject($this->_obj_stack[$filename][$n][1]);
24844
- $this->_newobj($this->_obj_stack[$filename][$n][0]);
24845
- if ($nObj[0] == pdf_parser::TYPE_STREAM) {
24846
- $this->pdf_write_value($nObj);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24847
  } else {
24848
- $this->pdf_write_value($nObj[1]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24849
  }
24850
- $this->_out('endobj');
24851
- $this->_obj_stack[$filename][$n] = null; // free memory
24852
- unset($this->_obj_stack[$filename][$n]);
24853
- reset($this->_obj_stack[$filename]);
24854
  }
24855
- }
24856
- }
24857
- }
24858
- }
24859
-
24860
- function _putformxobjects()
24861
- {
24862
- $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
24863
- reset($this->tpls);
24864
- foreach ($this->tpls as $tplidx => $tpl) {
24865
- $p = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
24866
- $this->_newobj();
24867
- $this->tpls[$tplidx]['n'] = $this->n;
24868
- $this->_out('<<' . $filter . '/Type /XObject');
24869
- $this->_out('/Subtype /Form');
24870
- $this->_out('/FormType 1');
24871
- // Left/Bottom/Right/Top
24872
- $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', $tpl['box']['x'] * Mpdf::SCALE, $tpl['box']['y'] * Mpdf::SCALE, ($tpl['box']['x'] + $tpl['box']['w']) * Mpdf::SCALE, ($tpl['box']['y'] + $tpl['box']['h']) * Mpdf::SCALE));
24873
-
24874
-
24875
- if (isset($tpl['box'])) {
24876
- $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]', -$tpl['box']['x'] * Mpdf::SCALE, -$tpl['box']['y'] * Mpdf::SCALE));
24877
- }
24878
- $this->_out('/Resources ');
24879
 
24880
- if (isset($tpl['resources'])) {
24881
- $this->current_parser = $tpl['parser'];
24882
- $this->pdf_write_value($tpl['resources']);
24883
- } else {
24884
- $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
24885
- if (isset($this->_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) {
24886
- $this->_out('/Font <<');
24887
- foreach ($this->_res['tpl'][$tplidx]['fonts'] as $font) {
24888
- $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
24889
- }
24890
- $this->_out('>>');
24891
- }
24892
- if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) ||
24893
- isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) {
24894
- $this->_out('/XObject <<');
24895
- if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) {
24896
- foreach ($this->_res['tpl'][$tplidx]['images'] as $image) {
24897
- $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
 
 
 
 
24898
  }
24899
- }
24900
- if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) {
24901
- foreach ($this->_res['tpl'][$tplidx]['tpls'] as $i => $itpl) {
24902
- $this->_out($this->tplprefix . $i . ' ' . $itpl['n'] . ' 0 R');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24903
  }
24904
  }
24905
- $this->_out('>>');
24906
- }
24907
- $this->_out('>>');
24908
- }
24909
-
24910
- $this->_out('/Length ' . strlen($p) . ' >>');
24911
- $this->_putstream($p);
24912
- $this->_out('endobj');
24913
- }
24914
- }
24915
-
24916
- /* -- END IMPORTS -- */
24917
-
24918
- function _putpatterns()
24919
- {
24920
- for ($i = 1; $i <= count($this->patterns); $i++) {
24921
- $x = $this->patterns[$i]['x'];
24922
- $y = $this->patterns[$i]['y'];
24923
- $w = $this->patterns[$i]['w'];
24924
- $h = $this->patterns[$i]['h'];
24925
- $pgh = $this->patterns[$i]['pgh'];
24926
- $orig_w = $this->patterns[$i]['orig_w'];
24927
- $orig_h = $this->patterns[$i]['orig_h'];
24928
- $image_id = $this->patterns[$i]['image_id'];
24929
- $itype = $this->patterns[$i]['itype'];
24930
-
24931
- if (isset($this->patterns[$i]['bpa'])) {
24932
- $bpa = $this->patterns[$i]['bpa'];
24933
- } else {
24934
- $bpa = []; // background positioning area
24935
- }
24936
-
24937
- if ($this->patterns[$i]['x_repeat']) {
24938
- $x_repeat = true;
24939
- } else {
24940
- $x_repeat = false;
24941
- }
24942
-
24943
- if ($this->patterns[$i]['y_repeat']) {
24944
- $y_repeat = true;
24945
- } else {
24946
- $y_repeat = false;
24947
- }
24948
-
24949
- $x_pos = $this->patterns[$i]['x_pos'];
24950
 
24951
- if (stristr($x_pos, '%')) {
24952
- $x_pos = (float) $x_pos;
24953
- $x_pos /= 100;
24954
-
24955
- if (isset($bpa['w']) && $bpa['w']) {
24956
- $x_pos = ($bpa['w'] * $x_pos) - ($orig_w / Mpdf::SCALE * $x_pos);
24957
- } else {
24958
- $x_pos = ($w * $x_pos) - ($orig_w / Mpdf::SCALE * $x_pos);
24959
- }
24960
- }
24961
-
24962
- $y_pos = $this->patterns[$i]['y_pos'];
24963
-
24964
- if (stristr($y_pos, '%')) {
24965
- $y_pos = (float) $y_pos;
24966
- $y_pos /= 100;
24967
-
24968
- if (isset($bpa['h']) && $bpa['h']) {
24969
- $y_pos = ($bpa['h'] * $y_pos) - ($orig_h / Mpdf::SCALE * $y_pos);
24970
- } else {
24971
- $y_pos = ($h * $y_pos) - ($orig_h / Mpdf::SCALE * $y_pos);
24972
- }
24973
- }
24974
-
24975
- if (isset($bpa['x']) && $bpa['x']) {
24976
- $adj_x = ($x_pos + $bpa['x']) * Mpdf::SCALE;
24977
- } else {
24978
- $adj_x = ($x_pos + $x) * Mpdf::SCALE;
24979
- }
24980
-
24981
- if (isset($bpa['y']) && $bpa['y']) {
24982
- $adj_y = (($pgh - $y_pos - $bpa['y']) * Mpdf::SCALE) - $orig_h;
24983
- } else {
24984
- $adj_y = (($pgh - $y_pos - $y) * Mpdf::SCALE) - $orig_h;
24985
- }
24986
-
24987
- $img_obj = false;
24988
-
24989
- if ($itype == 'svg' || $itype == 'wmf') {
24990
- foreach ($this->formobjects as $fo) {
24991
- if ($fo['i'] == $image_id) {
24992
- $img_obj = $fo['n'];
24993
- $fo_w = $fo['w'];
24994
- $fo_h = -$fo['h'];
24995
- $wmf_x = $fo['x'];
24996
- $wmf_y = $fo['y'];
24997
- break;
24998
- }
24999
- }
25000
- } else {
25001
- foreach ($this->images as $img) {
25002
- if ($img['i'] == $image_id) {
25003
- $img_obj = $img['n'];
25004
- break;
25005
- }
25006
- }
25007
- }
25008
 
25009
- if (!$img_obj) {
25010
- throw new \Mpdf\MpdfException("Problem: Image object not found for background pattern " . $img['i']);
25011
- }
 
 
 
 
 
 
 
 
25012
 
25013
- $this->_newobj();
25014
- $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
25015
- if ($itype == 'svg' || $itype == 'wmf') {
25016
- $this->_out('/XObject <</FO' . $image_id . ' ' . $img_obj . ' 0 R >>');
25017
- // ******* ADD ANY ExtGStates, Shading AND Fonts needed for the FormObject
25018
- // Set in classes/svg array['fo'] = true
25019
- // Required that _putshaders comes before _putpatterns in _putresources
25020
- // This adds any resources associated with any FormObject to every Formobject - overkill but works!
25021
- if (count($this->extgstates)) {
25022
- $this->_out('/ExtGState <<');
25023
- foreach ($this->extgstates as $k => $extgstate) {
25024
- if (isset($extgstate['fo']) && $extgstate['fo']) {
25025
- if (isset($extgstate['trans'])) {
25026
- $this->_out('/' . $extgstate['trans'] . ' ' . $extgstate['n'] . ' 0 R');
25027
- } else {
25028
- $this->_out('/GS' . $k . ' ' . $extgstate['n'] . ' 0 R');
25029
- }
25030
  }
25031
- }
25032
- $this->_out('>>');
25033
- }
25034
- /* -- BACKGROUNDS -- */
25035
- if (isset($this->gradients) and ( count($this->gradients) > 0)) {
25036
- $this->_out('/Shading <<');
25037
- foreach ($this->gradients as $id => $grad) {
25038
- if (isset($grad['fo']) && $grad['fo']) {
25039
- $this->_out('/Sh' . $id . ' ' . $grad['id'] . ' 0 R');
25040
  }
25041
- }
25042
- $this->_out('>>');
25043
- }
25044
- /* -- END BACKGROUNDS -- */
25045
- $this->_out('/Font <<');
25046
- foreach ($this->fonts as $font) {
25047
- if (!$font['used'] && $font['type'] == 'TTF') {
25048
- continue;
25049
- }
25050
- if (isset($font['fo']) && $font['fo']) {
25051
- if ($font['type'] == 'TTF' && ($font['sip'] || $font['smp'])) {
25052
- foreach ($font['n'] as $k => $fid) {
25053
- $this->_out('/F' . $font['subsetfontids'][$k] . ' ' . $font['n'][$k] . ' 0 R');
25054
- }
25055
- } else {
25056
- $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
25057
  }
 
25058
  }
25059
- }
25060
- $this->_out('>>');
25061
- } else {
25062
- $this->_out('/XObject <</I' . $image_id . ' ' . $img_obj . ' 0 R >>');
25063
- }
25064
- $this->_out('>>');
25065
- $this->_out('endobj');
25066
-
25067
- $this->_newobj();
25068
- $this->patterns[$i]['n'] = $this->n;
25069
- $this->_out('<< /Type /Pattern /PatternType 1 /PaintType 1 /TilingType 2');
25070
- $this->_out('/Resources ' . ($this->n - 1) . ' 0 R');
25071
-
25072
- $this->_out(sprintf('/BBox [0 0 %.3F %.3F]', $orig_w, $orig_h));
25073
- if ($x_repeat) {
25074
- $this->_out(sprintf('/XStep %.3F', $orig_w));
25075
- } else {
25076
- $this->_out(sprintf('/XStep %d', 99999));
25077
- }
25078
- if ($y_repeat) {
25079
- $this->_out(sprintf('/YStep %.3F', $orig_h));
25080
- } else {
25081
- $this->_out(sprintf('/YStep %d', 99999));
25082
- }
25083
-
25084
- if ($itype == 'svg' || $itype == 'wmf') {
25085
- $this->_out(sprintf('/Matrix [1 0 0 -1 %.3F %.3F]', $adj_x, ($adj_y + $orig_h)));
25086
- $s = sprintf("q %.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q", ($orig_w / $fo_w), (-$orig_h / $fo_h), -($orig_w / $fo_w) * $wmf_x, ($orig_w / $fo_w) * $wmf_y, $image_id);
25087
- } else {
25088
- $this->_out(sprintf('/Matrix [1 0 0 1 %.3F %.3F]', $adj_x, $adj_y));
25089
- $s = sprintf("q %.3F 0 0 %.3F 0 0 cm /I%d Do Q", $orig_w, $orig_h, $image_id);
25090
- }
25091
 
25092
- if ($this->compress) {
25093
- $this->_out('/Filter /FlateDecode');
25094
- $s = gzcompress($s);
25095
- }
25096
- $this->_out('/Length ' . strlen($s) . '>>');
25097
- $this->_putstream($s);
25098
- $this->_out('endobj');
25099
- }
25100
- }
25101
 
25102
- /* -- BACKGROUNDS -- */
 
25103
 
25104
- function _putshaders()
25105
- {
25106
- $maxid = count($this->gradients); // index for transparency gradients
25107
- foreach ($this->gradients as $id => $grad) {
25108
- if (($grad['type'] == 2 || $grad['type'] == 3) && empty($grad['is_mask'])) {
25109
- $this->_newobj();
25110
- $this->_out('<<');
25111
- $this->_out('/FunctionType 3');
25112
- $this->_out('/Domain [0 1]');
25113
- $fn = [];
25114
- $bd = [];
25115
- $en = [];
25116
- for ($i = 0; $i < (count($grad['stops']) - 1); $i++) {
25117
- $fn[] = ($this->n + 1 + $i) . ' 0 R';
25118
- $en[] = '0 1';
25119
- if ($i > 0) {
25120
- $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']);
25121
- }
25122
- }
25123
- $this->_out('/Functions [' . implode(' ', $fn) . ']');
25124
- $this->_out('/Bounds [' . implode(' ', $bd) . ']');
25125
- $this->_out('/Encode [' . implode(' ', $en) . ']');
25126
- $this->_out('>>');
25127
- $this->_out('endobj');
25128
- $f1 = $this->n;
25129
- for ($i = 0; $i < (count($grad['stops']) - 1); $i++) {
25130
- $this->_newobj();
25131
- $this->_out('<<');
25132
- $this->_out('/FunctionType 2');
25133
- $this->_out('/Domain [0 1]');
25134
- $this->_out('/C0 [' . $grad['stops'][$i]['col'] . ']');
25135
- $this->_out('/C1 [' . $grad['stops'][$i + 1]['col'] . ']');
25136
- $this->_out('/N 1');
25137
- $this->_out('>>');
25138
- $this->_out('endobj');
25139
- }
25140
- }
25141
- if ($grad['type'] == 2 || $grad['type'] == 3) {
25142
- if (isset($grad['trans']) && $grad['trans']) {
25143
- $this->_newobj();
25144
- $this->_out('<<');
25145
- $this->_out('/FunctionType 3');
25146
- $this->_out('/Domain [0 1]');
25147
- $fn = [];
25148
- $bd = [];
25149
- $en = [];
25150
- for ($i = 0; $i < (count($grad['stops']) - 1); $i++) {
25151
- $fn[] = ($this->n + 1 + $i) . ' 0 R';
25152
- $en[] = '0 1';
25153
- if ($i > 0) {
25154
- $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']);
25155
- }
25156
- }
25157
- $this->_out('/Functions [' . implode(' ', $fn) . ']');
25158
- $this->_out('/Bounds [' . implode(' ', $bd) . ']');
25159
- $this->_out('/Encode [' . implode(' ', $en) . ']');
25160
- $this->_out('>>');
25161
- $this->_out('endobj');
25162
- $f2 = $this->n;
25163
- for ($i = 0; $i < (count($grad['stops']) - 1); $i++) {
25164
- $this->_newobj();
25165
- $this->_out('<<');
25166
- $this->_out('/FunctionType 2');
25167
- $this->_out('/Domain [0 1]');
25168
- $this->_out(sprintf('/C0 [%.3F]', $grad['stops'][$i]['opacity']));
25169
- $this->_out(sprintf('/C1 [%.3F]', $grad['stops'][$i + 1]['opacity']));
25170
- $this->_out('/N 1');
25171
- $this->_out('>>');
25172
- $this->_out('endobj');
25173
- }
25174
- }
25175
- }
25176
-
25177
- if (empty($grad['is_mask'])) {
25178
- $this->_newobj();
25179
- $this->_out('<<');
25180
- $this->_out('/ShadingType ' . $grad['type']);
25181
- if (isset($grad['colorspace'])) {
25182
- $this->_out('/ColorSpace /Device' . $grad['colorspace']); // Can use CMYK if all C0 and C1 above have 4 values
25183
- } else {
25184
- $this->_out('/ColorSpace /DeviceRGB');
25185
- }
25186
- if ($grad['type'] == 2) {
25187
- $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]));
25188
- $this->_out('/Function ' . $f1 . ' 0 R');
25189
- $this->_out('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] ');
25190
- $this->_out('>>');
25191
- } elseif ($grad['type'] == 3) {
25192
- // x0, y0, r0, x1, y1, r1
25193
- // at this this time radius of inner circle is 0
25194
- $ir = 0;
25195
- if (isset($grad['coords'][5]) && $grad['coords'][5]) {
25196
- $ir = $grad['coords'][5];
25197
- }
25198
- $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $ir, $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]));
25199
- $this->_out('/Function ' . $f1 . ' 0 R');
25200
- $this->_out('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] ');
25201
- $this->_out('>>');
25202
- } elseif ($grad['type'] == 6) {
25203
- $this->_out('/BitsPerCoordinate 16');
25204
- $this->_out('/BitsPerComponent 8');
25205
- if ($grad['colorspace'] == 'CMYK') {
25206
- $this->_out('/Decode[0 1 0 1 0 1 0 1 0 1 0 1]');
25207
- } elseif ($grad['colorspace'] == 'Gray') {
25208
- $this->_out('/Decode[0 1 0 1 0 1]');
25209
- } else {
25210
- $this->_out('/Decode[0 1 0 1 0 1 0 1 0 1]');
25211
- }
25212
- $this->_out('/BitsPerFlag 8');
25213
- $this->_out('/Length ' . strlen($grad['stream']));
25214
- $this->_out('>>');
25215
- $this->_putstream($grad['stream']);
25216
- }
25217
- $this->_out('endobj');
25218
- }
25219
-
25220
- $this->gradients[$id]['id'] = $this->n;
25221
-
25222
- // set pattern object
25223
- $this->_newobj();
25224
- $out = '<< /Type /Pattern /PatternType 2';
25225
- $out .= ' /Shading ' . $this->gradients[$id]['id'] . ' 0 R';
25226
- $out .= ' >>';
25227
- $out .= "\n" . 'endobj';
25228
- $this->_out($out);
25229
-
25230
-
25231
- $this->gradients[$id]['pattern'] = $this->n;
25232
-
25233
- if (isset($grad['trans']) && $grad['trans']) {
25234
- // luminosity pattern
25235
- $transid = $id + $maxid;
25236
- $this->_newobj();
25237
- $this->_out('<<');
25238
- $this->_out('/ShadingType ' . $grad['type']);
25239
- $this->_out('/ColorSpace /DeviceGray');
25240
- if ($grad['type'] == 2) {
25241
- $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]));
25242
- $this->_out('/Function ' . $f2 . ' 0 R');
25243
- $this->_out('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] ');
25244
- $this->_out('>>');
25245
- } elseif ($grad['type'] == 3) {
25246
- // x0, y0, r0, x1, y1, r1
25247
- // at this this time radius of inner circle is 0
25248
- $ir = 0;
25249
- if (isset($grad['coords'][5]) && $grad['coords'][5]) {
25250
- $ir = $grad['coords'][5];
25251
- }
25252
- $this->_out(sprintf('/Coords [%.3F %.3F %.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $ir, $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]));
25253
- $this->_out('/Function ' . $f2 . ' 0 R');
25254
- $this->_out('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] ');
25255
- $this->_out('>>');
25256
- } elseif ($grad['type'] == 6) {
25257
- $this->_out('/BitsPerCoordinate 16');
25258
- $this->_out('/BitsPerComponent 8');
25259
- $this->_out('/Decode[0 1 0 1 0 1]');
25260
- $this->_out('/BitsPerFlag 8');
25261
- $this->_out('/Length ' . strlen($grad['stream_trans']));
25262
- $this->_out('>>');
25263
- $this->_putstream($grad['stream_trans']);
25264
- }
25265
- $this->_out('endobj');
25266
-
25267
- $this->gradients[$transid]['id'] = $this->n;
25268
- $this->_newobj();
25269
- $this->_out('<< /Type /Pattern /PatternType 2');
25270
- $this->_out('/Shading ' . $this->gradients[$transid]['id'] . ' 0 R');
25271
- $this->_out('>>');
25272
- $this->_out('endobj');
25273
- $this->gradients[$transid]['pattern'] = $this->n;
25274
- $this->_newobj();
25275
- // Need to extend size of viewing box in case of transformations
25276
- $str = 'q /a0 gs /Pattern cs /p' . $transid . ' scn -' . ($this->wPt / 2) . ' -' . ($this->hPt / 2) . ' ' . (2 * $this->wPt) . ' ' . (2 * $this->hPt) . ' re f Q';
25277
- $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
25278
- $p = ($this->compress) ? gzcompress($str) : $str;
25279
- $this->_out('<< /Type /XObject /Subtype /Form /FormType 1 ' . $filter);
25280
- $this->_out('/Length ' . strlen($p));
25281
- $this->_out('/BBox [-' . ($this->wPt / 2) . ' -' . ($this->hPt / 2) . ' ' . (2 * $this->wPt) . ' ' . (2 * $this->hPt) . ']');
25282
- $this->_out('/Group << /Type /Group /S /Transparency /CS /DeviceGray >>');
25283
- $this->_out('/Resources <<');
25284
- $this->_out('/ExtGState << /a0 << /ca 1 /CA 1 >> >>');
25285
- $this->_out('/Pattern << /p' . $transid . ' ' . $this->gradients[$transid]['pattern'] . ' 0 R >>');
25286
- $this->_out('>>');
25287
- $this->_out('>>');
25288
- $this->_putstream($p);
25289
- $this->_out('endobj');
25290
- $this->_newobj();
25291
- $this->_out('<< /Type /Mask /S /Luminosity /G ' . ($this->n - 1) . ' 0 R >>' . "\n" . 'endobj');
25292
- $this->_newobj();
25293
- $this->_out('<< /Type /ExtGState /SMask ' . ($this->n - 1) . ' 0 R /AIS false >>' . "\n" . 'endobj');
25294
- if (isset($grad['fo']) && $grad['fo']) {
25295
- $this->extgstates[] = ['n' => $this->n, 'trans' => 'TGS' . $id, 'fo' => true];
25296
- } else {
25297
- $this->extgstates[] = ['n' => $this->n, 'trans' => 'TGS' . $id];
25298
  }
25299
  }
25300
- }
25301
- }
25302
-
25303
- /* -- END BACKGROUNDS -- */
25304
-
25305
- function _putspotcolors()
25306
- {
25307
- foreach ($this->spotColors as $name => $color) {
25308
- $this->_newobj();
25309
- $this->_out('[/Separation /' . str_replace(' ', '#20', $name));
25310
- $this->_out('/DeviceCMYK <<');
25311
- $this->_out('/Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] ');
25312
- $this->_out(sprintf('/C1 [%.3F %.3F %.3F %.3F] ', $color['c'] / 100, $color['m'] / 100, $color['y'] / 100, $color['k'] / 100));
25313
- $this->_out('/FunctionType 2 /Domain [0 1] /N 1>>]');
25314
- $this->_out('endobj');
25315
- $this->spotColors[$name]['n'] = $this->n;
25316
- }
25317
- }
25318
-
25319
- function _putresources()
25320
- {
25321
- if ($this->hasOC || count($this->layers)) {
25322
- $this->_putocg();
25323
- }
25324
- $this->_putextgstates();
25325
- $this->_putspotcolors();
25326
-
25327
- // @log Compiling Fonts
25328
 
25329
- $this->_putfonts();
 
 
 
 
 
 
25330
 
25331
- // @log Compiling Images
 
 
25332
 
25333
- $this->_putimages();
25334
- $this->_putformobjects(); // *IMAGES-CORE*
25335
 
25336
- /* -- IMPORTS -- */
25337
- if ($this->enableImports) {
25338
- $this->_putformxobjects();
25339
- $this->_putimportedobjects();
25340
  }
25341
- /* -- END IMPORTS -- */
25342
-
25343
- /* -- BACKGROUNDS -- */
25344
- $this->_putshaders();
25345
- $this->_putpatterns();
25346
- /* -- END BACKGROUNDS -- */
25347
 
 
 
 
 
 
 
25348
 
25349
- // Resource dictionary
25350
- $this->offsets[2] = strlen($this->buffer);
25351
- $this->_out('2 0 obj');
25352
- $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
 
25353
 
25354
- $this->_out('/Font <<');
25355
- foreach ($this->fonts as $font) {
25356
- if (isset($font['type']) && $font['type'] == 'TTF' && !$font['used']) {
25357
- continue;
25358
- }
25359
- if (isset($font['type']) && $font['type'] == 'TTF' && ($font['sip'] || $font['smp'])) {
25360
- foreach ($font['n'] as $k => $fid) {
25361
- $this->_out('/F' . $font['subsetfontids'][$k] . ' ' . $font['n'][$k] . ' 0 R');
25362
  }
 
 
25363
  } else {
25364
- $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
25365
  }
 
 
25366
  }
25367
- $this->_out('>>');
25368
-
25369
- if (count($this->spotColors)) {
25370
- $this->_out('/ColorSpace <<');
25371
- foreach ($this->spotColors as $color) {
25372
- $this->_out('/CS' . $color['i'] . ' ' . $color['n'] . ' 0 R');
25373
- }
25374
- $this->_out('>>');
25375
  }
25376
 
25377
- if (count($this->extgstates)) {
25378
- $this->_out('/ExtGState <<');
25379
- foreach ($this->extgstates as $k => $extgstate) {
25380
- if (isset($extgstate['trans'])) {
25381
- $this->_out('/' . $extgstate['trans'] . ' ' . $extgstate['n'] . ' 0 R');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25382
  } else {
25383
- $this->_out('/GS' . $k . ' ' . $extgstate['n'] . ' 0 R');
 
 
 
25384
  }
25385
  }
25386
- $this->_out('>>');
 
25387
  }
25388
 
25389
- /* -- BACKGROUNDS -- */
25390
- if ((isset($this->gradients) and ( count($this->gradients) > 0)) || ($this->enableImports && count($this->tpls))) { // mPDF 5.7.3
25391
-
25392
- $this->_out('/Shading <<');
25393
-
25394
- foreach ($this->gradients as $id => $grad) {
25395
- $this->_out('/Sh' . $id . ' ' . $grad['id'] . ' 0 R');
25396
  }
25397
 
25398
- // mPDF 5.7.3
25399
- // If a shading dictionary is in an object (tpl) imported from another PDF, it needs to be included
25400
- // in the document resources, as well as the object resources
25401
- // Otherwise get an error in some PDF viewers
25402
- if ($this->enableImports && count($this->tpls)) {
25403
-
25404
- foreach ($this->tpls as $tplidx => $tpl) {
25405
-
25406
- if (isset($tpl['resources'])) {
25407
-
25408
- $this->current_parser = $tpl['parser'];
25409
 
25410
- foreach ($tpl['resources'][1] as $k => $v) {
25411
- if ($k == '/Shading') {
25412
- foreach ($v[1] as $k2 => $v2) {
25413
- $this->_out($k2 . " ", false);
25414
- $this->pdf_write_value($v2);
25415
- }
25416
- }
25417
- }
25418
  }
 
 
 
 
 
 
 
 
 
 
 
 
25419
  }
25420
  }
25421
-
25422
- $this->_out('>>');
25423
-
25424
- /*
25425
- // ??? Not needed !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
25426
- $this->_out('/Pattern <<');
25427
- foreach ($this->gradients as $id => $grad) {
25428
- $this->_out('/P'.$id.' '.$grad['pattern'].' 0 R');
25429
- }
25430
- $this->_out('>>');
25431
- */
25432
  }
25433
- /* -- END BACKGROUNDS -- */
25434
 
25435
- if (count($this->images) || count($this->formobjects) || ($this->enableImports && count($this->tpls))) {
25436
- $this->_out('/XObject <<');
25437
- foreach ($this->images as $image) {
25438
- $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
25439
- }
25440
- foreach ($this->formobjects as $formobject) {
25441
- $this->_out('/FO' . $formobject['i'] . ' ' . $formobject['n'] . ' 0 R');
25442
- }
25443
- /* -- IMPORTS -- */
25444
- if ($this->enableImports && count($this->tpls)) {
25445
- foreach ($this->tpls as $tplidx => $tpl) {
25446
- $this->_out($this->tplprefix . $tplidx . ' ' . $tpl['n'] . ' 0 R');
 
 
 
 
25447
  }
25448
  }
25449
- /* -- END IMPORTS -- */
25450
- $this->_out('>>');
25451
  }
25452
 
25453
- /* -- BACKGROUNDS -- */
25454
-
25455
- if (count($this->patterns)) {
25456
- $this->_out('/Pattern <<');
25457
- foreach ($this->patterns as $k => $patterns) {
25458
- $this->_out('/P' . $k . ' ' . $patterns['n'] . ' 0 R');
25459
- }
25460
- $this->_out('>>');
25461
- }
25462
- /* -- END BACKGROUNDS -- */
25463
 
25464
- if ($this->hasOC || count($this->layers)) {
25465
- $this->_out('/Properties <<');
25466
- if ($this->hasOC) {
25467
- $this->_out('/OC1 ' . $this->n_ocg_print . ' 0 R /OC2 ' . $this->n_ocg_view . ' 0 R /OC3 ' . $this->n_ocg_hidden . ' 0 R ');
25468
- }
25469
- if (count($this->layers)) {
25470
- foreach ($this->layers as $id => $layer) {
25471
- $this->_out('/ZI' . $id . ' ' . $layer['n'] . ' 0 R');
25472
- }
25473
  }
25474
- $this->_out('>>');
25475
  }
25476
 
25477
- $this->_out('>>');
25478
- $this->_out('endobj'); // end resource dictionary
25479
-
25480
- $this->_putbookmarks();
25481
-
25482
- if (isset($this->js) && $this->js) {
25483
- $this->_putjavascript();
25484
- }
25485
 
25486
- if ($this->encrypted) {
25487
- $this->_newobj();
25488
- $this->enc_obj_id = $this->n;
25489
- $this->_out('<<');
25490
- $this->_putencryption();
25491
- $this->_out('>>');
25492
- $this->_out('endobj');
 
 
25493
  }
25494
  }
25495
 
25496
- function _putjavascript()
25497
- {
25498
- $this->_newobj();
25499
- $this->n_js = $this->n;
25500
- $this->_out('<<');
25501
- $this->_out('/Names [(EmbeddedJS) ' . (1 + $this->n) . ' 0 R ]');
25502
- $this->_out('>>');
25503
- $this->_out('endobj');
25504
-
25505
- $this->_newobj();
25506
- $this->_out('<<');
25507
- $this->_out('/S /JavaScript');
25508
- $this->_out('/JS ' . $this->_textstring($this->js));
25509
- $this->_out('>>');
25510
- $this->_out('endobj');
25511
- }
25512
-
25513
- function _putencryption()
25514
- {
25515
- $this->_out('/Filter /Standard');
25516
- if ($this->protection->getUseRC128Encryption()) {
25517
- $this->_out('/V 2');
25518
- $this->_out('/R 3');
25519
- $this->_out('/Length 128');
25520
- } else {
25521
- $this->_out('/V 1');
25522
- $this->_out('/R 2');
25523
- }
25524
- $this->_out('/O (' . $this->_escape($this->protection->getOValue()) . ')');
25525
- $this->_out('/U (' . $this->_escape($this->protection->getUvalue()) . ')');
25526
- $this->_out('/P ' . $this->protection->getPvalue());
25527
- }
25528
 
25529
- function _puttrailer()
25530
  {
25531
- $this->_out('/Size ' . ($this->n + 1));
25532
- $this->_out('/Root ' . $this->n . ' 0 R');
25533
- $this->_out('/Info ' . $this->InfoRoot . ' 0 R');
25534
-
25535
- if ($this->encrypted) {
25536
- $this->_out('/Encrypt ' . $this->enc_obj_id . ' 0 R');
25537
- $this->_out('/ID [<' . $this->protection->getUniqid() . '> <' . $this->protection->getUniqid() . '>]');
25538
- } else {
25539
- $uniqid = md5(time() . $this->buffer);
25540
- $this->_out('/ID [<' . $uniqid . '> <' . $uniqid . '>]');
25541
  }
25542
  }
25543
 
25544
  function SetProtection($permissions = [], $user_pass = '', $owner_pass = null, $length = 40)
25545
  {
25546
- if (!$this->protection) {
25547
- $this->protection = new Protection(new UniqidGenerator());
25548
- }
25549
-
25550
  $this->encrypted = $this->protection->setProtection($permissions, $user_pass, $owner_pass, $length);
25551
  }
25552
 
25553
  // =========================================
25554
- /* -- BOOKMARKS -- */
25555
  // FROM class PDF_Bookmark
25556
  function Bookmark($txt, $level = 0, $y = 0)
25557
  {
@@ -25566,132 +22951,24 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
25566
  $y = $this->y0;
25567
  } // If columns are on - mark top of columns
25568
  }
 
25569
  // else y is used as set, or =0 i.e. top of page
25570
  // DIRECTIONALITY RTL
25571
  $bmo = ['t' => $txt, 'l' => $level, 'y' => $y, 'p' => $this->page];
 
25572
  if ($this->keep_block_together) {
25573
  // do nothing
25574
- } /* -- TABLES -- */ elseif ($this->table_rotate) {
25575
  $this->tbrot_BMoutlines[] = $bmo;
25576
  } elseif ($this->kwt) {
25577
  $this->kwt_BMoutlines[] = $bmo;
25578
- } /* -- END TABLES -- */ elseif ($this->ColActive) { // *COLUMNS*
25579
- $this->col_BMoutlines[] = $bmo; // *COLUMNS*
25580
- } // *COLUMNS*
25581
- else {
25582
  $this->BMoutlines[] = $bmo;
25583
  }
25584
  }
25585
 
25586
- function _putbookmarks()
25587
- {
25588
- $nb = count($this->BMoutlines);
25589
- if ($nb == 0) {
25590
- return;
25591
- }
25592
-
25593
- $bmo = $this->BMoutlines;
25594
- $this->BMoutlines = [];
25595
- $lastlevel = -1;
25596
- for ($i = 0; $i < count($bmo); $i++) {
25597
- if ($bmo[$i]['l'] > 0) {
25598
- while ($bmo[$i]['l'] - $lastlevel > 1) { // If jump down more than one level, insert a new entry
25599
- $new = $bmo[$i];
25600
- $new['t'] = "[" . $new['t'] . "]"; // Put [] around text/title to highlight
25601
- $new['l'] = $lastlevel + 1;
25602
- $lastlevel++;
25603
- $this->BMoutlines[] = $new;
25604
- }
25605
- }
25606
- $this->BMoutlines[] = $bmo[$i];
25607
- $lastlevel = $bmo[$i]['l'];
25608
- }
25609
- $nb = count($this->BMoutlines);
25610
-
25611
- $lru = [];
25612
- $level = 0;
25613
- foreach ($this->BMoutlines as $i => $o) {
25614
- if ($o['l'] > 0) {
25615
- $parent = $lru[$o['l'] - 1];
25616
- // Set parent and last pointers
25617
- $this->BMoutlines[$i]['parent'] = $parent;
25618
- $this->BMoutlines[$parent]['last'] = $i;
25619
- if ($o['l'] > $level) {
25620
- // Level increasing: set first pointer
25621
- $this->BMoutlines[$parent]['first'] = $i;
25622
- }
25623
- } else {
25624
- $this->BMoutlines[$i]['parent'] = $nb;
25625
- }
25626
- if ($o['l'] <= $level and $i > 0) {
25627
- // Set prev and next pointers
25628
- $prev = $lru[$o['l']];
25629
- $this->BMoutlines[$prev]['next'] = $i;
25630
- $this->BMoutlines[$i]['prev'] = $prev;
25631
- }
25632
- $lru[$o['l']] = $i;
25633
- $level = $o['l'];
25634
- }
25635
-
25636
-
25637
- // Outline items
25638
- $n = $this->n + 1;
25639
- foreach ($this->BMoutlines as $i => $o) {
25640
- $this->_newobj();
25641
- $this->_out('<</Title ' . $this->_UTF16BEtextstring($o['t']));
25642
- $this->_out('/Parent ' . ($n + $o['parent']) . ' 0 R');
25643
- if (isset($o['prev'])) {
25644
- $this->_out('/Prev ' . ($n + $o['prev']) . ' 0 R');
25645
- }
25646
- if (isset($o['next'])) {
25647
- $this->_out('/Next ' . ($n + $o['next']) . ' 0 R');
25648
- }
25649
- if (isset($o['first'])) {
25650
- $this->_out('/First ' . ($n + $o['first']) . ' 0 R');
25651
- }
25652
- if (isset($o['last'])) {
25653
- $this->_out('/Last ' . ($n + $o['last']) . ' 0 R');
25654
- }
25655
-
25656
-
25657
- if (isset($this->pageDim[$o['p']]['h'])) {
25658
- $h = $this->pageDim[$o['p']]['h'];
25659
- } else {
25660
- $h = 0;
25661
- }
25662
-
25663
- $this->_out(sprintf('/Dest [%d 0 R /XYZ 0 %.3F null]', 1 + 2 * ($o['p']), ($h - $o['y']) * Mpdf::SCALE));
25664
- if (isset($this->bookmarkStyles) && isset($this->bookmarkStyles[$o['l']])) {
25665
- // font style
25666
- $bms = $this->bookmarkStyles[$o['l']]['style'];
25667
- $style = 0;
25668
- if (strpos($bms, 'B') !== false) {
25669
- $style += 2;
25670
- }
25671
- if (strpos($bms, 'I') !== false) {
25672
- $style += 1;
25673
- }
25674
- $this->_out(sprintf('/F %d', $style));
25675
- // Colour
25676
- $col = $this->bookmarkStyles[$o['l']]['color'];
25677
- if (isset($col) && is_array($col) && count($col) == 3) {
25678
- $this->_out(sprintf('/C [%.3F %.3F %.3F]', ($col[0] / 255), ($col[1] / 255), ($col[2] / 255)));
25679
- }
25680
- }
25681
-
25682
- $this->_out('/Count 0>>');
25683
- $this->_out('endobj');
25684
- }
25685
- // Outline root
25686
- $this->_newobj();
25687
- $this->OutlineRoot = $this->n;
25688
- $this->_out('<</Type /BMoutlines /First ' . $n . ' 0 R');
25689
- $this->_out('/Last ' . ($n + $lru[0]) . ' 0 R>>');
25690
- $this->_out('endobj');
25691
- }
25692
-
25693
- /* -- END BOOKMARKS -- */
25694
-
25695
  /**
25696
  * Initiate, and Mark a place for the Table of Contents to be inserted
25697
  */
@@ -27671,10 +24948,10 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
27671
 
27672
  $h = $this->h;
27673
 
27674
- $this->_out(sprintf('%.3F %.3F m %.3F %.3F %.3F %.3F %.3F %.3F c', ($x + $rx) * Mpdf::SCALE, ($h - $y) * Mpdf::SCALE, ($x + $rx) * Mpdf::SCALE, ($h - ($y - $ly)) * Mpdf::SCALE, ($x + $lx) * Mpdf::SCALE, ($h - ($y - $ry)) * Mpdf::SCALE, $x * Mpdf::SCALE, ($h - ($y - $ry)) * Mpdf::SCALE));
27675
- $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c', ($x - $lx) * Mpdf::SCALE, ($h - ($y - $ry)) * Mpdf::SCALE, ($x - $rx) * Mpdf::SCALE, ($h - ($y - $ly)) * Mpdf::SCALE, ($x - $rx) * Mpdf::SCALE, ($h - $y) * Mpdf::SCALE));
27676
- $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c', ($x - $rx) * Mpdf::SCALE, ($h - ($y + $ly)) * Mpdf::SCALE, ($x - $lx) * Mpdf::SCALE, ($h - ($y + $ry)) * Mpdf::SCALE, $x * Mpdf::SCALE, ($h - ($y + $ry)) * Mpdf::SCALE));
27677
- $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c %s', ($x + $lx) * Mpdf::SCALE, ($h - ($y + $ry)) * Mpdf::SCALE, ($x + $rx) * Mpdf::SCALE, ($h - ($y + $ly)) * Mpdf::SCALE, ($x + $rx) * Mpdf::SCALE, ($h - $y) * Mpdf::SCALE, $op));
27678
  }
27679
 
27680
  /* -- DIRECTW -- */
@@ -28589,7 +25866,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
28589
  $xtra = $fbwi - $sz;
28590
  $charspacing = $xtra / (strlen($codestr) - 1);
28591
  if ($charspacing) {
28592
- $this->_out(sprintf('BT %.3F Tc ET', $charspacing * Mpdf::SCALE));
28593
  }
28594
  }
28595
 
@@ -28597,7 +25874,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
28597
  $this->Cell($fbw, $codestr_fontsize, $codestr);
28598
 
28599
  if ($charspacing) {
28600
- $this->_out('BT 0 Tc ET');
28601
  }
28602
  }
28603
 
@@ -28690,7 +25967,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
28690
  $xtra = $textw - ($cw * $chars);
28691
  $charspacing = $xtra / ($chars - 1);
28692
  if ($charspacing) {
28693
- $this->_out(sprintf('BT %.3F Tc ET', $charspacing * Mpdf::SCALE));
28694
  }
28695
 
28696
  if ($bgcol) {
@@ -28712,7 +25989,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
28712
  $this->Cell($textw, $num_height, $charRI, 0, 0, '', 1);
28713
 
28714
  if ($charspacing) {
28715
- $this->_out('BT 0 Tc ET');
28716
  }
28717
 
28718
  // Outer Right character
@@ -28893,7 +26170,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
28893
  if ($returnstring) {
28894
  return('q');
28895
  } else {
28896
- $this->_out('q');
28897
  }
28898
  }
28899
 
@@ -28902,7 +26179,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
28902
  if ($returnstring) {
28903
  return('Q');
28904
  } else {
28905
- $this->_out('Q');
28906
  }
28907
  }
28908
 
@@ -29033,7 +26310,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
29033
  if ($returnstring) {
29034
  return(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5]));
29035
  } else {
29036
- $this->_out(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5]));
29037
  }
29038
  }
29039
 
@@ -29459,106 +26736,42 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
29459
  return current(unpack("H*", $str));
29460
  }
29461
 
29462
- /**
29463
- * Un-escapes a PDF string
29464
- *
29465
- * @param string $s
29466
- * @return string
29467
- */
29468
- function _unescape($s)
29469
- {
29470
- $out = '';
29471
- for ($count = 0, $n = strlen($s); $count < $n; $count++) {
29472
- if ($s[$count] != '\\' || $count == $n-1) {
29473
- $out .= $s[$count];
29474
- } else {
29475
- switch ($s[++$count]) {
29476
- case ')':
29477
- case '(':
29478
- case '\\':
29479
- $out .= $s[$count];
29480
- break;
29481
- case 'f':
29482
- $out .= chr(0x0C);
29483
- break;
29484
- case 'b':
29485
- $out .= chr(0x08);
29486
- break;
29487
- case 't':
29488
- $out .= chr(0x09);
29489
- break;
29490
- case 'r':
29491
- $out .= chr(0x0D);
29492
- break;
29493
- case 'n':
29494
- $out .= chr(0x0A);
29495
- break;
29496
- case "\r":
29497
- if ($count != $n-1 && $s[$count+1] == "\n") {
29498
- $count++;
29499
- }
29500
- break;
29501
- case "\n":
29502
- break;
29503
- default:
29504
- // Octal-Values
29505
- if (ord($s[$count]) >= ord('0') &&
29506
- ord($s[$count]) <= ord('9')) {
29507
- $oct = ''. $s[$count];
29508
- if (ord($s[$count+1]) >= ord('0') &&
29509
- ord($s[$count+1]) <= ord('9')) {
29510
- $oct .= $s[++$count];
29511
- if (ord($s[$count+1]) >= ord('0') &&
29512
- ord($s[$count+1]) <= ord('9')) {
29513
- $oct .= $s[++$count];
29514
- }
29515
- }
29516
- $out .= chr(octdec($oct));
29517
- } else {
29518
- $out .= $s[$count];
29519
- }
29520
- }
29521
- }
29522
- }
29523
- return $out;
29524
- }
29525
-
29526
  function pdf_write_value(&$value)
29527
  {
29528
  switch ($value[0]) {
29529
  case pdf_parser::TYPE_TOKEN:
29530
- $this->_out($value[1] . ' ', false);
29531
  break;
29532
 
29533
  case pdf_parser::TYPE_NUMERIC:
29534
  case pdf_parser::TYPE_REAL:
29535
  if (is_float($value[1]) && $value[1] != 0) {
29536
- $this->_out(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' ', false);
29537
  } else {
29538
- $this->_out($value[1] . ' ', false);
29539
  }
29540
  break;
29541
 
29542
  case pdf_parser::TYPE_ARRAY:
29543
  // An array. Output the proper
29544
  // structure and move on.
29545
- $this->_out("[", false);
29546
  for ($i = 0; $i < count($value[1]); $i++) {
29547
  $this->pdf_write_value($value[1][$i]);
29548
  }
29549
- $this->_out("]");
29550
  break;
29551
 
29552
  case pdf_parser::TYPE_DICTIONARY:
29553
  // A dictionary.
29554
- $this->_out("<<", false);
29555
 
29556
  foreach ($value[1] as $k => $v) {
29557
- $this->_out($k . ' ', false);
29558
  $this->pdf_write_value($v);
29559
  }
29560
 
29561
- $this->_out(">>");
29562
  break;
29563
 
29564
  case pdf_parser::TYPE_OBJREF:
@@ -29566,22 +26779,22 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
29566
  // Fill the object stack if needed
29567
  $cpfn = $this->current_parser->filename;
29568
  if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) {
29569
- $this->_newobj(false, true);
29570
  $this->_obj_stack[$cpfn][$value[1]] = [$this->n, $value];
29571
  $this->_don_obj_stack[$cpfn][$value[1]] = [$this->n, $value];
29572
  }
29573
  $objid = $this->_don_obj_stack[$cpfn][$value[1]][0];
29574
- $this->_out("{$objid} 0 R"); // {$value[2]}
29575
  break;
29576
 
29577
  case pdf_parser::TYPE_STRING:
29578
  if ($this->encrypted) {
29579
- $value[1] = $this->_unescape($value[1]);
29580
  $value[1] = $this->protection->rc4($this->protection->objectKey($this->_current_obj_id), $value[1]);
29581
- $value[1] = $this->_escape($value[1]);
29582
  }
29583
  // A string.
29584
- $this->_out('(' . $value[1] . ')');
29585
  break;
29586
 
29587
  case pdf_parser::TYPE_STREAM:
@@ -29592,9 +26805,9 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
29592
  if ($this->encrypted) {
29593
  $value[2][1] = $this->protection->rc4($this->protection->objectKey($this->_current_obj_id), $value[2][1]);
29594
  }
29595
- $this->_out("stream");
29596
- $this->_out($value[2][1]);
29597
- $this->_out("endstream");
29598
  break;
29599
 
29600
  case pdf_parser::TYPE_HEX:
@@ -29604,16 +26817,16 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
29604
  // remake hexstring of encrypted string
29605
  $value[1] = $this->str2hex($value[1]);
29606
  }
29607
- $this->_out("<" . $value[1] . ">");
29608
  break;
29609
 
29610
  case pdf_parser::TYPE_BOOLEAN:
29611
- $this->_out($value[1] ? 'true' : 'false');
29612
  break;
29613
 
29614
  case pdf_parser::TYPE_NULL:
29615
  // The null object.
29616
- $this->_out("null");
29617
  break;
29618
  }
29619
  }
@@ -29634,15 +26847,15 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
29634
 
29635
  if (!$this->onlyCoreFonts && !$this->usingCoreFont) {
29636
  foreach ($search as $k => $val) {
29637
- $search[$k] = $this->UTF8ToUTF16BE($search[$k], false);
29638
- $search[$k] = $this->_escape($search[$k]);
29639
- $replacement[$k] = $this->UTF8ToUTF16BE($replacement[$k], false);
29640
- $replacement[$k] = $this->_escape($replacement[$k]);
29641
  }
29642
  } else {
29643
  foreach ($replacement as $k => $val) {
29644
  $replacement[$k] = mb_convert_encoding($replacement[$k], $this->mb_enc, 'utf-8');
29645
- $replacement[$k] = $this->_escape($replacement[$k]);
29646
  }
29647
  }
29648
 
@@ -30015,12 +27228,12 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
30015
  // JAVASCRIPT
30016
  function _set_object_javascript($string)
30017
  {
30018
- $this->_newobj();
30019
- $this->_out('<<');
30020
- $this->_out('/S /JavaScript ');
30021
- $this->_out('/JS ' . $this->_textstring($string));
30022
- $this->_out('>>');
30023
- $this->_out('endobj');
30024
  }
30025
 
30026
  function SetJS($script)
@@ -30056,4 +27269,12 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface
30056
  return $this->fontDescriptor;
30057
  }
30058
 
 
 
 
 
 
 
 
 
30059
  }
5
  use fpdi_pdf_parser;
6
  use pdf_parser;
7
 
8
+ use Mpdf\Strict;
9
+
10
  use Mpdf\Config\ConfigVariables;
11
  use Mpdf\Config\FontVariables;
12
 
 
 
 
 
13
  use Mpdf\Conversion;
14
 
15
  use Mpdf\Css\Border;
16
  use Mpdf\Css\TextVars;
17
 
 
 
 
 
 
18
  use Mpdf\Log\Context as LogContext;
19
 
 
 
20
  use Mpdf\Fonts\MetricsGenerator;
21
 
22
  use Mpdf\Output\Destination;
23
 
 
 
 
24
  use Mpdf\QrCode;
25
 
26
  use Mpdf\Utils\Arrays;
 
27
  use Mpdf\Utils\NumericString;
28
  use Mpdf\Utils\UtfString;
29
 
36
  * based on FPDF by Olivier Plathey
37
  * and HTML2FPDF by Renato Coelho
38
  *
 
39
  * @license GPL-2.0
40
  */
41
  class Mpdf implements \Psr\Log\LoggerAwareInterface
42
  {
43
 
44
+ use Strict;
45
+
46
+ const VERSION = '7.1.6';
47
 
48
  const SCALE = 72 / 25.4;
49
 
162
  var $list_auto_mode; // mPDF 6
163
  var $list_indent_first_level; // mPDF 6
164
  var $list_indent_default; // mPDF 6
165
+ var $list_indent_default_mpdf;
166
  var $list_marker_offset; // mPDF 6
167
  var $list_symbol_size;
168
 
235
  var $OTLtags; // mPDF 5.7.1
236
  var $OTLdata; // mPDF 5.7.1
237
 
238
+ var $useDictionaryLBR;
239
+ var $useTibetanLBR;
240
+
241
  var $writingToC;
242
  var $layers;
243
  var $layerDetails;
597
  var $enabledtags;
598
 
599
  var $lineheight;
600
+ var $default_lineheight_correction;
601
  var $basepath;
602
  var $textparam;
603
 
908
  */
909
  private $protection;
910
 
911
+ /**
912
+ * @var \Mpdf\RemoteContentFetcher
913
+ */
914
+ private $remoteContentFetcher;
915
+
916
  /**
917
  * @var \Mpdf\Image\ImageProcessor
918
  */
933
  */
934
  private $logger;
935
 
936
+ /**
937
+ * @var \Mpdf\Writer\BaseWriter
938
+ */
939
+ private $writer;
940
+
941
+ /**
942
+ * @var Mpdf\Writer\FontWriter
943
+ */
944
+ private $fontWriter;
945
+
946
+ /**
947
+ * @var Mpdf\Writer\MetadataWriter
948
+ */
949
+ private $metadataWriter;
950
+
951
+ /**
952
+ * @var Mpdf\Writer\ImageWriter
953
+ */
954
+ private $imageWriter;
955
+
956
+ /**
957
+ * @var Mpdf\Writer\FormWriter
958
+ */
959
+ private $formWriter;
960
+
961
+ /**
962
+ * @var Mpdf\Writer\PageWriter
963
+ */
964
+ private $pageWriter;
965
+
966
+ /**
967
+ * @var Mpdf\Writer\BookmarkWriter
968
+ */
969
+ private $bookmarkWriter;
970
+
971
+ /**
972
+ * @var Mpdf\Writer\OptionalContentWriter
973
+ */
974
+ private $optionalContentWriter;
975
+
976
+ /**
977
+ * @var Mpdf\Writer\ColorWriter
978
+ */
979
+ private $colorWriter;
980
+
981
+ /**
982
+ * @var Mpdf\Writer\BackgroundWriter
983
+ */
984
+ private $backgroundWriter;
985
+
986
+ /**
987
+ * @var Mpdf\Writer\ObjectWriter
988
+ */
989
+ private $objectWriter;
990
+
991
+ /**
992
+ * @var Mpdf\Writer\JavaScriptWriter
993
+ */
994
+ private $javaScriptWriter;
995
+
996
+ /**
997
+ * @var Mpdf\Writer\ResourceWriter
998
+ */
999
+ private $resourceWriter;
1000
+
1001
  /**
1002
  * @var string[]
1003
  */
1029
  $originalConfig = $config;
1030
  $config = $this->initConfig($originalConfig);
1031
 
1032
+ $serviceFactory = new ServiceFactory();
1033
+ $services = $serviceFactory->getServices(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1034
  $this,
1035
+ $this->logger,
1036
+ $config,
1037
+ $this->restrictColorSpace,
 
 
 
1038
  $this->languageToFont,
1039
  $this->scriptToLanguage,
1040
+ $this->fontDescriptor,
1041
+ $this->bmp,
1042
+ $this->directWrite,
1043
+ $this->wmf
1044
  );
1045
 
1046
+ $this->services = [];
 
 
 
 
 
 
 
 
 
 
 
1047
 
1048
+ foreach ($services as $key => $service) {
1049
+ $this->{$key} = $service;
1050
+ $this->services[] = $key;
1051
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1052
 
1053
  $this->time0 = microtime(true);
1054
 
1755
  } else {
1756
  throw new \Mpdf\MpdfException('Incorrect zoom display mode: ' . $zoom);
1757
  }
1758
+
1759
  if ($layout == 'single' or $layout == 'continuous' or $layout == 'two' or $layout == 'twoleft' or $layout == 'tworight' or $layout == 'default') {
1760
  $this->LayoutMode = $layout;
1761
  } else {
1883
  if ($return) {
1884
  return sprintf('/GS%d gs', $gs);
1885
  } else {
1886
+ $this->writer->write(sprintf('/GS%d gs', $gs));
1887
  }
1888
  }
1889
 
1919
  $this->pdf_version = '1.5';
1920
  }
1921
  if ($this->visibility != 'visible') {
1922
+ $this->writer->write('EMC');
1923
  $this->hasOC = intval($this->hasOC);
1924
  }
1925
  if ($v == 'printonly') {
1926
+ $this->writer->write('/OC /OC1 BDC');
1927
  $this->hasOC = ($this->hasOC | 1);
1928
  } elseif ($v == 'screenonly') {
1929
+ $this->writer->write('/OC /OC2 BDC');
1930
  $this->hasOC = ($this->hasOC | 2);
1931
  } elseif ($v == 'hidden') {
1932
+ $this->writer->write('/OC /OC3 BDC');
1933
  $this->hasOC = ($this->hasOC | 4);
1934
  } elseif ($v != 'visible') {
1935
  throw new \Mpdf\MpdfException('Incorrect visibility: ' . $v);
1944
  // Was is function _begindoc()
1945
  // Start document
1946
  $this->state = 1;
1947
+ $this->writer->write('%PDF-' . $this->pdf_version);
1948
+ $this->writer->write('%' . chr(226) . chr(227) . chr(207) . chr(211)); // 4 chars > 128 to show binary file
1949
  }
1950
  }
1951
 
2704
  }
2705
  }
2706
  $this->current_layer = $id;
2707
+ $this->writer->write('/OCZ-index /ZI' . $id . ' BDC');
2708
 
2709
  $this->pageoutput[$this->page] = [];
2710
  }
2712
  function EndLayer()
2713
  {
2714
  if ($this->current_layer > 0) {
2715
+ $this->writer->write('EMCZ-index');
2716
  $this->current_layer = 0;
2717
  }
2718
  }
2911
  $this->x = $this->lMargin;
2912
  $this->y = $this->tMargin;
2913
  $this->FontFamily = '';
2914
+ $this->writer->write('2 J');
2915
  $this->LineWidth = $lw;
2916
+ $this->writer->write(sprintf('%.3F w', $lw * Mpdf::SCALE));
2917
 
2918
  if ($family) {
2919
  $this->SetFont($family, $style, $size, true, true);
2922
  $this->DrawColor = $dc;
2923
 
2924
  if ($dc != $this->defDrawColor) {
2925
+ $this->writer->write($dc);
2926
  }
2927
 
2928
  $this->FillColor = $fc;
2929
 
2930
  if ($fc != $this->defFillColor) {
2931
+ $this->writer->write($fc);
2932
  }
2933
 
2934
  $this->TextColor = $tc;
3135
  }
3136
 
3137
  // Tiling Patterns
3138
+ $this->writer->write('___PAGE___START' . $this->uniqstr);
3139
+ $this->writer->write('___BACKGROUND___PATTERNS' . $this->uniqstr);
3140
+ $this->writer->write('___HEADER___MARKER' . $this->uniqstr);
3141
  $this->pageBackgrounds = [];
3142
 
3143
  // Set line cap style to square
3144
  $this->SetLineCap(2);
3145
  // Set line width
3146
  $this->LineWidth = $lw;
3147
+ $this->writer->write(sprintf('%.3F w', $lw * Mpdf::SCALE));
3148
  // Set font
3149
  if ($family) {
3150
  $this->SetFont($family, $style, $size, true, true); // forces write
3153
  // Set colors
3154
  $this->DrawColor = $dc;
3155
  if ($dc != $this->defDrawColor) {
3156
+ $this->writer->write($dc);
3157
  }
3158
  $this->FillColor = $fc;
3159
  if ($fc != $this->defFillColor) {
3160
+ $this->writer->write($fc);
3161
  }
3162
  $this->TextColor = $tc;
3163
  $this->ColorFlag = $cf;
3168
  // Restore line width
3169
  if ($this->LineWidth != $lw) {
3170
  $this->LineWidth = $lw;
3171
+ $this->writer->write(sprintf('%.3F w', $lw * Mpdf::SCALE));
3172
  }
3173
  // Restore font
3174
  if ($family) {
3178
  // Restore colors
3179
  if ($this->DrawColor != $dc) {
3180
  $this->DrawColor = $dc;
3181
+ $this->writer->write($dc);
3182
  }
3183
  if ($this->FillColor != $fc) {
3184
  $this->FillColor = $fc;
3185
+ $this->writer->write($fc);
3186
  }
3187
  $this->TextColor = $tc;
3188
  $this->ColorFlag = $cf;
3305
  }
3306
  $this->DrawColor = $out;
3307
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['DrawColor']) && $this->pageoutput[$this->page]['DrawColor'] != $this->DrawColor) || !isset($this->pageoutput[$this->page]['DrawColor']))) {
3308
+ $this->writer->write($this->DrawColor);
3309
  }
3310
  $this->pageoutput[$this->page]['DrawColor'] = $this->DrawColor;
3311
  }
3322
  $this->FillColor = $out;
3323
  $this->ColorFlag = ($out != $this->TextColor);
3324
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['FillColor']) && $this->pageoutput[$this->page]['FillColor'] != $this->FillColor) || !isset($this->pageoutput[$this->page]['FillColor']))) {
3325
+ $this->writer->write($this->FillColor);
3326
  }
3327
  $this->pageoutput[$this->page]['FillColor'] = $this->FillColor;
3328
  }
3668
  $this->LineWidth = $width;
3669
  $lwout = (sprintf('%.3F w', $width * Mpdf::SCALE));
3670
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['LineWidth']) && $this->pageoutput[$this->page]['LineWidth'] != $lwout) || !isset($this->pageoutput[$this->page]['LineWidth']))) {
3671
+ $this->writer->write($lwout);
3672
  }
3673
  $this->pageoutput[$this->page]['LineWidth'] = $lwout;
3674
  }
3676
  function Line($x1, $y1, $x2, $y2)
3677
  {
3678
  // Draw a line
3679
+ $this->writer->write(sprintf('%.3F %.3F m %.3F %.3F l S', $x1 * Mpdf::SCALE, ($this->h - $y1) * Mpdf::SCALE, $x2 * Mpdf::SCALE, ($this->h - $y2) * Mpdf::SCALE));
3680
  }
3681
 
3682
  function Arrow($x1, $y1, $x2, $y2, $headsize = 3, $fill = 'B', $angle = 25)
3703
 
3704
  $s = '';
3705
  $s .= sprintf('%.3F %.3F m %.3F %.3F l S', $x1 * Mpdf::SCALE, ($this->h - $y1) * Mpdf::SCALE, $x5 * Mpdf::SCALE, $y5 * Mpdf::SCALE);
3706
+ $this->writer->write($s);
3707
 
3708
  $s = '';
3709
  $s .= sprintf('%.3F %.3F m %.3F %.3F l %.3F %.3F l %.3F %.3F l %.3F %.3F l ', $x5 * Mpdf::SCALE, $y5 * Mpdf::SCALE, $x3 * Mpdf::SCALE, $y3 * Mpdf::SCALE, $x2 * Mpdf::SCALE, ($this->h - $y2) * Mpdf::SCALE, $x4 * Mpdf::SCALE, $y4 * Mpdf::SCALE, $x5 * Mpdf::SCALE, $y5 * Mpdf::SCALE);
3710
  $s .= $fill;
3711
+ $this->writer->write($s);
3712
  }
3713
 
3714
  function Rect($x, $y, $w, $h, $style = '')
3721
  } else {
3722
  $op = 'S';
3723
  }
3724
+ $this->writer->write(sprintf('%.3F %.3F %.3F %.3F re %s', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$h * Mpdf::SCALE, $op));
3725
  }
3726
 
3727
  function AddFontDirectory($directory)
4150
  if ($write) {
4151
  $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
4152
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) {
4153
+ $this->writer->write($fontout);
4154
  }
4155
  $this->pageoutput[$this->page]['Font'] = $fontout;
4156
  }
4218
  if ($write) {
4219
  $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
4220
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) {
4221
+ $this->writer->write($fontout);
4222
  }
4223
  $this->pageoutput[$this->page]['Font'] = $fontout;
4224
  }
4244
  $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
4245
  // Edited mPDF 3.0
4246
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) {
4247
+ $this->writer->write($fontout);
4248
  }
4249
  $this->pageoutput[$this->page]['Font'] = $fontout;
4250
  }
4345
  // IF corefonts AND NOT SmCaps AND NOT Kerning
4346
  // Just output text
4347
  if ($this->usingCoreFont && !($textvar & TextVars::FC_SMALLCAPS) && !($textvar & TextVars::FC_KERNING)) {
4348
+ $txt2 = $this->writer->escape($txt2);
4349
+ $s .= sprintf('BT ' . $aix . ' (%s) Tj ET', $px, $py, $txt2);
4350
  } // IF NOT corefonts [AND NO wordspacing] AND NOT SIP/SMP AND NOT SmCaps AND NOT Kerning AND NOT OTL
4351
  // Just output text
4352
  elseif (!$this->usingCoreFont && !($textvar & TextVars::FC_SMALLCAPS) && !($textvar & TextVars::FC_KERNING) && !(isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF) && !empty($OTLdata['GPOSinfo']))) {
4356
  $s .=sprintf('BT ' . $aix . ' %s Tj ET', $px, $py, $txt2);
4357
  } // NOT SIP/SMP
4358
  else {
4359
+ $txt2 = $this->writer->utf8ToUtf16BigEndian($txt2, false);
4360
+ $txt2 = $this->writer->escape($txt2);
4361
  $s .=sprintf('BT ' . $aix . ' (%s) Tj ET', $px, $py, $txt2);
4362
  }
4363
  } // IF NOT corefonts [AND IS wordspacing] AND NOT SIP AND NOT SmCaps AND NOT Kerning AND NOT OTL
4425
  if ($return) {
4426
  return $s . " \n";
4427
  }
4428
+ $this->writer->write($s);
4429
  }
4430
 
4431
  /* -- DIRECTW -- */
4516
  function ResetSpacing()
4517
  {
4518
  if ($this->ws != 0) {
4519
+ $this->writer->write('BT 0 Tw ET');
4520
  }
4521
  $this->ws = 0;
4522
  if ($this->charspacing != 0) {
4523
+ $this->writer->write('BT 0 Tc ET');
4524
  }
4525
  $this->charspacing = 0;
4526
  }
4531
  $cs = 0;
4532
  }
4533
  if ($cs) {
4534
+ $this->writer->write(sprintf('BT %.3F Tc ET', $cs));
4535
  } elseif ($this->charspacing != 0) {
4536
+ $this->writer->write('BT 0 Tc ET');
4537
  }
4538
  $this->charspacing = $cs;
4539
  if (intval($ws * 1000) == 0) {
4540
  $ws = 0;
4541
  }
4542
  if ($ws) {
4543
+ $this->writer->write(sprintf('BT %.3F Tw ET', $ws));
4544
  } elseif ($this->ws != 0) {
4545
+ $this->writer->write('BT 0 Tw ET');
4546
  }
4547
  $this->ws = $ws;
4548
  }
5130
  // IF corefonts AND NOT SmCaps AND NOT Kerning
5131
  // Just output text; charspacing and wordspacing already set by charspacing (Tc) and ws (Tw)
5132
  if ($this->usingCoreFont && !($textvar & TextVars::FC_SMALLCAPS) && !($textvar & TextVars::FC_KERNING)) {
5133
+ $txt2 = $this->writer->escape($txt2);
5134
  $sub .=sprintf('BT ' . $aix . ' (%s) Tj ET', $px, $py, $txt2);
5135
  } // IF NOT corefonts AND NO wordspacing AND NOT SIP/SMP AND NOT SmCaps AND NOT Kerning AND NOT OTL
5136
  // Just output text
5141
  $sub .=sprintf('BT ' . $aix . ' %s Tj ET', $px, $py, $txt2);
5142
  } // NOT SIP/SMP
5143
  else {
5144
+ $txt2 = $this->writer->utf8ToUtf16BigEndian($txt2, false);
5145
+ $txt2 = $this->writer->escape($txt2);
5146
  $sub .=sprintf('BT ' . $aix . ' (%s) Tj ET', $px, $py, $txt2);
5147
  }
5148
  } // IF NOT corefonts AND IS wordspacing AND NOT SIP AND NOT SmCaps AND NOT Kerning AND NOT OTL
5150
  // IF multibyte - Tw has no effect - need to do word spacing using an adjustment before each space
5151
  elseif (!$this->usingCoreFont && $this->ws && !((isset($this->CurrentFont['sip']) && $this->CurrentFont['sip']) || (isset($this->CurrentFont['smp']) && $this->CurrentFont['smp'])) && !($textvar & TextVars::FC_SMALLCAPS) && !($textvar & TextVars::FC_KERNING) && !(isset($this->CurrentFont['useOTL']) && ($this->CurrentFont['useOTL'] & 0xFF) && (!empty($OTLdata['GPOSinfo']) || (strpos($OTLdata['group'], 'M') !== false && $this->charspacing)) )) {
5152
  $space = " ";
5153
+ $space = $this->writer->utf8ToUtf16BigEndian($space, false);
5154
+ $space = $this->writer->escape($space);
5155
  $sub .=sprintf('BT ' . $aix . ' %.3F Tc [', $px, $py, $this->charspacing);
5156
  $t = explode(' ', $txt2);
5157
  $numt = count($t);
5158
  for ($i = 0; $i < $numt; $i++) {
5159
  $tx = $t[$i];
5160
+ $tx = $this->writer->utf8ToUtf16BigEndian($tx, false);
5161
+ $tx = $this->writer->escape($tx);
5162
  $sub .=sprintf('(%s) ', $tx);
5163
  if (($i + 1) < $numt) {
5164
  $adj = -($this->ws) * 1000 / $this->FontSizePt;
5338
  }
5339
  }
5340
  if ($s) {
5341
+ $this->writer->write($s);
5342
  }
5343
 
5344
  // WORD SPACING
5345
  if ($this->ws && !$this->usingCoreFont) {
5346
+ $this->writer->write(sprintf('BT %.3F Tc ET', $this->charspacing));
5347
  }
5348
  $this->lasth = $h;
5349
  if (strpos($txt, "\n") !== false) {
5553
  if ($this->usingCoreFont) {
5554
  $tx = utf8_decode($tx);
5555
  } else {
5556
+ $tx = $this->writer->utf8ToUtf16BigEndian($tx, false);
5557
  }
5558
+ $tx = $this->writer->escape($tx);
5559
  }
5560
 
5561
  // If any settings require a new Text Group
5632
  }
5633
  } else {
5634
  $tx = UtfString::code2utf($c);
5635
+ $tx = $this->writer->utf8ToUtf16BigEndian($tx, false);
5636
+ $tx = $this->writer->escape($tx);
5637
  }
5638
 
5639
  if ($kashida > $tatw) {
5720
  if ($mode == 'MBTw') { // Multibyte requiring word spacing
5721
  $space = ' ';
5722
  // Convert string to UTF-16BE without BOM
5723
+ $space = $this->writer->utf8ToUtf16BigEndian($space, false);
5724
+ $space = $this->writer->escape($space);
5725
  $s = sprintf(' BT ' . $aix, $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE);
5726
  $t = explode(' ', $txt);
5727
  for ($i = 0; $i < count($t); $i++) {
5735
  $tj .= sprintf(')%d(', $kern);
5736
  }
5737
  $tc = UtfString::code2utf($unicode[$ti]);
5738
+ $tc = $this->writer->utf8ToUtf16BigEndian($tc, false);
5739
+ $tj .= $this->writer->escape($tc);
5740
  }
5741
  $tj .= ')';
5742
  $s .= sprintf(' %.3F Tc [%s] TJ', $this->charspacing, $tj);
5757
  $tj .= sprintf(')%d(', $kern);
5758
  }
5759
  $tx = UtfString::code2utf($unicode[$i]);
5760
+ $tx = $this->writer->utf8ToUtf16BigEndian($tx, false);
5761
+ $tj .= $this->writer->escape($tx);
5762
  }
5763
  $tj .= ')';
5764
  $s .= sprintf(' BT ' . $aix . ' [%s] TJ ET ', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $tj);
5771
  $kern = -$this->CurrentFont['kerninfo'][$txt[($i - 1)]][$txt[$i]];
5772
  $tj .= sprintf(')%d(', $kern);
5773
  }
5774
+ $tj .= $this->writer->escape($txt[$i]);
5775
  }
5776
  $tj .= ')';
5777
  $s .= sprintf(' BT ' . $aix . ' [%s] TJ ET ', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $tj);
6253
  $this->SetFont($saved['family'], $saved['style'], $saved['sizePt'], true, true); // force output
6254
  $fontout = (sprintf('BT /F%d %.3F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
6255
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Font']) && $this->pageoutput[$this->page]['Font'] != $fontout) || !isset($this->pageoutput[$this->page]['Font']))) {
6256
+ $this->writer->write($fontout);
6257
  }
6258
  $this->pageoutput[$this->page]['Font'] = $fontout;
6259
  } else {
7054
  if ($objattr['type'] == 'image') {
7055
  // mPDF 5.7.3 TRANSFORMS
7056
  if (isset($objattr['transform'])) {
7057
+ $this->writer->write("\n" . '% BTR'); // Begin Transform
7058
  }
7059
  if (isset($objattr['z-index']) && $objattr['z-index'] > 0 && $this->current_layer == 0) {
7060
  $this->BeginLayer($objattr['z-index']);
7184
  // mPDF 5.7.3 TRANSFORMS / BACKGROUND COLOR
7185
  // Transform also affects image background
7186
  if ($tr2) {
7187
+ $this->writer->write('q ' . $tr2 . ' ');
7188
  }
7189
  if (isset($objattr['bgcolor']) && $objattr['bgcolor']) {
7190
  $bgcol = $objattr['bgcolor'];
7193
  $this->SetFColor($this->colorConverter->convert(255, $this->PDFAXwarnings));
7194
  }
7195
  if ($tr2) {
7196
+ $this->writer->write('Q');
7197
  }
7198
 
7199
  /* -- BACKGROUNDS -- */
7215
  $outstring = sprintf("q " . $tr . $tr2 . "%.3F 0 0 %.3F %.3F %.3F cm " . $gradmask . "/I%d Do Q", $obiw * Mpdf::SCALE, $obih * Mpdf::SCALE, $objattr['INNER-X'] * Mpdf::SCALE, ($this->h - ($objattr['INNER-Y'] + $obih )) * Mpdf::SCALE, $objattr['ID']); // mPDF 5.7.3 TRANSFORMS
7216
  }
7217
  }
7218
+ $this->writer->write($outstring);
7219
  // LINK
7220
  if (isset($objattr['link'])) {
7221
  $this->Link($objattr['INNER-X'], $objattr['INNER-Y'], $objattr['INNER-WIDTH'], $objattr['INNER-HEIGHT'], $objattr['link']);
7227
  // mPDF 5.7.3 TRANSFORMS
7228
  // Transform also affects image borders
7229
  if ($tr2) {
7230
+ $this->writer->write('q ' . $tr2 . ' ');
7231
  }
7232
  if ((isset($objattr['border_top']) && $objattr['border_top'] > 0) || (isset($objattr['border_left']) && $objattr['border_left'] > 0) || (isset($objattr['border_right']) && $objattr['border_right'] > 0) || (isset($objattr['border_bottom']) && $objattr['border_bottom'] > 0)) {
7233
  $this->PaintImgBorder($objattr, $is_table);
7234
  }
7235
  if ($tr2) {
7236
+ $this->writer->write('Q');
7237
  }
7238
 
7239
  if (isset($objattr['visibility']) && $objattr['visibility'] != 'visible' && $objattr['visibility']) {
7244
  }
7245
  // mPDF 5.7.3 TRANSFORMS
7246
  if (isset($objattr['transform'])) {
7247
+ $this->writer->write("\n" . '% ETR'); // End Transform
7248
  }
7249
  }
7250
 
7522
  // x and y are the centre of the bullet; size is the width and/or height in mm
7523
  $fcol = $this->SetTColor($color, true);
7524
  $lcol = strtoupper($fcol); // change 0 0 0 rg to 0 0 0 RG
7525
+ $this->writer->write(sprintf('q %s %s', $lcol, $fcol));
7526
+ $this->writer->write('0 j 0 J [] 0 d');
7527
  if ($type == 'square') {
7528
  $size *= 0.85; // Smaller to appear the same size as circle/disc
7529
+ $this->writer->write(sprintf('%.3F %.3F %.3F %.3F re f', ($x - $size / 2) * Mpdf::SCALE, ($this->h - $y + $size / 2) * Mpdf::SCALE, ($size) * Mpdf::SCALE, (-$size) * Mpdf::SCALE));
7530
  } elseif ($type == 'disc') {
7531
  $this->Circle($x, $y, $size / 2, 'F'); // Fill
7532
  } elseif ($type == 'circle') {
7533
  $lw = $size / 12; // Line width
7534
+ $this->writer->write(sprintf('%.3F w ', $lw * Mpdf::SCALE));
7535
  $this->Circle($x, $y, $size / 2 - $lw / 2, 'S'); // Stroke
7536
  }
7537
+ $this->writer->write('Q');
7538
  }
7539
 
7540
  // mPDF 6
8663
  }
8664
  $tr = ($mode . ' Tr');
8665
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']))) {
8666
+ $this->writer->write($tr);
8667
  }
8668
  $this->pageoutput[$this->page]['TextRendering'] = $tr;
8669
  }
8675
  $this->SetDColor($params['outline-COLOR']);
8676
  $tr = ('2 Tr');
8677
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']))) {
8678
+ $this->writer->write($tr);
8679
  }
8680
  $this->pageoutput[$this->page]['TextRendering'] = $tr;
8681
  } else { // Now resets all values
8684
  $this->_SetTextRendering(0);
8685
  $tr = ('0 Tr');
8686
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['TextRendering']) && $this->pageoutput[$this->page]['TextRendering'] != $tr) || !isset($this->pageoutput[$this->page]['TextRendering']))) {
8687
+ $this->writer->write($tr);
8688
  }
8689
  $this->pageoutput[$this->page]['TextRendering'] = $tr;
8690
  }
8824
  $outstring = $this->watermarkImgAlpha . "\n" . $outstring . "\n" . $this->SetAlpha(1, 'Normal', true) . "\n";
8825
  $this->pages[$this->page] = preg_replace('/(___BACKGROUND___PATTERNS' . $this->uniqstr . ')/', "\n" . $outstring . "\n" . '\\1', $this->pages[$this->page]);
8826
  } else {
8827
+ $this->writer->write($outstring);
8828
  }
8829
 
8830
  return 0;
8895
  }
8896
 
8897
  if ($paint) {
8898
+ $this->writer->write($outstring);
8899
  if ($link) {
8900
  $this->Link($x, $y, $w, $h, $link);
8901
  }
9166
  {
9167
  $s = sprintf('%d j', $mode);
9168
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['LineJoin']) && $this->pageoutput[$this->page]['LineJoin'] != $s) || !isset($this->pageoutput[$this->page]['LineJoin']))) {
9169
+ $this->writer->write($s);
9170
  }
9171
  $this->pageoutput[$this->page]['LineJoin'] = $s;
9172
  }
9175
  {
9176
  $s = sprintf('%d J', $mode);
9177
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['LineCap']) && $this->pageoutput[$this->page]['LineCap'] != $s) || !isset($this->pageoutput[$this->page]['LineCap']))) {
9178
+ $this->writer->write($s);
9179
  }
9180
  $this->pageoutput[$this->page]['LineCap'] = $s;
9181
  }
9188
  $s = '[] 0 d';
9189
  }
9190
  if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Dash']) && $this->pageoutput[$this->page]['Dash'] != $s) || !isset($this->pageoutput[$this->page]['Dash']))) {
9191
+ $this->writer->write($s);
9192
  }
9193
  $this->pageoutput[$this->page]['Dash'] = $s;
9194
  }
9704
  $this->state = 1;
9705
  }
9706
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9707
  /* -- ANNOTATIONS -- */
 
9708
  function Annotation($text, $x = 0, $y = 0, $icon = 'Note', $author = '', $subject = '', $opacity = 0, $colarray = false, $popup = '', $file = '')
9709
  {
9710
  if (is_array($colarray) && count($colarray) == 3) {
9775
 
9776
  /* -- END ANNOTATIONS -- */
9777
 
9778
+ function _enddoc()
9779
+ {
9780
+ // @log Writing Headers & Footers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9781
 
9782
+ $this->_puthtmlheaders();
 
 
9783
 
9784
+ // @log Writing Pages
 
9785
 
9786
+ // Remove references to unused fonts (usually default font)
9787
+ foreach ($this->fonts as $fk => $font) {
9788
+ if (isset($font['type']) && $font['type'] == 'TTF' && !$font['used']) {
9789
+ if ($font['sip'] || $font['smp']) {
9790
+ foreach ($font['subsetfontids'] as $k => $fid) {
9791
+ foreach ($this->pages as $pn => $page) {
9792
+ $this->pages[$pn] = preg_replace('/\s\/F' . $fid . ' \d[\d.]* Tf\s/is', ' ', $this->pages[$pn]);
 
 
 
 
9793
  }
9794
  }
9795
+ } else {
9796
+ foreach ($this->pages as $pn => $page) {
9797
+ $this->pages[$pn] = preg_replace('/\s\/F' . $font['i'] . ' \d[\d.]* Tf\s/is', ' ', $this->pages[$pn]);
9798
+ }
 
 
 
9799
  }
9800
  }
9801
  }
9802
 
9803
+ if (count($this->layers)) {
9804
+ foreach ($this->pages as $pn => $page) {
9805
+ preg_match_all('/\/OCZ-index \/ZI(\d+) BDC(.*?)(EMCZ)-index/is', $this->pages[$pn], $m1);
9806
+ preg_match_all('/\/OCBZ-index \/ZI(\d+) BDC(.*?)(EMCBZ)-index/is', $this->pages[$pn], $m2);
9807
+ preg_match_all('/\/OCGZ-index \/ZI(\d+) BDC(.*?)(EMCGZ)-index/is', $this->pages[$pn], $m3);
9808
+ $m = [];
9809
+ for ($i = 0; $i < 4; $i++) {
9810
+ $m[$i] = array_merge($m1[$i], $m2[$i], $m3[$i]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9811
  }
9812
+ if (count($m[0])) {
9813
+ $sortarr = [];
9814
+ for ($i = 0; $i < count($m[0]); $i++) {
9815
+ $key = $m[1][$i] * 2;
9816
+ if ($m[3][$i] == 'EMCZ') {
9817
+ $key +=2; // background first then gradient then normal
9818
+ } elseif ($m[3][$i] == 'EMCGZ') {
9819
+ $key +=1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9820
  }
9821
+ $sortarr[$i] = $key;
9822
  }
9823
+ asort($sortarr);
9824
+ foreach ($sortarr as $i => $k) {
9825
+ $this->pages[$pn] = str_replace($m[0][$i], '', $this->pages[$pn]);
9826
+ $this->pages[$pn] .= "\n" . $m[0][$i] . "\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9827
  }
9828
+ $this->pages[$pn] = preg_replace('/\/OC[BG]{0,1}Z-index \/ZI(\d+) BDC/is', '/OC /ZI\\1 BDC ', $this->pages[$pn]);
9829
+ $this->pages[$pn] = preg_replace('/EMC[BG]{0,1}Z-index/is', 'EMC', $this->pages[$pn]);
 
 
 
 
9830
  }
 
 
9831
  }
9832
  }
 
 
9833
 
9834
+ $this->pageWriter->writePages();
9835
 
9836
+ // @log Writing document resources
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9837
 
9838
+ $this->resourceWriter->writeResources();
9839
 
9840
+ // Info
9841
+ $this->writer->object();
9842
+ $this->InfoRoot = $this->n;
9843
+ $this->writer->write('<<');
9844
 
9845
+ // @log Writing document info
9846
+ $this->metadataWriter->writeInfo();
9847
 
9848
+ $this->writer->write('>>');
9849
+ $this->writer->write('endobj');
9850
 
9851
+ // METADATA
9852
+ if ($this->PDFA || $this->PDFX) {
9853
+ $this->metadataWriter->writeMetadata();
9854
+ }
9855
 
9856
+ // OUTPUTINTENT
9857
+ if ($this->PDFA || $this->PDFX || $this->ICCProfile) {
9858
+ $this->metadataWriter->writeOutputIntent();
9859
+ }
9860
 
9861
+ // Associated files
9862
+ if ($this->associatedFiles) {
9863
+ $this->metadataWriter->writeAssociatedFiles();
9864
+ }
9865
 
9866
+ // Catalog
9867
+ $this->writer->object();
9868
+ $this->writer->write('<<');
9869
 
9870
+ // @log Writing document catalog
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9871
 
9872
+ $this->metadataWriter->writeCatalog();
9873
 
9874
+ $this->writer->write('>>');
9875
+ $this->writer->write('endobj');
 
9876
 
9877
+ // Cross-ref
9878
+ $o = strlen($this->buffer);
9879
+ $this->writer->write('xref');
9880
+ $this->writer->write('0 ' . ($this->n + 1));
9881
+ $this->writer->write('0000000000 65535 f ');
9882
 
9883
+ for ($i = 1; $i <= $this->n; $i++) {
9884
+ $this->writer->write(sprintf('%010d 00000 n ', $this->offsets[$i]));
9885
+ }
 
 
 
 
9886
 
9887
+ // Trailer
9888
+ $this->writer->write('trailer');
9889
+ $this->writer->write('<<');
9890
 
9891
+ $this->metadataWriter->writeTrailer();
9892
 
9893
+ $this->writer->write('>>');
9894
+ $this->writer->write('startxref');
9895
+ $this->writer->write($o);
9896
 
9897
+ $this->buffer .= '%%EOF';
9898
+ $this->state = 3;
 
 
 
 
 
 
 
 
 
 
 
 
 
9899
 
9900
+ // Imports
9901
+ if ($this->enableImports && count($this->parsers) > 0) {
9902
+ foreach ($this->parsers as $k => $_) {
9903
+ $this->parsers[$k]->closeFile();
9904
+ $this->parsers[$k] = null;
9905
+ unset($this->parsers[$k]);
 
 
 
 
 
 
 
9906
  }
9907
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9908
  }
9909
 
9910
+ function _beginpage(
9911
+ $orientation,
9912
+ $mgl = '',
9913
+ $mgr = '',
9914
+ $mgt = '',
9915
+ $mgb = '',
9916
+ $mgh = '',
9917
+ $mgf = '',
9918
+ $ohname = '',
9919
+ $ehname = '',
9920
+ $ofname = '',
9921
+ $efname = '',
9922
+ $ohvalue = 0,
9923
+ $ehvalue = 0,
9924
+ $ofvalue = 0,
9925
+ $efvalue = 0,
9926
+ $pagesel = '',
9927
+ $newformat = ''
9928
+ ) {
9929
+ if (!($pagesel && $this->page == 1 && (sprintf("%0.4f", $this->y) == sprintf("%0.4f", $this->tMargin)))) {
9930
+ $this->page++;
9931
+ $this->pages[$this->page] = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9932
  }
9933
+ $this->state = 2;
9934
+ $resetHTMLHeadersrequired = false;
9935
 
9936
+ if ($newformat) {
9937
+ $this->_setPageSize($newformat, $orientation);
9938
  }
9939
 
9940
+ /* -- CSS-PAGE -- */
9941
+ // Paged media (page-box)
9942
+ if ($pagesel || (isset($this->page_box['using']) && $this->page_box['using'])) {
 
 
9943
 
9944
+ if ($pagesel || $this->page == 1) {
9945
+ $first = true;
9946
+ } else {
9947
+ $first = false;
9948
  }
9949
 
9950
+ if ($this->mirrorMargins && ($this->page % 2 == 0)) {
9951
+ $oddEven = 'E';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9952
  } else {
9953
+ $oddEven = 'O';
 
 
 
9954
  }
 
 
 
 
 
 
 
 
 
9955
 
9956
+ if ($pagesel) {
9957
+ $psel = $pagesel;
9958
+ } elseif ($this->page_box['current']) {
9959
+ $psel = $this->page_box['current'];
9960
+ } else {
9961
+ $psel = '';
9962
  }
 
 
 
 
9963
 
9964
+ list($orientation, $mgl, $mgr, $mgt, $mgb, $mgh, $mgf, $hname, $fname, $bg, $resetpagenum, $pagenumstyle, $suppress, $marks, $newformat) = $this->SetPagedMediaCSS($psel, $first, $oddEven);
 
 
9965
 
9966
+ if ($this->mirrorMargins && ($this->page % 2 == 0)) {
9967
 
9968
+ if ($hname) {
9969
+ $ehvalue = 1;
9970
+ $ehname = $hname;
9971
+ } else {
9972
+ $ehvalue = -1;
9973
+ }
9974
 
9975
+ if ($fname) {
9976
+ $efvalue = 1;
9977
+ $efname = $fname;
9978
+ } else {
9979
+ $efvalue = -1;
9980
+ }
9981
 
9982
+ } else {
 
 
 
9983
 
9984
+ if ($hname) {
9985
+ $ohvalue = 1;
9986
+ $ohname = $hname;
9987
+ } else {
9988
+ $ohvalue = -1;
9989
+ }
9990
 
9991
+ if ($fname) {
9992
+ $ofvalue = 1;
9993
+ $ofname = $fname;
9994
+ } else {
9995
+ $ofvalue = -1;
9996
+ }
 
 
 
 
 
 
 
 
 
 
9997
  }
 
 
 
9998
 
9999
+ if ($resetpagenum || $pagenumstyle || $suppress) {
10000
+ $this->PageNumSubstitutions[] = ['from' => ($this->page), 'reset' => $resetpagenum, 'type' => $pagenumstyle, 'suppress' => $suppress];
 
 
 
10001
  }
10002
 
10003
+ // PAGED MEDIA - CROP / CROSS MARKS from @PAGE
10004
+ $this->show_marks = $marks;
 
10005
 
10006
+ // Background color
10007
+ if (isset($bg['BACKGROUND-COLOR'])) {
10008
+ $cor = $this->colorConverter->convert($bg['BACKGROUND-COLOR'], $this->PDFAXwarnings);
10009
+ if ($cor) {
10010
+ $this->bodyBackgroundColor = $cor;
10011
+ }
10012
+ } else {
10013
+ $this->bodyBackgroundColor = false;
10014
  }
10015
+
10016
+ /* -- BACKGROUNDS -- */
10017
+ if (isset($bg['BACKGROUND-GRADIENT'])) {
10018
+ $this->bodyBackgroundGradient = $bg['BACKGROUND-GRADIENT'];
10019
  } else {
10020
+ $this->bodyBackgroundGradient = false;
10021
  }
10022
 
10023
+ // Tiling Patterns
10024
+ if (isset($bg['BACKGROUND-IMAGE']) && $bg['BACKGROUND-IMAGE']) {
10025
+ $ret = $this->SetBackground($bg, $this->pgwidth);
10026
+ if ($ret) {
10027
+ $this->bodyBackgroundImage = $ret;
10028
+ }
10029
+ } else {
10030
+ $this->bodyBackgroundImage = false;
10031
+ }
10032
+ /* -- END BACKGROUNDS -- */
10033
 
10034
+ $this->page_box['current'] = $psel;
10035
+ $this->page_box['using'] = true;
 
 
 
10036
  }
10037
+ /* -- END CSS-PAGE -- */
 
 
 
10038
 
10039
+ // Page orientation
10040
+ if (!$orientation) {
10041
+ $orientation = $this->DefOrientation;
 
 
 
 
 
 
 
 
 
10042
  } else {
10043
+ $orientation = strtoupper(substr($orientation, 0, 1));
10044
+ if ($orientation != $this->DefOrientation) {
10045
+ $this->OrientationChanges[$this->page] = true;
 
 
 
 
 
 
 
 
 
 
 
 
10046
  }
10047
  }
10048
 
10049
+ if ($orientation != $this->CurOrientation || $newformat) {
 
 
 
 
10050
 
10051
+ // Change orientation
10052
+ if ($orientation == 'P') {
10053
+ $this->wPt = $this->fwPt;
10054
+ $this->hPt = $this->fhPt;
10055
+ $this->w = $this->fw;
10056
+ $this->h = $this->fh;
10057
+ if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation == 'P') {
10058
+ $this->tMargin = $this->orig_tMargin;
10059
+ $this->bMargin = $this->orig_bMargin;
10060
+ $this->DeflMargin = $this->orig_lMargin;
10061
+ $this->DefrMargin = $this->orig_rMargin;
10062
+ $this->margin_header = $this->orig_hMargin;
10063
+ $this->margin_footer = $this->orig_fMargin;
10064
+ } else {
10065
+ $resetHTMLHeadersrequired = true;
10066
+ }
10067
+ } else {
10068
+ $this->wPt = $this->fhPt;
10069
+ $this->hPt = $this->fwPt;
10070
+ $this->w = $this->fh;
10071
+ $this->h = $this->fw;
10072
 
10073
+ if (($this->forcePortraitHeaders || $this->forcePortraitMargins) && $this->DefOrientation == 'P') {
10074
+ $this->tMargin = $this->orig_lMargin;
10075
+ $this->bMargin = $this->orig_rMargin;
10076
+ $this->DeflMargin = $this->orig_bMargin;
10077
+ $this->DefrMargin = $this->orig_tMargin;
10078
+ $this->margin_header = $this->orig_hMargin;
10079
+ $this->margin_footer = $this->orig_fMargin;
10080
+ } else {
10081
+ $resetHTMLHeadersrequired = true;
10082
+ }
10083
+ }
10084
 
10085
+ $this->CurOrientation = $orientation;
10086
+ $this->ResetMargins();
10087
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
10088
+ $this->PageBreakTrigger = $this->h - $this->bMargin;
10089
  }
10090
 
10091
+ $this->pageDim[$this->page]['w'] = $this->w;
10092
+ $this->pageDim[$this->page]['h'] = $this->h;
 
10093
 
10094
+ $this->pageDim[$this->page]['outer_width_LR'] = isset($this->page_box['outer_width_LR']) ? $this->page_box['outer_width_LR'] : 0;
10095
+ $this->pageDim[$this->page]['outer_width_TB'] = isset($this->page_box['outer_width_TB']) ? $this->page_box['outer_width_TB'] : 0;
 
 
 
 
10096
 
10097
+ if (!isset($this->page_box['outer_width_LR']) && !isset($this->page_box['outer_width_TB'])) {
10098
+ $this->pageDim[$this->page]['bleedMargin'] = 0;
10099
+ } elseif ($this->bleedMargin <= $this->page_box['outer_width_LR'] && $this->bleedMargin <= $this->page_box['outer_width_TB']) {
10100
+ $this->pageDim[$this->page]['bleedMargin'] = $this->bleedMargin;
10101
+ } else {
10102
+ $this->pageDim[$this->page]['bleedMargin'] = min($this->page_box['outer_width_LR'], $this->page_box['outer_width_TB']) - 0.01;
10103
  }
10104
 
10105
+ // If Page Margins are re-defined
10106
+ // strlen()>0 is used to pick up (integer) 0, (string) '0', or set value
10107
+ if ((strlen($mgl) > 0 && $this->DeflMargin != $mgl) || (strlen($mgr) > 0 && $this->DefrMargin != $mgr) || (strlen($mgt) > 0 && $this->tMargin != $mgt) || (strlen($mgb) > 0 && $this->bMargin != $mgb) || (strlen($mgh) > 0 && $this->margin_header != $mgh) || (strlen($mgf) > 0 && $this->margin_footer != $mgf)) {
10108
 
10109
+ if (strlen($mgl) > 0) {
10110
+ $this->DeflMargin = $mgl;
 
 
 
 
 
10111
  }
10112
+
10113
+ if (strlen($mgr) > 0) {
10114
+ $this->DefrMargin = $mgr;
10115
  }
10116
+
10117
+ if (strlen($mgt) > 0) {
10118
+ $this->tMargin = $mgt;
10119
  }
10120
+
10121
+ if (strlen($mgb) > 0) {
10122
+ $this->bMargin = $mgb;
10123
  }
10124
+
10125
+ if (strlen($mgh) > 0) {
10126
+ $this->margin_header = $mgh;
10127
  }
10128
+
10129
+ if (strlen($mgf) > 0) {
10130
+ $this->margin_footer = $mgf;
10131
  }
10132
+
10133
+ $this->ResetMargins();
10134
+ $this->SetAutoPageBreak($this->autoPageBreak, $this->bMargin);
10135
+
10136
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
10137
+ $resetHTMLHeadersrequired = true;
10138
+ }
10139
+
10140
+ $this->ResetMargins();
10141
+ $this->pgwidth = $this->w - $this->lMargin - $this->rMargin;
10142
+ $this->SetAutoPageBreak($this->autoPageBreak, $this->bMargin);
10143
+
10144
+ // Reset column top margin
10145
+ $this->y0 = $this->tMargin;
10146
+
10147
+ $this->x = $this->lMargin;
10148
+ $this->y = $this->tMargin;
10149
+ $this->FontFamily = '';
10150
+
10151
+ // HEADERS AND FOOTERS // mPDF 6
10152
+ if ($ohvalue < 0 || strtoupper($ohvalue) == 'OFF') {
10153
+ $this->HTMLHeader = '';
10154
+ $resetHTMLHeadersrequired = true;
10155
+ } elseif ($ohname && $ohvalue > 0) {
10156
+ if (preg_match('/^html_(.*)$/i', $ohname, $n)) {
10157
+ $name = $n[1];
10158
+ } else {
10159
+ $name = $ohname;
10160
  }
10161
+ if (isset($this->pageHTMLheaders[$name])) {
10162
+ $this->HTMLHeader = $this->pageHTMLheaders[$name];
10163
+ } else {
10164
+ $this->HTMLHeader = '';
10165
  }
10166
+ $resetHTMLHeadersrequired = true;
10167
  }
10168
 
10169
+ if ($ehvalue < 0 || strtoupper($ehvalue) == 'OFF') {
10170
+ $this->HTMLHeaderE = '';
10171
+ $resetHTMLHeadersrequired = true;
10172
+ } elseif ($ehname && $ehvalue > 0) {
10173
+ if (preg_match('/^html_(.*)$/i', $ehname, $n)) {
10174
+ $name = $n[1];
10175
+ } else {
10176
+ $name = $ehname;
10177
+ }
10178
+ if (isset($this->pageHTMLheaders[$name])) {
10179
+ $this->HTMLHeaderE = $this->pageHTMLheaders[$name];
10180
+ } else {
10181
+ $this->HTMLHeaderE = '';
10182
+ }
10183
+ $resetHTMLHeadersrequired = true;
10184
  }
10185
 
10186
+ if ($ofvalue < 0 || strtoupper($ofvalue) == 'OFF') {
10187
+ $this->HTMLFooter = '';
10188
+ $resetHTMLHeadersrequired = true;
10189
+ } elseif ($ofname && $ofvalue > 0) {
10190
+ if (preg_match('/^html_(.*)$/i', $ofname, $n)) {
10191
+ $name = $n[1];
10192
+ } else {
10193
+ $name = $ofname;
 
 
 
 
 
10194
  }
10195
+ if (isset($this->pageHTMLfooters[$name])) {
10196
+ $this->HTMLFooter = $this->pageHTMLfooters[$name];
10197
+ } else {
10198
+ $this->HTMLFooter = '';
10199
+ }
10200
+ $resetHTMLHeadersrequired = true;
10201
+ }
10202
 
10203
+ if ($efvalue < 0 || strtoupper($efvalue) == 'OFF') {
10204
+ $this->HTMLFooterE = '';
10205
+ $resetHTMLHeadersrequired = true;
10206
+ } elseif ($efname && $efvalue > 0) {
10207
+ if (preg_match('/^html_(.*)$/i', $efname, $n)) {
10208
+ $name = $n[1];
10209
+ } else {
10210
+ $name = $efname;
 
10211
  }
10212
+ if (isset($this->pageHTMLfooters[$name])) {
10213
+ $this->HTMLFooterE = $this->pageHTMLfooters[$name];
10214
+ } else {
10215
+ $this->HTMLFooterE = '';
10216
  }
10217
+ $resetHTMLHeadersrequired = true;
10218
  }
 
10219
 
10220
+ if ($resetHTMLHeadersrequired) {
10221
+ $this->SetHTMLHeader($this->HTMLHeader);
10222
+ $this->SetHTMLHeader($this->HTMLHeaderE, 'E');
10223
+ $this->SetHTMLFooter($this->HTMLFooter);
10224
+ $this->SetHTMLFooter($this->HTMLFooterE, 'E');
10225
+ }
10226
 
 
10227
 
10228
+ if (($this->mirrorMargins) && (($this->page) % 2 == 0)) { // EVEN
10229
+ $this->_setAutoHeaderHeight($this->HTMLHeaderE);
10230
+ $this->_setAutoFooterHeight($this->HTMLFooterE);
10231
+ } else { // ODD or DEFAULT
10232
+ $this->_setAutoHeaderHeight($this->HTMLHeader);
10233
+ $this->_setAutoFooterHeight($this->HTMLFooter);
10234
+ }
10235
 
10236
+ // Reset column top margin
10237
+ $this->y0 = $this->tMargin;
10238
+
10239
+ $this->x = $this->lMargin;
10240
+ $this->y = $this->tMargin;
10241
+ }
10242
+
10243
+ // mPDF 6
10244
+ function _setAutoHeaderHeight(&$htmlh)
10245
+ {
10246
+ /* When the setAutoTopMargin option is set to pad/stretch, only apply auto header height when a header exists */
10247
+ if ($this->HTMLHeader === '' && $this->HTMLHeaderE === '') {
10248
+ return;
 
 
10249
  }
10250
 
10251
+ if ($this->setAutoTopMargin == 'pad') {
10252
+ if (isset($htmlh['h']) && $htmlh['h']) {
10253
+ $h = $htmlh['h'];
10254
+ } // 5.7.3
10255
+ else {
10256
+ $h = 0;
10257
+ }
10258
+ $this->tMargin = $this->margin_header + $h + $this->orig_tMargin;
10259
+ } elseif ($this->setAutoTopMargin == 'stretch') {
10260
+ if (isset($htmlh['h']) && $htmlh['h']) {
10261
+ $h = $htmlh['h'];
10262
+ } // 5.7.3
10263
+ else {
10264
+ $h = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10265
  }
10266
+ $this->tMargin = max($this->orig_tMargin, $this->margin_header + $h + $this->autoMarginPadding);
10267
  }
10268
+ }
10269
 
10270
+ // mPDF 6
10271
+ function _setAutoFooterHeight(&$htmlf)
10272
+ {
10273
+ /* When the setAutoTopMargin option is set to pad/stretch, only apply auto footer height when a footer exists */
10274
+ if ($this->HTMLFooter === '' && $this->HTMLFooterE === '') {
10275
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
10276
  }
10277
 
10278
+ if ($this->setAutoBottomMargin == 'pad') {
10279
+ if (isset($htmlf['h']) && $htmlf['h']) {
10280
+ $h = $htmlf['h'];
10281
+ } // 5.7.3
10282
+ else {
10283
+ $h = 0;
10284
+ }
10285
+ $this->bMargin = $this->margin_footer + $h + $this->orig_bMargin;
10286
+ $this->PageBreakTrigger = $this->h - $this->bMargin;
10287
+ } elseif ($this->setAutoBottomMargin == 'stretch') {
10288
+ if (isset($htmlf['h']) && $htmlf['h']) {
10289
+ $h = $htmlf['h'];
10290
+ } // 5.7.3
10291
+ else {
10292
+ $h = 0;
10293
+ }
10294
+ $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $h + $this->autoMarginPadding);
10295
+ $this->PageBreakTrigger = $this->h - $this->bMargin;
10296
  }
10297
+ }
10298
 
10299
+ function _endpage()
10300
+ {
10301
+ /* -- CSS-IMAGE-FLOAT -- */
10302
+ $this->printfloatbuffer();
10303
+ /* -- END CSS-IMAGE-FLOAT -- */
10304
+
10305
+ if ($this->visibility != 'visible') {
10306
+ $this->SetVisibility('visible');
10307
  }
10308
+ $this->EndLayer();
10309
+ // End of page contents
10310
+ $this->state = 1;
10311
+ }
10312
 
10313
+ function _dounderline($x, $y, $txt, $OTLdata = false, $textvar = 0)
10314
+ {
10315
+ // Now print line exactly where $y secifies - called from Text() and Cell() - adjust position there
10316
+ // WORD SPACING
10317
+ $w = ($this->GetStringWidth($txt, false, $OTLdata, $textvar) * Mpdf::SCALE) + ($this->charspacing * mb_strlen($txt, $this->mb_enc)) + ( $this->ws * mb_substr_count($txt, ' ', $this->mb_enc));
10318
+ // Draw a line
10319
+ return sprintf('%.3F %.3F m %.3F %.3F l S', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, ($x * Mpdf::SCALE) + $w, ($this->h - $y) * Mpdf::SCALE);
10320
+ }
10321
 
 
10322
 
 
 
 
10323
 
10324
+ /* -- WATERMARK -- */
 
 
 
 
10325
 
10326
+ // add a watermark
10327
+ function watermark($texte, $angle = 45, $fontsize = 96, $alpha = 0.2)
10328
+ {
10329
+ if ($this->PDFA || $this->PDFX) {
10330
+ throw new \Mpdf\MpdfException('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!');
10331
  }
10332
 
10333
+ if (!$this->watermark_font) {
10334
+ $this->watermark_font = $this->default_font;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10335
  }
 
10336
 
10337
+ $this->SetFont($this->watermark_font, "B", $fontsize, false); // Don't output
10338
+ $texte = $this->purify_utf8_text($texte);
10339
+
10340
+ if ($this->text_input_as_HTML) {
10341
+ $texte = $this->all_entities_to_utf8($texte);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10342
  }
 
 
10343
 
10344
+ if ($this->usingCoreFont) {
10345
+ $texte = mb_convert_encoding($texte, $this->mb_enc, 'UTF-8');
10346
  }
10347
 
10348
+ // DIRECTIONALITY
10349
+ if (preg_match("/([" . $this->pregRTLchars . "])/u", $texte)) {
10350
+ $this->biDirectional = true;
10351
+ } // *OTL*
10352
 
10353
+ $textvar = 0;
10354
+ $save_OTLtags = $this->OTLtags;
10355
+ $this->OTLtags = [];
10356
+ if ($this->useKerning) {
10357
+ if ($this->CurrentFont['haskernGPOS']) {
10358
+ $this->OTLtags['Plus'] .= ' kern';
10359
  } else {
10360
+ $textvar = ($textvar | TextVars::FC_KERNING);
10361
  }
10362
+ }
10363
 
10364
+ /* -- OTL -- */
10365
+ // Use OTL OpenType Table Layout - GSUB & GPOS
10366
+ if (isset($this->CurrentFont['useOTL']) && $this->CurrentFont['useOTL']) {
10367
+ $texte = $this->otl->applyOTL($texte, $this->CurrentFont['useOTL']);
10368
+ $OTLdata = $this->otl->OTLdata;
10369
+ }
10370
+ /* -- END OTL -- */
10371
+ $this->OTLtags = $save_OTLtags;
10372
 
10373
+ $this->magic_reverse_dir($texte, $this->directionality, $OTLdata);
 
 
 
 
 
 
10374
 
10375
+ $this->SetAlpha($alpha);
10376
 
10377
+ $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings));
10378
 
10379
+ $szfont = $fontsize;
10380
+ $loop = 0;
10381
+ $maxlen = (min($this->w, $this->h) ); // sets max length of text as 7/8 width/height of page
 
 
 
10382
 
10383
+ while ($loop == 0) {
10384
+ $this->SetFont($this->watermark_font, "B", $szfont, false); // Don't output
10385
+ $offset = ((sin(deg2rad($angle))) * ($szfont / Mpdf::SCALE));
 
 
 
10386
 
10387
+ $strlen = $this->GetStringWidth($texte, true, $OTLdata, $textvar);
10388
+ if ($strlen > $maxlen - $offset) {
10389
+ $szfont --;
10390
  } else {
10391
+ $loop ++;
 
 
 
 
 
 
 
 
 
 
 
 
 
10392
  }
10393
+ }
10394
 
10395
+ $this->SetFont($this->watermark_font, "B", $szfont - 0.1, true, true); // Output The -0.1 is because SetFont above is not written to PDF
 
 
10396
 
10397
+ // Repeating it will not output anything as mPDF thinks it is set
10398
+ $adj = ((cos(deg2rad($angle))) * ($strlen / 2));
10399
+ $opp = ((sin(deg2rad($angle))) * ($strlen / 2));
10400
 
10401
+ $wx = ($this->w / 2) - $adj + $offset / 3;
10402
+ $wy = ($this->h / 2) + $opp;
 
 
 
 
 
 
 
10403
 
10404
+ $this->Rotate($angle, $wx, $wy);
10405
+ $this->Text($wx, $wy, $texte, $OTLdata, $textvar);
10406
+ $this->Rotate(0);
10407
+ $this->SetTColor($this->colorConverter->convert(0, $this->PDFAXwarnings));
 
 
10408
 
10409
+ $this->SetAlpha(1);
10410
+ }
 
 
 
 
 
 
 
 
10411
 
10412
+ function watermarkImg($src, $alpha = 0.2)
10413
+ {
10414
+ if ($this->PDFA || $this->PDFX) {
10415
+ throw new \Mpdf\MpdfException('PDFA and PDFX do not permit transparency, so mPDF does not allow Watermarks!');
10416
  }
 
10417
 
10418
+ if ($this->watermarkImgBehind) {
10419
+ $this->watermarkImgAlpha = $this->SetAlpha($alpha, 'Normal', true);
 
10420
  } else {
10421
+ $this->SetAlpha($alpha, $this->watermarkImgAlphaBlend);
 
 
 
10422
  }
10423
 
10424
+ $this->Image($src, 0, 0, 0, 0, '', '', true, true, true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10425
 
10426
+ if (!$this->watermarkImgBehind) {
10427
+ $this->SetAlpha(1);
 
 
10428
  }
10429
+ }
10430
 
10431
+ /* -- END WATERMARK -- */
 
10432
 
10433
+ function Rotate($angle, $x = -1, $y = -1)
10434
+ {
10435
+ if ($x == -1) {
10436
+ $x = $this->x;
10437
+ }
10438
+ if ($y == -1) {
10439
+ $y = $this->y;
10440
+ }
10441
+ if ($this->angle != 0) {
10442
+ $this->writer->write('Q');
10443
+ }
10444
+ $this->angle = $angle;
10445
+ if ($angle != 0) {
10446
+ $angle*=M_PI / 180;
10447
+ $c = cos($angle);
10448
+ $s = sin($angle);
10449
+ $cx = $x * Mpdf::SCALE;
10450
+ $cy = ($this->h - $y) * Mpdf::SCALE;
10451
+ $this->writer->write(sprintf('q %.5F %.5F %.5F %.5F %.3F %.3F cm 1 0 0 1 %.3F %.3F cm', $c, $s, -$s, $c, $cx, $cy, -$cx, -$cy));
10452
+ }
10453
+ }
10454
 
10455
+ function CircularText($x, $y, $r, $text, $align = 'top', $fontfamily = '', $fontsize = 0, $fontstyle = '', $kerning = 120, $fontwidth = 100, $divider = '')
10456
+ {
10457
+ if (empty($this->directWrite)) {
10458
+ $this->directWrite = new DirectWrite($this, $this->otl, $this->sizeConverter, $this->colorConverter);
 
 
10459
  }
10460
 
10461
+ $this->directWrite->CircularText($x, $y, $r, $text, $align, $fontfamily, $fontsize, $fontstyle, $kerning, $fontwidth, $divider);
10462
+ }
 
10463
 
10464
+ // From Invoice
10465
+ function RoundedRect($x, $y, $w, $h, $r, $style = '')
10466
+ {
10467
+ $hp = $this->h;
10468
 
10469
+ if ($style == 'F') {
10470
+ $op = 'f';
10471
+ } elseif ($style == 'FD' or $style == 'DF') {
10472
+ $op = 'B';
10473
+ } else {
10474
+ $op = 'S';
10475
+ }
10476
 
10477
+ $MyArc = 4 / 3 * (sqrt(2) - 1);
10478
+ $this->writer->write(sprintf('%.3F %.3F m', ($x + $r) * Mpdf::SCALE, ($hp - $y) * Mpdf::SCALE));
10479
+ $xc = $x + $w - $r;
10480
+ $yc = $y + $r;
10481
+ $this->writer->write(sprintf('%.3F %.3F l', $xc * Mpdf::SCALE, ($hp - $y) * Mpdf::SCALE));
10482
 
10483
+ $this->_Arc($xc + $r * $MyArc, $yc - $r, $xc + $r, $yc - $r * $MyArc, $xc + $r, $yc);
10484
+ $xc = $x + $w - $r;
10485
+ $yc = $y + $h - $r;
10486
+ $this->writer->write(sprintf('%.3F %.3F l', ($x + $w) * Mpdf::SCALE, ($hp - $yc) * Mpdf::SCALE));
10487
 
10488
+ $this->_Arc($xc + $r, $yc + $r * $MyArc, $xc + $r * $MyArc, $yc + $r, $xc, $yc + $r);
10489
+ $xc = $x + $r;
10490
+ $yc = $y + $h - $r;
10491
+ $this->writer->write(sprintf('%.3F %.3F l', $xc * Mpdf::SCALE, ($hp - ($y + $h)) * Mpdf::SCALE));
10492
 
10493
+ $this->_Arc($xc - $r * $MyArc, $yc + $r, $xc - $r, $yc + $r * $MyArc, $xc - $r, $yc);
10494
+ $xc = $x + $r;
10495
+ $yc = $y + $r;
10496
+ $this->writer->write(sprintf('%.3F %.3F l', ($x) * Mpdf::SCALE, ($hp - $yc) * Mpdf::SCALE));
10497
 
10498
+ $this->_Arc($xc - $r, $yc - $r * $MyArc, $xc - $r * $MyArc, $yc - $r, $xc, $yc - $r);
10499
+ $this->writer->write($op);
10500
+ }
10501
 
10502
+ function _Arc($x1, $y1, $x2, $y2, $x3, $y3)
10503
+ {
10504
+ $h = $this->h;
10505
+ $this->writer->write(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x1 * Mpdf::SCALE, ($h - $y1) * Mpdf::SCALE, $x2 * Mpdf::SCALE, ($h - $y2) * Mpdf::SCALE, $x3 * Mpdf::SCALE, ($h - $y3) * Mpdf::SCALE));
10506
+ }
10507
 
10508
+ // ====================================================
 
 
10509
 
 
 
10510
 
 
 
 
10511
 
10512
+ /* -- DIRECTW -- */
10513
+ function Shaded_box($text, $font = '', $fontstyle = 'B', $szfont = '', $width = '70%', $style = 'DF', $radius = 2.5, $fill = '#FFFFFF', $color = '#000000', $pad = 2)
10514
+ {
10515
+ // F (shading - no line),S (line, no shading),DF (both)
10516
+ if (empty($this->directWrite)) {
10517
+ $this->directWrite = new DirectWrite($this, $this->otl, $this->sizeConverter, $this->colorConverter);
 
 
 
 
 
 
 
 
 
 
10518
  }
10519
+ $this->directWrite->Shaded_box($text, $font, $fontstyle, $szfont, $width, $style, $radius, $fill, $color, $pad);
10520
+ }
10521
 
10522
+ /* -- END DIRECTW -- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10523
 
10524
+ function UTF8StringToArray($str, $addSubset = true)
10525
+ {
10526
+ $out = [];
10527
+ $len = strlen($str);
10528
+ for ($i = 0; $i < $len; $i++) {
10529
+ $uni = -1;
10530
+ $h = ord($str[$i]);
10531
+ if ($h <= 0x7F) {
10532
+ $uni = $h;
10533
+ } elseif ($h >= 0xC2) {
10534
+ if (($h <= 0xDF) && ($i < $len - 1)) {
10535
+ $uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
10536
+ } elseif (($h <= 0xEF) && ($i < $len - 2)) {
10537
+ $uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
10538
+ } elseif (($h <= 0xF4) && ($i < $len - 3)) {
10539
+ $uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
10540
+ }
10541
  }
10542
+ if ($uni >= 0) {
10543
+ $out[] = $uni;
10544
+ if ($addSubset && isset($this->CurrentFont['subset'])) {
10545
+ $this->CurrentFont['subset'][$uni] = $uni;
10546
+ }
10547
  }
 
10548
  }
10549
+ return $out;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10550
  }
10551
 
10552
+ // Convert utf-8 string to <HHHHHH> for Font Subsets
10553
+ function UTF8toSubset($str)
10554
  {
10555
+ $ret = '<';
10556
+ // $str = preg_replace('/'.preg_quote($this->aliasNbPg,'/').'/', chr(7), $str ); // mPDF 6 deleted
10557
+ // $str = preg_replace('/'.preg_quote($this->aliasNbPgGp,'/').'/', chr(8), $str ); // mPDF 6 deleted
10558
+ $unicode = $this->UTF8StringToArray($str);
10559
+ $orig_fid = $this->CurrentFont['subsetfontids'][0];
10560
+ $last_fid = $this->CurrentFont['subsetfontids'][0];
10561
+ foreach ($unicode as $c) {
10562
+ /* // mPDF 6 deleted
10563
+ if ($c == 7 || $c == 8) {
10564
+ if ($orig_fid != $last_fid) {
10565
+ $ret .= '> Tj /F'.$orig_fid.' '.$this->FontSizePt.' Tf <';
10566
+ $last_fid = $orig_fid;
10567
+ }
10568
+ if ($c == 7) { $ret .= $this->aliasNbPgHex; }
10569
+ else { $ret .= $this->aliasNbPgGpHex; }
10570
+ continue;
10571
+ }
10572
+ */
10573
+ if (!$this->_charDefined($this->CurrentFont['cw'], $c)) {
10574
+ $c = 0;
10575
+ } // mPDF 6
10576
+ for ($i = 0; $i < 99; $i++) {
10577
+ // return c as decimal char
10578
+ $init = array_search($c, $this->CurrentFont['subsets'][$i]);
10579
+ if ($init !== false) {
10580
+ if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
10581
+ $ret .= '> Tj /F' . $this->CurrentFont['subsetfontids'][$i] . ' ' . $this->FontSizePt . ' Tf <';
10582
+ $last_fid = $this->CurrentFont['subsetfontids'][$i];
10583
+ }
10584
+ $ret .= sprintf("%02s", strtoupper(dechex($init)));
10585
+ break;
10586
+ } // TrueType embedded SUBSETS
10587
+ elseif (count($this->CurrentFont['subsets'][$i]) < 255) {
10588
+ $n = count($this->CurrentFont['subsets'][$i]);
10589
+ $this->CurrentFont['subsets'][$i][$n] = $c;
10590
+ if ($this->CurrentFont['subsetfontids'][$i] != $last_fid) {
10591
+ $ret .= '> Tj /F' . $this->CurrentFont['subsetfontids'][$i] . ' ' . $this->FontSizePt . ' Tf <';
10592
+ $last_fid = $this->CurrentFont['subsetfontids'][$i];
10593
+ }
10594
+ $ret .= sprintf("%02s", strtoupper(dechex($n)));
10595
+ break;
10596
+ } elseif (!isset($this->CurrentFont['subsets'][($i + 1)])) {
10597
+ // TrueType embedded SUBSETS
10598
+ $this->CurrentFont['subsets'][($i + 1)] = [0 => 0];
10599
+ $new_fid = count($this->fonts) + $this->extraFontSubsets + 1;
10600
+ $this->CurrentFont['subsetfontids'][($i + 1)] = $new_fid;
10601
+ $this->extraFontSubsets++;
10602
+ }
10603
  }
 
10604
  }
10605
+ $ret .= '>';
10606
+ if ($last_fid != $orig_fid) {
10607
+ $ret .= ' Tj /F' . $orig_fid . ' ' . $this->FontSizePt . ' Tf <> ';
10608
+ }
10609
+ return $ret;
10610
  }
10611
 
10612
+ /* -- CJK-FONTS -- */
10613
+
10614
+ // from class PDF_Chinese CJK EXTENSIONS
10615
+ function AddCIDFont($family, $style, $name, &$cw, $CMap, $registry, $desc)
10616
  {
10617
+ $fontkey = strtolower($family) . strtoupper($style);
10618
+ if (isset($this->fonts[$fontkey])) {
10619
+ throw new \Mpdf\MpdfException("Font already added: $family $style");
10620
  }
10621
+ $i = count($this->fonts) + $this->extraFontSubsets + 1;
10622
+ $name = str_replace(' ', '', $name);
10623
+ if ($family == 'sjis') {
10624
+ $up = -120;
10625
+ } else {
10626
+ $up = -130;
 
 
 
 
 
 
 
 
 
 
 
 
 
10627
  }
10628
+ // ? 'up' and 'ut' do not seem to be referenced anywhere
10629
+ $this->fonts[$fontkey] = ['i' => $i, 'type' => 'Type0', 'name' => $name, 'up' => $up, 'ut' => 40, 'cw' => $cw, 'CMap' => $CMap, 'registry' => $registry, 'MissingWidth' => 1000, 'desc' => $desc];
10630
  }
10631
 
10632
+ function AddCJKFont($family)
10633
  {
 
 
 
10634
 
10635
+ if ($this->PDFA || $this->PDFX) {
10636
+ throw new \Mpdf\MpdfException("Adobe CJK fonts cannot be embedded in mPDF (required for PDFA1-b and PDFX/1-a).");
10637
+ }
10638
+ if ($family == 'big5') {
10639
+ $this->AddBig5Font();
10640
+ } elseif ($family == 'gb') {
10641
+ $this->AddGBFont();
10642
+ } elseif ($family == 'sjis') {
10643
+ $this->AddSJISFont();
10644
+ } elseif ($family == 'uhc') {
10645
+ $this->AddUHCFont();
10646
  }
 
 
 
10647
  }
10648
 
10649
+ function AddBig5Font()
10650
  {
10651
+ // Add Big5 font with proportional Latin
10652
+ $family = 'big5';
10653
+ $name = 'MSungStd-Light-Acro';
10654
+ $cw = $this->Big5_widths;
10655
+ $CMap = 'UniCNS-UTF16-H';
10656
+ $registry = ['ordering' => 'CNS1', 'supplement' => 4];
10657
+ $desc = [
10658
+ 'Ascent' => 880,
10659
+ 'Descent' => -120,
10660
+ 'CapHeight' => 880,
10661
+ 'Flags' => 6,
10662
+ 'FontBBox' => '[-160 -249 1015 1071]',
10663
+ 'ItalicAngle' => 0,
10664
+ 'StemV' => 93,
10665
+ ];
10666
+ $this->AddCIDFont($family, '', $name, $cw, $CMap, $registry, $desc);
10667
+ $this->AddCIDFont($family, 'B', $name . ',Bold', $cw, $CMap, $registry, $desc);
10668
+ $this->AddCIDFont($family, 'I', $name . ',Italic', $cw, $CMap, $registry, $desc);
10669
+ $this->AddCIDFont($family, 'BI', $name . ',BoldItalic', $cw, $CMap, $registry, $desc);
10670
  }
10671
 
10672
+ function AddGBFont()
10673
  {
10674
+ // Add GB font with proportional Latin
10675
+ $family = 'gb';
10676
+ $name = 'STSongStd-Light-Acro';
10677
+ $cw = $this->GB_widths;
10678
+ $CMap = 'UniGB-UTF16-H';
10679
+ $registry = ['ordering' => 'GB1', 'supplement' => 4];
10680
+ $desc = [
10681
+ 'Ascent' => 880,
10682
+ 'Descent' => -120,
10683
+ 'CapHeight' => 737,
10684
+ 'Flags' => 6,
10685
+ 'FontBBox' => '[-25 -254 1000 880]',
10686
+ 'ItalicAngle' => 0,
10687
+ 'StemV' => 58,
10688
+ 'Style' => '<< /Panose <000000000400000000000000> >>',
10689
+ ];
10690
+ $this->AddCIDFont($family, '', $name, $cw, $CMap, $registry, $desc);
10691
+ $this->AddCIDFont($family, 'B', $name . ',Bold', $cw, $CMap, $registry, $desc);
10692
+ $this->AddCIDFont($family, 'I', $name . ',Italic', $cw, $CMap, $registry, $desc);
10693
+ $this->AddCIDFont($family, 'BI', $name . ',BoldItalic', $cw, $CMap, $registry, $desc);
10694
  }
10695
 
10696
+ function AddSJISFont()
10697
  {
10698
+ // Add SJIS font with proportional Latin
10699
+ $family = 'sjis';
10700
+ $name = 'KozMinPro-Regular-Acro';
10701
+ $cw = $this->SJIS_widths;
10702
+ $CMap = 'UniJIS-UTF16-H';
10703
+ $registry = ['ordering' => 'Japan1', 'supplement' => 5];
10704
+ $desc = [
10705
+ 'Ascent' => 880,
10706
+ 'Descent' => -120,
10707
+ 'CapHeight' => 740,
10708
+ 'Flags' => 6,
10709
+ 'FontBBox' => '[-195 -272 1110 1075]',
10710
+ 'ItalicAngle' => 0,
10711
+ 'StemV' => 86,
10712
+ 'XHeight' => 502,
10713
+ ];
10714
+ $this->AddCIDFont($family, '', $name, $cw, $CMap, $registry, $desc);
10715
+ $this->AddCIDFont($family, 'B', $name . ',Bold', $cw, $CMap, $registry, $desc);
10716
+ $this->AddCIDFont($family, 'I', $name . ',Italic', $cw, $CMap, $registry, $desc);
10717
+ $this->AddCIDFont($family, 'BI', $name . ',BoldItalic', $cw, $CMap, $registry, $desc);
 
10718
  }
10719
 
10720
+ function AddUHCFont()
10721
  {
10722
+ // Add UHC font with proportional Latin
10723
+ $family = 'uhc';
10724
+ $name = 'HYSMyeongJoStd-Medium-Acro';
10725
+ $cw = $this->UHC_widths;
10726
+ $CMap = 'UniKS-UTF16-H';
10727
+ $registry = ['ordering' => 'Korea1', 'supplement' => 2];
10728
+ $desc = [
10729
+ 'Ascent' => 880,
10730
+ 'Descent' => -120,
10731
+ 'CapHeight' => 720,
10732
+ 'Flags' => 6,
10733
+ 'FontBBox' => '[-28 -148 1001 880]',
10734
+ 'ItalicAngle' => 0,
10735
+ 'StemV' => 60,
10736
+ 'Style' => '<< /Panose <000000000600000000000000> >>',
10737
+ ];
10738
+ $this->AddCIDFont($family, '', $name, $cw, $CMap, $registry, $desc);
10739
+ $this->AddCIDFont($family, 'B', $name . ',Bold', $cw, $CMap, $registry, $desc);
10740
+ $this->AddCIDFont($family, 'I', $name . ',Italic', $cw, $CMap, $registry, $desc);
10741
+ $this->AddCIDFont($family, 'BI', $name . ',BoldItalic', $cw, $CMap, $registry, $desc);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10742
  }
10743
 
10744
+ /* -- END CJK-FONTS -- */
 
 
 
 
 
 
 
 
10745
 
10746
+ //////////////////////////////////////////////////////////////////////////////
10747
+ //////////////////////////////////////////////////////////////////////////////
10748
+ //////////////////////////////////////////////////////////////////////////////
10749
+ //////////////////////////////////////////////////////////////////////////////
10750
+ //////////////////////////////////////////////////////////////////////////////
10751
+ //////////////////////////////////////////////////////////////////////////////
10752
+ //////////////////////////////////////////////////////////////////////////////
10753
 
10754
+ function SetDefaultFont($font)
10755
+ {
10756
+ // Disallow embedded fonts to be used as defaults in PDFA
10757
+ if ($this->PDFA || $this->PDFX) {
10758
+ if (strtolower($font) == 'ctimes') {
10759
+ $font = 'serif';
10760
+ }
10761
+ if (strtolower($font) == 'ccourier') {
10762
+ $font = 'monospace';
10763
+ }
10764
+ if (strtolower($font) == 'chelvetica') {
10765
+ $font = 'sans-serif';
10766
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10767
  }
10768
+ $font = $this->SetFont($font); // returns substituted font if necessary
10769
+ $this->default_font = $font;
10770
+ $this->original_default_font = $font;
10771
+ if (!$this->watermark_font) {
10772
+ $this->watermark_font = $font;
10773
+ } // *WATERMARK*
10774
+ $this->defaultCSS['BODY']['FONT-FAMILY'] = $font;
10775
+ $this->cssManager->CSS['BODY']['FONT-FAMILY'] = $font;
10776
  }
10777
 
10778
+ function SetDefaultFontSize($fontsize)
10779
  {
10780
+ $this->default_font_size = $fontsize;
10781
+ $this->original_default_font_size = $fontsize;
10782
+ $this->SetFontSize($fontsize);
10783
+ $this->defaultCSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
10784
+ $this->cssManager->CSS['BODY']['FONT-SIZE'] = $fontsize . 'pt';
 
10785
  }
10786
 
10787
+ function SetDefaultBodyCSS($prop, $val)
10788
  {
10789
+ if ($prop) {
10790
+ $this->defaultCSS['BODY'][strtoupper($prop)] = $val;
10791
+ $this->cssManager->CSS['BODY'][strtoupper($prop)] = $val;
10792
  }
 
 
10793
  }
10794
 
10795
+ function SetDirectionality($dir = 'ltr')
10796
  {
10797
+ /* -- OTL -- */
10798
+ if (strtolower($dir) == 'rtl') {
10799
+ if ($this->directionality != 'rtl') {
10800
+ // Swop L/R Margins so page 1 RTL is an 'even' page
10801
+ $tmp = $this->DeflMargin;
10802
+ $this->DeflMargin = $this->DefrMargin;
10803
+ $this->DefrMargin = $tmp;
10804
+ $this->orig_lMargin = $this->DeflMargin;
10805
+ $this->orig_rMargin = $this->DefrMargin;
10806
 
10807
+ $this->SetMargins($this->DeflMargin, $this->DefrMargin, $this->tMargin);
10808
+ }
10809
+ $this->directionality = 'rtl';
10810
+ $this->defaultAlign = 'R';
10811
+ $this->defaultTableAlign = 'R';
10812
+ } else {
10813
+ /* -- END OTL -- */
10814
+ $this->directionality = 'ltr';
10815
+ $this->defaultAlign = 'L';
10816
+ $this->defaultTableAlign = 'L';
10817
+ } // *OTL*
10818
+ $this->cssManager->CSS['BODY']['DIRECTION'] = $this->directionality;
10819
  }
10820
 
10821
+ // Return either a number (factor) - based on current set fontsize (if % or em) - or exact lineheight (with 'mm' after it)
10822
+ function fixLineheight($v)
10823
  {
10824
+ $lh = false;
10825
+ if (preg_match('/^[0-9\.,]*$/', $v) && $v >= 0) {
10826
+ return ($v + 0);
10827
+ } elseif (strtoupper($v) == 'NORMAL' || $v == 'N') {
10828
+ return 'N'; // mPDF 6
10829
+ } else {
10830
+ $tlh = $this->sizeConverter->convert($v, $this->FontSize, $this->FontSize, true);
10831
+ if ($tlh) {
10832
+ return ($tlh . 'mm');
10833
+ }
10834
+ }
10835
+ return $this->normalLineheight;
10836
  }
10837
 
10838
+ function _getNormalLineheight($desc = false)
10839
  {
10840
+ if (!$desc) {
10841
+ $desc = $this->CurrentFont['desc'];
10842
+ }
10843
+ if (!isset($desc['Leading'])) {
10844
+ $desc['Leading'] = 0;
10845
+ }
10846
+ if ($this->useFixedNormalLineHeight) {
10847
+ $lh = $this->normalLineheight;
10848
+ } elseif (isset($desc['Ascent']) && $desc['Ascent']) {
10849
+ $lh = ($this->adjustFontDescLineheight * ($desc['Ascent'] - $desc['Descent'] + $desc['Leading']) / 1000);
10850
+ } else {
10851
+ $lh = $this->normalLineheight;
10852
+ }
10853
+ return $lh;
10854
  }
10855
 
10856
+ // Set a (fixed) lineheight to an actual value - either to named fontsize(pts) or default
10857
+ function SetLineHeight($FontPt = '', $lh = '')
10858
  {
10859
+ if (!$FontPt) {
10860
+ $FontPt = $this->FontSizePt;
10861
  }
10862
+ $fs = $FontPt / Mpdf::SCALE;
10863
+ $this->lineheight = $this->_computeLineheight($lh, $fs);
 
 
10864
  }
10865
 
10866
+ function _computeLineheight($lh, $fs = '')
10867
  {
10868
+ if ($this->shrin_k > 1) {
10869
+ $k = $this->shrin_k;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10870
  } else {
10871
+ $k = 1;
10872
+ }
10873
+ if (!$fs) {
10874
+ $fs = $this->FontSize;
10875
+ }
10876
+ if ($lh == 'N') {
10877
+ $lh = $this->_getNormalLineheight();
10878
+ }
10879
+ if (preg_match('/mm/', $lh)) {
10880
+ return (((float) $lh) / $k); // convert to number
10881
+ } elseif ($lh > 0) {
10882
+ return ($fs * $lh);
10883
  }
10884
+ return ($fs * $this->normalLineheight);
10885
  }
10886
 
10887
+ function _setLineYpos(&$fontsize, &$fontdesc, &$CSSlineheight, $blockYpos = false)
 
 
 
10888
  {
10889
+ $ypos['glyphYorigin'] = 0;
10890
+ $ypos['baseline-shift'] = 0;
10891
+ $linegap = 0;
10892
+ $leading = 0;
10893
 
10894
+ if (isset($fontdesc['Ascent']) && $fontdesc['Ascent'] && !$this->useFixedTextBaseline) {
10895
+ // Fontsize uses font metrics - this method seems to produce results compatible with browsers (except IE9)
10896
+ $ypos['boxtop'] = $fontdesc['Ascent'] / 1000 * $fontsize;
10897
+ $ypos['boxbottom'] = $fontdesc['Descent'] / 1000 * $fontsize;
10898
+ if (isset($fontdesc['Leading'])) {
10899
+ $linegap = $fontdesc['Leading'] / 1000 * $fontsize;
10900
+ }
10901
+ } // Default if not set - uses baselineC
10902
+ else {
10903
+ $ypos['boxtop'] = (0.5 + $this->baselineC) * $fontsize;
10904
+ $ypos['boxbottom'] = -(0.5 - $this->baselineC) * $fontsize;
10905
  }
10906
+ $fontheight = $ypos['boxtop'] - $ypos['boxbottom'];
10907
 
10908
+ if ($this->shrin_k > 1) {
10909
+ $shrin_k = $this->shrin_k;
10910
+ } else {
10911
+ $shrin_k = 1;
 
10912
  }
10913
 
10914
+ $leading = 0;
10915
+ if ($CSSlineheight == 'N') {
10916
+ $lh = $this->_getNormalLineheight($fontdesc);
10917
+ $lineheight = ($fontsize * $lh);
10918
+ $leading += $linegap; // specified in hhea or sTypo in OpenType tables
10919
+ } elseif (preg_match('/mm/', $CSSlineheight)) {
10920
+ $lineheight = (((float) $CSSlineheight) / $shrin_k); // convert to number
10921
+ } // ??? If lineheight is a factor e.g. 1.3 ?? use factor x 1em or ? use 'normal' lineheight * factor
10922
+ // Could depend on value for $text_height - a draft CSS value as set above for now
10923
+ elseif ($CSSlineheight > 0) {
10924
+ $lineheight = ($fontsize * $CSSlineheight);
10925
+ } else {
10926
+ $lineheight = ($fontsize * $this->normalLineheight);
10927
  }
10928
 
10929
+ // In general, calculate the "leading" - the difference between the fontheight and the lineheight
10930
+ // and add half to the top and half to the bottom. BUT
10931
+ // If an inline element has a font-size less than the block element, and the line-height is set as an em or % value
10932
+ // it will add too much leading below the font and expand the height of the line - so just use the block element exttop/extbottom:
10933
+ if (preg_match('/mm/', $CSSlineheight) && $ypos['boxtop'] < $blockYpos['boxtop'] && $ypos['boxbottom'] > $blockYpos['boxbottom']) {
10934
+ $ypos['exttop'] = $blockYpos['exttop'];
10935
+ $ypos['extbottom'] = $blockYpos['extbottom'];
10936
+ } else {
10937
+ $leading += ($lineheight - $fontheight);
 
 
 
 
 
 
10938
 
10939
+ $ypos['exttop'] = $ypos['boxtop'] + $leading / 2;
10940
+ $ypos['extbottom'] = $ypos['boxbottom'] - $leading / 2;
 
 
 
10941
  }
 
 
10942
 
 
10943
 
10944
+ // TEMP ONLY FOR DEBUGGING *********************************
10945
+ // $ypos['lineheight'] = $lineheight;
10946
+ // $ypos['fontheight'] = $fontheight;
10947
+ // $ypos['leading'] = $leading;
10948
 
10949
+ return $ypos;
10950
+ }
10951
 
10952
+ /* Called from WriteFlowingBlock() and finishFlowingBlock()
10953
+ Determines the line hieght and glyph/writing position
10954
+ for each element in the line to be written */
10955
 
10956
+ function _setInlineBlockHeights(&$lineBox, &$stackHeight, &$content, &$font, $is_table)
10957
+ {
10958
+ if ($this->shrin_k > 1) {
10959
+ $shrin_k = $this->shrin_k;
10960
+ } else {
10961
+ $shrin_k = 1;
10962
+ }
10963
 
10964
+ $ypos = [];
10965
+ $bordypos = [];
10966
+ $bgypos = [];
10967
+
10968
+ if ($is_table) {
10969
+ // FOR TABLE
10970
+ $fontsize = $this->FontSize;
10971
+ $fontkey = $this->FontFamily . $this->FontStyle;
10972
+ $fontdesc = $this->fonts[$fontkey]['desc'];
10973
+ $CSSlineheight = $this->cellLineHeight;
10974
+ $line_stacking_strategy = $this->cellLineStackingStrategy; // inline-line-height [default] | block-line-height | max-height | grid-height
10975
+ $line_stacking_shift = $this->cellLineStackingShift; // consider-shifts [default] | disregard-shifts
10976
+ } else {
10977
+ // FOR BLOCK FONT
10978
+ $fontsize = $this->blk[$this->blklvl]['InlineProperties']['size'];
10979
+ $fontkey = $this->blk[$this->blklvl]['InlineProperties']['family'] . $this->blk[$this->blklvl]['InlineProperties']['style'];
10980
+ $fontdesc = $this->fonts[$fontkey]['desc'];
10981
+ $CSSlineheight = $this->blk[$this->blklvl]['line_height'];
10982
+ // inline-line-height | block-line-height | max-height | grid-height
10983
+ $line_stacking_strategy = (isset($this->blk[$this->blklvl]['line_stacking_strategy']) ? $this->blk[$this->blklvl]['line_stacking_strategy'] : 'inline-line-height');
10984
+ // consider-shifts | disregard-shifts
10985
+ $line_stacking_shift = (isset($this->blk[$this->blklvl]['line_stacking_shift']) ? $this->blk[$this->blklvl]['line_stacking_shift'] : 'consider-shifts');
10986
  }
10987
+ $boxLineHeight = $this->_computeLineheight($CSSlineheight, $fontsize);
10988
 
 
10989
 
10990
+ // First, set a "strut" using block font at index $lineBox[-1]
10991
+ $ypos[-1] = $this->_setLineYpos($fontsize, $fontdesc, $CSSlineheight);
 
10992
 
10993
+ // for the block element - always taking the block EXTENDED progression including leading - which may be negative
10994
+ if ($line_stacking_strategy == 'block-line-height') {
10995
+ $topy = $ypos[-1]['exttop'];
10996
+ $bottomy = $ypos[-1]['extbottom'];
10997
+ } else {
10998
+ $topy = 0;
10999
+ $bottomy = 0;
11000
+ }
11001
 
11002
+ // Get text-middle for aligning images/objects
11003
+ $midpoint = $ypos[-1]['boxtop'] - (($ypos[-1]['boxtop'] - $ypos[-1]['boxbottom']) / 2);
 
 
11004
 
11005
+ // for images / inline objects / replaced elements
11006
+ $mta = 0; // Maximum top-aligned
11007
+ $mba = 0; // Maximum bottom-aligned
11008
+ foreach ($content as $k => $chunk) {
11009
+ if (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]['type'] == 'listmarker') {
11010
+ $ypos[$k] = $ypos[-1];
11011
+ // UPDATE Maximums
11012
+ if ($line_stacking_strategy == 'block-line-height' || $line_stacking_strategy == 'grid-height' || $line_stacking_strategy == 'max-height') { // don't include extended block progression of all inline elements
11013
+ if ($ypos[$k]['boxtop'] > $topy) {
11014
+ $topy = $ypos[$k]['boxtop'];
11015
+ }
11016
+ if ($ypos[$k]['boxbottom'] < $bottomy) {
11017
+ $bottomy = $ypos[$k]['boxbottom'];
11018
+ }
11019
+ } else {
11020
+ if ($ypos[$k]['exttop'] > $topy) {
11021
+ $topy = $ypos[$k]['exttop'];
11022
+ }
11023
+ if ($ypos[$k]['extbottom'] < $bottomy) {
11024
+ $bottomy = $ypos[$k]['extbottom'];
11025
+ }
11026
+ }
11027
+ } elseif (isset($this->objectbuffer[$k]) && $this->objectbuffer[$k]['type'] == 'dottab') { // mPDF 6 DOTTAB
11028
+ $fontsize = $font[$k]['size'];
11029
+ $fontdesc = $font[$k]['curr']['desc'];
11030
+ $lh = 1;
11031
+ $ypos[$k] = $this->_setLineYpos($fontsize, $fontdesc, $lh, $ypos[-1]); // Lineheight=1 fixed
11032
+ } elseif (isset($this->objectbuffer[$k])) {
11033
+ $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
11034
+ $va = $this->objectbuffer[$k]['vertical-align'];
11035
 
11036
+ if ($va == 'BS') { // (BASELINE default)
11037
+ if ($oh > $topy) {
11038
+ $topy = $oh;
11039
+ }
11040
+ } elseif ($va == 'M') {
11041
+ if (($midpoint + $oh / 2) > $topy) {
11042
+ $topy = $midpoint + $oh / 2;
11043
+ }
11044
+ if (($midpoint - $oh / 2) < $bottomy) {
11045
+ $bottomy = $midpoint - $oh / 2;
11046
+ }
11047
+ } elseif ($va == 'TT') {
11048
+ if (($ypos[-1]['boxtop'] - $oh) < $bottomy) {
11049
+ $bottomy = $ypos[-1]['boxtop'] - $oh;
11050
+ $topy = max($topy, $ypos[-1]['boxtop']);
11051
+ }
11052
+ } elseif ($va == 'TB') {
11053
+ if (($ypos[-1]['boxbottom'] + $oh) > $topy) {
11054
+ $topy = $ypos[-1]['boxbottom'] + $oh;
11055
+ $bottomy = min($bottomy, $ypos[-1]['boxbottom']);
11056
+ }
11057
+ } elseif ($va == 'T') {
11058
+ if ($oh > $mta) {
11059
+ $mta = $oh;
11060
+ }
11061
+ } elseif ($va == 'B') {
11062
+ if ($oh > $mba) {
11063
+ $mba = $oh;
11064
+ }
11065
+ }
11066
+ } elseif ($content[$k] || $content[$k] === '0') {
11067
+ // FOR FLOWING BLOCK
11068
+ $fontsize = $font[$k]['size'];
11069
+ $fontdesc = $font[$k]['curr']['desc'];
11070
+ // In future could set CSS line-height from inline elements; for now, use block level:
11071
+ $ypos[$k] = $this->_setLineYpos($fontsize, $fontdesc, $CSSlineheight, $ypos[-1]);
11072
 
11073
+ if (isset($font[$k]['textparam']['text-baseline']) && $font[$k]['textparam']['text-baseline'] != 0) {
11074
+ $ypos[$k]['baseline-shift'] = $font[$k]['textparam']['text-baseline'];
11075
+ }
 
 
11076
 
11077
+ // DO ALIGNMENT FOR BASELINES *******************
11078
+ // Until most fonts have OpenType BASE tables, this won't work
11079
+ // $ypos[$k] compared to $ypos[-1] or $ypos[$k-1] using $dominant_baseline and $baseline_table
11080
+ // UPDATE Maximums
11081
+ if ($line_stacking_strategy == 'block-line-height' || $line_stacking_strategy == 'grid-height' || $line_stacking_strategy == 'max-height') { // don't include extended block progression of all inline elements
11082
+ if ($line_stacking_shift == 'disregard-shifts') {
11083
+ if ($ypos[$k]['boxtop'] > $topy) {
11084
+ $topy = $ypos[$k]['boxtop'];
11085
+ }
11086
+ if ($ypos[$k]['boxbottom'] < $bottomy) {
11087
+ $bottomy = $ypos[$k]['boxbottom'];
11088
+ }
11089
+ } else {
11090
+ if (($ypos[$k]['boxtop'] + $ypos[$k]['baseline-shift']) > $topy) {
11091
+ $topy = $ypos[$k]['boxtop'] + $ypos[$k]['baseline-shift'];
11092
+ }
11093
+ if (($ypos[$k]['boxbottom'] + $ypos[$k]['baseline-shift']) < $bottomy) {
11094
+ $bottomy = $ypos[$k]['boxbottom'] + $ypos[$k]['baseline-shift'];
11095
+ }
11096
+ }
11097
+ } else {
11098
+ if ($line_stacking_shift == 'disregard-shifts') {
11099
+ if ($ypos[$k]['exttop'] > $topy) {
11100
+ $topy = $ypos[$k]['exttop'];
11101
+ }
11102
+ if ($ypos[$k]['extbottom'] < $bottomy) {
11103
+ $bottomy = $ypos[$k]['extbottom'];
11104
+ }
11105
+ } else {
11106
+ if (($ypos[$k]['exttop'] + $ypos[$k]['baseline-shift']) > $topy) {
11107
+ $topy = $ypos[$k]['exttop'] + $ypos[$k]['baseline-shift'];
11108
+ }
11109
+ if (($ypos[$k]['extbottom'] + $ypos[$k]['baseline-shift']) < $bottomy) {
11110
+ $bottomy = $ypos[$k]['extbottom'] + $ypos[$k]['baseline-shift'];
11111
+ }
11112
+ }
11113
+ }
11114
 
11115
+ // If BORDER set on inline element
11116
+ if (isset($font[$k]['bord']) && $font[$k]['bord']) {
11117
+ $bordfontsize = $font[$k]['textparam']['bord-decoration']['fontsize'] / $shrin_k;
11118
+ $bordfontkey = $font[$k]['textparam']['bord-decoration']['fontkey'];
11119
+ if ($bordfontkey != $fontkey || $bordfontsize != $fontsize || isset($font[$k]['textparam']['bord-decoration']['baseline'])) {
11120
+ $bordfontdesc = $this->fonts[$bordfontkey]['desc'];
11121
+ $bordypos[$k] = $this->_setLineYpos($bordfontsize, $bordfontdesc, $CSSlineheight, $ypos[-1]);
11122
+ if (isset($font[$k]['textparam']['bord-decoration']['baseline']) && $font[$k]['textparam']['bord-decoration']['baseline'] != 0) {
11123
+ $bordypos[$k]['baseline-shift'] = $font[$k]['textparam']['bord-decoration']['baseline'] / $shrin_k;
11124
+ }
11125
+ }
11126
+ }
11127
+ // If BACKGROUND set on inline element
11128
+ if (isset($font[$k]['spanbgcolor']) && $font[$k]['spanbgcolor']) {
11129
+ $bgfontsize = $font[$k]['textparam']['bg-decoration']['fontsize'] / $shrin_k;
11130
+ $bgfontkey = $font[$k]['textparam']['bg-decoration']['fontkey'];
11131
+ if ($bgfontkey != $fontkey || $bgfontsize != $fontsize || isset($font[$k]['textparam']['bg-decoration']['baseline'])) {
11132
+ $bgfontdesc = $this->fonts[$bgfontkey]['desc'];
11133
+ $bgypos[$k] = $this->_setLineYpos($bgfontsize, $bgfontdesc, $CSSlineheight, $ypos[-1]);
11134
+ if (isset($font[$k]['textparam']['bg-decoration']['baseline']) && $font[$k]['textparam']['bg-decoration']['baseline'] != 0) {
11135
+ $bgypos[$k]['baseline-shift'] = $font[$k]['textparam']['bg-decoration']['baseline'] / $shrin_k;
11136
+ }
11137
+ }
11138
+ }
11139
+ }
11140
  }
 
11141
 
 
11142
 
11143
+ // TOP or BOTTOM aligned images
11144
+ if ($mta > ($topy - $bottomy)) {
11145
+ if (($topy - $mta) < $bottomy) {
11146
+ $bottomy = $topy - $mta;
11147
+ }
 
 
 
 
 
11148
  }
11149
+ if ($mba > ($topy - $bottomy)) {
11150
+ if (($bottomy + $mba) > $topy) {
11151
+ $topy = $bottomy + $mba;
11152
+ }
 
 
 
 
11153
  }
 
11154
 
11155
+ if ($line_stacking_strategy == 'block-line-height') { // fixed height set by block element (whether present or not)
11156
+ $topy = $ypos[-1]['exttop'];
11157
+ $bottomy = $ypos[-1]['extbottom'];
 
11158
  }
11159
 
11160
+ $inclusiveHeight = $topy - $bottomy;
 
 
 
 
 
 
11161
 
11162
+ // SET $stackHeight taking note of line_stacking_strategy
11163
+ // NB inclusive height already takes account of need to consider block progression height (excludes leading set by lineheight)
11164
+ // or extended block progression height (includes leading set by lineheight)
11165
+ if ($line_stacking_strategy == 'block-line-height') { // fixed = extended block progression height of block element
11166
+ $stackHeight = $boxLineHeight;
11167
+ } elseif ($line_stacking_strategy == 'max-height') { // smallest height which includes extended block progression height of block element
11168
+ // and block progression heights of inline elements (NOT extended)
11169
+ $stackHeight = $inclusiveHeight;
11170
+ } elseif ($line_stacking_strategy == 'grid-height') { // smallest multiple of block element lineheight to include
11171
+ // block progression heights of inline elements (NOT extended)
11172
+ $stackHeight = $boxLineHeight;
11173
+ while ($stackHeight < $inclusiveHeight) {
11174
+ $stackHeight += $boxLineHeight;
11175
+ }
11176
+ } else { // 'inline-line-height' = default // smallest height which includes extended block progression height of block element
11177
+ // AND extended block progression heights of inline elements
11178
+ $stackHeight = $inclusiveHeight;
11179
  }
11180
 
11181
+ $diff = $stackHeight - $inclusiveHeight;
11182
+ $topy += $diff / 2;
11183
+ $bottomy -= $diff / 2;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11184
 
11185
+ // ADJUST $ypos => lineBox using $stackHeight; lineBox are all offsets from the top of stackHeight in mm
11186
+ // and SET IMAGE OFFSETS
11187
+ $lineBox[-1]['boxtop'] = $topy - $ypos[-1]['boxtop'];
11188
+ $lineBox[-1]['boxbottom'] = $topy - $ypos[-1]['boxbottom'];
11189
+ // $lineBox[-1]['exttop'] = $topy - $ypos[-1]['exttop'];
11190
+ // $lineBox[-1]['extbottom'] = $topy - $ypos[-1]['extbottom'];
11191
+ $lineBox[-1]['glyphYorigin'] = $topy - $ypos[-1]['glyphYorigin'];
11192
+ $lineBox[-1]['baseline-shift'] = $ypos[-1]['baseline-shift'];
11193
 
11194
+ $midpoint = $lineBox[-1]['boxbottom'] - (($lineBox[-1]['boxbottom'] - $lineBox[-1]['boxtop']) / 2);
 
 
 
 
 
 
 
 
11195
 
11196
+ foreach ($content as $k => $chunk) {
11197
+ if (isset($this->objectbuffer[$k])) {
11198
+ $oh = $this->objectbuffer[$k]['OUTER-HEIGHT'];
11199
+ // LIST MARKERS
11200
+ if ($this->objectbuffer[$k]['type'] == 'listmarker') {
11201
+ $oh = $fontsize;
11202
+ } elseif ($this->objectbuffer[$k]['type'] == 'dottab') { // mPDF 6 DOTTAB
11203
+ $oh = $font[$k]['size']; // == $this->objectbuffer[$k]['fontsize']/Mpdf::SCALE;
11204
+ $lineBox[$k]['boxtop'] = $topy - $ypos[$k]['boxtop'];
11205
+ $lineBox[$k]['boxbottom'] = $topy - $ypos[$k]['boxbottom'];
11206
+ $lineBox[$k]['glyphYorigin'] = $topy - $ypos[$k]['glyphYorigin'];
11207
+ $lineBox[$k]['baseline-shift'] = 0;
11208
+ // continue;
11209
+ }
11210
+ $va = $this->objectbuffer[$k]['vertical-align']; // = $objattr['vertical-align'] = set as M,T,B,S
11211
 
11212
+ if ($va == 'BS') { // (BASELINE default)
11213
+ $lineBox[$k]['top'] = $lineBox[-1]['glyphYorigin'] - $oh;
11214
+ } elseif ($va == 'M') {
11215
+ $lineBox[$k]['top'] = $midpoint - $oh / 2;
11216
+ } elseif ($va == 'TT') {
11217
+ $lineBox[$k]['top'] = $lineBox[-1]['boxtop'];
11218
+ } elseif ($va == 'TB') {
11219
+ $lineBox[$k]['top'] = $lineBox[-1]['boxbottom'] - $oh;
11220
+ } elseif ($va == 'T') {
11221
+ $lineBox[$k]['top'] = 0;
11222
+ } elseif ($va == 'B') {
11223
+ $lineBox[$k]['top'] = $stackHeight - $oh;
 
 
 
 
11224
  }
11225
+ } elseif ($content[$k] || $content[$k] === '0') {
11226
+ $lineBox[$k]['boxtop'] = $topy - $ypos[$k]['boxtop'];
11227
+ $lineBox[$k]['boxbottom'] = $topy - $ypos[$k]['boxbottom'];
11228
+ // $lineBox[$k]['exttop'] = $topy - $ypos[$k]['exttop'];
11229
+ // $lineBox[$k]['extbottom'] = $topy - $ypos[$k]['extbottom'];
11230
+ $lineBox[$k]['glyphYorigin'] = $topy - $ypos[$k]['glyphYorigin'];
11231
+ $lineBox[$k]['baseline-shift'] = $ypos[$k]['baseline-shift'];
11232
+ if (isset($bordypos[$k]['boxtop'])) {
11233
+ $lineBox[$k]['border-boxtop'] = $topy - $bordypos[$k]['boxtop'];
11234
+ $lineBox[$k]['border-boxbottom'] = $topy - $bordypos[$k]['boxbottom'];
11235
+ $lineBox[$k]['border-baseline-shift'] = $bordypos[$k]['baseline-shift'];
11236
+ }
11237
+ if (isset($bgypos[$k]['boxtop'])) {
11238
+ $lineBox[$k]['background-boxtop'] = $topy - $bgypos[$k]['boxtop'];
11239
+ $lineBox[$k]['background-boxbottom'] = $topy - $bgypos[$k]['boxbottom'];
11240
+ $lineBox[$k]['background-baseline-shift'] = $bgypos[$k]['baseline-shift'];
11241
  }
11242
  }
11243
  }
 
11244
  }
11245
 
11246
+ function SetBasePath($str = '')
 
11247
  {
11248
+ if (isset($_SERVER['HTTP_HOST'])) {
11249
+ $host = $_SERVER['HTTP_HOST'];
11250
+ } elseif (isset($_SERVER['SERVER_NAME'])) {
11251
+ $host = $_SERVER['SERVER_NAME'];
11252
+ } else {
11253
+ $host = '';
11254
+ }
11255
+ if (!$str) {
11256
+ if ($_SERVER['SCRIPT_NAME']) {
11257
+ $currentPath = dirname($_SERVER['SCRIPT_NAME']);
11258
+ } else {
11259
+ $currentPath = dirname($_SERVER['PHP_SELF']);
11260
+ }
11261
+ $currentPath = str_replace("\\", "/", $currentPath);
11262
+ if ($currentPath == '/') {
11263
+ $currentPath = '';
11264
+ }
11265
+ if ($host) { // mPDF 6
11266
+ if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && $_SERVER['HTTPS'] !== 'off') {
11267
+ $currpath = 'https://' . $host . $currentPath . '/';
11268
+ } else {
11269
+ $currpath = 'http://' . $host . $currentPath . '/';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11270
  }
11271
+ } else {
11272
+ $currpath = '';
11273
  }
11274
+ $this->basepath = $currpath;
11275
+ $this->basepathIsLocal = true;
11276
+ return;
11277
  }
11278
+ $str = preg_replace('/\?.*/', '', $str);
11279
+ if (!preg_match('/(http|https|ftp):\/\/.*\//i', $str)) {
11280
+ $str .= '/';
11281
+ }
11282
+ $str .= 'xxx'; // in case $str ends in / e.g. http://www.bbc.co.uk/
11283
+ $this->basepath = dirname($str) . "/"; // returns e.g. e.g. http://www.google.com/dir1/dir2/dir3/
11284
+ $this->basepath = str_replace("\\", "/", $this->basepath); // If on Windows
11285
+ $tr = parse_url($this->basepath);
11286
+ if (isset($tr['host']) && ($tr['host'] == $host)) {
11287
+ $this->basepathIsLocal = true;
11288
+ } else {
11289
+ $this->basepathIsLocal = false;
11290
  }
 
11291
  }
11292
 
11293
+ public function GetFullPath(&$path, $basepath = '')
 
11294
  {
11295
+ // When parsing CSS need to pass temporary basepath - so links are relative to current stylesheet
11296
+ if (!$basepath) {
11297
+ $basepath = $this->basepath;
 
 
 
 
 
11298
  }
11299
+
11300
+ // Fix path value
11301
+ $path = str_replace("\\", '/', $path); // If on Windows
11302
+
11303
+ // mPDF 5.7.2
11304
+ if (substr($path, 0, 2) === '//') {
11305
+ $scheme = parse_url($basepath, PHP_URL_SCHEME);
11306
+ $scheme = $scheme ?: 'http';
11307
+ $path = $scheme . ':' . $path;
11308
  }
 
 
 
11309
 
11310
+ $path = preg_replace('|^./|', '', $path); // Inadvertently corrects "./path/etc" and "//www.domain.com/etc"
11311
 
11312
+ if (substr($path, 0, 1) == '#') {
11313
+ return;
 
 
 
 
11314
  }
11315
+
11316
+ if (preg_match('@^(mailto|tel|fax):.*@i', $path)) {
11317
+ return;
 
 
 
11318
  }
 
 
 
11319
 
11320
+ if (substr($path, 0, 3) == "../") { // It is a relative link
 
11321
 
11322
+ $backtrackamount = substr_count($path, "../");
11323
+ $maxbacktrack = substr_count($basepath, "/") - 3;
11324
+ $filepath = str_replace("../", '', $path);
11325
+ $path = $basepath;
 
 
 
 
 
 
 
 
 
11326
 
11327
+ // If it is an invalid relative link, then make it go to directory root
11328
+ if ($backtrackamount > $maxbacktrack) {
11329
+ $backtrackamount = $maxbacktrack;
11330
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11331
 
11332
+ // Backtrack some directories
11333
+ for ($i = 0; $i < $backtrackamount + 1; $i++) {
11334
+ $path = substr($path, 0, strrpos($path, "/"));
11335
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11336
 
11337
+ $path = $path . "/" . $filepath; // Make it an absolute path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11338
 
11339
+ } elseif ((strpos($path, ":/") === false || strpos($path, ":/") > 10) && !is_file($path)) { // It is a local link
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11340
 
11341
+ if (substr($path, 0, 1) == "/") {
11342
 
11343
+ $tr = parse_url($basepath);
 
 
 
 
 
 
11344
 
11345
+ // mPDF 5.7.2
11346
+ $root = '';
11347
+ if (!empty($tr['scheme'])) {
11348
+ $root .= $tr['scheme'] . '://';
11349
+ }
11350
+
11351
+ $root .= isset($tr['host']) ? $tr['host'] : '';
11352
+ $root .= ((isset($tr['port']) && $tr['port']) ? (':' . $tr['port']) : ''); // mPDF 5.7.3
11353
+
11354
+ $path = $root . $path;
11355
+
11356
+ } else {
11357
+ $path = $basepath . $path;
11358
  }
11359
  }
11360
+ // Do nothing if it is an Absolute Link
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11361
  }
11362
 
11363
+ function docPageNum($num = 0, $extras = false)
11364
  {
11365
+ if ($num < 1) {
11366
+ $num = $this->page;
 
11367
  }
 
11368
 
11369
+ $type = $this->defaultPageNumStyle; // set default Page Number Style
11370
+ $ppgno = $num;
11371
+ $suppress = 0;
11372
+ $offset = 0;
11373
+ $lastreset = 0;
 
 
 
 
 
 
11374
 
11375
+ foreach ($this->PageNumSubstitutions as $psarr) {
 
 
 
 
 
 
 
 
 
 
 
 
11376
 
11377
+ if ($num >= $psarr['from']) {
11378
+
11379
+ if ($psarr['reset']) {
11380
+ if ($psarr['reset'] > 1) {
11381
+ $offset = $psarr['reset'] - 1;
11382
+ }
11383
+ $ppgno = $num - $psarr['from'] + 1 + $offset;
11384
+ $lastreset = $psarr['from'];
11385
+ }
11386
+
11387
+ if ($psarr['type']) {
11388
+ $type = $psarr['type'];
11389
+ }
11390
+
11391
+ if (strtoupper($psarr['suppress']) == 'ON' || $psarr['suppress'] == 1) {
11392
+ $suppress = 1;
11393
+ } elseif (strtoupper($psarr['suppress']) == 'OFF') {
11394
+ $suppress = 0;
11395
+ }
11396
  }
11397
  }
 
 
11398
 
11399
+ if ($suppress) {
11400
+ return '';
 
 
 
 
 
 
 
 
 
 
 
 
11401
  }
 
 
11402
 
11403
+ $ppgno = $this->_getStyledNumber($ppgno, $type);
11404
+
11405
+ if ($extras) {
11406
+ $ppgno = $this->pagenumPrefix . $ppgno . $this->pagenumSuffix;
 
11407
  }
11408
+
11409
+ return $ppgno;
11410
  }
11411
 
11412
+ function docPageNumTotal($num = 0, $extras = false)
11413
  {
11414
+ if ($num < 1) {
11415
+ $num = $this->page;
 
 
 
 
 
 
 
 
 
 
 
 
 
11416
  }
 
 
11417
 
11418
+ $type = $this->defaultPageNumStyle; // set default Page Number Style
11419
+ $ppgstart = 1;
11420
+ $ppgend = count($this->pages) + 1;
11421
+ $suppress = 0;
11422
+ $offset = 0;
 
11423
 
11424
+ foreach ($this->PageNumSubstitutions as $psarr) {
11425
+ if ($num >= $psarr['from']) {
11426
+ if ($psarr['reset']) {
11427
+ if ($psarr['reset'] > 1) {
11428
+ $offset = $psarr['reset'] - 1;
11429
+ }
11430
+ $ppgstart = $psarr['from'] + $offset;
11431
+ $ppgend = count($this->pages) + 1 + $offset;
11432
+ }
11433
+ if ($psarr['type']) {
11434
+ $type = $psarr['type'];
11435
+ }
11436
+ if (strtoupper($psarr['suppress']) == 'ON' || $psarr['suppress'] == 1) {
11437
+ $suppress = 1;
11438
+ } elseif (strtoupper($psarr['suppress']) == 'OFF') {
11439
+ $suppress = 0;
11440
+ }
11441
+ }
11442
+ if ($num < $psarr['from']) {
11443
+ if ($psarr['reset']) {
11444
+ $ppgend = $psarr['from'] + $offset;
11445
+ break;
11446
+ }
11447
  }
 
 
 
 
11448
  }
 
11449
 
11450
+ if ($suppress) {
11451
+ return '';
 
 
11452
  }
11453
 
11454
+ $ppgno = $ppgend - $ppgstart + $offset;
11455
+ $ppgno = $this->_getStyledNumber($ppgno, $type);
11456
+
11457
+ if ($extras) {
11458
+ $ppgno = $this->pagenumPrefix . $ppgno . $this->pagenumSuffix;
 
 
 
 
 
 
 
 
11459
  }
11460
 
11461
+ return $ppgno;
11462
+ }
 
 
 
 
 
 
 
11463
 
11464
+ // mPDF 6
11465
+ function _getStyledNumber($ppgno, $type, $listmarker = false)
11466
+ {
11467
+ if ($listmarker) {
11468
+ $reverse = true; // Reverse RTL numerals (Hebrew) when using for list
11469
+ $checkfont = true; // Using list - font is set, so check if character is available
11470
+ } else {
11471
+ $reverse = false; // For pagenumbers, RTL numerals (Hebrew) will get reversed later by bidi
11472
+ $checkfont = false; // For pagenumbers - font is not set, so no check
11473
  }
11474
 
11475
+ $decToAlpha = new Conversion\DecToAlpha();
11476
+ $decToCjk = new Conversion\DecToCjk();
11477
+ $decToHebrew = new Conversion\DecToHebrew();
11478
+ $decToRoman = new Conversion\DecToRoman();
11479
+ $decToOther = new Conversion\DecToOther($this);
11480
 
11481
+ $lowertype = strtolower($type);
 
 
 
11482
 
11483
+ if ($lowertype == 'upper-latin' || $lowertype == 'upper-alpha' || $type == 'A') {
 
11484
 
11485
+ $ppgno = $decToAlpha->convert($ppgno, true);
 
 
11486
 
11487
+ } elseif ($lowertype == 'lower-latin' || $lowertype == 'lower-alpha' || $type == 'a') {
 
 
 
 
 
 
11488
 
11489
+ $ppgno = $decToAlpha->convert($ppgno, false);
 
 
11490
 
11491
+ } elseif ($lowertype == 'upper-roman' || $type == 'I') {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11492
 
11493
+ $ppgno = $decToRoman->convert($ppgno, true);
11494
 
11495
+ } elseif ($lowertype == 'lower-roman' || $type == 'i') {
11496
+
11497
+ $ppgno = $decToRoman->convert($ppgno, false);
11498
+
11499
+ } elseif ($lowertype == 'hebrew') {
11500
+
11501
+ $ppgno = $decToHebrew->convert($ppgno, $reverse);
11502
+
11503
+ } elseif (preg_match('/(arabic-indic|bengali|devanagari|gujarati|gurmukhi|kannada|malayalam|oriya|persian|tamil|telugu|thai|urdu|cambodian|khmer|lao)/i', $lowertype, $m)) {
11504
+
11505
+ $cp = $decToOther->getCodePage($m[1]);
11506
+ $ppgno = $decToOther->convert($ppgno, $cp, $checkfont);
11507
+
11508
+ } elseif ($lowertype == 'cjk-decimal') {
11509
+
11510
+ $ppgno = $decToCjk->convert($ppgno);
11511
 
 
 
 
 
 
 
 
11512
  }
11513
 
11514
+ return $ppgno;
11515
+ }
11516
 
11517
+ function docPageSettings($num = 0)
11518
+ {
11519
+ // Returns current type (numberstyle), suppression state for this page number;
11520
+ // reset is only returned if set for this page number
11521
+ if ($num < 1) {
11522
+ $num = $this->page;
11523
+ }
11524
+
11525
+ $type = $this->defaultPageNumStyle; // set default Page Number Style
11526
+ $ppgno = $num;
11527
+ $suppress = 0;
11528
+ $offset = 0;
11529
+ $reset = '';
11530
+
11531
+ foreach ($this->PageNumSubstitutions as $psarr) {
11532
+ if ($num >= $psarr['from']) {
11533
+ if ($psarr['reset']) {
11534
+ if ($psarr['reset'] > 1) {
11535
+ $offset = $psarr['reset'] - 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11536
  }
11537
+ $ppgno = $num - $psarr['from'] + 1 + $offset;
11538
  }
11539
+ if ($psarr['type']) {
11540
+ $type = $psarr['type'];
 
 
 
 
 
 
 
 
 
 
11541
  }
11542
+ if (strtoupper($psarr['suppress']) == 'ON' || $psarr['suppress'] == 1) {
11543
+ $suppress = 1;
11544
+ } elseif (strtoupper($psarr['suppress']) == 'OFF') {
11545
+ $suppress = 0;
 
 
 
 
 
 
 
11546
  }
11547
  }
11548
+ if ($num == $psarr['from']) {
11549
+ $reset = $psarr['reset'];
 
 
 
 
 
 
 
 
 
 
11550
  }
11551
  }
11552
 
11553
+ if ($suppress) {
11554
+ $suppress = 'on';
11555
+ } else {
11556
+ $suppress = 'off';
11557
  }
11558
 
11559
+ return [$type, $suppress, $reset];
11560
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11561
 
11562
+ function RestartDocTemplate()
11563
+ {
11564
+ $this->docTemplateStart = $this->page;
11565
+ }
11566
 
11567
+ // Page header
11568
+ function Header($content = '')
11569
+ {
 
 
 
 
 
11570
 
11571
+ $this->cMarginL = 0;
11572
+ $this->cMarginR = 0;
11573
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11574
 
11575
+ if (($this->mirrorMargins && ($this->page % 2 == 0) && $this->HTMLHeaderE) || ($this->mirrorMargins && ($this->page % 2 == 1) && $this->HTMLHeader) || (!$this->mirrorMargins && $this->HTMLHeader)) {
11576
+ $this->writeHTMLHeaders();
11577
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11578
  }
11579
  }
11580
 
11581
+ /* -- TABLES -- */
11582
+ function TableHeaderFooter($content = '', $tablestartpage = '', $tablestartcolumn = '', $horf = 'H', $level = 0, $firstSpread = true, $finalSpread = true)
11583
  {
11584
+ if (($horf == 'H' || $horf == 'F') && !empty($content)) { // mPDF 5.7.2
11585
+ $table = &$this->table[1][1];
11586
+
11587
+ // mPDF 5.7.2
11588
+ if ($horf == 'F') { // Table Footer
11589
+ $firstrow = count($table['cells']) - $table['footernrows'];
11590
+ $lastrow = count($table['cells']) - 1;
11591
+ } else { // Table Header
11592
+ $firstrow = 0;
11593
+ $lastrow = $table['headernrows'] - 1;
11594
+ }
11595
+ if (empty($content[$firstrow])) {
11596
+ if ($this->debug) {
11597
+ throw new \Mpdf\MpdfException("<tfoot> must precede <tbody> in a table");
 
 
 
 
 
 
11598
  } else {
11599
+ return;
11600
  }
 
 
11601
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11602
 
 
 
 
 
11603
 
11604
+ // Advance down page by half width of top border
11605
+ if ($horf == 'H') { // Only if header
11606
+ if ($table['borders_separate']) {
11607
+ $adv = $table['border_spacing_V'] / 2 + $table['border_details']['T']['w'] + $table['padding']['T'];
11608
+ } else {
11609
+ $adv = $table['max_cell_border_width']['T'] / 2;
11610
+ }
11611
+ if ($adv) {
11612
+ if ($this->table_rotate) {
11613
+ $this->y += ($adv);
11614
+ } else {
11615
+ $this->DivLn($adv, $this->blklvl, true);
11616
+ }
11617
+ }
11618
  }
11619
 
11620
+ $topy = $content[$firstrow][0]['y'] - $this->y;
 
 
 
11621
 
11622
+ for ($i = $firstrow; $i <= $lastrow; $i++) {
11623
+ $y = $this->y;
11624
 
11625
+ /* -- COLUMNS -- */
11626
+ // If outside columns, this is done in PaintDivBB
11627
+ if ($this->ColActive) {
11628
+ // OUTER FILL BGCOLOR of DIVS
11629
+ if ($this->blklvl > 0) {
11630
+ $firstblockfill = $this->GetFirstBlockFill();
11631
+ if ($firstblockfill && $this->blklvl >= $firstblockfill) {
11632
+ $divh = $content[$i][0]['h'];
11633
+ $bak_x = $this->x;
11634
+ $this->DivLn($divh, -3, false);
11635
+ // Reset current block fill
11636
+ $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
11637
+ $this->SetFColor($bcor);
11638
+ $this->x = $bak_x;
11639
+ }
11640
+ }
11641
+ }
11642
+ /* -- END COLUMNS -- */
11643
 
11644
+ $colctr = 0;
11645
+ foreach ($content[$i] as $tablehf) {
11646
+ $colctr++;
11647
+ $y = Arrays::get($tablehf, 'y', null) - $topy;
11648
+ $this->y = $y;
11649
+ // Set some cell values
11650
+ $x = Arrays::get($tablehf, 'x', null);
11651
+ if (($this->mirrorMargins) && ($tablestartpage == 'ODD') && (($this->page) % 2 == 0)) { // EVEN
11652
+ $x = $x + $this->MarginCorrection;
11653
+ } elseif (($this->mirrorMargins) && ($tablestartpage == 'EVEN') && (($this->page) % 2 == 1)) { // ODD
11654
+ $x = $x + $this->MarginCorrection;
11655
+ }
11656
+ /* -- COLUMNS -- */
11657
+ // Added to correct for Columns
11658
+ if ($this->ColActive) {
11659
+ if ($this->directionality == 'rtl') { // *OTL*
11660
+ $x -= ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth + $this->ColGap); // *OTL*
11661
+ } // *OTL*
11662
+ else { // *OTL*
11663
+ $x += ($this->CurrCol - $tablestartcolumn) * ($this->ColWidth + $this->ColGap);
11664
+ } // *OTL*
11665
+ }
11666
+ /* -- END COLUMNS -- */
11667
 
11668
+ if ($colctr == 1) {
11669
+ $x0 = $x;
11670
+ }
11671
 
11672
+ // mPDF ITERATION
11673
+ if ($this->iterationCounter) {
11674
+ foreach ($tablehf['textbuffer'] as $k => $t) {
11675
+ if (!is_array($t[0]) && preg_match('/{iteration ([a-zA-Z0-9_]+)}/', $t[0], $m)) {
11676
+ $vname = '__' . $m[1] . '_';
11677
+ if (!isset($this->$vname)) {
11678
+ $this->$vname = 1;
11679
+ } else {
11680
+ $this->$vname++;
11681
+ }
11682
+ $tablehf['textbuffer'][$k][0] = preg_replace('/{iteration ' . $m[1] . '}/', $this->$vname, $tablehf['textbuffer'][$k][0]);
11683
+ }
11684
+ }
11685
+ }
11686
 
11687
+ $w = Arrays::get($tablehf, 'w', null);
11688
+ $h = Arrays::get($tablehf, 'h', null);
11689
+ $va = Arrays::get($tablehf, 'va', null);
11690
+ $R = Arrays::get($tablehf, 'R', null);
11691
+ $direction = Arrays::get($tablehf, 'direction', null);
11692
+ $mih = Arrays::get($tablehf, 'mih', null);
11693
+ $border = Arrays::get($tablehf, 'border', null);
11694
+ $border_details = Arrays::get($tablehf, 'border_details', null);
11695
+ $padding = Arrays::get($tablehf, 'padding', null);
11696
+ $this->tabletheadjustfinished = true;
11697
 
11698
+ $textbuffer = Arrays::get($tablehf, 'textbuffer', null);
11699
 
11700
+ // Align
11701
+ $align = Arrays::get($tablehf, 'a', null);
11702
+ $this->cellTextAlign = $align;
 
 
 
11703
 
11704
+ $this->cellLineHeight = Arrays::get($tablehf, 'cellLineHeight', null);
11705
+ $this->cellLineStackingStrategy = Arrays::get($tablehf, 'cellLineStackingStrategy', null);
11706
+ $this->cellLineStackingShift = Arrays::get($tablehf, 'cellLineStackingShift', null);
 
 
11707
 
11708
+ $this->x = $x;
 
 
 
 
11709
 
11710
+ if ($this->ColActive) {
11711
+ if ($table['borders_separate']) {
11712
+ $tablefill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
11713
+ if ($tablefill) {
11714
+ $color = $this->colorConverter->convert($tablefill, $this->PDFAXwarnings);
11715
+ if ($color) {
11716
+ $xadj = ($table['border_spacing_H'] / 2);
11717
+ $yadj = ($table['border_spacing_V'] / 2);
11718
+ $wadj = $table['border_spacing_H'];
11719
+ $hadj = $table['border_spacing_V'];
11720
+ if ($i == $firstrow && $horf == 'H') { // Top
11721
+ $yadj += $table['padding']['T'] + $table['border_details']['T']['w'];
11722
+ $hadj += $table['padding']['T'] + $table['border_details']['T']['w'];
11723
+ }
11724
+ if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i + $tablehf['rowspan']) == ($lastrow + 1)) || (!isset($tablehf['rowspan']) && ($i + 1) == ($lastrow + 1))) && $horf == 'F') { // Bottom
11725
+ $hadj += $table['padding']['B'] + $table['border_details']['B']['w'];
11726
+ }
11727
+ if ($colctr == 1) { // Left
11728
+ $xadj += $table['padding']['L'] + $table['border_details']['L']['w'];
11729
+ $wadj += $table['padding']['L'] + $table['border_details']['L']['w'];
11730
+ }
11731
+ if ($colctr == count($content[$i])) { // Right
11732
+ $wadj += $table['padding']['R'] + $table['border_details']['R']['w'];
11733
+ }
11734
+ $this->SetFColor($color);
11735
+ $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
11736
+ }
11737
+ }
11738
+ }
11739
+ }
11740
 
11741
+ if ($table['empty_cells'] != 'hide' || !empty($textbuffer) || !$table['borders_separate']) {
11742
+ $paintcell = true;
11743
+ } else {
11744
+ $paintcell = false;
11745
+ }
11746
 
11747
+ // Vertical align
11748
+ if ($R && intval($R) > 0 && isset($va) && $va != 'B') {
11749
+ $va = 'B';
11750
  }
 
 
 
11751
 
11752
+ if (!isset($va) || empty($va) || $va == 'M') {
11753
+ $this->y += ($h - $mih) / 2;
11754
+ } elseif (isset($va) && $va == 'B') {
11755
+ $this->y += $h - $mih;
11756
+ }
11757
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11758
 
11759
+ // TABLE ROW OR CELL FILL BGCOLOR
11760
+ $fill = 0;
11761
+ if (isset($tablehf['bgcolor']) && $tablehf['bgcolor'] && $tablehf['bgcolor'] != 'transparent') {
11762
+ $fill = $tablehf['bgcolor'];
11763
+ $leveladj = 6;
11764
+ } elseif (isset($content[$i][0]['trbgcolor']) && $content[$i][0]['trbgcolor'] && $content[$i][0]['trbgcolor'] != 'transparent') { // Row color
11765
+ $fill = $content[$i][0]['trbgcolor'];
11766
+ $leveladj = 3;
11767
+ }
11768
+ if ($fill && $paintcell) {
11769
+ $color = $this->colorConverter->convert($fill, $this->PDFAXwarnings);
11770
+ if ($color) {
11771
+ if ($table['borders_separate']) {
11772
+ if ($this->ColActive) {
11773
+ $this->SetFColor($color);
11774
+ $this->Rect($x + ($table['border_spacing_H'] / 2), $y + ($table['border_spacing_V'] / 2), $w - $table['border_spacing_H'], $h - $table['border_spacing_V'], 'F');
11775
+ } else {
11776
+ $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => ($x + ($table['border_spacing_H'] / 2)), 'y' => ($y + ($table['border_spacing_V'] / 2)), 'w' => ($w - $table['border_spacing_H']), 'h' => ($h - $table['border_spacing_V']), 'col' => $color];
11777
+ }
11778
+ } else {
11779
+ if ($this->ColActive) {
11780
+ $this->SetFColor($color);
11781
+ $this->Rect($x, $y, $w, $h, 'F');
11782
+ } else {
11783
+ $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'col' => $color];
11784
+ }
11785
+ }
11786
+ }
11787
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11788
 
 
 
11789
 
11790
+ /* -- BACKGROUNDS -- */
11791
+ if (isset($tablehf['gradient']) && $tablehf['gradient'] && $paintcell) {
11792
+ $g = $this->gradient->parseBackgroundGradient($tablehf['gradient']);
11793
+ if ($g) {
11794
+ if ($table['borders_separate']) {
11795
+ $px = $x + ($table['border_spacing_H'] / 2);
11796
+ $py = $y + ($table['border_spacing_V'] / 2);
11797
+ $pw = $w - $table['border_spacing_H'];
11798
+ $ph = $h - $table['border_spacing_V'];
11799
+ } else {
11800
+ $px = $x;
11801
+ $py = $y;
11802
+ $pw = $w;
11803
+ $ph = $h;
11804
+ }
11805
+ if ($this->ColActive) {
11806
+ $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
11807
+ } else {
11808
+ $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
11809
+ }
11810
+ }
11811
+ }
11812
 
11813
+ if (isset($tablehf['background-image']) && $paintcell) {
11814
+ if ($tablehf['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $tablehf['background-image']['gradient'])) {
11815
+ $g = $this->gradient->parseMozGradient($tablehf['background-image']['gradient']);
11816
+ if ($g) {
11817
+ if ($table['borders_separate']) {
11818
+ $px = $x + ($table['border_spacing_H'] / 2);
11819
+ $py = $y + ($table['border_spacing_V'] / 2);
11820
+ $pw = $w - $table['border_spacing_H'];
11821
+ $ph = $h - $table['border_spacing_V'];
11822
+ } else {
11823
+ $px = $x;
11824
+ $py = $y;
11825
+ $pw = $w;
11826
+ $ph = $h;
11827
+ }
11828
+ if ($this->ColActive) {
11829
+ $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
11830
+ } else {
11831
+ $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
11832
+ }
11833
+ }
11834
+ } elseif ($tablehf['background-image']['image_id']) { // Background pattern
11835
+ $n = count($this->patterns) + 1;
11836
+ if ($table['borders_separate']) {
11837
+ $px = $x + ($table['border_spacing_H'] / 2);
11838
+ $py = $y + ($table['border_spacing_V'] / 2);
11839
+ $pw = $w - $table['border_spacing_H'];
11840
+ $ph = $h - $table['border_spacing_V'];
11841
+ } else {
11842
+ $px = $x;
11843
+ $py = $y;
11844
+ $pw = $w;
11845
+ $ph = $h;
11846
+ }
11847
+ if ($this->ColActive) {
11848
+ list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($tablehf['background-image']['orig_w'], $tablehf['background-image']['orig_h'], $pw, $ph, $tablehf['background-image']['resize'], $tablehf['background-image']['x_repeat'], $tablehf['background-image']['y_repeat']);
11849
+ $this->patterns[$n] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'pgh' => $this->h, 'image_id' => $tablehf['background-image']['image_id'], 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $tablehf['background-image']['x_pos'], 'y_pos' => $tablehf['background-image']['y_pos'], 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'itype' => $tablehf['background-image']['itype']];
11850
+ if ($tablehf['background-image']['opacity'] > 0 && $tablehf['background-image']['opacity'] < 1) {
11851
+ $opac = $this->SetAlpha($tablehf['background-image']['opacity'], 'Normal', true);
11852
+ } else {
11853
+ $opac = '';
11854
+ }
11855
+ $this->writer->write(sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $px * Mpdf::SCALE, ($this->h - $py) * Mpdf::SCALE, $pw * Mpdf::SCALE, -$ph * Mpdf::SCALE));
11856
+ } else {
11857
+ $this->tableBackgrounds[$level * 9 + 8][] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'image_id' => $tablehf['background-image']['image_id'], 'orig_w' => $tablehf['background-image']['orig_w'], 'orig_h' => $tablehf['background-image']['orig_h'], 'x_pos' => $tablehf['background-image']['x_pos'], 'y_pos' => $tablehf['background-image']['y_pos'], 'x_repeat' => $tablehf['background-image']['x_repeat'], 'y_repeat' => $tablehf['background-image']['y_repeat'], 'clippath' => '', 'resize' => $tablehf['background-image']['resize'], 'opacity' => $tablehf['background-image']['opacity'], 'itype' => $tablehf['background-image']['itype']];
11858
+ }
11859
+ }
11860
+ }
11861
+ /* -- END BACKGROUNDS -- */
11862
 
11863
+ // Cell Border
11864
+ if ($table['borders_separate'] && $paintcell && $border) {
11865
+ $this->_tableRect($x + ($table['border_spacing_H'] / 2) + ($border_details['L']['w'] / 2), $y + ($table['border_spacing_V'] / 2) + ($border_details['T']['w'] / 2), $w - $table['border_spacing_H'] - ($border_details['L']['w'] / 2) - ($border_details['R']['w'] / 2), $h - $table['border_spacing_V'] - ($border_details['T']['w'] / 2) - ($border_details['B']['w'] / 2), $border, $border_details, false, $table['borders_separate']);
11866
+ } elseif ($paintcell && $border) {
11867
+ $this->_tableRect($x, $y, $w, $h, $border, $border_details, true, $table['borders_separate']); // true causes buffer
11868
+ }
 
 
 
 
11869
 
11870
+ // Print cell content
11871
+ if (!empty($textbuffer)) {
11872
+ if ($horf == 'F' && preg_match('/{colsum([0-9]*)[_]*}/', $textbuffer[0][0], $m)) {
11873
+ $rep = sprintf("%01." . intval($m[1]) . "f", $this->colsums[$colctr - 1]);
11874
+ $textbuffer[0][0] = preg_replace('/{colsum[0-9_]*}/', $rep, $textbuffer[0][0]);
11875
+ }
11876
 
11877
+ if ($R) {
11878
+ $cellPtSize = $textbuffer[0][11] / $this->shrin_k;
11879
+ if (!$cellPtSize) {
11880
+ $cellPtSize = $this->default_font_size;
11881
+ }
11882
+ $cellFontHeight = ($cellPtSize / Mpdf::SCALE);
11883
+ $opx = $this->x;
11884
+ $opy = $this->y;
11885
+ $angle = intval($R);
11886
 
11887
+ // Only allow 45 - 90 degrees (when bottom-aligned) or -90
11888
+ if ($angle > 90) {
11889
+ $angle = 90;
11890
+ } elseif ($angle > 0 && (isset($va) && $va != 'B')) {
11891
+ $angle = 90;
11892
+ } elseif ($angle > 0 && $angle < 45) {
11893
+ $angle = 45;
11894
+ } elseif ($angle < 0) {
11895
+ $angle = -90;
11896
+ }
11897
 
11898
+ $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
11899
+ if (isset($align) && $align == 'R') {
11900
+ $this->x += ($w) + ($offset) - ($cellFontHeight / 3) - ($padding['R'] + $border_details['R']['w']);
11901
+ } elseif (!isset($align) || $align == 'C') {
11902
+ $this->x += ($w / 2) + ($offset);
11903
+ } else {
11904
+ $this->x += ($offset) + ($cellFontHeight / 3) + ($padding['L'] + $border_details['L']['w']);
11905
+ }
11906
+ $str = '';
11907
+ foreach ($tablehf['textbuffer'] as $t) {
11908
+ $str .= $t[0] . ' ';
11909
+ }
11910
+ $str = rtrim($str);
11911
 
11912
+ if (!isset($va) || $va == 'M') {
11913
+ $this->y -= ($h - $mih) / 2; // Undo what was added earlier VERTICAL ALIGN
11914
+ if ($angle > 0) {
11915
+ $this->y += (($h - $mih) / 2) + ($padding['T'] + $border_details['T']['w']) + ($mih - ($padding['T'] + $border_details['T']['w'] + $border_details['B']['w'] + $padding['B']));
11916
+ } elseif ($angle < 0) {
11917
+ $this->y += (($h - $mih) / 2) + ($padding['T'] + $border_details['T']['w']);
11918
+ }
11919
+ } elseif (isset($va) && $va == 'B') {
11920
+ $this->y -= $h - $mih; // Undo what was added earlier VERTICAL ALIGN
11921
+ if ($angle > 0) {
11922
+ $this->y += $h - ($border_details['B']['w'] + $padding['B']);
11923
+ } elseif ($angle < 0) {
11924
+ $this->y += $h - $mih + ($padding['T'] + $border_details['T']['w']);
11925
+ }
11926
+ } elseif (isset($va) && $va == 'T') {
11927
+ if ($angle > 0) {
11928
+ $this->y += $mih - ($border_details['B']['w'] + $padding['B']);
11929
+ } elseif ($angle < 0) {
11930
+ $this->y += ($padding['T'] + $border_details['T']['w']);
11931
+ }
11932
+ }
11933
 
11934
+ $this->Rotate($angle, $this->x, $this->y);
11935
+ $s_fs = $this->FontSizePt;
11936
+ $s_f = $this->FontFamily;
11937
+ $s_st = $this->FontStyle;
11938
+ if (!empty($textbuffer[0][3])) { // Font Color
11939
+ $cor = $textbuffer[0][3];
11940
+ $this->SetTColor($cor);
11941
+ }
11942
+ $this->SetFont($textbuffer[0][4], $textbuffer[0][2], $cellPtSize, true, true);
11943
 
11944
+ $this->magic_reverse_dir($str, $this->directionality, $textbuffer[0][18]);
11945
+ $this->Text($this->x, $this->y, $str, $textbuffer[0][18], $textbuffer[0][8]); // textvar
11946
+ $this->Rotate(0);
11947
+ $this->SetFont($s_f, $s_st, $s_fs, true, true);
11948
+ $this->SetTColor(0);
11949
+ $this->x = $opx;
11950
+ $this->y = $opy;
11951
+ } else {
11952
+ if ($table['borders_separate']) { // NB twice border width
11953
+ $xadj = $border_details['L']['w'] + $padding['L'] + ($table['border_spacing_H'] / 2);
11954
+ $wadj = $border_details['L']['w'] + $border_details['R']['w'] + $padding['L'] + $padding['R'] + $table['border_spacing_H'];
11955
+ $yadj = $border_details['T']['w'] + $padding['T'] + ($table['border_spacing_H'] / 2);
11956
+ } else {
11957
+ $xadj = $border_details['L']['w'] / 2 + $padding['L'];
11958
+ $wadj = ($border_details['L']['w'] + $border_details['R']['w']) / 2 + $padding['L'] + $padding['R'];
11959
+ $yadj = $border_details['T']['w'] / 2 + $padding['T'];
11960
+ }
11961
 
11962
+ $this->divwidth = $w - ($wadj);
11963
+ $this->x += $xadj;
11964
+ $this->y += $yadj;
11965
+ $this->printbuffer($textbuffer, '', true, false, $direction);
11966
+ }
11967
+ }
11968
+ $textbuffer = [];
11969
 
11970
+ /* -- BACKGROUNDS -- */
11971
+ if (!$this->ColActive) {
11972
+ if (isset($content[$i][0]['trgradients']) && ($colctr == 1 || $table['borders_separate'])) {
11973
+ $g = $this->gradient->parseBackgroundGradient($content[$i][0]['trgradients']);
11974
+ if ($g) {
11975
+ $gx = $x0;
11976
+ $gy = $y;
11977
+ $gh = $h;
11978
+ $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
11979
+ if ($table['borders_separate']) {
11980
+ $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
11981
+ $clx = $x + ($table['border_spacing_H'] / 2);
11982
+ $cly = $y + ($table['border_spacing_V'] / 2);
11983
+ $clw = $w - $table['border_spacing_H'];
11984
+ $clh = $h - $table['border_spacing_V'];
11985
+ // Set clipping path
11986
+ $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
11987
+ $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s];
11988
+ } else {
11989
+ $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
11990
+ }
11991
+ }
11992
+ }
11993
 
11994
+ if (isset($content[$i][0]['trbackground-images']) && ($colctr == 1 || $table['borders_separate'])) {
11995
+ if ($content[$i][0]['trbackground-images']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $content[$i][0]['trbackground-images']['gradient'])) {
11996
+ $g = $this->gradient->parseMozGradient($content[$i][0]['trbackground-images']['gradient']);
11997
+ if ($g) {
11998
+ $gx = $x0;
11999
+ $gy = $y;
12000
+ $gh = $h;
12001
+ $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
12002
+ if ($table['borders_separate']) {
12003
+ $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
12004
+ $clx = $x + ($table['border_spacing_H'] / 2);
12005
+ $cly = $y + ($table['border_spacing_V'] / 2);
12006
+ $clw = $w - $table['border_spacing_H'];
12007
+ $clh = $h - $table['border_spacing_V'];
12008
+ // Set clipping path
12009
+ $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
12010
+ $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s];
12011
+ } else {
12012
+ $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
12013
+ }
12014
+ }
12015
+ } else {
12016
+ $image_id = $content[$i][0]['trbackground-images']['image_id'];
12017
+ $orig_w = $content[$i][0]['trbackground-images']['orig_w'];
12018
+ $orig_h = $content[$i][0]['trbackground-images']['orig_h'];
12019
+ $x_pos = $content[$i][0]['trbackground-images']['x_pos'];
12020
+ $y_pos = $content[$i][0]['trbackground-images']['y_pos'];
12021
+ $x_repeat = $content[$i][0]['trbackground-images']['x_repeat'];
12022
+ $y_repeat = $content[$i][0]['trbackground-images']['y_repeat'];
12023
+ $resize = $content[$i][0]['trbackground-images']['resize'];
12024
+ $opacity = $content[$i][0]['trbackground-images']['opacity'];
12025
+ $itype = $content[$i][0]['trbackground-images']['itype'];
12026
 
12027
+ $clippath = '';
12028
+ $gx = $x0;
12029
+ $gy = $y;
12030
+ $gh = $h;
12031
+ $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
12032
+ if ($table['borders_separate']) {
12033
+ $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
12034
+ $clx = $x + ($table['border_spacing_H'] / 2);
12035
+ $cly = $y + ($table['border_spacing_V'] / 2);
12036
+ $clw = $w - $table['border_spacing_H'];
12037
+ $clh = $h - $table['border_spacing_V'];
12038
+ // Set clipping path
12039
+ $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
12040
+ $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => $s, 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
12041
+ } else {
12042
+ $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
12043
+ }
12044
+ }
12045
+ }
12046
+ }
12047
+ /* -- END BACKGROUNDS -- */
12048
 
12049
+ // TABLE BORDER - if separate OR collapsed and only table border
12050
+ if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
12051
+ $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H'] / 2);
12052
+ $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H'] / 2);
12053
+ $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V'] / 2);
12054
+ $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V'] / 2);
12055
+ $tbx = $x;
12056
+ $tby = $y;
12057
+ $tbw = $w;
12058
+ $tbh = $h;
12059
+ $tab_bord = 0;
12060
+ $corner = '';
12061
+ if ($i == $firstrow && $horf == 'H') { // Top
12062
+ $tby -= $halfspaceT + ($table['border_details']['T']['w'] / 2);
12063
+ $tbh += $halfspaceT + ($table['border_details']['T']['w'] / 2);
12064
+ $this->setBorder($tab_bord, Border::TOP);
12065
+ $corner .= 'T';
12066
+ }
12067
+ if (($i == ($lastrow) || (isset($tablehf['rowspan']) && ($i + $tablehf['rowspan']) == ($lastrow + 1))) && $horf == 'F') { // Bottom
12068
+ $tbh += $halfspaceB + ($table['border_details']['B']['w'] / 2);
12069
+ $this->setBorder($tab_bord, Border::BOTTOM);
12070
+ $corner .= 'B';
12071
+ }
12072
+ if ($colctr == 1 && $firstSpread) { // Left
12073
+ $tbx -= $halfspaceL + ($table['border_details']['L']['w'] / 2);
12074
+ $tbw += $halfspaceL + ($table['border_details']['L']['w'] / 2);
12075
+ $this->setBorder($tab_bord, Border::LEFT);
12076
+ $corner .= 'L';
12077
+ }
12078
+ if ($colctr == count($content[$i]) && $finalSpread) { // Right
12079
+ $tbw += $halfspaceR + ($table['border_details']['R']['w'] / 2);
12080
+ $this->setBorder($tab_bord, Border::RIGHT);
12081
+ $corner .= 'R';
12082
+ }
12083
+ $this->_tableRect($tbx, $tby, $tbw, $tbh, $tab_bord, $table['border_details'], false, $table['borders_separate'], 'table', $corner, $table['border_spacing_V'], $table['border_spacing_H']);
12084
+ }
12085
+ }// end column $content
12086
+ $this->y = $y + $h; // Update y coordinate
12087
+ }// end row $i
12088
+ unset($table);
12089
+ $this->colsums = [];
12090
  }
 
 
12091
  }
12092
 
12093
+ /* -- END TABLES -- */
 
 
 
 
 
 
12094
 
12095
+ function SetHTMLHeader($header = '', $OE = '', $write = false)
12096
+ {
 
 
 
12097
 
12098
+ $height = 0;
12099
+ if (is_array($header) && isset($header['html']) && $header['html']) {
12100
+ $Hhtml = $header['html'];
12101
+ if ($this->setAutoTopMargin) {
12102
+ if (isset($header['h'])) {
12103
+ $height = $header['h'];
12104
+ } else {
12105
+ $height = $this->_getHtmlHeight($Hhtml);
 
 
 
 
 
 
 
12106
  }
12107
  }
12108
+ } elseif (!is_array($header) && $header) {
12109
+ $Hhtml = $header;
12110
+ if ($this->setAutoTopMargin) {
12111
+ $height = $this->_getHtmlHeight($Hhtml);
12112
  }
12113
+ } else {
12114
+ $Hhtml = '';
12115
  }
12116
 
12117
+ if ($OE !== 'E') {
12118
+ $OE = 'O';
12119
+ }
12120
+
12121
+ if ($OE === 'E') {
12122
+ if ($Hhtml) {
12123
+ $this->HTMLHeaderE = [];
12124
+ $this->HTMLHeaderE['html'] = $Hhtml;
12125
+ $this->HTMLHeaderE['h'] = $height;
12126
+ } else {
12127
+ $this->HTMLHeaderE = '';
12128
+ }
12129
  } else {
12130
+ if ($Hhtml) {
12131
+ $this->HTMLHeader = [];
12132
+ $this->HTMLHeader['html'] = $Hhtml;
12133
+ $this->HTMLHeader['h'] = $height;
12134
+ } else {
12135
+ $this->HTMLHeader = '';
12136
+ }
12137
  }
12138
 
12139
+ if (!$this->mirrorMargins && $OE == 'E') {
12140
+ return;
12141
+ }
12142
+ if ($Hhtml == '') {
12143
+ return;
12144
+ }
12145
 
12146
+ if ($this->setAutoTopMargin == 'pad') {
12147
+ $this->tMargin = $this->margin_header + $height + $this->orig_tMargin;
12148
+ if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) {
12149
+ $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin;
12150
+ }
12151
+ } elseif ($this->setAutoTopMargin == 'stretch') {
12152
+ $this->tMargin = max($this->orig_tMargin, $this->margin_header + $height + $this->autoMarginPadding);
12153
+ if (isset($this->saveHTMLHeader[$this->page][$OE]['mt'])) {
12154
+ $this->saveHTMLHeader[$this->page][$OE]['mt'] = $this->tMargin;
12155
+ }
12156
+ }
12157
+ if ($write && $this->state != 0 && (($this->mirrorMargins && $OE == 'E' && ($this->page) % 2 == 0) || ($this->mirrorMargins && $OE != 'E' && ($this->page) % 2 == 1) || !$this->mirrorMargins)) {
12158
+ $this->writeHTMLHeaders();
12159
+ }
12160
  }
12161
 
12162
+ function SetHTMLFooter($footer = '', $OE = '')
 
12163
  {
12164
+ $height = 0;
12165
+ if (is_array($footer) && isset($footer['html']) && $footer['html']) {
12166
+ $Fhtml = $footer['html'];
12167
+ if ($this->setAutoBottomMargin) {
12168
+ if (isset($footer['h'])) {
12169
+ $height = $footer['h'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12170
  } else {
12171
+ $height = $this->_getHtmlHeight($Fhtml);
12172
  }
12173
  }
12174
+ } elseif (!is_array($footer) && $footer) {
12175
+ $Fhtml = $footer;
12176
+ if ($this->setAutoBottomMargin) {
12177
+ $height = $this->_getHtmlHeight($Fhtml);
12178
+ }
12179
+ } else {
12180
+ $Fhtml = '';
12181
+ }
12182
 
12183
+ if ($OE !== 'E') {
12184
+ $OE = 'O';
12185
+ }
12186
 
12187
+ if ($OE === 'E') {
12188
+ if ($Fhtml) {
12189
+ $this->HTMLFooterE = [];
12190
+ $this->HTMLFooterE['html'] = $Fhtml;
12191
+ $this->HTMLFooterE['h'] = $height;
12192
+ } else {
12193
+ $this->HTMLFooterE = '';
12194
+ }
12195
+ } else {
12196
+ if ($Fhtml) {
12197
+ $this->HTMLFooter = [];
12198
+ $this->HTMLFooter['html'] = $Fhtml;
12199
+ $this->HTMLFooter['h'] = $height;
12200
+ } else {
12201
+ $this->HTMLFooter = '';
12202
  }
12203
+ }
12204
 
12205
+ if (!$this->mirrorMargins && $OE == 'E') {
12206
+ return;
12207
+ }
12208
 
12209
+ if ($Fhtml == '') {
12210
+ return false;
12211
+ }
12212
 
12213
+ if ($this->setAutoBottomMargin == 'pad') {
12214
+ $this->bMargin = $this->margin_footer + $height + $this->orig_bMargin;
12215
+ $this->PageBreakTrigger = $this->h - $this->bMargin;
12216
+ if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) {
12217
+ $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin;
12218
+ }
12219
+ } elseif ($this->setAutoBottomMargin == 'stretch') {
12220
+ $this->bMargin = max($this->orig_bMargin, $this->margin_footer + $height + $this->autoMarginPadding);
12221
+ $this->PageBreakTrigger = $this->h - $this->bMargin;
12222
+ if (isset($this->saveHTMLHeader[$this->page][$OE]['mb'])) {
12223
+ $this->saveHTMLHeader[$this->page][$OE]['mb'] = $this->bMargin;
12224
+ }
12225
+ }
12226
+ }
 
 
 
 
12227
 
12228
+ function _getHtmlHeight($html)
12229
+ {
12230
+ $save_state = $this->state;
12231
+ if ($this->state == 0) {
12232
+ $this->AddPage($this->CurOrientation);
12233
+ }
12234
+ $this->state = 2;
12235
+ $this->Reset();
12236
+ $this->pageoutput[$this->page] = [];
12237
+ $save_x = $this->x;
12238
+ $save_y = $this->y;
12239
+ $this->x = $this->lMargin;
12240
+ $this->y = $this->margin_header;
12241
+ $html = str_replace('{PAGENO}', $this->pagenumPrefix . $this->docPageNum($this->page) . $this->pagenumSuffix, $html);
12242
+ $html = str_replace($this->aliasNbPgGp, $this->nbpgPrefix . $this->docPageNumTotal($this->page) . $this->nbpgSuffix, $html);
12243
+ $html = str_replace($this->aliasNbPg, $this->page, $html);
12244
+ $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', [$this, 'date_callback'], $html); // mPDF 5.7
12245
+ $this->HTMLheaderPageLinks = [];
12246
+ $this->HTMLheaderPageAnnots = [];
12247
+ $this->HTMLheaderPageForms = [];
12248
+ $savepb = $this->pageBackgrounds;
12249
+ $this->writingHTMLheader = true;
12250
+ $this->WriteHTML($html, 4); // parameter 4 saves output to $this->headerbuffer
12251
+ $this->writingHTMLheader = false;
12252
+ $h = ($this->y - $this->margin_header);
12253
+ $this->Reset();
12254
+ // mPDF 5.7.2 - Clear in case Float used in Header/Footer
12255
+ $this->blk[0]['blockContext'] = 0;
12256
+ $this->blk[0]['float_endpos'] = 0;
12257
 
12258
+ $this->pageoutput[$this->page] = [];
12259
+ $this->headerbuffer = '';
12260
+ $this->pageBackgrounds = $savepb;
12261
+ $this->x = $save_x;
12262
+ $this->y = $save_y;
12263
+ $this->state = $save_state;
12264
+ if ($save_state == 0) {
12265
+ unset($this->pages[1]);
12266
+ $this->page = 0;
12267
+ }
12268
+ return $h;
12269
+ }
12270
 
12271
+ // Called internally from Header
12272
+ function writeHTMLHeaders()
12273
+ {
 
 
 
 
 
 
 
 
 
 
 
12274
 
12275
+ if ($this->mirrorMargins && ($this->page) % 2 == 0) {
12276
+ $OE = 'E';
12277
+ } else {
12278
+ $OE = 'O';
12279
+ }
 
 
 
 
 
12280
 
12281
+ if ($OE === 'E') {
12282
+ $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeaderE['html'];
12283
+ } else {
12284
+ $this->saveHTMLHeader[$this->page][$OE]['html'] = $this->HTMLHeader['html'];
12285
+ }
12286
 
12287
+ if ($this->forcePortraitHeaders && $this->CurOrientation == 'L' && $this->CurOrientation != $this->DefOrientation) {
12288
+ $this->saveHTMLHeader[$this->page][$OE]['rotate'] = true;
12289
+ $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->tMargin;
12290
+ $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->bMargin;
12291
+ $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
12292
+ $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
12293
+ $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->h;
12294
+ $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->w;
12295
+ } else {
12296
+ $this->saveHTMLHeader[$this->page][$OE]['ml'] = $this->lMargin;
12297
+ $this->saveHTMLHeader[$this->page][$OE]['mr'] = $this->rMargin;
12298
+ $this->saveHTMLHeader[$this->page][$OE]['mh'] = $this->margin_header;
12299
+ $this->saveHTMLHeader[$this->page][$OE]['mf'] = $this->margin_footer;
12300
+ $this->saveHTMLHeader[$this->page][$OE]['pw'] = $this->w;
12301
+ $this->saveHTMLHeader[$this->page][$OE]['ph'] = $this->h;
12302
+ }
12303
+ }
12304
 
12305
+ function writeHTMLFooters()
12306
+ {
 
12307
 
12308
+ if ($this->mirrorMargins && ($this->page) % 2 == 0) {
12309
+ $OE = 'E';
12310
+ } else {
12311
+ $OE = 'O';
12312
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12313
 
12314
  if ($OE === 'E') {
12315
  $this->saveHTMLFooter[$this->page][$OE]['html'] = $this->HTMLFooterE['html'];
12522
  {
12523
  $oddhtml = '';
12524
  $evenhtml = '';
12525
+
12526
  if (is_string($Harray)) {
12527
+
12528
+ if (strlen($Harray) === 0) {
12529
+
12530
  $oddhtml = '';
12531
  $evenhtml = '';
12532
+
12533
  } elseif (strpos($Harray, '|') !== false) {
12534
+
12535
  $hdet = explode('|', $Harray);
12536
+
12537
  list($lw, $cw, $rw) = $this->_shareHeaderFooterWidth($hdet[0], $hdet[1], $hdet[2]);
12538
  $oddhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: bottom; color: #000000; ';
12539
+
12540
  if ($this->defaultheaderfontsize) {
12541
  $oddhtml .= ' font-size: ' . $this->defaultheaderfontsize . 'pt;';
12542
  }
12543
+
12544
  if ($this->defaultheaderfontstyle) {
12545
+
12546
  if ($this->defaultheaderfontstyle == 'B' || $this->defaultheaderfontstyle == 'BI') {
12547
  $oddhtml .= ' font-weight: bold;';
12548
  }
12549
+
12550
  if ($this->defaultheaderfontstyle == 'I' || $this->defaultheaderfontstyle == 'BI') {
12551
  $oddhtml .= ' font-style: italic;';
12552
  }
12553
  }
12554
+
12555
  if ($this->defaultheaderline) {
12556
  $oddhtml .= ' border-bottom: 0.1mm solid #000000;';
12557
  }
12558
+
12559
  $oddhtml .= '">';
12560
  $oddhtml .= '<tr>';
12561
  $oddhtml .= '<td width="' . $lw . '%" style="padding: 0 0 ' . $this->header_line_spacing . 'em 0; text-align: left; ">' . $hdet[0] . '</td>';
12564
  $oddhtml .= '</tr></table>';
12565
 
12566
  $evenhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: bottom; color: #000000; ';
12567
+
12568
  if ($this->defaultheaderfontsize) {
12569
  $evenhtml .= ' font-size: ' . $this->defaultheaderfontsize . 'pt;';
12570
  }
12571
+
12572
  if ($this->defaultheaderfontstyle) {
12573
  if ($this->defaultheaderfontstyle == 'B' || $this->defaultheaderfontstyle == 'BI') {
12574
  $evenhtml .= ' font-weight: bold;';
12577
  $evenhtml .= ' font-style: italic;';
12578
  }
12579
  }
12580
+
12581
  if ($this->defaultheaderline) {
12582
  $evenhtml .= ' border-bottom: 0.1mm solid #000000;';
12583
  }
12584
+
12585
  $evenhtml .= '">';
12586
  $evenhtml .= '<tr>';
12587
  $evenhtml .= '<td width="' . $rw . '%" style="padding: 0 0 ' . $this->header_line_spacing . 'em 0; text-align: left; ">' . $hdet[2] . '</td>';
12588
  $evenhtml .= '<td width="' . $cw . '%" style="padding: 0 0 ' . $this->header_line_spacing . 'em 0; text-align: center; ">' . $hdet[1] . '</td>';
12589
  $evenhtml .= '<td width="' . $lw . '%" style="padding: 0 0 ' . $this->header_line_spacing . 'em 0; text-align: right; ">' . $hdet[0] . '</td>';
12590
  $evenhtml .= '</tr></table>';
12591
+
12592
  } else {
12593
+
12594
  $oddhtml = '<div style="margin: 0; color: #000000; ';
12595
+
12596
  if ($this->defaultheaderfontsize) {
12597
  $oddhtml .= ' font-size: ' . $this->defaultheaderfontsize . 'pt;';
12598
  }
12599
+
12600
  if ($this->defaultheaderfontstyle) {
12601
+
12602
  if ($this->defaultheaderfontstyle == 'B' || $this->defaultheaderfontstyle == 'BI') {
12603
  $oddhtml .= ' font-weight: bold;';
12604
  }
12605
+
12606
  if ($this->defaultheaderfontstyle == 'I' || $this->defaultheaderfontstyle == 'BI') {
12607
  $oddhtml .= ' font-style: italic;';
12608
  }
12609
  }
12610
+
12611
  if ($this->defaultheaderline) {
12612
  $oddhtml .= ' border-bottom: 0.1mm solid #000000;';
12613
  }
 
12614
 
12615
+ $oddhtml .= 'text-align: right; ">' . $Harray . '</div>';
12616
  $evenhtml = '<div style="margin: 0; color: #000000; ';
12617
+
12618
  if ($this->defaultheaderfontsize) {
12619
  $evenhtml .= ' font-size: ' . $this->defaultheaderfontsize . 'pt;';
12620
  }
12621
+
12622
  if ($this->defaultheaderfontstyle) {
12623
+
12624
  if ($this->defaultheaderfontstyle == 'B' || $this->defaultheaderfontstyle == 'BI') {
12625
  $evenhtml .= ' font-weight: bold;';
12626
  }
12627
+
12628
  if ($this->defaultheaderfontstyle == 'I' || $this->defaultheaderfontstyle == 'BI') {
12629
  $evenhtml .= ' font-style: italic;';
12630
  }
12631
  }
12632
+
12633
  if ($this->defaultheaderline) {
12634
  $evenhtml .= ' border-bottom: 0.1mm solid #000000;';
12635
  }
12636
+
12637
  $evenhtml .= 'text-align: left; ">' . $Harray . '</div>';
12638
  }
12639
+
12640
  } elseif (is_array($Harray) && !empty($Harray)) {
12641
+
12642
+ $odd = null;
12643
+ $even = null;
12644
+
12645
+ if ($side === 'O') {
12646
  $odd = $Harray;
12647
+ } elseif ($side === 'E') {
12648
  $even = $Harray;
12649
  } else {
12650
+ $odd = Arrays::get($Harray, 'odd', null);
12651
+ $even = Arrays::get($Harray, 'even', null);
12652
  }
 
12653
 
12654
+ $oddhtml = $this->_createHTMLheaderFooter($odd, 'H');
12655
  $evenhtml = $this->_createHTMLheaderFooter($even, 'H');
12656
  }
12657
 
12658
+ if ($side === 'E') {
12659
  $this->SetHTMLHeader($evenhtml, 'E', $write);
12660
+ } elseif ($side === 'O') {
12661
  $this->SetHTMLHeader($oddhtml, 'O', $write);
12662
  } else {
12663
  $this->SetHTMLHeader($oddhtml, 'O', $write);
12669
  {
12670
  $oddhtml = '';
12671
  $evenhtml = '';
12672
+
12673
  if (is_string($Farray)) {
12674
+
12675
  if (strlen($Farray) == 0) {
12676
+
12677
  $oddhtml = '';
12678
  $evenhtml = '';
12679
+
12680
  } elseif (strpos($Farray, '|') !== false) {
12681
+
12682
  $hdet = explode('|', $Farray);
12683
  $oddhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: top; color: #000000; ';
12684
+
12685
  if ($this->defaultfooterfontsize) {
12686
  $oddhtml .= ' font-size: ' . $this->defaultfooterfontsize . 'pt;';
12687
  }
12688
+
12689
  if ($this->defaultfooterfontstyle) {
12690
  if ($this->defaultfooterfontstyle == 'B' || $this->defaultfooterfontstyle == 'BI') {
12691
  $oddhtml .= ' font-weight: bold;';
12694
  $oddhtml .= ' font-style: italic;';
12695
  }
12696
  }
12697
+
12698
  if ($this->defaultfooterline) {
12699
  $oddhtml .= ' border-top: 0.1mm solid #000000;';
12700
  }
12701
+
12702
  $oddhtml .= '">';
12703
  $oddhtml .= '<tr>';
12704
  $oddhtml .= '<td width="33%" style="padding: ' . $this->footer_line_spacing . 'em 0 0 0; text-align: left; ">' . $hdet[0] . '</td>';
12707
  $oddhtml .= '</tr></table>';
12708
 
12709
  $evenhtml = '<table width="100%" style="border-collapse: collapse; margin: 0; vertical-align: top; color: #000000; ';
12710
+
12711
  if ($this->defaultfooterfontsize) {
12712
  $evenhtml .= ' font-size: ' . $this->defaultfooterfontsize . 'pt;';
12713
  }
12714
+
12715
  if ($this->defaultfooterfontstyle) {
12716
+
12717
  if ($this->defaultfooterfontstyle == 'B' || $this->defaultfooterfontstyle == 'BI') {
12718
  $evenhtml .= ' font-weight: bold;';
12719
  }
12720
+
12721
  if ($this->defaultfooterfontstyle == 'I' || $this->defaultfooterfontstyle == 'BI') {
12722
  $evenhtml .= ' font-style: italic;';
12723
  }
12724
  }
12725
+
12726
  if ($this->defaultfooterline) {
12727
  $evenhtml .= ' border-top: 0.1mm solid #000000;';
12728
  }
12729
+
12730
  $evenhtml .= '">';
12731
  $evenhtml .= '<tr>';
12732
  $evenhtml .= '<td width="33%" style="padding: ' . $this->footer_line_spacing . 'em 0 0 0; text-align: left; ">' . $hdet[2] . '</td>';
12733
  $evenhtml .= '<td width="33%" style="padding: ' . $this->footer_line_spacing . 'em 0 0 0; text-align: center; ">' . $hdet[1] . '</td>';
12734
  $evenhtml .= '<td width="33%" style="padding: ' . $this->footer_line_spacing . 'em 0 0 0; text-align: right; ">' . $hdet[0] . '</td>';
12735
  $evenhtml .= '</tr></table>';
12736
+
12737
  } else {
12738
+
12739
  $oddhtml = '<div style="margin: 0; color: #000000; ';
12740
+
12741
  if ($this->defaultfooterfontsize) {
12742
  $oddhtml .= ' font-size: ' . $this->defaultfooterfontsize . 'pt;';
12743
  }
12744
+
12745
  if ($this->defaultfooterfontstyle) {
12746
+
12747
  if ($this->defaultfooterfontstyle == 'B' || $this->defaultfooterfontstyle == 'BI') {
12748
  $oddhtml .= ' font-weight: bold;';
12749
  }
12750
+
12751
  if ($this->defaultfooterfontstyle == 'I' || $this->defaultfooterfontstyle == 'BI') {
12752
  $oddhtml .= ' font-style: italic;';
12753
  }
12754
  }
12755
+
12756
  if ($this->defaultfooterline) {
12757
  $oddhtml .= ' border-top: 0.1mm solid #000000;';
12758
  }
12759
+
12760
  $oddhtml .= 'text-align: right; ">' . $Farray . '</div>';
12761
 
12762
  $evenhtml = '<div style="margin: 0; color: #000000; ';
12763
+
12764
  if ($this->defaultfooterfontsize) {
12765
  $evenhtml .= ' font-size: ' . $this->defaultfooterfontsize . 'pt;';
12766
  }
12767
+
12768
  if ($this->defaultfooterfontstyle) {
12769
+
12770
  if ($this->defaultfooterfontstyle == 'B' || $this->defaultfooterfontstyle == 'BI') {
12771
  $evenhtml .= ' font-weight: bold;';
12772
  }
12773
+
12774
  if ($this->defaultfooterfontstyle == 'I' || $this->defaultfooterfontstyle == 'BI') {
12775
  $evenhtml .= ' font-style: italic;';
12776
  }
12777
  }
12778
+
12779
  if ($this->defaultfooterline) {
12780
  $evenhtml .= ' border-top: 0.1mm solid #000000;';
12781
  }
12782
+
12783
  $evenhtml .= 'text-align: left; ">' . $Farray . '</div>';
12784
  }
12785
+
12786
  } elseif (is_array($Farray)) {
12787
+
12788
+ $odd = null;
12789
+ $even = null;
12790
+
12791
+ if ($side === 'O') {
12792
  $odd = $Farray;
12793
  } elseif ($side == 'E') {
12794
  $even = $Farray;
12795
  } else {
12796
+ $odd = Arrays::get($Farray, 'odd', null);
12797
+ $even = Arrays::get($Farray, 'even', null);
 
 
 
 
 
 
 
 
12798
  }
12799
 
12800
+ $oddhtml = $this->_createHTMLheaderFooter($odd, 'F');
12801
+ $evenhtml = $this->_createHTMLheaderFooter($even, 'F');
 
12802
  }
12803
+
12804
+ if ($side === 'E') {
12805
  $this->SetHTMLFooter($evenhtml, 'E');
12806
+ } elseif ($side === 'O') {
12807
  $this->SetHTMLFooter($oddhtml, 'O');
12808
  } else {
12809
  $this->SetHTMLFooter($oddhtml, 'O');
12810
  $this->SetHTMLFooter($evenhtml, 'E');
12811
  }
 
12812
  }
12813
 
12814
  /* -- WATERMARK -- */
14391
  $this->blk[1]['y0'] = $bbox_y;
14392
  $this->blk[1]['startpage'] = $this->page;
14393
  $this->blk[1]['y1'] = $bbox_y + $bbox_bt + $bbox_pt + $inner_h + $bbox_pb + $bbox_bb;
14394
+ $this->writer->write($rot_start);
14395
  $this->PaintDivBB('', 0, 1); // Prints borders and sets backgrounds in $this->pageBackgrounds
14396
+ $this->writer->write($rot_end);
14397
  }
14398
 
14399
  $s = $this->PrintPageBackgrounds();
14401
  $this->pages[$this->page] = preg_replace('/___BEFORE_BORDERS___/', "\n" . $s . "\n", $this->pages[$this->page]);
14402
  $this->pageBackgrounds = [];
14403
 
14404
+ $this->writer->write($rot_start);
14405
 
14406
  // Clipping Output
14407
  if ($overflow == 'hidden') {
14412
  }
14413
  // $op = 'W* n'; // Clipping
14414
  $op = 'W n'; // Clipping alternative mode
14415
+ $this->writer->write("q");
14416
  $ch = $clip_y1 - $y;
14417
+ $this->writer->write(sprintf('%.3F %.3F %.3F %.3F re %s', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$ch * Mpdf::SCALE, $op));
14418
  if (!empty($block_s)) {
14419
  $tmp = "q\n" . sprintf('%.3F %.3F %.3F %.3F re %s', $x * Mpdf::SCALE, ($this->h - $y) * Mpdf::SCALE, $w * Mpdf::SCALE, -$ch * Mpdf::SCALE, $op);
14420
  $tmp .= "\n" . $block_s . "\nQ";
14429
  $tmp .= "\n" . $block_s . "\nQ";
14430
  $block_s = $tmp;
14431
  }
14432
+ $this->writer->write($block_s);
14433
  }
14434
 
14435
 
14439
  $this->transformScale(($shrink_f * 100), ($shrink_f * 100), $x, $y);
14440
  }
14441
 
14442
+ $this->writer->write($this->headerbuffer);
14443
 
14444
  if ($shrink_f != 1) { // i.e. autofit has resized the box
14445
  $this->StopTransform();
14447
 
14448
  if ($overflow == 'hidden') {
14449
  // End clipping
14450
+ $this->writer->write("Q");
14451
  }
14452
 
14453
+ $this->writer->write($rot_end);
14454
 
14455
 
14456
  // Page Links
15546
  return ($blt_width + $markeroffset);
15547
  }
15548
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15549
  function _saveTextBuffer($t, $link = '', $intlink = '', $return = false)
15550
  {
15551
  // mPDF 6 Lists
16622
 
16623
  if (isset($tbd['s']) && $tbd['s']) {
16624
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
16625
+ $this->writer->write('q');
16626
  $this->SetLineWidth(0);
16627
+ $this->writer->write(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE));
16628
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE));
16629
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE));
16630
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE));
16631
+ $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path
16632
  }
16633
 
16634
  $this->_setBorderLine($tbd);
16693
  }
16694
  /* -- END BORDER-RADIUS -- */
16695
  $s .= 'S' . "\n";
16696
+ $this->writer->write($s);
16697
 
16698
  if ($tbd['style'] == 'double') {
16699
  $this->SetLineWidth($tbd['w'] / 3);
16700
  $this->SetDColor($tbcol);
16701
+ $this->writer->write($s);
16702
  }
16703
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
16704
+ $this->writer->write('Q');
16705
  }
16706
 
16707
  // Reset Corners and Dash off
16719
  $tbd = $this->blk[$blvl]['border_bottom'];
16720
  if (isset($tbd['s']) && $tbd['s']) {
16721
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
16722
+ $this->writer->write('q');
16723
  $this->SetLineWidth(0);
16724
+ $this->writer->write(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE));
16725
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE));
16726
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE));
16727
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE));
16728
+ $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path
16729
  }
16730
 
16731
  $this->_setBorderLine($tbd);
16757
  }
16758
  }
16759
  $s .= 'S' . "\n";
16760
+ $this->writer->write($s);
16761
 
16762
  if ($tbd['style'] == 'double') {
16763
  $this->SetLineWidth($tbd['w'] / 3);
16764
  $this->SetDColor($tbcol);
16765
+ $this->writer->write($s);
16766
  }
16767
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
16768
+ $this->writer->write('Q');
16769
  }
16770
 
16771
  // Reset Corners and Dash off
16783
  $tbd = $this->blk[$blvl]['border_left'];
16784
  if (isset($tbd['s']) && $tbd['s']) {
16785
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
16786
+ $this->writer->write('q');
16787
  $this->SetLineWidth(0);
16788
+ $this->writer->write(sprintf('%.3F %.3F m ', ($x0) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE));
16789
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE));
16790
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $border_left) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE));
16791
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE));
16792
+ $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path
16793
  }
16794
 
16795
  $this->_setBorderLine($tbd);
16821
  }
16822
  }
16823
  $s .= 'S' . "\n";
16824
+ $this->writer->write($s);
16825
 
16826
  if ($tbd['style'] == 'double') {
16827
  $this->SetLineWidth($tbd['w'] / 3);
16828
  $this->SetDColor($tbcol);
16829
+ $this->writer->write($s);
16830
  }
16831
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
16832
+ $this->writer->write('Q');
16833
  }
16834
 
16835
  // Reset Corners and Dash off
16844
  $tbd = $this->blk[$blvl]['border_right'];
16845
  if (isset($tbd['s']) && $tbd['s']) {
16846
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
16847
+ $this->writer->write('q');
16848
  $this->SetLineWidth(0);
16849
+ $this->writer->write(sprintf('%.3F %.3F m ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0)) * Mpdf::SCALE));
16850
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $border_top)) * Mpdf::SCALE));
16851
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w - $border_right) * Mpdf::SCALE, ($this->h - ($y0 + $h - $border_bottom)) * Mpdf::SCALE));
16852
+ $this->writer->write(sprintf('%.3F %.3F l ', ($x0 + $w) * Mpdf::SCALE, ($this->h - ($y0 + $h)) * Mpdf::SCALE));
16853
+ $this->writer->write(' h W n '); // Ends path no-op & Sets the clipping path
16854
  }
16855
 
16856
  $this->_setBorderLine($tbd);
16882
  }
16883
  }
16884
  $s .= 'S' . "\n";
16885
+ $this->writer->write($s);
16886
 
16887
  if ($tbd['style'] == 'double') {
16888
  $this->SetLineWidth($tbd['w'] / 3);
16889
  $this->SetDColor($tbcol);
16890
+ $this->writer->write($s);
16891
  }
16892
  if (!$brset && $tbd['style'] != 'dotted' && $tbd['style'] != 'dashed') {
16893
+ $this->writer->write('Q');
16894
  }
16895
 
16896
  // Reset Corners and Dash off
21566
  if ($table['overflow'] == 'hidden' && $level == 1 && !$this->table_rotate && !$this->ColActive) {
21567
  // Bounding rectangle to clip
21568
  $this->tableClipPath = sprintf('q %.3F %.3F %.3F %.3F re W n', $x0 * Mpdf::SCALE, $this->h * Mpdf::SCALE, $this->blk[$this->blklvl]['inner_width'] * Mpdf::SCALE, -$this->h * Mpdf::SCALE);
21569
+ $this->writer->write($this->tableClipPath);
21570
  } else {
21571
  $this->tableClipPath = '';
21572
  }
21686
  }
21687
 
21688
  if ($level == 1) {
21689
+ $this->writer->write('___TABLE___BACKGROUNDS' . $this->uniqstr);
21690
  }
21691
  $tableheaderadj = 0;
21692
  $tablefooteradj = 0;
21834
  }
21835
 
21836
  if ($this->tableClipPath) {
21837
+ $this->writer->write("Q");
21838
  }
21839
 
21840
  $bx = $x0;
21899
  }
21900
  $this->Line($blx, $this->y + ($this->splitTableBorderWidth / 2), $blx + $blw, $this->y + ($this->splitTableBorderWidth / 2));
21901
  $this->DrawColor = $prevDrawColor;
21902
+ $this->writer->write($this->DrawColor);
21903
  $this->SetLineWidth($lw);
21904
  $this->SetLineJoin(2);
21905
  $this->SetLineCap(2);
21977
 
21978
  $this->AddPage($this->CurOrientation);
21979
 
21980
+ $this->writer->write('___TABLE___BACKGROUNDS' . $this->uniqstr);
21981
 
21982
 
21983
  if ($this->tableClipPath) {
21984
+ $this->writer->write($this->tableClipPath);
21985
  }
21986
 
21987
  // Added to correct for OddEven Margins
21998
  $blx += $this->MarginCorrection;
21999
  $this->Line($blx, $this->y - ($this->splitTableBorderWidth / 2), $blx + $blw, $this->y - ($this->splitTableBorderWidth / 2));
22000
  $this->DrawColor = $prevDrawColor;
22001
+ $this->writer->write($this->DrawColor);
22002
  $this->SetLineWidth($lw);
22003
  $this->SetLineJoin(2);
22004
  $this->SetLineCap(2);
22065
  }
22066
  if ($adv) {
22067
  if ($this->table_rotate) {
22068
+ $this->y += ($adv);
22069
+ } else {
22070
+ $this->DivLn($adv, $this->blklvl, true);
22071
+ }
22072
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22073
  }
22074
+
22075
+ $outerfilled = 0;
22076
+ $y = $y0 = $this->y;
22077
  }
22078
+
22079
+ /* -- COLUMNS -- */
22080
+ // COLS
22081
+ // COLUMN CHANGE
22082
+ if ($this->CurrCol != $oldcolumn) {
22083
+ // Added to correct for Columns
22084
+ $x += $this->ChangeColumn * ($this->ColWidth + $this->ColGap);
22085
+ $x0 += $this->ChangeColumn * ($this->ColWidth + $this->ColGap);
22086
+ if ($this->CurrCol == 0) { // just added a page - possibly with tableheader
22087
+ $y0 = $this->y; // this->y0 is global used by Columns - $y0 is internal to tablewrite
 
 
 
 
 
 
 
 
22088
  } else {
22089
+ $y0 = $this->y0; // this->y0 is global used by Columns - $y0 is internal to tablewrite
22090
+ }
22091
+ $y = $y0;
22092
+ $outerfilled = 0;
22093
+ if ($this->CurrCol != 0 && ($this->keepColumns && $this->ColActive) && !empty($tableheader) && $i > 0) {
22094
+ $this->x = $x;
22095
+ $this->y = $y;
22096
+ $this->TableHeaderFooter($tableheader, $tablestartpage, $tablestartcolumn, 'H', $level);
22097
+ $y0 = $y = $this->y;
22098
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
22099
  }
22100
+ /* -- END COLUMNS -- */
22101
  }
22102
+ $skippage = true;
 
 
 
 
 
 
 
 
 
 
 
22103
  }
22104
 
22105
+ $this->x = $x;
22106
+ $this->y = $y;
22107
 
22108
+ if ($this->kwt_saved && $level == 1) {
22109
+ $this->printkwtbuffer();
22110
+ $x0 = $x = $this->x;
22111
+ $y0 = $y = $this->y;
22112
+ $this->kwt_moved = false;
22113
+ $this->kwt_saved = false;
 
 
 
 
 
 
22114
  }
22115
 
22116
 
22117
+ // Set the Page & Column where table actually starts
22118
+ if ($i == 0 && $j == 0 && $level == 1) {
22119
+ if (($this->mirrorMargins) && (($this->page) % 2 == 0)) { // EVEN
22120
+ $tablestartpage = 'EVEN';
22121
+ } elseif (($this->mirrorMargins) && (($this->page) % 2 == 1)) { // ODD
22122
+ $tablestartpage = 'ODD';
 
 
 
 
 
 
 
 
 
22123
  } else {
22124
+ $tablestartpage = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22125
  }
22126
+ $tablestartpageno = $this->page;
22127
+ if ($this->ColActive) {
22128
+ $tablestartcolumn = $this->CurrCol;
22129
+ } // *COLUMNS*
22130
  }
22131
 
22132
+ // ALIGN
22133
+ $align = $cell['a'];
 
 
 
 
 
 
22134
 
22135
+ /* -- COLUMNS -- */
22136
+ // If outside columns, this is done in PaintDivBB
22137
+ if ($this->ColActive) {
22138
+ // OUTER FILL BGCOLOR of DIVS
22139
+ if ($this->blklvl > 0 && ($j == 0) && !$this->table_rotate && $level == 1) {
22140
+ $firstblockfill = $this->GetFirstBlockFill();
22141
+ if ($firstblockfill && $this->blklvl >= $firstblockfill) {
22142
+ $divh = $maxrowheight;
22143
+ // Last row
22144
+ if ((!isset($cell['rowspan']) && $i == $numrows - 1) || (isset($cell['rowspan']) && (($i == $numrows - 1 && $cell['rowspan'] < 2) || ($cell['rowspan'] > 1 && ($i + $cell['rowspan'] - 1) == $numrows - 1)))) {
22145
+ if ($table['borders_separate']) {
22146
+ $adv = $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2;
22147
+ } else {
22148
+ $adv = $table['margin']['B'] + $table['max_cell_border_width']['B'] / 2;
22149
+ }
22150
+ $divh += $adv; // last row: fill bottom half of bottom border (y advanced at end)
22151
+ }
22152
 
22153
+ if (($this->y + $divh) > $outerfilled) { // if not already painted by previous rowspan
22154
+ $bak_x = $this->x;
22155
+ $bak_y = $this->y;
22156
+ if ($outerfilled > $this->y) {
22157
+ $divh = ($this->y + $divh) - $outerfilled;
22158
+ $this->y = $outerfilled;
22159
+ }
22160
 
22161
+ $this->DivLn($divh, -3, false);
22162
+ $outerfilled = $this->y + $divh;
22163
+ // Reset current block fill
22164
+ $bcor = $this->blk[$this->blklvl]['bgcolorarray'];
22165
+ if ($bcor) {
22166
+ $this->SetFColor($bcor);
22167
+ }
22168
+ $this->x = $bak_x;
22169
+ $this->y = $bak_y;
 
 
 
 
 
 
 
 
22170
  }
22171
  }
22172
  }
22173
+ }
22174
+
22175
+ // TABLE BACKGROUND FILL BGCOLOR - for cellSpacing
22176
+ if ($this->ColActive) {
22177
+ if ($table['borders_separate']) {
22178
+ $fill = isset($table['bgcolor'][-1]) ? $table['bgcolor'][-1] : 0;
22179
+ if ($fill) {
22180
+ $color = $this->colorConverter->convert($fill, $this->PDFAXwarnings);
22181
+ if ($color) {
22182
+ $xadj = ($table['border_spacing_H'] / 2);
22183
+ $yadj = ($table['border_spacing_V'] / 2);
22184
+ $wadj = $table['border_spacing_H'];
22185
+ $hadj = $table['border_spacing_V'];
22186
+ if ($i == 0) { // Top
22187
+ $yadj += $table['padding']['T'] + $table['border_details']['T']['w'];
22188
+ $hadj += $table['padding']['T'] + $table['border_details']['T']['w'];
22189
+ }
22190
+ if ($j == 0) { // Left
22191
+ $xadj += $table['padding']['L'] + $table['border_details']['L']['w'];
22192
+ $wadj += $table['padding']['L'] + $table['border_details']['L']['w'];
22193
+ }
22194
+ if ($i == ($numrows - 1) || (isset($cell['rowspan']) && ($i + $cell['rowspan']) == $numrows) || (!isset($cell['rowspan']) && ($i + 1) == $numrows)) { // Bottom
22195
+ $hadj += $table['padding']['B'] + $table['border_details']['B']['w'];
22196
+ }
22197
+ if ($j == ($numcols - 1) || (isset($cell['colspan']) && ($j + $cell['colspan']) == $numcols) || (!isset($cell['colspan']) && ($j + 1) == $numcols)) { // Right
22198
+ $wadj += $table['padding']['R'] + $table['border_details']['R']['w'];
22199
  }
22200
+ $this->SetFColor($color);
22201
+ $this->Rect($x - $xadj, $y - $yadj, $w + $wadj, $h + $hadj, 'F');
22202
  }
22203
  }
22204
  }
22205
+ }
22206
+ /* -- END COLUMNS -- */
22207
 
22208
+ if ($table['empty_cells'] != 'hide' || !empty($cell['textbuffer']) || (isset($cell['nestedcontent']) && $cell['nestedcontent']) || !$table['borders_separate']) {
22209
+ $paintcell = true;
22210
+ } else {
22211
+ $paintcell = false;
22212
+ }
22213
 
22214
+ // Set Borders
22215
+ $bord = 0;
22216
+ $bord_det = [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22217
 
22218
+ if (!$this->simpleTables) {
22219
+ if ($this->packTableData) {
22220
+ $c = $this->_unpackCellBorder($cell['borderbin']);
22221
+ $bord = $c['border'];
22222
+ $bord_det = $c['border_details'];
 
22223
  } else {
22224
+ $bord = $cell['border'];
22225
+ $bord_det = $cell['border_details'];
22226
+ }
22227
+ } elseif ($this->simpleTables) {
22228
+ $bord = $table['simple']['border'];
22229
+ $bord_det = $table['simple']['border_details'];
22230
+ }
22231
+
22232
+ // TABLE ROW OR CELL FILL BGCOLOR
22233
+ $fill = 0;
22234
+ if (isset($cell['bgcolor']) && $cell['bgcolor'] && $cell['bgcolor'] != 'transparent') {
22235
+ $fill = $cell['bgcolor'];
22236
+ $leveladj = 6;
22237
+ } elseif (isset($table['bgcolor'][$i]) && $table['bgcolor'][$i] && $table['bgcolor'][$i] != 'transparent') { // Row color
22238
+ $fill = $table['bgcolor'][$i];
22239
+ $leveladj = 3;
22240
+ }
22241
+ if ($fill && $paintcell) {
22242
+ $color = $this->colorConverter->convert($fill, $this->PDFAXwarnings);
22243
+ if ($color) {
22244
+ if ($table['borders_separate']) {
22245
+ if ($this->ColActive) {
22246
+ $this->SetFColor($color);
22247
+ $this->Rect($x + ($table['border_spacing_H'] / 2), $y + ($table['border_spacing_V'] / 2), $w - $table['border_spacing_H'], $h - $table['border_spacing_V'], 'F');
22248
  } else {
22249
+ $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => ($x + ($table['border_spacing_H'] / 2)), 'y' => ($y + ($table['border_spacing_V'] / 2)), 'w' => ($w - $table['border_spacing_H']), 'h' => ($h - $table['border_spacing_V']), 'col' => $color];
 
 
22250
  }
22251
+ } else {
22252
+ if ($this->ColActive) {
22253
+ $this->SetFColor($color);
22254
+ $this->Rect($x, $y, $w, $h, 'F');
 
22255
  } else {
22256
+ $this->tableBackgrounds[$level * 9 + $leveladj][] = ['gradient' => false, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'col' => $color];
 
 
 
 
 
 
 
 
 
 
22257
  }
22258
  }
 
 
 
 
 
 
 
22259
  }
 
22260
  }
22261
 
22262
  /* -- BACKGROUNDS -- */
22263
+ if (isset($cell['gradient']) && $cell['gradient'] && $paintcell) {
22264
+ $g = $this->gradient->parseBackgroundGradient($cell['gradient']);
22265
+ if ($g) {
22266
+ if ($table['borders_separate']) {
22267
+ $px = $x + ($table['border_spacing_H'] / 2);
22268
+ $py = $y + ($table['border_spacing_V'] / 2);
22269
+ $pw = $w - $table['border_spacing_H'];
22270
+ $ph = $h - $table['border_spacing_V'];
22271
+ } else {
22272
+ $px = $x;
22273
+ $py = $y;
22274
+ $pw = $w;
22275
+ $ph = $h;
 
 
 
 
 
 
 
22276
  }
22277
+ if ($this->ColActive) {
22278
+ $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22279
  } else {
22280
+ $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
22281
+ }
22282
+ }
22283
+ }
22284
+
22285
+ if (isset($cell['background-image']) && $paintcell) {
22286
+ if (isset($cell['background-image']['gradient']) && $cell['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $cell['background-image']['gradient'])) {
22287
+ $g = $this->gradient->parseMozGradient($cell['background-image']['gradient']);
22288
+ if ($g) {
 
 
 
 
 
 
22289
  if ($table['borders_separate']) {
22290
+ $px = $x + ($table['border_spacing_H'] / 2);
22291
+ $py = $y + ($table['border_spacing_V'] / 2);
22292
+ $pw = $w - $table['border_spacing_H'];
22293
+ $ph = $h - $table['border_spacing_V'];
 
 
 
 
22294
  } else {
22295
+ $px = $x;
22296
+ $py = $y;
22297
+ $pw = $w;
22298
+ $ph = $h;
22299
+ }
22300
+ if ($this->ColActive) {
22301
+ $this->gradient->Gradient($px, $py, $pw, $ph, $g['type'], $g['stops'], $g['colorspace'], $g['coords'], $g['extend']);
22302
+ } else {
22303
+ $this->tableBackgrounds[$level * 9 + 7][] = ['gradient' => true, 'x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
22304
+ }
22305
+ }
22306
+ } elseif (isset($cell['background-image']['image_id']) && $cell['background-image']['image_id']) { // Background pattern
22307
+ $n = count($this->patterns) + 1;
22308
+ if ($table['borders_separate']) {
22309
+ $px = $x + ($table['border_spacing_H'] / 2);
22310
+ $py = $y + ($table['border_spacing_V'] / 2);
22311
+ $pw = $w - $table['border_spacing_H'];
22312
+ $ph = $h - $table['border_spacing_V'];
22313
+ } else {
22314
+ $px = $x;
22315
+ $py = $y;
22316
+ $pw = $w;
22317
+ $ph = $h;
22318
+ }
22319
+ if ($this->ColActive) {
22320
+ list($orig_w, $orig_h, $x_repeat, $y_repeat) = $this->_resizeBackgroundImage($cell['background-image']['orig_w'], $cell['background-image']['orig_h'], $pw, $ph, $cell['background-image']['resize'], $cell['background-image']['x_repeat'], $cell['background-image']['y_repeat']);
22321
+ $this->patterns[$n] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'pgh' => $this->h, 'image_id' => $cell['background-image']['image_id'], 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $cell['background-image']['x_pos'], 'y_pos' => $cell['background-image']['y_pos'], 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat];
22322
+ if ($cell['background-image']['opacity'] > 0 && $cell['background-image']['opacity'] < 1) {
22323
+ $opac = $this->SetAlpha($cell['background-image']['opacity'], 'Normal', true);
22324
+ } else {
22325
+ $opac = '';
22326
  }
22327
+ $this->writer->write(sprintf('q /Pattern cs /P%d scn %s %.3F %.3F %.3F %.3F re f Q', $n, $opac, $px * Mpdf::SCALE, ($this->h - $py) * Mpdf::SCALE, $pw * Mpdf::SCALE, -$ph * Mpdf::SCALE));
22328
+ } else {
22329
+ $image_id = $cell['background-image']['image_id'];
22330
+ $orig_w = $cell['background-image']['orig_w'];
22331
+ $orig_h = $cell['background-image']['orig_h'];
22332
+ $x_pos = $cell['background-image']['x_pos'];
22333
+ $y_pos = $cell['background-image']['y_pos'];
22334
+ $x_repeat = $cell['background-image']['x_repeat'];
22335
+ $y_repeat = $cell['background-image']['y_repeat'];
22336
+ $resize = $cell['background-image']['resize'];
22337
+ $opacity = $cell['background-image']['opacity'];
22338
+ $itype = $cell['background-image']['itype'];
22339
+ $this->tableBackgrounds[$level * 9 + 8][] = ['x' => $px, 'y' => $py, 'w' => $pw, 'h' => $ph, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
22340
  }
22341
  }
22342
  }
 
22343
  /* -- END BACKGROUNDS -- */
22344
 
22345
+ if (isset($cell['colspan']) && $cell['colspan'] > 1) {
22346
+ $ccolsp = $cell['colspan'];
22347
+ } else {
22348
+ $ccolsp = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22349
  }
22350
+ if (isset($cell['rowspan']) && $cell['rowspan'] > 1) {
22351
+ $crowsp = $cell['rowspan'];
22352
+ } else {
22353
+ $crowsp = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22354
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22355
 
22356
+
22357
+ // but still need to do this for repeated headers...
22358
+ if (!$table['borders_separate'] && $this->tabletheadjustfinished && !$this->simpleTables) {
22359
+ if (isset($table['topntail']) && $table['topntail']) {
22360
+ $bord_det['T'] = $this->border_details($table['topntail']);
22361
+ $bord_det['T']['w'] /= $this->shrin_k;
22362
+ $this->setBorder($bord, Border::TOP);
22363
+ }
22364
+ if (isset($table['thead-underline']) && $table['thead-underline']) {
22365
+ $bord_det['T'] = $this->border_details($table['thead-underline']);
22366
+ $bord_det['T']['w'] /= $this->shrin_k;
22367
+ $this->setBorder($bord, Border::TOP);
22368
+ }
22369
+ }
 
 
 
 
 
 
22370
 
22371
 
22372
+ // Get info of first row ==>> table header
22373
+ // Use > 1 row if THEAD
22374
+ if (isset($table['is_thead'][$i]) && $table['is_thead'][$i] && $level == 1) {
22375
+ if ($j == 0) {
22376
+ $tableheaderrowheight += $table['hr'][$i];
22377
+ }
22378
+ $tableheader[$i][0]['trbackground-images'] = (isset($table['trbackground-images'][$i]) ? $table['trbackground-images'][$i] : null);
22379
+ $tableheader[$i][0]['trgradients'] = (isset($table['trgradients'][$i]) ? $table['trgradients'][$i] : null);
22380
+ $tableheader[$i][0]['trbgcolor'] = (isset($table['bgcolor'][$i]) ? $table['bgcolor'][$i] : null);
22381
+ $tableheader[$i][$j]['x'] = $x;
22382
+ $tableheader[$i][$j]['y'] = $y;
22383
+ $tableheader[$i][$j]['h'] = $h;
22384
+ $tableheader[$i][$j]['w'] = $w;
22385
+ if (isset($cell['textbuffer'])) {
22386
+ $tableheader[$i][$j]['textbuffer'] = $cell['textbuffer'];
22387
+ } else {
22388
+ $tableheader[$i][$j]['textbuffer'] = '';
22389
+ }
22390
+ $tableheader[$i][$j]['a'] = $cell['a'];
22391
+ $tableheader[$i][$j]['R'] = $cell['R'];
22392
 
22393
+ $tableheader[$i][$j]['va'] = $cell['va'];
22394
+ $tableheader[$i][$j]['mih'] = $cell['mih'];
22395
+ $tableheader[$i][$j]['gradient'] = (isset($cell['gradient']) ? $cell['gradient'] : null); // *BACKGROUNDS*
22396
+ $tableheader[$i][$j]['background-image'] = (isset($cell['background-image']) ? $cell['background-image'] : null); // *BACKGROUNDS*
22397
+ $tableheader[$i][$j]['rowspan'] = (isset($cell['rowspan']) ? $cell['rowspan'] : null);
22398
+ $tableheader[$i][$j]['colspan'] = (isset($cell['colspan']) ? $cell['colspan'] : null);
22399
+ $tableheader[$i][$j]['bgcolor'] = $cell['bgcolor'];
22400
 
22401
+ if (!$this->simpleTables) {
22402
+ $tableheader[$i][$j]['border'] = $bord;
22403
+ $tableheader[$i][$j]['border_details'] = $bord_det;
22404
+ } elseif ($this->simpleTables) {
22405
+ $tableheader[$i][$j]['border'] = $table['simple']['border'];
22406
+ $tableheader[$i][$j]['border_details'] = $table['simple']['border_details'];
22407
+ }
22408
+ $tableheader[$i][$j]['padding'] = $cell['padding'];
22409
+ if (isset($cell['direction'])) {
22410
+ $tableheader[$i][$j]['direction'] = $cell['direction'];
22411
+ }
22412
+ if (isset($cell['cellLineHeight'])) {
22413
+ $tableheader[$i][$j]['cellLineHeight'] = $cell['cellLineHeight'];
22414
+ }
22415
+ if (isset($cell['cellLineStackingStrategy'])) {
22416
+ $tableheader[$i][$j]['cellLineStackingStrategy'] = $cell['cellLineStackingStrategy'];
22417
+ }
22418
+ if (isset($cell['cellLineStackingShift'])) {
22419
+ $tableheader[$i][$j]['cellLineStackingShift'] = $cell['cellLineStackingShift'];
22420
+ }
22421
+ }
22422
 
22423
+ // CELL BORDER
22424
+ if ($bord) {
22425
+ if ($table['borders_separate'] && $paintcell) {
22426
+ $this->_tableRect($x + ($table['border_spacing_H'] / 2) + ($bord_det['L']['w'] / 2), $y + ($table['border_spacing_V'] / 2) + ($bord_det['T']['w'] / 2), $w - $table['border_spacing_H'] - ($bord_det['L']['w'] / 2) - ($bord_det['R']['w'] / 2), $h - $table['border_spacing_V'] - ($bord_det['T']['w'] / 2) - ($bord_det['B']['w'] / 2), $bord, $bord_det, false, $table['borders_separate']);
22427
+ } elseif (!$table['borders_separate']) {
22428
+ $this->_tableRect($x, $y, $w, $h, $bord, $bord_det, true, $table['borders_separate']); // true causes buffer
22429
+ }
22430
+ }
22431
 
22432
+ // VERTICAL ALIGN
22433
+ if ($cell['R'] && intval($cell['R']) > 0 && intval($cell['R']) < 90 && isset($cell['va']) && $cell['va'] != 'B') {
22434
+ $cell['va'] = 'B';
22435
+ }
22436
+ if (!isset($cell['va']) || $cell['va'] == 'M') {
22437
+ $this->y += ($h - $cell['mih']) / 2;
22438
+ } elseif (isset($cell['va']) && $cell['va'] == 'B') {
22439
+ $this->y += $h - $cell['mih'];
22440
+ }
 
 
 
 
22441
 
22442
+ // NESTED CONTENT
22443
+ // TEXT (and nested tables)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22444
 
22445
+ $this->divwidth = $w;
22446
+ if (!empty($cell['textbuffer'])) {
22447
+ $this->cellTextAlign = $align;
22448
+ $this->cellLineHeight = $cell['cellLineHeight'];
22449
+ $this->cellLineStackingStrategy = $cell['cellLineStackingStrategy'];
22450
+ $this->cellLineStackingShift = $cell['cellLineStackingShift'];
22451
+ if ($level == 1) {
22452
+ if (isset($table['is_tfoot'][$i]) && $table['is_tfoot'][$i]) {
22453
+ if (preg_match('/{colsum([0-9]*)[_]*}/', $cell['textbuffer'][0][0], $m)) {
22454
+ $rep = sprintf("%01." . intval($m[1]) . "f", $this->colsums[$j]);
22455
+ $cell['textbuffer'][0][0] = preg_replace('/{colsum[0-9_]*}/', $rep, $cell['textbuffer'][0][0]);
22456
+ }
22457
+ } elseif (!isset($table['is_thead'][$i])) {
22458
+ if (isset($this->colsums[$j])) {
22459
+ $this->colsums[$j] += $this->toFloat($cell['textbuffer'][0][0]);
22460
+ } else {
22461
+ $this->colsums[$j] = $this->toFloat($cell['textbuffer'][0][0]);
22462
+ }
22463
+ }
22464
+ }
22465
+ $opy = $this->y;
22466
+ // mPDF ITERATION
22467
+ if ($this->iterationCounter) {
22468
+ foreach ($cell['textbuffer'] as $k => $t) {
22469
+ if (preg_match('/{iteration ([a-zA-Z0-9_]+)}/', $t[0], $m)) {
22470
+ $vname = '__' . $m[1] . '_';
22471
+ if (!isset($this->$vname)) {
22472
+ $this->$vname = 1;
22473
+ } else {
22474
+ $this->$vname++;
22475
+ }
22476
+ $cell['textbuffer'][$k][0] = preg_replace('/{iteration ' . $m[1] . '}/', $this->$vname, $cell['textbuffer'][$k][0]);
22477
+ }
22478
+ }
22479
+ }
22480
 
22481
+
22482
+ if ($cell['R']) {
22483
+ $cellPtSize = $cell['textbuffer'][0][11] / $this->shrin_k;
22484
+ if (!$cellPtSize) {
22485
+ $cellPtSize = $this->default_font_size;
22486
+ }
22487
+ $cellFontHeight = ($cellPtSize / Mpdf::SCALE);
22488
+ $opx = $this->x;
22489
+ $angle = intval($cell['R']);
22490
+ // Only allow 45 to 89 degrees (when bottom-aligned) or exactly 90 or -90
22491
+ if ($angle > 90) {
22492
+ $angle = 90;
22493
+ } elseif ($angle > 0 && $angle < 45) {
22494
+ $angle = 45;
22495
+ } elseif ($angle < 0) {
22496
+ $angle = -90;
22497
+ }
22498
+ $offset = ((sin(deg2rad($angle))) * 0.37 * $cellFontHeight);
22499
+ if (isset($cell['a']) && $cell['a'] == 'R') {
22500
+ $this->x += ($w) + ($offset) - ($cellFontHeight / 3) - ($cell['padding']['R'] + ($table['border_spacing_H'] / 2));
22501
+ } elseif (!isset($cell['a']) || $cell['a'] == 'C') {
22502
+ $this->x += ($w / 2) + ($offset);
22503
+ } else {
22504
+ $this->x += ($offset) + ($cellFontHeight / 3) + ($cell['padding']['L'] + ($table['border_spacing_H'] / 2));
22505
+ }
22506
+ $str = '';
22507
+ foreach ($cell['textbuffer'] as $t) {
22508
+ $str .= $t[0] . ' ';
22509
+ }
22510
+ $str = rtrim($str);
22511
+ if (!isset($cell['va']) || $cell['va'] == 'M') {
22512
+ $this->y -= ($h - $cell['mih']) / 2; // Undo what was added earlier VERTICAL ALIGN
22513
+ if ($angle > 0) {
22514
+ $this->y += (($h - $cell['mih']) / 2) + $cell['padding']['T'] + ($cell['mih'] - ($cell['padding']['T'] + $cell['padding']['B']));
22515
+ } elseif ($angle < 0) {
22516
+ $this->y += (($h - $cell['mih']) / 2) + ($cell['padding']['T'] + ($table['border_spacing_V'] / 2));
22517
+ }
22518
+ } elseif (isset($cell['va']) && $cell['va'] == 'B') {
22519
+ $this->y -= $h - $cell['mih']; // Undo what was added earlier VERTICAL ALIGN
22520
+ if ($angle > 0) {
22521
+ $this->y += $h - ($cell['padding']['B'] + ($table['border_spacing_V'] / 2));
22522
+ } elseif ($angle < 0) {
22523
+ $this->y += $h - $cell['mih'] + ($cell['padding']['T'] + ($table['border_spacing_V'] / 2));
22524
+ }
22525
+ } elseif (isset($cell['va']) && $cell['va'] == 'T') {
22526
+ if ($angle > 0) {
22527
+ $this->y += $cell['mih'] - ($cell['padding']['B'] + ($table['border_spacing_V'] / 2));
22528
+ } elseif ($angle < 0) {
22529
+ $this->y += ($cell['padding']['T'] + ($table['border_spacing_V'] / 2));
22530
+ }
22531
+ }
22532
+ $this->Rotate($angle, $this->x, $this->y);
22533
+ $s_fs = $this->FontSizePt;
22534
+ $s_f = $this->FontFamily;
22535
+ $s_st = $this->FontStyle;
22536
+ if (!empty($cell['textbuffer'][0][3])) { // Font Color
22537
+ $cor = $cell['textbuffer'][0][3];
22538
+ $this->SetTColor($cor);
22539
+ }
22540
+ $this->SetFont($cell['textbuffer'][0][4], $cell['textbuffer'][0][2], $cellPtSize, true, true);
22541
+
22542
+ $this->magic_reverse_dir($str, $this->directionality, $cell['textbuffer'][0][18]);
22543
+ $this->Text($this->x, $this->y, $str, $cell['textbuffer'][0][18], $cell['textbuffer'][0][8]); // textvar
22544
+ $this->Rotate(0);
22545
+ $this->SetFont($s_f, $s_st, $s_fs, true, true);
22546
+ $this->SetTColor(0);
22547
+ $this->x = $opx;
22548
  } else {
22549
+ if (!$this->simpleTables) {
22550
+ if ($bord_det) {
22551
+ $btlw = $bord_det['L']['w'];
22552
+ $btrw = $bord_det['R']['w'];
22553
+ $bttw = $bord_det['T']['w'];
22554
+ } else {
22555
+ $btlw = 0;
22556
+ $btrw = 0;
22557
+ $bttw = 0;
22558
+ }
22559
+ if ($table['borders_separate']) {
22560
+ $xadj = $btlw + $cell['padding']['L'] + ($table['border_spacing_H'] / 2);
22561
+ $wadj = $btlw + $btrw + $cell['padding']['L'] + $cell['padding']['R'] + $table['border_spacing_H'];
22562
+ $yadj = $bttw + $cell['padding']['T'] + ($table['border_spacing_H'] / 2);
22563
+ } else {
22564
+ $xadj = $btlw / 2 + $cell['padding']['L'];
22565
+ $wadj = ($btlw + $btrw) / 2 + $cell['padding']['L'] + $cell['padding']['R'];
22566
+ $yadj = $bttw / 2 + $cell['padding']['T'];
22567
+ }
22568
+ } elseif ($this->simpleTables) {
22569
+ if ($table['borders_separate']) { // NB twice border width
22570
+ $xadj = $table['simple']['border_details']['L']['w'] + $cell['padding']['L'] + ($table['border_spacing_H'] / 2);
22571
+ $wadj = $table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w'] + $cell['padding']['L'] + $cell['padding']['R'] + $table['border_spacing_H'];
22572
+ $yadj = $table['simple']['border_details']['T']['w'] + $cell['padding']['T'] + ($table['border_spacing_H'] / 2);
22573
+ } else {
22574
+ $xadj = $table['simple']['border_details']['L']['w'] / 2 + $cell['padding']['L'];
22575
+ $wadj = ($table['simple']['border_details']['L']['w'] + $table['simple']['border_details']['R']['w']) / 2 + $cell['padding']['L'] + $cell['padding']['R'];
22576
+ $yadj = $table['simple']['border_details']['T']['w'] / 2 + $cell['padding']['T'];
22577
+ }
22578
+ }
22579
+ $this->decimal_offset = 0;
22580
+ if (substr($cell['a'], 0, 1) == 'D') {
22581
+ if (isset($cell['colspan']) && $cell['colspan'] > 1) {
22582
+ $this->cellTextAlign = $c['a'] = substr($cell['a'], 2, 1);
22583
+ } else {
22584
+ $smax = $table['decimal_align'][$j]['maxs0'];
22585
+ $d_content = $table['decimal_align'][$j]['maxs0'] + $table['decimal_align'][$j]['maxs1'];
22586
+ $this->decimal_offset = $smax;
22587
+ $extra = ($w - $d_content - $wadj);
22588
+ if ($extra > 0) {
22589
+ if (substr($cell['a'], 2, 1) == 'R') {
22590
+ $this->decimal_offset += $extra;
22591
+ } elseif (substr($cell['a'], 2, 1) == 'C') {
22592
+ $this->decimal_offset += ($extra) / 2;
22593
+ }
22594
+ }
22595
+ }
22596
+ }
22597
+ $this->divwidth = $w - $wadj;
22598
+ if ($this->divwidth == 0) {
22599
+ $this->divwidth = 0.0001;
22600
+ }
22601
+ $this->x += $xadj;
22602
+ $this->y += $yadj;
22603
+ $this->printbuffer($cell['textbuffer'], '', true, false, $cell['direction']);
22604
  }
22605
+ $this->y = $opy;
 
 
 
22606
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22607
 
22608
+ /* -- BACKGROUNDS -- */
22609
+ if (!$this->ColActive) {
22610
+ if (isset($table['trgradients'][$i]) && ($j == 0 || $table['borders_separate'])) {
22611
+ $g = $this->gradient->parseBackgroundGradient($table['trgradients'][$i]);
22612
+ if ($g) {
22613
+ $gx = $x0;
22614
+ $gy = $y;
22615
+ $gh = $h;
22616
+ $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
22617
+ if ($table['borders_separate']) {
22618
+ $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
22619
+ $clx = $x + ($table['border_spacing_H'] / 2);
22620
+ $cly = $y + ($table['border_spacing_V'] / 2);
22621
+ $clw = $w - $table['border_spacing_H'];
22622
+ $clh = $h - $table['border_spacing_V'];
22623
+ // Set clipping path
22624
+ $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
22625
+ $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s];
22626
+ } else {
22627
+ $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
22628
+ }
22629
+ }
22630
  }
22631
+ if (isset($table['trbackground-images'][$i]) && ($j == 0 || $table['borders_separate'])) {
22632
+ if (isset($table['trbackground-images'][$i]['gradient']) && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['trbackground-images'][$i]['gradient'])) {
22633
+ $g = $this->gradient->parseMozGradient($table['trbackground-images'][$i]['gradient']);
22634
+ if ($g) {
22635
+ $gx = $x0;
22636
+ $gy = $y;
22637
+ $gh = $h;
22638
+ $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
22639
+ if ($table['borders_separate']) {
22640
+ $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
22641
+ $clx = $x + ($table['border_spacing_H'] / 2);
22642
+ $cly = $y + ($table['border_spacing_V'] / 2);
22643
+ $clw = $w - $table['border_spacing_H'];
22644
+ $clh = $h - $table['border_spacing_V'];
22645
+ // Set clipping path
22646
+ $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
22647
+ $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => $s];
22648
+ } else {
22649
+ $this->tableBackgrounds[$level * 9 + 4][] = ['gradient' => true, 'x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
22650
+ }
22651
+ }
22652
+ } else {
22653
+ $image_id = $table['trbackground-images'][$i]['image_id'];
22654
+ $orig_w = $table['trbackground-images'][$i]['orig_w'];
22655
+ $orig_h = $table['trbackground-images'][$i]['orig_h'];
22656
+ $x_pos = $table['trbackground-images'][$i]['x_pos'];
22657
+ $y_pos = $table['trbackground-images'][$i]['y_pos'];
22658
+ $x_repeat = $table['trbackground-images'][$i]['x_repeat'];
22659
+ $y_repeat = $table['trbackground-images'][$i]['y_repeat'];
22660
+ $resize = $table['trbackground-images'][$i]['resize'];
22661
+ $opacity = $table['trbackground-images'][$i]['opacity'];
22662
+ $itype = $table['trbackground-images'][$i]['itype'];
22663
+ $clippath = '';
22664
+ $gx = $x0;
22665
+ $gy = $y;
22666
+ $gh = $h;
22667
+ $gw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
22668
+ if ($table['borders_separate']) {
22669
+ $gw -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['padding']['R'] + $table['border_details']['R']['w'] + $table['border_spacing_H']);
22670
+ $clx = $x + ($table['border_spacing_H'] / 2);
22671
+ $cly = $y + ($table['border_spacing_V'] / 2);
22672
+ $clw = $w - $table['border_spacing_H'];
22673
+ $clh = $h - $table['border_spacing_V'];
22674
+ // Set clipping path
22675
+ $s = $this->_setClippingPath($clx, $cly, $clw, $clh); // mPDF 6
22676
+ $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx + ($table['border_spacing_H'] / 2), 'y' => $gy + ($table['border_spacing_V'] / 2), 'w' => $gw - $table['border_spacing_V'], 'h' => $gh - $table['border_spacing_H'], 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => $s, 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
22677
+ } else {
22678
+ $this->tableBackgrounds[$level * 9 + 5][] = ['x' => $gx, 'y' => $gy, 'w' => $gw, 'h' => $gh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
22679
+ }
22680
+ }
22681
  }
22682
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22683
 
22684
+ /* -- END BACKGROUNDS -- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22685
 
22686
+ // TABLE BORDER - if separate
22687
+ if (($table['borders_separate'] || ($this->simpleTables && !$table['simple']['border'])) && $table['border']) {
22688
+ $halfspaceL = $table['padding']['L'] + ($table['border_spacing_H'] / 2);
22689
+ $halfspaceR = $table['padding']['R'] + ($table['border_spacing_H'] / 2);
22690
+ $halfspaceT = $table['padding']['T'] + ($table['border_spacing_V'] / 2);
22691
+ $halfspaceB = $table['padding']['B'] + ($table['border_spacing_V'] / 2);
22692
+ $tbx = $x;
22693
+ $tby = $y;
22694
+ $tbw = $w;
22695
+ $tbh = $h;
22696
+ $tab_bord = 0;
22697
 
22698
+ $corner = '';
22699
+ if ($i == 0) { // Top
22700
+ $tby -= $halfspaceT + ($table['border_details']['T']['w'] / 2);
22701
+ $tbh += $halfspaceT + ($table['border_details']['T']['w'] / 2);
22702
+ $this->setBorder($tab_bord, Border::TOP);
22703
+ $corner .= 'T';
 
 
 
 
 
 
 
 
 
 
 
22704
  }
22705
+ if ($i == ($numrows - 1) || (isset($cell['rowspan']) && ($i + $cell['rowspan']) == $numrows)) { // Bottom
22706
+ $tbh += $halfspaceB + ($table['border_details']['B']['w'] / 2);
22707
+ $this->setBorder($tab_bord, Border::BOTTOM);
22708
+ $corner .= 'B';
 
 
 
 
 
22709
  }
22710
+ if ($j == 0) { // Left
22711
+ $tbx -= $halfspaceL + ($table['border_details']['L']['w'] / 2);
22712
+ $tbw += $halfspaceL + ($table['border_details']['L']['w'] / 2);
22713
+ $this->setBorder($tab_bord, Border::LEFT);
22714
+ $corner .= 'L';
22715
+ }
22716
+ if ($j == ($numcols - 1) || (isset($cell['colspan']) && ($j + $cell['colspan']) == $numcols)) { // Right
22717
+ $tbw += $halfspaceR + ($table['border_details']['R']['w'] / 2);
22718
+ $this->setBorder($tab_bord, Border::RIGHT);
22719
+ $corner .= 'R';
 
 
 
 
 
 
22720
  }
22721
+ $this->_tableRect($tbx, $tby, $tbw, $tbh, $tab_bord, $table['border_details'], false, $table['borders_separate'], 'table', $corner, $table['border_spacing_V'], $table['border_spacing_H']);
22722
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22723
 
22724
+ unset($cell);
22725
+ // Reset values
22726
+ $this->Reset();
22727
+ }//end of (if isset(cells)...)
22728
+ }// end of columns
 
 
 
 
22729
 
22730
+ $newpagestarted = false;
22731
+ $this->tabletheadjustfinished = false;
22732
 
22733
+ /* -- COLUMNS -- */
22734
+ if ($this->ColActive) {
22735
+ if (!$this->table_keep_together && $i < $numrows - 1 && $level == 1) {
22736
+ $this->breakpoints[$this->CurrCol][] = $y + $h;
22737
+ } // mPDF 6
22738
+ if (count($this->cellBorderBuffer)) {
22739
+ $this->printcellbuffer();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22740
  }
22741
  }
22742
+ /* -- END COLUMNS -- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22743
 
22744
+ if ($i == $numrows - 1) {
22745
+ $this->y = $y + $h;
22746
+ } // last row jump (update this->y position)
22747
+ if ($this->table_rotate && $level == 1) {
22748
+ $this->tbrot_h += $h;
22749
+ }
22750
+ } // end of rows
22751
 
22752
+ if (count($this->cellBorderBuffer)) {
22753
+ $this->printcellbuffer();
22754
+ }
22755
 
 
 
22756
 
22757
+ if ($this->tableClipPath) {
22758
+ $this->writer->write("Q");
 
 
22759
  }
22760
+ $this->tableClipPath = '';
 
 
 
 
 
22761
 
22762
+ // Advance down page by half width of bottom border
22763
+ if ($table['borders_separate']) {
22764
+ $this->y += $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2;
22765
+ } else {
22766
+ $this->y += $table['max_cell_border_width']['B'] / 2;
22767
+ }
22768
 
22769
+ if ($table['borders_separate'] && $level == 1) {
22770
+ $this->tbrot_h += $table['margin']['B'] + $table['padding']['B'] + $table['border_details']['B']['w'] + $table['border_spacing_V'] / 2;
22771
+ } elseif ($level == 1) {
22772
+ $this->tbrot_h += $table['margin']['B'] + $table['max_cell_border_width']['B'] / 2;
22773
+ }
22774
 
22775
+ $bx = $x0;
22776
+ $by = $y0;
22777
+ if ($table['borders_separate']) {
22778
+ $bx -= ($table['padding']['L'] + $table['border_details']['L']['w'] + $table['border_spacing_H'] / 2);
22779
+ if ($tablestartpageno != $this->page) { // IF broken across page
22780
+ $by += $table['max_cell_border_width']['T'] / 2;
22781
+ if (empty($tableheader)) {
22782
+ $by -= ($table['border_spacing_V'] / 2);
22783
  }
22784
+ } elseif ($split && $startrow > 0 && empty($tableheader)) {
22785
+ $by -= ($table['border_spacing_V'] / 2);
22786
  } else {
22787
+ $by -= ($table['padding']['T'] + $table['border_details']['T']['w'] + $table['border_spacing_V'] / 2);
22788
  }
22789
+ } elseif ($tablestartpageno != $this->page && !empty($tableheader)) {
22790
+ $by += $maxbwtop / 2;
22791
  }
22792
+ $by -= $tableheaderadj;
22793
+ $bh = $this->y - $by;
22794
+ if (!$table['borders_separate']) {
22795
+ $bh -= $table['max_cell_border_width']['B'] / 2;
 
 
 
 
22796
  }
22797
 
22798
+ if ($split) {
22799
+ $bw = 0;
22800
+ $finalSpread = true;
22801
+ for ($t = $startcol; $t < $numcols; $t++) {
22802
+ if ($table['colPg'][$t] == $splitpg) {
22803
+ $bw += $table['wc'][$t];
22804
+ }
22805
+ if ($table['colPg'][$t] > $splitpg) {
22806
+ $finalSpread = false;
22807
+ break;
22808
+ }
22809
+ }
22810
+ if ($startcol == 0) {
22811
+ $firstSpread = true;
22812
+ } else {
22813
+ $firstSpread = false;
22814
+ }
22815
+ if ($table['borders_separate']) {
22816
+ $bw += $table['border_spacing_H'];
22817
+ if ($firstSpread) {
22818
+ $bw += $table['padding']['L'] + $table['border_details']['L']['w'];
22819
  } else {
22820
+ $bx += ($table['padding']['L'] + $table['border_details']['L']['w']);
22821
+ }
22822
+ if ($finalSpread) {
22823
+ $bw += $table['padding']['R'] + $table['border_details']['R']['w'];
22824
  }
22825
  }
22826
+ } else {
22827
+ $bw = $table['w'] - ($table['max_cell_border_width']['L'] / 2) - ($table['max_cell_border_width']['R'] / 2) - $table['margin']['L'] - $table['margin']['R'];
22828
  }
22829
 
22830
+ if (!$this->ColActive) {
22831
+ if (isset($table['bgcolor'][-1])) {
22832
+ $color = $this->colorConverter->convert($table['bgcolor'][-1], $this->PDFAXwarnings);
22833
+ if ($color) {
22834
+ $this->tableBackgrounds[$level * 9][] = ['gradient' => false, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'col' => $color];
22835
+ }
 
22836
  }
22837
 
22838
+ /* -- BACKGROUNDS -- */
22839
+ if (isset($table['gradient'])) {
22840
+ $g = $this->gradient->parseBackgroundGradient($table['gradient']);
22841
+ if ($g) {
22842
+ $this->tableBackgrounds[$level * 9 + 1][] = ['gradient' => true, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
22843
+ }
22844
+ }
 
 
 
 
22845
 
22846
+ if (isset($table['background-image'])) {
22847
+ if (isset($table['background-image']['gradient']) && $table['background-image']['gradient'] && preg_match('/(-moz-)*(repeating-)*(linear|radial)-gradient/', $table['background-image']['gradient'])) {
22848
+ $g = $this->gradient->parseMozGradient($table['background-image']['gradient']);
22849
+ if ($g) {
22850
+ $this->tableBackgrounds[$level * 9 + 1][] = ['gradient' => true, 'x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'gradtype' => $g['type'], 'stops' => $g['stops'], 'colorspace' => $g['colorspace'], 'coords' => $g['coords'], 'extend' => $g['extend'], 'clippath' => ''];
 
 
 
22851
  }
22852
+ } else {
22853
+ $image_id = $table['background-image']['image_id'];
22854
+ $orig_w = $table['background-image']['orig_w'];
22855
+ $orig_h = $table['background-image']['orig_h'];
22856
+ $x_pos = $table['background-image']['x_pos'];
22857
+ $y_pos = $table['background-image']['y_pos'];
22858
+ $x_repeat = $table['background-image']['x_repeat'];
22859
+ $y_repeat = $table['background-image']['y_repeat'];
22860
+ $resize = $table['background-image']['resize'];
22861
+ $opacity = $table['background-image']['opacity'];
22862
+ $itype = $table['background-image']['itype'];
22863
+ $this->tableBackgrounds[$level * 9 + 2][] = ['x' => $bx, 'y' => $by, 'w' => $bw, 'h' => $bh, 'image_id' => $image_id, 'orig_w' => $orig_w, 'orig_h' => $orig_h, 'x_pos' => $x_pos, 'y_pos' => $y_pos, 'x_repeat' => $x_repeat, 'y_repeat' => $y_repeat, 'clippath' => '', 'resize' => $resize, 'opacity' => $opacity, 'itype' => $itype];
22864
  }
22865
  }
22866
+ /* -- END BACKGROUNDS -- */
 
 
 
 
 
 
 
 
 
 
22867
  }
 
22868
 
22869
+ if ($this->tableBackgrounds && $level == 1) {
22870
+ $s = $this->PrintTableBackgrounds();
22871
+ if ($this->table_rotate && !$this->processingHeader && !$this->processingFooter) {
22872
+ $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->tablebuffer);
22873
+ if ($level == 1) {
22874
+ $this->tablebuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->tablebuffer);
22875
+ }
22876
+ } elseif ($this->bufferoutput) {
22877
+ $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->headerbuffer);
22878
+ if ($level == 1) {
22879
+ $this->headerbuffer = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->headerbuffer);
22880
+ }
22881
+ } else {
22882
+ $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', '\\1' . "\n" . $s . "\n", $this->pages[$this->page]);
22883
+ if ($level == 1) {
22884
+ $this->pages[$this->page] = preg_replace('/(___TABLE___BACKGROUNDS' . $this->uniqstr . ')/', " ", $this->pages[$this->page]);
22885
  }
22886
  }
22887
+ $this->tableBackgrounds = [];
 
22888
  }
22889
 
 
 
 
 
 
 
 
 
 
 
22890
 
22891
+ // TABLE BOTTOM MARGIN
22892
+ if ($table['margin']['B']) {
22893
+ if (!$this->table_rotate && $level == 1) {
22894
+ $this->DivLn($table['margin']['B'], $this->blklvl, true); // collapsible
22895
+ } else {
22896
+ $this->y += ($table['margin']['B']);
 
 
 
22897
  }
 
22898
  }
22899
 
22900
+ if ($this->ColActive && $level == 1) {
22901
+ $this->breakpoints[$this->CurrCol][] = $this->y;
22902
+ } // *COLUMNS*
 
 
 
 
 
22903
 
22904
+ if ($split) {
22905
+ // Are there more columns to print on a next page?
22906
+ if ($lastCol < $numcols - 1) {
22907
+ $splitpg++;
22908
+ $startcol = $lastCol + 1;
22909
+ return [false, $startrow, $startcol, $splitpg, $returny, $y0];
22910
+ } else {
22911
+ return [true, 0, 0, 0, false, false];
22912
+ }
22913
  }
22914
  }
22915
 
22916
+ // END OF FUNCTION _tableWrite()
22917
+ /////////////////////////END OF TABLE CODE//////////////////////////////////
22918
+ /* -- END TABLES -- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22919
 
22920
+ function _putextgstates()
22921
  {
22922
+ for ($i = 1; $i <= count($this->extgstates); $i++) {
22923
+ $this->writer->object();
22924
+ $this->extgstates[$i]['n'] = $this->n;
22925
+ $this->writer->write('<</Type /ExtGState');
22926
+ foreach ($this->extgstates[$i]['parms'] as $k => $v) {
22927
+ $this->writer->write('/' . $k . ' ' . $v);
22928
+ }
22929
+ $this->writer->write('>>');
22930
+ $this->writer->write('endobj');
 
22931
  }
22932
  }
22933
 
22934
  function SetProtection($permissions = [], $user_pass = '', $owner_pass = null, $length = 40)
22935
  {
 
 
 
 
22936
  $this->encrypted = $this->protection->setProtection($permissions, $user_pass, $owner_pass, $length);
22937
  }
22938
 
22939
  // =========================================
 
22940
  // FROM class PDF_Bookmark
22941
  function Bookmark($txt, $level = 0, $y = 0)
22942
  {
22951
  $y = $this->y0;
22952
  } // If columns are on - mark top of columns
22953
  }
22954
+
22955
  // else y is used as set, or =0 i.e. top of page
22956
  // DIRECTIONALITY RTL
22957
  $bmo = ['t' => $txt, 'l' => $level, 'y' => $y, 'p' => $this->page];
22958
+
22959
  if ($this->keep_block_together) {
22960
  // do nothing
22961
+ } elseif ($this->table_rotate) {
22962
  $this->tbrot_BMoutlines[] = $bmo;
22963
  } elseif ($this->kwt) {
22964
  $this->kwt_BMoutlines[] = $bmo;
22965
+ } elseif ($this->ColActive) {
22966
+ $this->col_BMoutlines[] = $bmo;
22967
+ } else {
 
22968
  $this->BMoutlines[] = $bmo;
22969
  }
22970
  }
22971
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22972
  /**
22973
  * Initiate, and Mark a place for the Table of Contents to be inserted
22974
  */
24948
 
24949
  $h = $this->h;
24950
 
24951
+ $this->writer->write(sprintf('%.3F %.3F m %.3F %.3F %.3F %.3F %.3F %.3F c', ($x + $rx) * Mpdf::SCALE, ($h - $y) * Mpdf::SCALE, ($x + $rx) * Mpdf::SCALE, ($h - ($y - $ly)) * Mpdf::SCALE, ($x + $lx) * Mpdf::SCALE, ($h - ($y - $ry)) * Mpdf::SCALE, $x * Mpdf::SCALE, ($h - ($y - $ry)) * Mpdf::SCALE));
24952
+ $this->writer->write(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c', ($x - $lx) * Mpdf::SCALE, ($h - ($y - $ry)) * Mpdf::SCALE, ($x - $rx) * Mpdf::SCALE, ($h - ($y - $ly)) * Mpdf::SCALE, ($x - $rx) * Mpdf::SCALE, ($h - $y) * Mpdf::SCALE));
24953
+ $this->writer->write(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c', ($x - $rx) * Mpdf::SCALE, ($h - ($y + $ly)) * Mpdf::SCALE, ($x - $lx) * Mpdf::SCALE, ($h - ($y + $ry)) * Mpdf::SCALE, $x * Mpdf::SCALE, ($h - ($y + $ry)) * Mpdf::SCALE));
24954
+ $this->writer->write(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c %s', ($x + $lx) * Mpdf::SCALE, ($h - ($y + $ry)) * Mpdf::SCALE, ($x + $rx) * Mpdf::SCALE, ($h - ($y + $ly)) * Mpdf::SCALE, ($x + $rx) * Mpdf::SCALE, ($h - $y) * Mpdf::SCALE, $op));
24955
  }
24956
 
24957
  /* -- DIRECTW -- */
25866
  $xtra = $fbwi - $sz;
25867
  $charspacing = $xtra / (strlen($codestr) - 1);
25868
  if ($charspacing) {
25869
+ $this->writer->write(sprintf('BT %.3F Tc ET', $charspacing * Mpdf::SCALE));
25870
  }
25871
  }
25872
 
25874
  $this->Cell($fbw, $codestr_fontsize, $codestr);
25875
 
25876
  if ($charspacing) {
25877
+ $this->writer->write('BT 0 Tc ET');
25878
  }
25879
  }
25880
 
25967
  $xtra = $textw - ($cw * $chars);
25968
  $charspacing = $xtra / ($chars - 1);
25969
  if ($charspacing) {
25970
+ $this->writer->write(sprintf('BT %.3F Tc ET', $charspacing * Mpdf::SCALE));
25971
  }
25972
 
25973
  if ($bgcol) {
25989
  $this->Cell($textw, $num_height, $charRI, 0, 0, '', 1);
25990
 
25991
  if ($charspacing) {
25992
+ $this->writer->write('BT 0 Tc ET');
25993
  }
25994
 
25995
  // Outer Right character
26170
  if ($returnstring) {
26171
  return('q');
26172
  } else {
26173
+ $this->writer->write('q');
26174
  }
26175
  }
26176
 
26179
  if ($returnstring) {
26180
  return('Q');
26181
  } else {
26182
+ $this->writer->write('Q');
26183
  }
26184
  }
26185
 
26310
  if ($returnstring) {
26311
  return(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5]));
26312
  } else {
26313
+ $this->writer->write(sprintf('%.4F %.4F %.4F %.4F %.4F %.4F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5]));
26314
  }
26315
  }
26316
 
26736
  return current(unpack("H*", $str));
26737
  }
26738
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26739
  function pdf_write_value(&$value)
26740
  {
26741
  switch ($value[0]) {
26742
  case pdf_parser::TYPE_TOKEN:
26743
+ $this->writer->write($value[1] . ' ', false);
26744
  break;
26745
 
26746
  case pdf_parser::TYPE_NUMERIC:
26747
  case pdf_parser::TYPE_REAL:
26748
  if (is_float($value[1]) && $value[1] != 0) {
26749
+ $this->writer->write(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' ', false);
26750
  } else {
26751
+ $this->writer->write($value[1] . ' ', false);
26752
  }
26753
  break;
26754
 
26755
  case pdf_parser::TYPE_ARRAY:
26756
  // An array. Output the proper
26757
  // structure and move on.
26758
+ $this->writer->write("[", false);
26759
  for ($i = 0; $i < count($value[1]); $i++) {
26760
  $this->pdf_write_value($value[1][$i]);
26761
  }
26762
+ $this->writer->write("]");
26763
  break;
26764
 
26765
  case pdf_parser::TYPE_DICTIONARY:
26766
  // A dictionary.
26767
+ $this->writer->write("<<", false);
26768
 
26769
  foreach ($value[1] as $k => $v) {
26770
+ $this->writer->write($k . ' ', false);
26771
  $this->pdf_write_value($v);
26772
  }
26773
 
26774
+ $this->writer->write(">>");
26775
  break;
26776
 
26777
  case pdf_parser::TYPE_OBJREF:
26779
  // Fill the object stack if needed
26780
  $cpfn = $this->current_parser->filename;
26781
  if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) {
26782
+ $this->writer->object(false, true);
26783
  $this->_obj_stack[$cpfn][$value[1]] = [$this->n, $value];
26784
  $this->_don_obj_stack[$cpfn][$value[1]] = [$this->n, $value];
26785
  }
26786
  $objid = $this->_don_obj_stack[$cpfn][$value[1]][0];
26787
+ $this->writer->write("{$objid} 0 R"); // {$value[2]}
26788
  break;
26789
 
26790
  case pdf_parser::TYPE_STRING:
26791
  if ($this->encrypted) {
26792
+ $value[1] = $this->writer->unescape($value[1]);
26793
  $value[1] = $this->protection->rc4($this->protection->objectKey($this->_current_obj_id), $value[1]);
26794
+ $value[1] = $this->writer->escape($value[1]);
26795
  }
26796
  // A string.
26797
+ $this->writer->write('(' . $value[1] . ')');
26798
  break;
26799
 
26800
  case pdf_parser::TYPE_STREAM:
26805
  if ($this->encrypted) {
26806
  $value[2][1] = $this->protection->rc4($this->protection->objectKey($this->_current_obj_id), $value[2][1]);
26807
  }
26808
+ $this->writer->write("stream");
26809
+ $this->writer->write($value[2][1]);
26810
+ $this->writer->write("endstream");
26811
  break;
26812
 
26813
  case pdf_parser::TYPE_HEX:
26817
  // remake hexstring of encrypted string
26818
  $value[1] = $this->str2hex($value[1]);
26819
  }
26820
+ $this->writer->write("<" . $value[1] . ">");
26821
  break;
26822
 
26823
  case pdf_parser::TYPE_BOOLEAN:
26824
+ $this->writer->write($value[1] ? 'true' : 'false');
26825
  break;
26826
 
26827
  case pdf_parser::TYPE_NULL:
26828
  // The null object.
26829
+ $this->writer->write("null");
26830
  break;
26831
  }
26832
  }
26847
 
26848
  if (!$this->onlyCoreFonts && !$this->usingCoreFont) {
26849
  foreach ($search as $k => $val) {
26850
+ $search[$k] = $this->writer->utf8ToUtf16BigEndian($search[$k], false);
26851
+ $search[$k] = $this->writer->escape($search[$k]);
26852
+ $replacement[$k] = $this->writer->utf8ToUtf16BigEndian($replacement[$k], false);
26853
+ $replacement[$k] = $this->writer->escape($replacement[$k]);
26854
  }
26855
  } else {
26856
  foreach ($replacement as $k => $val) {
26857
  $replacement[$k] = mb_convert_encoding($replacement[$k], $this->mb_enc, 'utf-8');
26858
+ $replacement[$k] = $this->writer->escape($replacement[$k]);
26859
  }
26860
  }
26861
 
27228
  // JAVASCRIPT
27229
  function _set_object_javascript($string)
27230
  {
27231
+ $this->writer->object();
27232
+ $this->writer->write('<<');
27233
+ $this->writer->write('/S /JavaScript ');
27234
+ $this->writer->write('/JS ' . $this->writer->string($string));
27235
+ $this->writer->write('>>');
27236
+ $this->writer->write('endobj');
27237
  }
27238
 
27239
  function SetJS($script)
27269
  return $this->fontDescriptor;
27270
  }
27271
 
27272
+ /**
27273
+ * Temporarily return the method to preserve example 44 yearbook
27274
+ */
27275
+ public function _out($s)
27276
+ {
27277
+ $this->writer->write($s);
27278
+ }
27279
+
27280
  }
vendor/mpdf/mpdf/src/Otl.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace Mpdf;
4
 
 
 
5
  use Mpdf\Css\TextVars;
6
  use Mpdf\Fonts\FontCache;
7
 
@@ -14,6 +16,8 @@ use Mpdf\Utils\UtfString;
14
  class Otl
15
  {
16
 
 
 
17
  const _OTL_OLD_SPEC_COMPAT_1 = true;
18
  const _DICT_NODE_TYPE_SPLIT = 0x01;
19
  const _DICT_NODE_TYPE_LINEAR = 0x02;
@@ -100,6 +104,8 @@ class Otl
100
 
101
  var $schOTLdata;
102
 
 
 
103
  var $debugOTL = false;
104
 
105
  public function __construct(Mpdf $mpdf, FontCache $fontCache)
@@ -293,13 +299,12 @@ class Otl
293
  }
294
  }
295
 
296
- ////////////////////////////////////////////////////////////////
297
  // This is just for the font_dump_OTL utility to set script and langsys override
298
- if (isset($this->mpdf->overrideOTLsettings) && isset($this->mpdf->overrideOTLsettings[$this->fontkey])) {
 
299
  $GSUBscriptTag = $GPOSscriptTag = $this->mpdf->overrideOTLsettings[$this->fontkey]['script'];
300
  $GSUBlangsys = $GPOSlangsys = $this->mpdf->overrideOTLsettings[$this->fontkey]['lang'];
301
- }
302
- ////////////////////////////////////////////////////////////////
303
 
304
  if (!$GSUBscriptTag && !$GSUBlangsys && !$GPOSscriptTag && !$GPOSlangsys) {
305
  // Remove ZWJ and ZWNJ
2
 
3
  namespace Mpdf;
4
 
5
+ use Mpdf\Strict;
6
+
7
  use Mpdf\Css\TextVars;
8
  use Mpdf\Fonts\FontCache;
9
 
16
  class Otl
17
  {
18
 
19
+ use Strict;
20
+
21
  const _OTL_OLD_SPEC_COMPAT_1 = true;
22
  const _DICT_NODE_TYPE_SPLIT = 0x01;
23
  const _DICT_NODE_TYPE_LINEAR = 0x02;
104
 
105
  var $schOTLdata;
106
 
107
+ var $lastBidiStrongType;
108
+
109
  var $debugOTL = false;
110
 
111
  public function __construct(Mpdf $mpdf, FontCache $fontCache)
299
  }
300
  }
301
 
 
302
  // This is just for the font_dump_OTL utility to set script and langsys override
303
+ // $mpdf->overrideOTLsettings does not exist, this is never called
304
+ /*if (isset($this->mpdf->overrideOTLsettings) && isset($this->mpdf->overrideOTLsettings[$this->fontkey])) {
305
  $GSUBscriptTag = $GPOSscriptTag = $this->mpdf->overrideOTLsettings[$this->fontkey]['script'];
306
  $GSUBlangsys = $GPOSlangsys = $this->mpdf->overrideOTLsettings[$this->fontkey]['lang'];
307
+ }*/
 
308
 
309
  if (!$GSUBscriptTag && !$GSUBlangsys && !$GPOSscriptTag && !$GPOSlangsys) {
310
  // Remove ZWJ and ZWNJ
vendor/mpdf/mpdf/src/RemoteContentFetcher.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf;
4
+
5
+ use Mpdf\Utils\Arrays;
6
+ use Psr\Log\LoggerInterface;
7
+ use Mpdf\Log\Context as LogContext;
8
+
9
+ class RemoteContentFetcher implements \Psr\Log\LoggerAwareInterface
10
+ {
11
+
12
+ /**
13
+ * @var \Mpdf\Mpdf
14
+ */
15
+ private $mpdf;
16
+
17
+ /**
18
+ * @var \Psr\Log\LoggerInterface
19
+ */
20
+ private $logger;
21
+
22
+ public function __construct(Mpdf $mpdf, LoggerInterface $logger)
23
+ {
24
+ $this->mpdf = $mpdf;
25
+ $this->logger = $logger;
26
+ }
27
+
28
+ public function getFileContentsByCurl($url)
29
+ {
30
+ $this->logger->debug(sprintf('Fetching (cURL) content of remote URL "%s"', $url), ['context' => LogContext::REMOTE_CONTENT]);
31
+
32
+ $ch = curl_init($url);
33
+
34
+ curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1'); // mPDF 5.7.4
35
+ curl_setopt($ch, CURLOPT_HEADER, 0);
36
+ curl_setopt($ch, CURLOPT_NOBODY, 0);
37
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
38
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->mpdf->curlTimeout);
39
+
40
+ if ($this->mpdf->curlFollowLocation) {
41
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
42
+ }
43
+
44
+ if ($this->mpdf->curlAllowUnsafeSslRequests) {
45
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
46
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
47
+ }
48
+
49
+ $data = curl_exec($ch);
50
+ curl_close($ch);
51
+
52
+ return $data;
53
+ }
54
+
55
+ public function getFileContentsBySocket($url)
56
+ {
57
+ $this->logger->debug(sprintf('Fetching (socket) content of remote URL "%s"', $url), ['context' => LogContext::REMOTE_CONTENT]);
58
+ // mPDF 5.7.3
59
+
60
+ $timeout = 1;
61
+ $p = parse_url($url);
62
+
63
+ $file = Arrays::get($p, 'path', '');
64
+ $scheme = Arrays::get($p, 'scheme', '');
65
+ $port = Arrays::get($p, 'port', 80);
66
+ $prefix = '';
67
+
68
+ if ($scheme === 'https') {
69
+ $prefix = 'ssl://';
70
+ $port = Arrays::get($p, 'port', 443);
71
+ }
72
+
73
+ $query = Arrays::get($p, 'query', null);
74
+ if ($query) {
75
+ $file .= '?' . $query;
76
+ }
77
+
78
+ if (!($fh = @fsockopen($prefix . $p['host'], $port, $errno, $errstr, $timeout))) {
79
+ return false;
80
+ }
81
+
82
+ $getstring = 'GET ' . $file . " HTTP/1.0 \r\n" .
83
+ 'Host: ' . $p['host'] . " \r\n" .
84
+ "Connection: close\r\n\r\n";
85
+
86
+ fwrite($fh, $getstring);
87
+
88
+ // Get rid of HTTP header
89
+ $s = fgets($fh, 1024);
90
+ if (!$s) {
91
+ return false;
92
+ }
93
+
94
+ while (!feof($fh)) {
95
+ $s = fgets($fh, 1024);
96
+ if ($s === "\r\n") {
97
+ break;
98
+ }
99
+ }
100
+
101
+ $data = '';
102
+
103
+ while (!feof($fh)) {
104
+ $data .= fgets($fh, 1024);
105
+ }
106
+
107
+ fclose($fh);
108
+
109
+ return $data;
110
+ }
111
+
112
+ public function setLogger(LoggerInterface $logger)
113
+ {
114
+ $this->logger = $logger;
115
+ }
116
+ }
vendor/mpdf/mpdf/src/ServiceFactory.php ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf;
4
+
5
+ use Mpdf\Color\ColorConverter;
6
+ use Mpdf\Color\ColorModeConverter;
7
+ use Mpdf\Color\ColorSpaceRestrictor;
8
+
9
+ use Mpdf\Fonts\FontCache;
10
+ use Mpdf\Fonts\FontFileFinder;
11
+
12
+ use Mpdf\Image\ImageProcessor;
13
+
14
+ use Mpdf\Pdf\Protection;
15
+ use Mpdf\Pdf\Protection\UniqidGenerator;
16
+
17
+ use Mpdf\Writer\BaseWriter;
18
+ use Mpdf\Writer\BackgroundWriter;
19
+ use Mpdf\Writer\ColorWriter;
20
+ use Mpdf\Writer\BookmarkWriter;
21
+ use Mpdf\Writer\FontWriter;
22
+ use Mpdf\Writer\FormWriter;
23
+ use Mpdf\Writer\ImageWriter;
24
+ use Mpdf\Writer\JavaScriptWriter;
25
+ use Mpdf\Writer\MetadataWriter;
26
+ use Mpdf\Writer\ObjectWriter;
27
+ use Mpdf\Writer\OptionalContentWriter;
28
+ use Mpdf\Writer\PageWriter;
29
+
30
+ use Mpdf\Writer\ResourceWriter;
31
+ use Psr\Log\LoggerInterface;
32
+
33
+ class ServiceFactory
34
+ {
35
+
36
+ public function getServices(
37
+ Mpdf $mpdf,
38
+ LoggerInterface $logger,
39
+ $config,
40
+ $restrictColorSpace,
41
+ $languageToFont,
42
+ $scriptToLanguage,
43
+ $fontDescriptor,
44
+ $bmp,
45
+ $directWrite,
46
+ $wmf
47
+ ) {
48
+ $sizeConverter = new SizeConverter($mpdf->dpi, $mpdf->default_font_size, $mpdf, $logger);
49
+
50
+ $colorModeConverter = new ColorModeConverter();
51
+ $colorSpaceRestrictor = new ColorSpaceRestrictor(
52
+ $mpdf,
53
+ $colorModeConverter,
54
+ $restrictColorSpace
55
+ );
56
+ $colorConverter = new ColorConverter($mpdf, $colorModeConverter, $colorSpaceRestrictor);
57
+
58
+ $tableOfContents = new TableOfContents($mpdf, $sizeConverter);
59
+
60
+ $cache = new Cache($config['tempDir']);
61
+ $fontCache = new FontCache(new Cache($config['tempDir'] . '/ttfontdata'));
62
+
63
+ $fontFileFinder = new FontFileFinder($config['fontDir']);
64
+
65
+ $cssManager = new CssManager($mpdf, $cache, $sizeConverter, $colorConverter);
66
+
67
+ $otl = new Otl($mpdf, $fontCache);
68
+
69
+ $protection = new Protection(new UniqidGenerator());
70
+
71
+ $writer = new BaseWriter($mpdf, $protection);
72
+
73
+ $gradient = new Gradient($mpdf, $sizeConverter, $colorConverter, $writer);
74
+
75
+ $formWriter = new FormWriter($mpdf, $writer);
76
+
77
+ $form = new Form($mpdf, $otl, $colorConverter, $writer, $formWriter);
78
+
79
+ $hyphenator = new Hyphenator($mpdf);
80
+
81
+ $remoteContentFetcher = new RemoteContentFetcher($mpdf, $logger);
82
+
83
+ $imageProcessor = new ImageProcessor(
84
+ $mpdf,
85
+ $otl,
86
+ $cssManager,
87
+ $sizeConverter,
88
+ $colorConverter,
89
+ $colorModeConverter,
90
+ $cache,
91
+ $languageToFont,
92
+ $scriptToLanguage,
93
+ $remoteContentFetcher,
94
+ $logger
95
+ );
96
+
97
+ $tag = new Tag(
98
+ $mpdf,
99
+ $cache,
100
+ $cssManager,
101
+ $form,
102
+ $otl,
103
+ $tableOfContents,
104
+ $sizeConverter,
105
+ $colorConverter,
106
+ $imageProcessor,
107
+ $languageToFont
108
+ );
109
+
110
+ $fontWriter = new FontWriter($mpdf, $writer, $fontCache, $fontDescriptor);
111
+ $metadataWriter = new MetadataWriter($mpdf, $writer, $form, $protection, $logger);
112
+ $imageWriter = new ImageWriter($mpdf, $writer);
113
+ $pageWriter = new PageWriter($mpdf, $form, $writer, $metadataWriter);
114
+ $bookmarkWriter = new BookmarkWriter($mpdf, $writer);
115
+ $optionalContentWriter = new OptionalContentWriter($mpdf, $writer);
116
+ $colorWriter = new ColorWriter($mpdf, $writer);
117
+ $backgroundWriter = new BackgroundWriter($mpdf, $writer);
118
+ $objectWriter = new ObjectWriter($mpdf, $writer);
119
+ $javaScriptWriter = new JavaScriptWriter($mpdf, $writer);
120
+
121
+ $resourceWriter = new ResourceWriter(
122
+ $mpdf,
123
+ $writer,
124
+ $colorWriter,
125
+ $fontWriter,
126
+ $imageWriter,
127
+ $formWriter,
128
+ $optionalContentWriter,
129
+ $backgroundWriter,
130
+ $bookmarkWriter,
131
+ $metadataWriter,
132
+ $objectWriter,
133
+ $javaScriptWriter,
134
+ $logger
135
+ );
136
+
137
+ return [
138
+ 'otl' => $otl,
139
+ 'bmp' => $bmp,
140
+ 'cache' => $cache,
141
+ 'cssManager' => $cssManager,
142
+ 'directWrite' => $directWrite,
143
+ 'fontCache' => $fontCache,
144
+ 'fontFileFinder' => $fontFileFinder,
145
+ 'form' => $form,
146
+ 'gradient' => $gradient,
147
+ 'tableOfContents' => $tableOfContents,
148
+ 'tag' => $tag,
149
+ 'wmf' => $wmf,
150
+ 'sizeConverter' => $sizeConverter,
151
+ 'colorConverter' => $colorConverter,
152
+ 'hyphenator' => $hyphenator,
153
+ 'remoteContentFetcher' => $remoteContentFetcher,
154
+ 'imageProcessor' => $imageProcessor,
155
+ 'protection' => $protection,
156
+
157
+ 'languageToFont' => $languageToFont,
158
+ 'scriptToLanguage' => $scriptToLanguage,
159
+
160
+ 'writer' => $writer,
161
+ 'fontWriter' => $fontWriter,
162
+ 'metadataWriter' => $metadataWriter,
163
+ 'imageWriter' => $imageWriter,
164
+ 'formWriter' => $formWriter,
165
+ 'pageWriter' => $pageWriter,
166
+ 'bookmarkWriter' => $bookmarkWriter,
167
+ 'optionalContentWriter' => $optionalContentWriter,
168
+ 'colorWriter' => $colorWriter,
169
+ 'backgroundWriter' => $backgroundWriter,
170
+ 'objectWriter' => $objectWriter,
171
+ 'javaScriptWriter' => $javaScriptWriter,
172
+
173
+ 'resourceWriter' => $resourceWriter
174
+ ];
175
+ }
176
+
177
+ }
vendor/mpdf/mpdf/src/Strict.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf;
4
+
5
+ trait Strict
6
+ {
7
+
8
+ /**
9
+ * @param string $name method name
10
+ * @param array $args arguments
11
+ */
12
+ public function __call($name, $args)
13
+ {
14
+ $class = method_exists($this, $name) ? 'parent' : get_class($this);
15
+ throw new \Mpdf\MpdfException("Call to undefined method $class::$name()");
16
+ }
17
+
18
+ /**
19
+ * @param string $name lowercase method name
20
+ * @param array $args arguments
21
+ */
22
+ public static function __callStatic($name, $args)
23
+ {
24
+ $class = get_called_class();
25
+ throw new \Mpdf\MpdfException("Call to undefined static function $class::$name()");
26
+ }
27
+
28
+ /**
29
+ * @param string $name property name
30
+ */
31
+ public function &__get($name)
32
+ {
33
+ $class = get_class($this);
34
+ throw new \Mpdf\MpdfException("Cannot read an undeclared property $class::\$$name");
35
+ }
36
+
37
+ /**
38
+ * @param string $name property name
39
+ * @param mixed $value property value
40
+ */
41
+ public function __set($name, $value)
42
+ {
43
+ $class = get_class($this);
44
+ throw new \Mpdf\MpdfException("Cannot write to an undeclared property $class::\$$name");
45
+ }
46
+
47
+ /**
48
+ * @param string $name property name
49
+ * @throws \Kdyby\StrictObjects\\Mpdf\MpdfException
50
+ */
51
+ public function __isset($name)
52
+ {
53
+ $class = get_class($this);
54
+ throw new \Mpdf\MpdfException("Cannot read an undeclared property $class::\$$name");
55
+ }
56
+
57
+ /**
58
+ * @param string $name property name
59
+ * @throws \Kdyby\StrictObjects\\Mpdf\MpdfException
60
+ */
61
+ public function __unset($name)
62
+ {
63
+ $class = get_class($this);
64
+ throw new \Mpdf\MpdfException("Cannot unset the property $class::\$$name.");
65
+ }
66
+
67
+ }
vendor/mpdf/mpdf/src/TTFontFile.php CHANGED
@@ -49,6 +49,8 @@ if (!function_exists('\Mpdf\unicode_hex')) {
49
  class TTFontFile
50
  {
51
 
 
 
52
  private $fontCache;
53
 
54
  private $fontDescriptor;
49
  class TTFontFile
50
  {
51
 
52
+ use Strict;
53
+
54
  private $fontCache;
55
 
56
  private $fontDescriptor;
vendor/mpdf/mpdf/src/Tag.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace Mpdf;
4
 
 
 
5
  use Mpdf\Color\ColorConverter;
6
 
7
  use Mpdf\Image\ImageProcessor;
@@ -11,6 +13,8 @@ use Mpdf\Language\LanguageToFontInterface;
11
  class Tag
12
  {
13
 
 
 
14
  /**
15
  * @var \Mpdf\Mpdf
16
  */
2
 
3
  namespace Mpdf;
4
 
5
+ use Mpdf\Strict;
6
+
7
  use Mpdf\Color\ColorConverter;
8
 
9
  use Mpdf\Image\ImageProcessor;
13
  class Tag
14
  {
15
 
16
+ use Strict;
17
+
18
  /**
19
  * @var \Mpdf\Mpdf
20
  */
vendor/mpdf/mpdf/src/Tag/BlockTag.php CHANGED
@@ -230,6 +230,7 @@ abstract class BlockTag extends Tag
230
  elseif ($this->mpdf->lastblocklevelchange < 1) {
231
  $blockstate = 0;
232
  } // NO margins/padding
 
233
  $this->mpdf->printbuffer($this->mpdf->textbuffer, $blockstate);
234
  $this->mpdf->textbuffer = [];
235
 
230
  elseif ($this->mpdf->lastblocklevelchange < 1) {
231
  $blockstate = 0;
232
  } // NO margins/padding
233
+
234
  $this->mpdf->printbuffer($this->mpdf->textbuffer, $blockstate);
235
  $this->mpdf->textbuffer = [];
236
 
vendor/mpdf/mpdf/src/Tag/Table.php CHANGED
@@ -883,13 +883,13 @@ class Table extends Tag
883
  $forcerecalc = false;
884
  // RESIZING ALGORITHM
885
  if ($maxrowheight > $fullpage) {
886
- $recalculate = $this->mpdf->tbsqrt($maxrowheight / $fullpage, 1);
887
  $forcerecalc = true;
888
  } elseif ($this->mpdf->table_rotate) { // NB $remainingpage == $fullpage == the width of the page
889
  if ($tableheight > $remainingpage) {
890
  // If can fit on remainder of page whilst respecting autsize value..
891
- if (($this->mpdf->shrin_k * $this->mpdf->tbsqrt($tableheight / $remainingpage, 1)) <= $this->mpdf->shrink_this_table_to_fit) {
892
- $recalculate = $this->mpdf->tbsqrt($tableheight / $remainingpage, 1);
893
  } elseif (!$added_page) {
894
  if ($this->mpdf->y != $this->mpdf->tMargin) {
895
  $this->mpdf->AddPage($this->mpdf->CurOrientation);
@@ -905,8 +905,8 @@ class Table extends Tag
905
  }
906
  } elseif ($this->mpdf->table_keep_together || ($this->mpdf->table[1][1]['nr'] == 1 && !$this->mpdf->writingHTMLfooter)) {
907
  if ($tableheight > $fullpage) {
908
- if (($this->mpdf->shrin_k * $this->mpdf->tbsqrt($tableheight / $fullpage, 1)) <= $this->mpdf->shrink_this_table_to_fit) {
909
- $recalculate = $this->mpdf->tbsqrt($tableheight / $fullpage, 1);
910
  } elseif ($this->mpdf->tableMinSizePriority) {
911
  $this->mpdf->table_keep_together = false;
912
  $recalculate = 1.001;
@@ -917,12 +917,12 @@ class Table extends Tag
917
  }
918
  $added_page = true;
919
  $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height;
920
- $recalculate = $this->mpdf->tbsqrt($tableheight / $fullpage, 1);
921
  }
922
  } elseif ($tableheight > $remainingpage) {
923
  // If can fit on remainder of page whilst respecting autsize value..
924
- if (($this->mpdf->shrin_k * $this->mpdf->tbsqrt($tableheight / $remainingpage, 1)) <= $this->mpdf->shrink_this_table_to_fit) {
925
- $recalculate = $this->mpdf->tbsqrt($tableheight / $remainingpage, 1);
926
  } else {
927
  if ($this->mpdf->y != $this->mpdf->tMargin) {
928
  // mPDF 6
@@ -1040,12 +1040,12 @@ class Table extends Tag
1040
  // RESIZING ALGORITHM
1041
 
1042
  if ($maxrowheight > $fullpage) {
1043
- $recalculate = $this->mpdf->tbsqrt($maxrowheight / $fullpage, $iteration);
1044
  $iteration++;
1045
  } elseif ($this->mpdf->table_rotate && $tableheight > $remainingpage && !$added_page) {
1046
  // If can fit on remainder of page whilst respecting autosize value..
1047
- if (($this->mpdf->shrin_k * $this->mpdf->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->mpdf->shrink_this_table_to_fit) {
1048
- $recalculate = $this->mpdf->tbsqrt($tableheight / $remainingpage, $iteration);
1049
  $iteration++;
1050
  } else {
1051
  if (!$added_page) {
@@ -1059,8 +1059,8 @@ class Table extends Tag
1059
  }
1060
  } elseif ($this->mpdf->table_keep_together || ($this->mpdf->table[1][1]['nr'] == 1 && !$this->mpdf->writingHTMLfooter)) {
1061
  if ($tableheight > $fullpage) {
1062
- if (($this->mpdf->shrin_k * $this->mpdf->tbsqrt($tableheight / $fullpage, $iteration)) <= $this->mpdf->shrink_this_table_to_fit) {
1063
- $recalculate = $this->mpdf->tbsqrt($tableheight / $fullpage, $iteration);
1064
  $iteration++;
1065
  } elseif ($this->mpdf->tableMinSizePriority) {
1066
  $this->mpdf->table_keep_together = false;
@@ -1072,13 +1072,13 @@ class Table extends Tag
1072
  $this->mpdf->kwt_moved = true;
1073
  $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height;
1074
  }
1075
- $recalculate = $this->mpdf->tbsqrt($tableheight / $fullpage, $iteration);
1076
  $iteration++;
1077
  }
1078
  } elseif ($tableheight > $remainingpage) {
1079
  // If can fit on remainder of page whilst respecting autosize value..
1080
- if (($this->mpdf->shrin_k * $this->mpdf->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->mpdf->shrink_this_table_to_fit) {
1081
- $recalculate = $this->mpdf->tbsqrt($tableheight / $remainingpage, $iteration);
1082
  $iteration++;
1083
  } else {
1084
  if (!$added_page) {
@@ -1093,7 +1093,7 @@ class Table extends Tag
1093
  $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height;
1094
  }
1095
 
1096
- //$recalculate = $this->mpdf->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
1097
  $recalculate = (1 / $this->mpdf->shrin_k) + 0.001; // undo any shrink
1098
  }
1099
  } else {
@@ -1169,7 +1169,6 @@ class Table extends Tag
1169
  $this->mpdf->shrin_k = 1;
1170
  $this->mpdf->shrink_this_table_to_fit = 0;
1171
 
1172
- unset($this->mpdf->table);
1173
  $this->mpdf->table = []; //array
1174
  $this->mpdf->tableLevel = 0;
1175
  $this->mpdf->tbctr = [];
@@ -1177,11 +1176,11 @@ class Table extends Tag
1177
  $this->cssManager->tbCSSlvl = 0;
1178
  $this->cssManager->tablecascadeCSS = [];
1179
 
1180
- unset($this->mpdf->cell);
1181
  $this->mpdf->cell = []; //array
1182
 
1183
  $this->mpdf->col = -1; //int
1184
  $this->mpdf->row = -1; //int
 
1185
  $this->mpdf->Reset();
1186
 
1187
  $this->mpdf->cellPaddingL = 0;
@@ -1237,4 +1236,36 @@ class Table extends Tag
1237
  }
1238
  }
1239
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1240
  }
883
  $forcerecalc = false;
884
  // RESIZING ALGORITHM
885
  if ($maxrowheight > $fullpage) {
886
+ $recalculate = $this->tbsqrt($maxrowheight / $fullpage, 1);
887
  $forcerecalc = true;
888
  } elseif ($this->mpdf->table_rotate) { // NB $remainingpage == $fullpage == the width of the page
889
  if ($tableheight > $remainingpage) {
890
  // If can fit on remainder of page whilst respecting autsize value..
891
+ if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->mpdf->shrink_this_table_to_fit) {
892
+ $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1);
893
  } elseif (!$added_page) {
894
  if ($this->mpdf->y != $this->mpdf->tMargin) {
895
  $this->mpdf->AddPage($this->mpdf->CurOrientation);
905
  }
906
  } elseif ($this->mpdf->table_keep_together || ($this->mpdf->table[1][1]['nr'] == 1 && !$this->mpdf->writingHTMLfooter)) {
907
  if ($tableheight > $fullpage) {
908
+ if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $fullpage, 1)) <= $this->mpdf->shrink_this_table_to_fit) {
909
+ $recalculate = $this->tbsqrt($tableheight / $fullpage, 1);
910
  } elseif ($this->mpdf->tableMinSizePriority) {
911
  $this->mpdf->table_keep_together = false;
912
  $recalculate = 1.001;
917
  }
918
  $added_page = true;
919
  $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height;
920
+ $recalculate = $this->tbsqrt($tableheight / $fullpage, 1);
921
  }
922
  } elseif ($tableheight > $remainingpage) {
923
  // If can fit on remainder of page whilst respecting autsize value..
924
+ if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $remainingpage, 1)) <= $this->mpdf->shrink_this_table_to_fit) {
925
+ $recalculate = $this->tbsqrt($tableheight / $remainingpage, 1);
926
  } else {
927
  if ($this->mpdf->y != $this->mpdf->tMargin) {
928
  // mPDF 6
1040
  // RESIZING ALGORITHM
1041
 
1042
  if ($maxrowheight > $fullpage) {
1043
+ $recalculate = $this->tbsqrt($maxrowheight / $fullpage, $iteration);
1044
  $iteration++;
1045
  } elseif ($this->mpdf->table_rotate && $tableheight > $remainingpage && !$added_page) {
1046
  // If can fit on remainder of page whilst respecting autosize value..
1047
+ if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->mpdf->shrink_this_table_to_fit) {
1048
+ $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration);
1049
  $iteration++;
1050
  } else {
1051
  if (!$added_page) {
1059
  }
1060
  } elseif ($this->mpdf->table_keep_together || ($this->mpdf->table[1][1]['nr'] == 1 && !$this->mpdf->writingHTMLfooter)) {
1061
  if ($tableheight > $fullpage) {
1062
+ if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $fullpage, $iteration)) <= $this->mpdf->shrink_this_table_to_fit) {
1063
+ $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration);
1064
  $iteration++;
1065
  } elseif ($this->mpdf->tableMinSizePriority) {
1066
  $this->mpdf->table_keep_together = false;
1072
  $this->mpdf->kwt_moved = true;
1073
  $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height;
1074
  }
1075
+ $recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration);
1076
  $iteration++;
1077
  }
1078
  } elseif ($tableheight > $remainingpage) {
1079
  // If can fit on remainder of page whilst respecting autosize value..
1080
+ if (($this->mpdf->shrin_k * $this->tbsqrt($tableheight / $remainingpage, $iteration)) <= $this->mpdf->shrink_this_table_to_fit) {
1081
+ $recalculate = $this->tbsqrt($tableheight / $remainingpage, $iteration);
1082
  $iteration++;
1083
  } else {
1084
  if (!$added_page) {
1093
  $this->mpdf->tbrot_maxw = $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height;
1094
  }
1095
 
1096
+ //$recalculate = $this->tbsqrt($tableheight / $fullpage, $iteration); $iteration++;
1097
  $recalculate = (1 / $this->mpdf->shrin_k) + 0.001; // undo any shrink
1098
  }
1099
  } else {
1169
  $this->mpdf->shrin_k = 1;
1170
  $this->mpdf->shrink_this_table_to_fit = 0;
1171
 
 
1172
  $this->mpdf->table = []; //array
1173
  $this->mpdf->tableLevel = 0;
1174
  $this->mpdf->tbctr = [];
1176
  $this->cssManager->tbCSSlvl = 0;
1177
  $this->cssManager->tablecascadeCSS = [];
1178
 
 
1179
  $this->mpdf->cell = []; //array
1180
 
1181
  $this->mpdf->col = -1; //int
1182
  $this->mpdf->row = -1; //int
1183
+
1184
  $this->mpdf->Reset();
1185
 
1186
  $this->mpdf->cellPaddingL = 0;
1236
  }
1237
  }
1238
 
1239
+ /**
1240
+ * This function determines the shrink factor when resizing tables
1241
+ * val is the table_height / page_height_available
1242
+ * returns a scaling factor used as $shrin_k to resize the table
1243
+ * Overcompensating will be quicker but may unnecessarily shrink table too much
1244
+ * Undercompensating means it will reiterate more times (taking more processing time)
1245
+ */
1246
+ private function tbsqrt($val, $iteration = 3)
1247
+ {
1248
+ // Alters number of iterations until it returns $val itself - Must be > 2
1249
+ $k = 4;
1250
+
1251
+ // Probably best guess and most accurate
1252
+ if ($iteration === 1) {
1253
+ return sqrt($val);
1254
+ }
1255
+
1256
+ // Faster than using sqrt (because it won't undercompensate), and gives reasonable results
1257
+ // return 1 + (($val - 1) / 2);
1258
+ $x = 2 - (($iteration - 2) / ($k - 2));
1259
+
1260
+ if ($x === 0) {
1261
+ $ret = $val + 0.00001;
1262
+ } elseif ($x < 0) {
1263
+ $ret = 1 + ( pow(2, ($iteration - 2 - $k)) / 1000 );
1264
+ } else {
1265
+ $ret = 1 + (($val - 1) / $x);
1266
+ }
1267
+
1268
+ return $ret;
1269
+ }
1270
+
1271
  }
vendor/mpdf/mpdf/src/Tag/Tag.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace Mpdf\Tag;
4
 
 
 
5
  use Mpdf\Cache;
6
  use Mpdf\Color\ColorConverter;
7
  use Mpdf\CssManager;
@@ -15,6 +17,9 @@ use Mpdf\TableOfContents;
15
 
16
  abstract class Tag
17
  {
 
 
 
18
  /**
19
  * @var \Mpdf\Mpdf
20
  */
2
 
3
  namespace Mpdf\Tag;
4
 
5
+ use Mpdf\Strict;
6
+
7
  use Mpdf\Cache;
8
  use Mpdf\Color\ColorConverter;
9
  use Mpdf\CssManager;
17
 
18
  abstract class Tag
19
  {
20
+
21
+ use Strict;
22
+
23
  /**
24
  * @var \Mpdf\Mpdf
25
  */
vendor/mpdf/mpdf/src/Writer/BackgroundWriter.php ADDED
@@ -0,0 +1,415 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf\Writer;
4
+
5
+ use Mpdf\Strict;
6
+ use Mpdf\Mpdf;
7
+
8
+ final class BackgroundWriter
9
+ {
10
+
11
+ use Strict;
12
+
13
+ /**
14
+ * @var \Mpdf\Mpdf
15
+ */
16
+ private $mpdf;
17
+
18
+ /**
19
+ * @var \Mpdf\Writer\BaseWriter
20
+ */
21
+ private $writer;
22
+
23
+ public function __construct(Mpdf $mpdf, BaseWriter $writer)
24
+ {
25
+ $this->mpdf = $mpdf;
26
+ $this->writer = $writer;
27
+ }
28
+
29
+ public function writePatterns() // _putpatterns
30
+ {
31
+ $patternCount = count($this->mpdf->patterns);
32
+
33
+ for ($i = 1; $i <= $patternCount; $i++) {
34
+
35
+ $x = $this->mpdf->patterns[$i]['x'];
36
+ $y = $this->mpdf->patterns[$i]['y'];
37
+ $w = $this->mpdf->patterns[$i]['w'];
38
+ $h = $this->mpdf->patterns[$i]['h'];
39
+ $pgh = $this->mpdf->patterns[$i]['pgh'];
40
+ $orig_w = $this->mpdf->patterns[$i]['orig_w'];
41
+ $orig_h = $this->mpdf->patterns[$i]['orig_h'];
42
+ $image_id = $this->mpdf->patterns[$i]['image_id'];
43
+ $itype = $this->mpdf->patterns[$i]['itype'];
44
+
45
+ if (isset($this->mpdf->patterns[$i]['bpa'])) {
46
+ $bpa = $this->mpdf->patterns[$i]['bpa'];
47
+ } else {
48
+ $bpa = []; // background positioning area
49
+ }
50
+
51
+ if ($this->mpdf->patterns[$i]['x_repeat']) {
52
+ $x_repeat = true;
53
+ } else {
54
+ $x_repeat = false;
55
+ }
56
+
57
+ if ($this->mpdf->patterns[$i]['y_repeat']) {
58
+ $y_repeat = true;
59
+ } else {
60
+ $y_repeat = false;
61
+ }
62
+
63
+ $x_pos = $this->mpdf->patterns[$i]['x_pos'];
64
+
65
+ if (false !== strpos($x_pos, '%')) {
66
+ $x_pos = (float) $x_pos;
67
+ $x_pos /= 100;
68
+
69
+ if (isset($bpa['w']) && $bpa['w']) {
70
+ $x_pos = ($bpa['w'] * $x_pos) - ($orig_w / Mpdf::SCALE * $x_pos);
71
+ } else {
72
+ $x_pos = ($w * $x_pos) - ($orig_w / Mpdf::SCALE * $x_pos);
73
+ }
74
+ }
75
+
76
+ $y_pos = $this->mpdf->patterns[$i]['y_pos'];
77
+
78
+ if (false !== strpos($y_pos, '%')) {
79
+ $y_pos = (float) $y_pos;
80
+ $y_pos /= 100;
81
+
82
+ if (isset($bpa['h']) && $bpa['h']) {
83
+ $y_pos = ($bpa['h'] * $y_pos) - ($orig_h / Mpdf::SCALE * $y_pos);
84
+ } else {
85
+ $y_pos = ($h * $y_pos) - ($orig_h / Mpdf::SCALE * $y_pos);
86
+ }
87
+ }
88
+
89
+ if (isset($bpa['x']) && $bpa['x']) {
90
+ $adj_x = ($x_pos + $bpa['x']) * Mpdf::SCALE;
91
+ } else {
92
+ $adj_x = ($x_pos + $x) * Mpdf::SCALE;
93
+ }
94
+
95
+ if (isset($bpa['y']) && $bpa['y']) {
96
+ $adj_y = (($pgh - $y_pos - $bpa['y']) * Mpdf::SCALE) - $orig_h;
97
+ } else {
98
+ $adj_y = (($pgh - $y_pos - $y) * Mpdf::SCALE) - $orig_h;
99
+ }
100
+
101
+ $img_obj = false;
102
+
103
+ if ($itype === 'svg' || $itype === 'wmf') {
104
+ foreach ($this->mpdf->formobjects as $fo) {
105
+ if ($fo['i'] == $image_id) {
106
+ $img_obj = $fo['n'];
107
+ $fo_w = $fo['w'];
108
+ $fo_h = -$fo['h'];
109
+ $wmf_x = $fo['x'];
110
+ $wmf_y = $fo['y'];
111
+ break;
112
+ }
113
+ }
114
+ } else {
115
+ foreach ($this->mpdf->images as $img) {
116
+ if ($img['i'] == $image_id) {
117
+ $img_obj = $img['n'];
118
+ break;
119
+ }
120
+ }
121
+ }
122
+
123
+ if (!$img_obj) {
124
+ throw new \Mpdf\MpdfException('Problem: Image object not found for background pattern ' . $img['i']);
125
+ }
126
+
127
+ $this->writer->object();
128
+ $this->writer->write('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
129
+ if ($itype === 'svg' || $itype === 'wmf') {
130
+ $this->writer->write('/XObject <</FO' . $image_id . ' ' . $img_obj . ' 0 R >>');
131
+ // ******* ADD ANY ExtGStates, Shading AND Fonts needed for the FormObject
132
+ // Set in classes/svg array['fo'] = true
133
+ // Required that _putshaders comes before _putpatterns in _putresources
134
+ // This adds any resources associated with any FormObject to every Formobject - overkill but works!
135
+ if (count($this->mpdf->extgstates)) {
136
+ $this->writer->write('/ExtGState <<');
137
+ foreach ($this->mpdf->extgstates as $k => $extgstate) {
138
+ if (isset($extgstate['fo']) && $extgstate['fo']) {
139
+ if (isset($extgstate['trans'])) {
140
+ $this->writer->write('/' . $extgstate['trans'] . ' ' . $extgstate['n'] . ' 0 R');
141
+ } else {
142
+ $this->writer->write('/GS' . $k . ' ' . $extgstate['n'] . ' 0 R');
143
+ }
144
+ }
145
+ }
146
+ $this->writer->write('>>');
147
+ }
148
+ /* -- BACKGROUNDS -- */
149
+ if (isset($this->gradients) && ( count($this->mpdf->gradients) > 0)) {
150
+ $this->writer->write('/Shading <<');
151
+ foreach ($this->gradients as $id => $grad) {
152
+ if (isset($grad['fo']) && $grad['fo']) {
153
+ $this->writer->write('/Sh' . $id . ' ' . $grad['id'] . ' 0 R');
154
+ }
155
+ }
156
+ $this->writer->write('>>');
157
+ }
158
+ /* -- END BACKGROUNDS -- */
159
+ $this->writer->write('/Font <<');
160
+ foreach ($this->mpdf->fonts as $font) {
161
+ if (!$font['used'] && $font['type'] === 'TTF') {
162
+ continue;
163
+ }
164
+ if (isset($font['fo']) && $font['fo']) {
165
+ if ($font['type'] === 'TTF' && ($font['sip'] || $font['smp'])) {
166
+ foreach ($font['n'] as $k => $fid) {
167
+ $this->writer->write('/F' . $font['subsetfontids'][$k] . ' ' . $font['n'][$k] . ' 0 R');
168
+ }
169
+ } else {
170
+ $this->writer->write('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
171
+ }
172
+ }
173
+ }
174
+ $this->writer->write('>>');
175
+ } else {
176
+ $this->writer->write('/XObject <</I' . $image_id . ' ' . $img_obj . ' 0 R >>');
177
+ }
178
+ $this->writer->write('>>');
179
+ $this->writer->write('endobj');
180
+
181
+ $this->writer->object();
182
+ $this->mpdf->patterns[$i]['n'] = $this->mpdf->n;
183
+ $this->writer->write('<< /Type /Pattern /PatternType 1 /PaintType 1 /TilingType 2');
184
+ $this->writer->write('/Resources ' . ($this->mpdf->n - 1) . ' 0 R');
185
+
186
+ $this->writer->write(sprintf('/BBox [0 0 %.3F %.3F]', $orig_w, $orig_h));
187
+ if ($x_repeat) {
188
+ $this->writer->write(sprintf('/XStep %.3F', $orig_w));
189
+ } else {
190
+ $this->writer->write(sprintf('/XStep %d', 99999));
191
+ }
192
+ if ($y_repeat) {
193
+ $this->writer->write(sprintf('/YStep %.3F', $orig_h));
194
+ } else {
195
+ $this->writer->write(sprintf('/YStep %d', 99999));
196
+ }
197
+
198
+ if ($itype === 'svg' || $itype === 'wmf') {
199
+ $this->writer->write(sprintf('/Matrix [1 0 0 -1 %.3F %.3F]', $adj_x, $adj_y + $orig_h));
200
+ $s = sprintf('q %.3F 0 0 %.3F %.3F %.3F cm /FO%d Do Q', $orig_w / $fo_w, -$orig_h / $fo_h, -($orig_w / $fo_w) * $wmf_x, ($orig_w / $fo_w) * $wmf_y, $image_id);
201
+ } else {
202
+ $this->writer->write(sprintf('/Matrix [1 0 0 1 %.3F %.3F]', $adj_x, $adj_y));
203
+ $s = sprintf('q %.3F 0 0 %.3F 0 0 cm /I%d Do Q', $orig_w, $orig_h, $image_id);
204
+ }
205
+
206
+ if ($this->mpdf->compress) {
207
+ $this->writer->write('/Filter /FlateDecode');
208
+ $s = gzcompress($s);
209
+ }
210
+ $this->writer->write('/Length ' . strlen($s) . '>>');
211
+ $this->writer->stream($s);
212
+ $this->writer->write('endobj');
213
+ }
214
+ }
215
+
216
+ public function writeShaders() // _putshaders
217
+ {
218
+ $maxid = count($this->mpdf->gradients); // index for transparency gradients
219
+ foreach ($this->mpdf->gradients as $id => $grad) {
220
+ if (empty($grad['is_mask']) && ($grad['type'] == 2 || $grad['type'] == 3)) {
221
+ $this->writer->object();
222
+ $this->writer->write('<<');
223
+ $this->writer->write('/FunctionType 3');
224
+ $this->writer->write('/Domain [0 1]');
225
+ $fn = [];
226
+ $bd = [];
227
+ $en = [];
228
+ for ($i = 0; $i < (count($grad['stops']) - 1); $i++) {
229
+ $fn[] = ($this->mpdf->n + 1 + $i) . ' 0 R';
230
+ $en[] = '0 1';
231
+ if ($i > 0) {
232
+ $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']);
233
+ }
234
+ }
235
+ $this->writer->write('/Functions [' . implode(' ', $fn) . ']');
236
+ $this->writer->write('/Bounds [' . implode(' ', $bd) . ']');
237
+ $this->writer->write('/Encode [' . implode(' ', $en) . ']');
238
+ $this->writer->write('>>');
239
+ $this->writer->write('endobj');
240
+ $f1 = $this->mpdf->n;
241
+ for ($i = 0; $i < (count($grad['stops']) - 1); $i++) {
242
+ $this->writer->object();
243
+ $this->writer->write('<<');
244
+ $this->writer->write('/FunctionType 2');
245
+ $this->writer->write('/Domain [0 1]');
246
+ $this->writer->write('/C0 [' . $grad['stops'][$i]['col'] . ']');
247
+ $this->writer->write('/C1 [' . $grad['stops'][$i + 1]['col'] . ']');
248
+ $this->writer->write('/N 1');
249
+ $this->writer->write('>>');
250
+ $this->writer->write('endobj');
251
+ }
252
+ }
253
+ if ($grad['type'] == 2 || $grad['type'] == 3) {
254
+ if (isset($grad['trans']) && $grad['trans']) {
255
+ $this->writer->object();
256
+ $this->writer->write('<<');
257
+ $this->writer->write('/FunctionType 3');
258
+ $this->writer->write('/Domain [0 1]');
259
+ $fn = [];
260
+ $bd = [];
261
+ $en = [];
262
+ for ($i = 0; $i < (count($grad['stops']) - 1); $i++) {
263
+ $fn[] = ($this->mpdf->n + 1 + $i) . ' 0 R';
264
+ $en[] = '0 1';
265
+ if ($i > 0) {
266
+ $bd[] = sprintf('%.3F', $grad['stops'][$i]['offset']);
267
+ }
268
+ }
269
+ $this->writer->write('/Functions [' . implode(' ', $fn) . ']');
270
+ $this->writer->write('/Bounds [' . implode(' ', $bd) . ']');
271
+ $this->writer->write('/Encode [' . implode(' ', $en) . ']');
272
+ $this->writer->write('>>');
273
+ $this->writer->write('endobj');
274
+ $f2 = $this->mpdf->n;
275
+ for ($i = 0; $i < (count($grad['stops']) - 1); $i++) {
276
+ $this->writer->object();
277
+ $this->writer->write('<<');
278
+ $this->writer->write('/FunctionType 2');
279
+ $this->writer->write('/Domain [0 1]');
280
+ $this->writer->write(sprintf('/C0 [%.3F]', $grad['stops'][$i]['opacity']));
281
+ $this->writer->write(sprintf('/C1 [%.3F]', $grad['stops'][$i + 1]['opacity']));
282
+ $this->writer->write('/N 1');
283
+ $this->writer->write('>>');
284
+ $this->writer->write('endobj');
285
+ }
286
+ }
287
+ }
288
+
289
+ if (empty($grad['is_mask'])) {
290
+ $this->writer->object();
291
+ $this->writer->write('<<');
292
+ $this->writer->write('/ShadingType ' . $grad['type']);
293
+ if (isset($grad['colorspace'])) {
294
+ $this->writer->write('/ColorSpace /Device' . $grad['colorspace']); // Can use CMYK if all C0 and C1 above have 4 values
295
+ } else {
296
+ $this->writer->write('/ColorSpace /DeviceRGB');
297
+ }
298
+ if ($grad['type'] == 2) {
299
+ $this->writer->write(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]));
300
+ $this->writer->write('/Function ' . $f1 . ' 0 R');
301
+ $this->writer->write('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] ');
302
+ $this->writer->write('>>');
303
+ } elseif ($grad['type'] == 3) {
304
+ // x0, y0, r0, x1, y1, r1
305
+ // at this this time radius of inner circle is 0
306
+ $ir = 0;
307
+ if (isset($grad['coords'][5]) && $grad['coords'][5]) {
308
+ $ir = $grad['coords'][5];
309
+ }
310
+ $this->writer->write(sprintf('/Coords [%.3F %.3F %.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $ir, $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]));
311
+ $this->writer->write('/Function ' . $f1 . ' 0 R');
312
+ $this->writer->write('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] ');
313
+ $this->writer->write('>>');
314
+ } elseif ($grad['type'] == 6) {
315
+ $this->writer->write('/BitsPerCoordinate 16');
316
+ $this->writer->write('/BitsPerComponent 8');
317
+ if ($grad['colorspace'] === 'CMYK') {
318
+ $this->writer->write('/Decode[0 1 0 1 0 1 0 1 0 1 0 1]');
319
+ } elseif ($grad['colorspace'] === 'Gray') {
320
+ $this->writer->write('/Decode[0 1 0 1 0 1]');
321
+ } else {
322
+ $this->writer->write('/Decode[0 1 0 1 0 1 0 1 0 1]');
323
+ }
324
+ $this->writer->write('/BitsPerFlag 8');
325
+ $this->writer->write('/Length ' . strlen($grad['stream']));
326
+ $this->writer->write('>>');
327
+ $this->writer->stream($grad['stream']);
328
+ }
329
+ $this->writer->write('endobj');
330
+ }
331
+
332
+ $this->mpdf->gradients[$id]['id'] = $this->mpdf->n;
333
+
334
+ // set pattern object
335
+ $this->writer->object();
336
+ $out = '<< /Type /Pattern /PatternType 2';
337
+ $out .= ' /Shading ' . $this->mpdf->gradients[$id]['id'] . ' 0 R';
338
+ $out .= ' >>';
339
+ $out .= "\n" . 'endobj';
340
+ $this->writer->write($out);
341
+
342
+
343
+ $this->mpdf->gradients[$id]['pattern'] = $this->mpdf->n;
344
+
345
+ if (isset($grad['trans']) && $grad['trans']) {
346
+ // luminosity pattern
347
+ $transid = $id + $maxid;
348
+ $this->writer->object();
349
+ $this->writer->write('<<');
350
+ $this->writer->write('/ShadingType ' . $grad['type']);
351
+ $this->writer->write('/ColorSpace /DeviceGray');
352
+ if ($grad['type'] == 2) {
353
+ $this->writer->write(sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]));
354
+ $this->writer->write('/Function ' . $f2 . ' 0 R');
355
+ $this->writer->write('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] ');
356
+ $this->writer->write('>>');
357
+ } elseif ($grad['type'] == 3) {
358
+ // x0, y0, r0, x1, y1, r1
359
+ // at this this time radius of inner circle is 0
360
+ $ir = 0;
361
+ if (isset($grad['coords'][5]) && $grad['coords'][5]) {
362
+ $ir = $grad['coords'][5];
363
+ }
364
+ $this->writer->write(sprintf('/Coords [%.3F %.3F %.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $ir, $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]));
365
+ $this->writer->write('/Function ' . $f2 . ' 0 R');
366
+ $this->writer->write('/Extend [' . $grad['extend'][0] . ' ' . $grad['extend'][1] . '] ');
367
+ $this->writer->write('>>');
368
+ } elseif ($grad['type'] == 6) {
369
+ $this->writer->write('/BitsPerCoordinate 16');
370
+ $this->writer->write('/BitsPerComponent 8');
371
+ $this->writer->write('/Decode[0 1 0 1 0 1]');
372
+ $this->writer->write('/BitsPerFlag 8');
373
+ $this->writer->write('/Length ' . strlen($grad['stream_trans']));
374
+ $this->writer->write('>>');
375
+ $this->writer->stream($grad['stream_trans']);
376
+ }
377
+ $this->writer->write('endobj');
378
+
379
+ $this->mpdf->gradients[$transid]['id'] = $this->mpdf->n;
380
+ $this->writer->object();
381
+ $this->writer->write('<< /Type /Pattern /PatternType 2');
382
+ $this->writer->write('/Shading ' . $this->mpdf->gradients[$transid]['id'] . ' 0 R');
383
+ $this->writer->write('>>');
384
+ $this->writer->write('endobj');
385
+ $this->mpdf->gradients[$transid]['pattern'] = $this->mpdf->n;
386
+ $this->writer->object();
387
+ // Need to extend size of viewing box in case of transformations
388
+ $str = 'q /a0 gs /Pattern cs /p' . $transid . ' scn -' . ($this->mpdf->wPt / 2) . ' -' . ($this->mpdf->hPt / 2) . ' ' . (2 * $this->mpdf->wPt) . ' ' . (2 * $this->mpdf->hPt) . ' re f Q';
389
+ $filter = ($this->mpdf->compress) ? '/Filter /FlateDecode ' : '';
390
+ $p = ($this->mpdf->compress) ? gzcompress($str) : $str;
391
+ $this->writer->write('<< /Type /XObject /Subtype /Form /FormType 1 ' . $filter);
392
+ $this->writer->write('/Length ' . strlen($p));
393
+ $this->writer->write('/BBox [-' . ($this->mpdf->wPt / 2) . ' -' . ($this->mpdf->hPt / 2) . ' ' . (2 * $this->mpdf->wPt) . ' ' . (2 * $this->mpdf->hPt) . ']');
394
+ $this->writer->write('/Group << /Type /Group /S /Transparency /CS /DeviceGray >>');
395
+ $this->writer->write('/Resources <<');
396
+ $this->writer->write('/ExtGState << /a0 << /ca 1 /CA 1 >> >>');
397
+ $this->writer->write('/Pattern << /p' . $transid . ' ' . $this->mpdf->gradients[$transid]['pattern'] . ' 0 R >>');
398
+ $this->writer->write('>>');
399
+ $this->writer->write('>>');
400
+ $this->writer->stream($p);
401
+ $this->writer->write('endobj');
402
+ $this->writer->object();
403
+ $this->writer->write('<< /Type /Mask /S /Luminosity /G ' . ($this->mpdf->n - 1) . ' 0 R >>' . "\n" . 'endobj');
404
+ $this->writer->object();
405
+ $this->writer->write('<< /Type /ExtGState /SMask ' . ($this->mpdf->n - 1) . ' 0 R /AIS false >>' . "\n" . 'endobj');
406
+ if (isset($grad['fo']) && $grad['fo']) {
407
+ $this->mpdf->extgstates[] = ['n' => $this->mpdf->n, 'trans' => 'TGS' . $id, 'fo' => true];
408
+ } else {
409
+ $this->mpdf->extgstates[] = ['n' => $this->mpdf->n, 'trans' => 'TGS' . $id];
410
+ }
411
+ }
412
+ }
413
+ }
414
+
415
+ }
vendor/mpdf/mpdf/src/Writer/BaseWriter.php ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf\Writer;
4
+
5
+ use Mpdf\Strict;
6
+
7
+ use Mpdf\Mpdf;
8
+ use Mpdf\Pdf\Protection;
9
+
10
+ final class BaseWriter
11
+ {
12
+
13
+ use Strict;
14
+
15
+ /**
16
+ * @var \Mpdf\Mpdf
17
+ */
18
+ private $mpdf;
19
+
20
+ /**
21
+ * @var \Mpdf\Pdf\Protection
22
+ */
23
+ private $protection;
24
+
25
+ public function __construct(Mpdf $mpdf, Protection $protection)
26
+ {
27
+ $this->mpdf = $mpdf;
28
+ $this->protection = $protection;
29
+ }
30
+
31
+ public function write($s, $ln = true)
32
+ {
33
+ if ($this->mpdf->state === 2) {
34
+ $this->endPage($s, $ln);
35
+ } else {
36
+ $this->mpdf->buffer .= $s . ($ln ? "\n" : '');
37
+ }
38
+ }
39
+
40
+ public function string($s)
41
+ {
42
+ if ($this->mpdf->encrypted) {
43
+ $s = $this->protection->rc4($this->protection->objectKey($this->mpdf->_current_obj_id), $s);
44
+ }
45
+
46
+ return '(' . $this->escape($s) . ')';
47
+ }
48
+
49
+ public function object($obj_id = false, $onlynewobj = false)
50
+ {
51
+ if (!$obj_id) {
52
+ $obj_id = ++$this->mpdf->n;
53
+ }
54
+
55
+ // Begin a new object
56
+ if (!$onlynewobj) {
57
+ $this->mpdf->offsets[$obj_id] = strlen($this->mpdf->buffer);
58
+ $this->write($obj_id . ' 0 obj');
59
+ $this->mpdf->_current_obj_id = $obj_id; // for later use with encryption
60
+ }
61
+ }
62
+
63
+ public function stream($s)
64
+ {
65
+ if ($this->mpdf->encrypted) {
66
+ $s = $this->protection->rc4($this->protection->objectKey($this->mpdf->_current_obj_id), $s);
67
+ }
68
+
69
+ $this->write('stream');
70
+ $this->write($s);
71
+ $this->write('endstream');
72
+ }
73
+
74
+ public function utf16BigEndianTextString($s) // _UTF16BEtextstring
75
+ {
76
+ $s = $this->utf8ToUtf16BigEndian($s, true);
77
+ if ($this->mpdf->encrypted) {
78
+ $s = $this->protection->rc4($this->protection->objectKey($this->mpdf->_current_obj_id), $s);
79
+ }
80
+
81
+ return '(' . $this->escape($s) . ')';
82
+ }
83
+
84
+ // Converts UTF-8 strings to UTF16-BE.
85
+ public function utf8ToUtf16BigEndian($str, $setbom = true) // UTF8ToUTF16BE
86
+ {
87
+ if ($this->mpdf->checkSIP && preg_match("/([\x{20000}-\x{2FFFF}])/u", $str)) {
88
+ if (!in_array($this->mpdf->currentfontfamily, ['gb', 'big5', 'sjis', 'uhc', 'gbB', 'big5B', 'sjisB', 'uhcB', 'gbI', 'big5I', 'sjisI', 'uhcI',
89
+ 'gbBI', 'big5BI', 'sjisBI', 'uhcBI'])) {
90
+ $str = preg_replace("/[\x{20000}-\x{2FFFF}]/u", chr(0), $str);
91
+ }
92
+ }
93
+ if ($this->mpdf->checkSMP && preg_match("/([\x{10000}-\x{1FFFF}])/u", $str)) {
94
+ $str = preg_replace("/[\x{10000}-\x{1FFFF}]/u", chr(0), $str);
95
+ }
96
+
97
+ $outstr = ''; // string to be returned
98
+ if ($setbom) {
99
+ $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM)
100
+ }
101
+
102
+ $outstr .= mb_convert_encoding($str, 'UTF-16BE', 'UTF-8');
103
+
104
+ return $outstr;
105
+ }
106
+
107
+ public function escape($s) // _escape
108
+ {
109
+ return strtr($s, [')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r']);
110
+ }
111
+
112
+ public function escapeSlashes($s) // _escapeName
113
+ {
114
+ return strtr($s, ['/' => '#2F']);
115
+ }
116
+
117
+ /**
118
+ * Un-escapes a PDF string
119
+ *
120
+ * @param string $s
121
+ * @return string
122
+ */
123
+ public function unescape($s)
124
+ {
125
+ $out = '';
126
+ for ($count = 0, $n = strlen($s); $count < $n; $count++) {
127
+ if ($count === $n - 1 || $s[$count] !== '\\') {
128
+ $out .= $s[$count];
129
+ } else {
130
+ switch ($s[++$count]) {
131
+ case ')':
132
+ case '(':
133
+ case '\\':
134
+ $out .= $s[$count];
135
+ break;
136
+ case 'f':
137
+ $out .= chr(0x0C);
138
+ break;
139
+ case 'b':
140
+ $out .= chr(0x08);
141
+ break;
142
+ case 't':
143
+ $out .= chr(0x09);
144
+ break;
145
+ case 'r':
146
+ $out .= chr(0x0D);
147
+ break;
148
+ case 'n':
149
+ $out .= chr(0x0A);
150
+ break;
151
+ case "\r":
152
+ if ($count !== $n - 1 && $s[$count + 1] === "\n") {
153
+ $count++;
154
+ }
155
+ break;
156
+ case "\n":
157
+ break;
158
+ default:
159
+ // Octal-Values
160
+ $ord = ord($s[$count]);
161
+ if ($ord >= ord('0') && $ord <= ord('9')) {
162
+ $oct = ''. $s[$count];
163
+ $ord = ord($s[$count + 1]);
164
+ if ($ord >= ord('0') && $ord <= ord('9')) {
165
+ $oct .= $s[++$count];
166
+ $ord = ord($s[$count + 1]);
167
+ if ($ord >= ord('0') && $ord <= ord('9')) {
168
+ $oct .= $s[++$count];
169
+ }
170
+ }
171
+ $out .= chr(octdec($oct));
172
+ } else {
173
+ $out .= $s[$count];
174
+ }
175
+ }
176
+ }
177
+ }
178
+
179
+ return $out;
180
+ }
181
+
182
+ private function endPage($s, $ln)
183
+ {
184
+ if ($this->mpdf->bufferoutput) {
185
+
186
+ $this->mpdf->headerbuffer.= $s . "\n";
187
+
188
+ } elseif ($this->mpdf->ColActive && !$this->mpdf->processingHeader && !$this->mpdf->processingFooter) {
189
+
190
+ // Captures everything in buffer for columns; Almost everything is sent from fn. Cell() except:
191
+ // Images sent from Image() or
192
+ // later sent as write($textto) in printbuffer
193
+ // Line()
194
+
195
+ if (preg_match('/q \d+\.\d\d+ 0 0 (\d+\.\d\d+) \d+\.\d\d+ \d+\.\d\d+ cm \/(I|FO)\d+ Do Q/', $s, $m)) { // Image data
196
+
197
+ $h = ($m[1] / Mpdf::SCALE);
198
+ // Update/overwrite the lowest bottom of printing y value for a column
199
+ $this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'] = $this->mpdf->y + $h;
200
+
201
+ } elseif ($this->mpdf->tableLevel > 0 && preg_match('/\d+\.\d\d+ \d+\.\d\d+ \d+\.\d\d+ ([\-]{0,1}\d+\.\d\d+) re/', $s, $m)) { // Rect in table
202
+
203
+ $h = ($m[1] / Mpdf::SCALE);
204
+ // Update/overwrite the lowest bottom of printing y value for a column
205
+ $this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'] = max($this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'], $this->mpdf->y + $h);
206
+
207
+ } elseif (isset($this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'])) {
208
+
209
+ $h = $this->mpdf->ColDetails[$this->mpdf->CurrCol]['bottom_margin'] - $this->mpdf->y;
210
+
211
+ } else {
212
+
213
+ $h = 0;
214
+
215
+ }
216
+
217
+ if ($h < 0) {
218
+ $h = -$h;
219
+ }
220
+
221
+ $this->mpdf->columnbuffer[] = [
222
+ 's' => $s, // Text string to output
223
+ 'col' => $this->mpdf->CurrCol, // Column when printed
224
+ 'x' => $this->mpdf->x, // x when printed
225
+ 'y' => $this->mpdf->y, // this->y when printed (after column break)
226
+ 'h' => $h // actual y at bottom when printed = y+h
227
+ ];
228
+
229
+ } elseif ($this->mpdf->table_rotate && !$this->mpdf->processingHeader && !$this->mpdf->processingFooter) {
230
+
231
+ // Captures eveything in buffer for rotated tables;
232
+ $this->mpdf->tablebuffer .= $s . "\n";
233
+
234
+ } elseif ($this->mpdf->kwt && !$this->mpdf->processingHeader && !$this->mpdf->processingFooter) {
235
+
236
+ // Captures eveything in buffer for keep-with-table (h1-6);
237
+ $this->mpdf->kwt_buffer[] = [
238
+ 's' => $s, // Text string to output
239
+ 'x' => $this->mpdf->x, // x when printed
240
+ 'y' => $this->mpdf->y, // y when printed
241
+ ];
242
+
243
+ } elseif ($this->mpdf->keep_block_together && !$this->mpdf->processingHeader && !$this->mpdf->processingFooter) {
244
+ // do nothing
245
+ } else {
246
+ $this->mpdf->pages[$this->mpdf->page] .= $s . ($ln ? "\n" : '');
247
+ }
248
+ }
249
+
250
+ }
vendor/mpdf/mpdf/src/Writer/BookmarkWriter.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf\Writer;
4
+
5
+ use Mpdf\Strict;
6
+ use Mpdf\Mpdf;
7
+
8
+ final class BookmarkWriter
9
+ {
10
+
11
+ use Strict;
12
+
13
+ /**
14
+ * @var \Mpdf\Mpdf
15
+ */
16
+ private $mpdf;
17
+
18
+ /**
19
+ * @var \Mpdf\Writer\BaseWriter
20
+ */
21
+ private $writer;
22
+
23
+ public function __construct(Mpdf $mpdf, BaseWriter $writer)
24
+ {
25
+ $this->mpdf = $mpdf;
26
+ $this->writer = $writer;
27
+ }
28
+
29
+ public function writeBookmarks() // _putbookmarks
30
+ {
31
+ $nb = count($this->mpdf->BMoutlines);
32
+ if ($nb === 0) {
33
+ return;
34
+ }
35
+
36
+ $bmo = $this->mpdf->BMoutlines;
37
+ $this->mpdf->BMoutlines = [];
38
+ $lastlevel = -1;
39
+ for ($i = 0; $i < count($bmo); $i++) {
40
+ if ($bmo[$i]['l'] > 0) {
41
+ while ($bmo[$i]['l'] - $lastlevel > 1) { // If jump down more than one level, insert a new entry
42
+ $new = $bmo[$i];
43
+ $new['t'] = "[" . $new['t'] . "]"; // Put [] around text/title to highlight
44
+ $new['l'] = $lastlevel + 1;
45
+ $lastlevel++;
46
+ $this->mpdf->BMoutlines[] = $new;
47
+ }
48
+ }
49
+ $this->mpdf->BMoutlines[] = $bmo[$i];
50
+ $lastlevel = $bmo[$i]['l'];
51
+ }
52
+ $nb = count($this->mpdf->BMoutlines);
53
+
54
+ $lru = [];
55
+ $level = 0;
56
+ foreach ($this->mpdf->BMoutlines as $i => $o) {
57
+ if ($o['l'] > 0) {
58
+ $parent = $lru[$o['l'] - 1];
59
+ // Set parent and last pointers
60
+ $this->mpdf->BMoutlines[$i]['parent'] = $parent;
61
+ $this->mpdf->BMoutlines[$parent]['last'] = $i;
62
+ if ($o['l'] > $level) {
63
+ // Level increasing: set first pointer
64
+ $this->mpdf->BMoutlines[$parent]['first'] = $i;
65
+ }
66
+ } else {
67
+ $this->mpdf->BMoutlines[$i]['parent'] = $nb;
68
+ }
69
+ if ($o['l'] <= $level and $i > 0) {
70
+ // Set prev and next pointers
71
+ $prev = $lru[$o['l']];
72
+ $this->mpdf->BMoutlines[$prev]['next'] = $i;
73
+ $this->mpdf->BMoutlines[$i]['prev'] = $prev;
74
+ }
75
+ $lru[$o['l']] = $i;
76
+ $level = $o['l'];
77
+ }
78
+
79
+
80
+ // Outline items
81
+ $n = $this->mpdf->n + 1;
82
+ foreach ($this->mpdf->BMoutlines as $i => $o) {
83
+ $this->writer->object();
84
+ $this->writer->write('<</Title ' . $this->writer->utf16BigEndianTextString($o['t']));
85
+ $this->writer->write('/Parent ' . ($n + $o['parent']) . ' 0 R');
86
+ if (isset($o['prev'])) {
87
+ $this->writer->write('/Prev ' . ($n + $o['prev']) . ' 0 R');
88
+ }
89
+ if (isset($o['next'])) {
90
+ $this->writer->write('/Next ' . ($n + $o['next']) . ' 0 R');
91
+ }
92
+ if (isset($o['first'])) {
93
+ $this->writer->write('/First ' . ($n + $o['first']) . ' 0 R');
94
+ }
95
+ if (isset($o['last'])) {
96
+ $this->writer->write('/Last ' . ($n + $o['last']) . ' 0 R');
97
+ }
98
+
99
+
100
+ if (isset($this->mpdf->pageDim[$o['p']]['h'])) {
101
+ $h = $this->mpdf->pageDim[$o['p']]['h'];
102
+ } else {
103
+ $h = 0;
104
+ }
105
+
106
+ $this->writer->write(sprintf('/Dest [%d 0 R /XYZ 0 %.3F null]', 1 + 2 * ($o['p']), ($h - $o['y']) * Mpdf::SCALE));
107
+ if (isset($this->mpdf->bookmarkStyles) && isset($this->mpdf->bookmarkStyles[$o['l']])) {
108
+ // font style
109
+ $bms = $this->mpdf->bookmarkStyles[$o['l']]['style'];
110
+ $style = 0;
111
+ if (strpos($bms, 'B') !== false) {
112
+ $style += 2;
113
+ }
114
+ if (strpos($bms, 'I') !== false) {
115
+ $style += 1;
116
+ }
117
+ $this->writer->write(sprintf('/F %d', $style));
118
+ // Colour
119
+ $col = $this->mpdf->bookmarkStyles[$o['l']]['color'];
120
+ if (isset($col) && is_array($col) && count($col) == 3) {
121
+ $this->writer->write(sprintf('/C [%.3F %.3F %.3F]', ($col[0] / 255), ($col[1] / 255), ($col[2] / 255)));
122
+ }
123
+ }
124
+
125
+ $this->writer->write('/Count 0>>');
126
+ $this->writer->write('endobj');
127
+ }
128
+ // Outline root
129
+ $this->writer->object();
130
+
131
+ $this->mpdf->OutlineRoot = $this->mpdf->n;
132
+
133
+ $this->writer->write('<</Type /BMoutlines /First ' . $n . ' 0 R');
134
+ $this->writer->write('/Last ' . ($n + $lru[0]) . ' 0 R>>');
135
+ $this->writer->write('endobj');
136
+ }
137
+
138
+ }
vendor/mpdf/mpdf/src/Writer/ColorWriter.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf\Writer;
4
+
5
+ use Mpdf\Strict;
6
+ use Mpdf\Mpdf;
7
+
8
+ final class ColorWriter
9
+ {
10
+
11
+ use Strict;
12
+
13
+ /**
14
+ * @var \Mpdf\Mpdf
15
+ */
16
+ private $mpdf;
17
+
18
+ /**
19
+ * @var \Mpdf\Writer\BaseWriter
20
+ */
21
+ private $writer;
22
+
23
+ public function __construct(Mpdf $mpdf, BaseWriter $writer)
24
+ {
25
+ $this->mpdf = $mpdf;
26
+ $this->writer = $writer;
27
+ }
28
+
29
+ public function writeSpotColors() // _putspotcolors
30
+ {
31
+ foreach ($this->mpdf->spotColors as $name => $color) {
32
+
33
+ $this->writer->object();
34
+
35
+ $this->writer->write('[/Separation /' . str_replace(' ', '#20', $name));
36
+ $this->writer->write('/DeviceCMYK <<');
37
+ $this->writer->write('/Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] ');
38
+ $this->writer->write(sprintf('/C1 [%.3F %.3F %.3F %.3F] ', $color['c'] / 100, $color['m'] / 100, $color['y'] / 100, $color['k'] / 100));
39
+ $this->writer->write('/FunctionType 2 /Domain [0 1] /N 1>>]');
40
+ $this->writer->write('endobj');
41
+
42
+ $this->mpdf->spotColors[$name]['n'] = $this->mpdf->n;
43
+ }
44
+ }
45
+
46
+ }
vendor/mpdf/mpdf/src/Writer/FontWriter.php ADDED
@@ -0,0 +1,686 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf\Writer;
4
+
5
+ use Mpdf\Strict;
6
+
7
+ use Mpdf\Fonts\FontCache;
8
+ use Mpdf\Mpdf;
9
+ use Mpdf\TTFontFile;
10
+
11
+ class FontWriter
12
+ {
13
+
14
+ use Strict;
15
+
16
+ /**
17
+ * @var \Mpdf\Mpdf
18
+ */
19
+ private $mpdf;
20
+
21
+ /**
22
+ * @var \Mpdf\Writer\BaseWriter
23
+ */
24
+ private $writer;
25
+
26
+ /**
27
+ * @var \Mpdf\Fonts\FontCache
28
+ */
29
+ private $fontCache;
30
+
31
+ /**
32
+ * @var string
33
+ */
34
+ private $fontDescriptor;
35
+
36
+ public function __construct(Mpdf $mpdf, BaseWriter $writer, FontCache $fontCache, $fontDescriptor)
37
+ {
38
+ $this->mpdf = $mpdf;
39
+ $this->writer = $writer;
40
+ $this->fontCache = $fontCache;
41
+ $this->fontDescriptor = $fontDescriptor;
42
+ }
43
+
44
+ public function writeFonts()
45
+ {
46
+ foreach ($this->mpdf->FontFiles as $fontkey => $info) {
47
+ // TrueType embedded
48
+ if (isset($info['type']) && $info['type'] === 'TTF' && !$info['sip'] && !$info['smp']) {
49
+ $used = true;
50
+ $asSubset = false;
51
+ foreach ($this->mpdf->fonts as $k => $f) {
52
+ if (isset($f['fontkey']) && $f['fontkey'] === $fontkey && $f['type'] === 'TTF') {
53
+ $used = $f['used'];
54
+ if ($used) {
55
+ $nChars = (ord($f['cw'][0]) << 8) + ord($f['cw'][1]);
56
+ $usage = (int) (count($f['subset']) * 100 / $nChars);
57
+ $fsize = $info['length1'];
58
+ // Always subset the very large TTF files
59
+ if ($fsize > ($this->mpdf->maxTTFFilesize * 1024)) {
60
+ $asSubset = true;
61
+ } elseif ($usage < $this->mpdf->percentSubset) {
62
+ $asSubset = true;
63
+ }
64
+ }
65
+ if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
66
+ $asSubset = false;
67
+ }
68
+ $this->mpdf->fonts[$k]['asSubset'] = $asSubset;
69
+ break;
70
+ }
71
+ }
72
+ if ($used && !$asSubset) {
73
+ // Font file embedding
74
+ $this->writer->object();
75
+ $this->mpdf->FontFiles[$fontkey]['n'] = $this->mpdf->n;
76
+ $originalsize = $info['length1'];
77
+ if ($this->mpdf->repackageTTF || $this->mpdf->fonts[$fontkey]['TTCfontID'] > 0 || $this->mpdf->fonts[$fontkey]['useOTL'] > 0) { // mPDF 5.7.1
78
+ // First see if there is a cached compressed file
79
+ if ($this->fontCache->has($fontkey . '.ps.z')) {
80
+ $font = $this->fontCache->load($fontkey . '.ps.z');
81
+ include $this->fontCache->tempFilename($fontkey . '.ps.php'); // sets $originalsize (of repackaged font)
82
+ } else {
83
+ $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor);
84
+ $font = $ttf->repackageTTF($this->mpdf->FontFiles[$fontkey]['ttffile'], $this->mpdf->fonts[$fontkey]['TTCfontID'], $this->mpdf->debugfonts, $this->mpdf->fonts[$fontkey]['useOTL']); // mPDF 5.7.1
85
+
86
+ $originalsize = strlen($font);
87
+ $font = gzcompress($font);
88
+ unset($ttf);
89
+
90
+ $len = "<?php \n";
91
+ $len .= '$originalsize=' . $originalsize . ";\n";
92
+
93
+ $this->fontCache->binaryWrite($fontkey . '.ps.z', $font);
94
+ $this->fontCache->write($fontkey . '.ps.php', $len);
95
+ }
96
+ } elseif ($this->fontCache->has($fontkey . '.z')) {
97
+ $font = $this->fontCache->load($fontkey . '.z');
98
+ } else {
99
+ $font = file_get_contents($this->mpdf->FontFiles[$fontkey]['ttffile']);
100
+ $font = gzcompress($font);
101
+ $this->fontCache->binaryWrite($fontkey . '.z', $font);
102
+ }
103
+
104
+ $this->writer->write('<</Length ' . strlen($font));
105
+ $this->writer->write('/Filter /FlateDecode');
106
+ $this->writer->write('/Length1 ' . $originalsize);
107
+ $this->writer->write('>>');
108
+ $this->writer->stream($font);
109
+ $this->writer->write('endobj');
110
+ }
111
+ }
112
+ }
113
+
114
+ foreach ($this->mpdf->fonts as $k => $font) {
115
+
116
+ // Font objects
117
+ $type = $font['type'];
118
+ $name = $font['name'];
119
+
120
+ if ($type === 'TTF' && (!isset($font['used']) || !$font['used'])) {
121
+ continue;
122
+ }
123
+
124
+ // @log Writing fonts
125
+
126
+ if (isset($font['asSubset'])) {
127
+ $asSubset = $font['asSubset'];
128
+ } else {
129
+ $asSubset = '';
130
+ }
131
+
132
+ if ($type === 'Type0') { // Adobe CJK Fonts
133
+
134
+ $this->mpdf->fonts[$k]['n'] = $this->mpdf->n + 1;
135
+ $this->writer->object();
136
+ $this->writer->write('<</Type /Font');
137
+ $this->writeType0($font);
138
+
139
+ } elseif ($type === 'core') {
140
+
141
+ // Standard font
142
+ $this->mpdf->fonts[$k]['n'] = $this->mpdf->n + 1;
143
+
144
+ if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
145
+ throw new \Mpdf\MpdfException('Core fonts are not allowed in PDF/A1-b or PDFX/1-a files (Times, Helvetica, Courier etc.)');
146
+ }
147
+
148
+ $this->writer->object();
149
+ $this->writer->write('<</Type /Font');
150
+ $this->writer->write('/BaseFont /' . $name);
151
+ $this->writer->write('/Subtype /Type1');
152
+
153
+ if ($name !== 'Symbol' && $name !== 'ZapfDingbats') {
154
+ $this->writer->write('/Encoding /WinAnsiEncoding');
155
+ }
156
+
157
+ $this->writer->write('>>');
158
+ $this->writer->write('endobj');
159
+
160
+ } elseif ($type === 'TTF' && ($font['sip'] || $font['smp'])) {
161
+
162
+ // TrueType embedded SUBSETS for SIP (CJK extB containing Supplementary Ideographic Plane 2)
163
+ // Or Unicode Plane 1 - Supplementary Multilingual Plane
164
+
165
+ if (!$font['used']) {
166
+ continue;
167
+ }
168
+
169
+ $ssfaid = 'AA';
170
+ $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor);
171
+ $subsetCount = count($font['subsetfontids']);
172
+ for ($sfid = 0; $sfid < $subsetCount; $sfid++) {
173
+ $this->mpdf->fonts[$k]['n'][$sfid] = $this->mpdf->n + 1; // NB an array for subset
174
+ $subsetname = 'MPDF' . $ssfaid . '+' . $font['name'];
175
+ $ssfaid++;
176
+
177
+ /* For some strange reason a subset ($sfid > 0) containing less than 97 characters causes an error
178
+ so fill up the array */
179
+ for ($j = count($font['subsets'][$sfid]); $j < 98; $j++) {
180
+ $font['subsets'][$sfid][$j] = 0;
181
+ }
182
+
183
+ $subset = $font['subsets'][$sfid];
184
+ unset($subset[0]);
185
+ $ttfontstream = $ttf->makeSubsetSIP($font['ttffile'], $subset, $font['TTCfontID'], $this->mpdf->debugfonts, $font['useOTL']); // mPDF 5.7.1
186
+ $ttfontsize = strlen($ttfontstream);
187
+ $fontstream = gzcompress($ttfontstream);
188
+ $widthstring = '';
189
+ $toUnistring = '';
190
+
191
+ foreach ($font['subsets'][$sfid] as $cp => $u) {
192
+ $w = $this->mpdf->_getCharWidth($font['cw'], $u);
193
+ if ($w !== false) {
194
+ $widthstring .= $w . ' ';
195
+ } else {
196
+ $widthstring .= round($ttf->defaultWidth) . ' ';
197
+ }
198
+ if ($u > 65535) {
199
+ $utf8 = chr(($u >> 18) + 240) . chr((($u >> 12) & 63) + 128) . chr((($u >> 6) & 63) + 128) . chr(($u & 63) + 128);
200
+ $utf16 = mb_convert_encoding($utf8, 'UTF-16BE', 'UTF-8');
201
+ $l1 = ord($utf16[0]);
202
+ $h1 = ord($utf16[1]);
203
+ $l2 = ord($utf16[2]);
204
+ $h2 = ord($utf16[3]);
205
+ $toUnistring .= sprintf("<%02s> <%02s%02s%02s%02s>\n", strtoupper(dechex($cp)), strtoupper(dechex($l1)), strtoupper(dechex($h1)), strtoupper(dechex($l2)), strtoupper(dechex($h2)));
206
+ } else {
207
+ $toUnistring .= sprintf("<%02s> <%04s>\n", strtoupper(dechex($cp)), strtoupper(dechex($u)));
208
+ }
209
+ }
210
+
211
+ // Additional Type1 or TrueType font
212
+ $this->writer->object();
213
+ $this->writer->write('<</Type /Font');
214
+ $this->writer->write('/BaseFont /' . $subsetname);
215
+ $this->writer->write('/Subtype /TrueType');
216
+ $this->writer->write('/FirstChar 0 /LastChar ' . (count($font['subsets'][$sfid]) - 1));
217
+ $this->writer->write('/Widths ' . ($this->mpdf->n + 1) . ' 0 R');
218
+ $this->writer->write('/FontDescriptor ' . ($this->mpdf->n + 2) . ' 0 R');
219
+ $this->writer->write('/ToUnicode ' . ($this->mpdf->n + 3) . ' 0 R');
220
+ $this->writer->write('>>');
221
+ $this->writer->write('endobj');
222
+
223
+ // Widths
224
+ $this->writer->object();
225
+ $this->writer->write('[' . $widthstring . ']');
226
+ $this->writer->write('endobj');
227
+
228
+ // Descriptor
229
+ $this->writer->object();
230
+ $s = '<</Type /FontDescriptor /FontName /' . $subsetname . "\n";
231
+ foreach ($font['desc'] as $kd => $v) {
232
+ if ($kd === 'Flags') {
233
+ $v |= 4;
234
+ $v &= ~32;
235
+ } // SYMBOLIC font flag
236
+ $s .= ' /' . $kd . ' ' . $v . "\n";
237
+ }
238
+ $s .= '/FontFile2 ' . ($this->mpdf->n + 2) . ' 0 R';
239
+ $this->writer->write($s . '>>');
240
+ $this->writer->write('endobj');
241
+
242
+ // ToUnicode
243
+ $this->writer->object();
244
+ $toUni = "/CIDInit /ProcSet findresource begin\n";
245
+ $toUni .= "12 dict begin\n";
246
+ $toUni .= "begincmap\n";
247
+ $toUni .= "/CIDSystemInfo\n";
248
+ $toUni .= "<</Registry (Adobe)\n";
249
+ $toUni .= "/Ordering (UCS)\n";
250
+ $toUni .= "/Supplement 0\n";
251
+ $toUni .= ">> def\n";
252
+ $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
253
+ $toUni .= "/CMapType 2 def\n";
254
+ $toUni .= "1 begincodespacerange\n";
255
+ $toUni .= "<00> <FF>\n";
256
+ // $toUni .= sprintf("<00> <%02s>\n", strtoupper(dechex(count($font['subsets'][$sfid])-1)));
257
+ $toUni .= "endcodespacerange\n";
258
+ $toUni .= count($font['subsets'][$sfid]) . " beginbfchar\n";
259
+ $toUni .= $toUnistring;
260
+ $toUni .= "endbfchar\n";
261
+ $toUni .= "endcmap\n";
262
+ $toUni .= "CMapName currentdict /CMap defineresource pop\n";
263
+ $toUni .= "end\n";
264
+ $toUni .= "end\n";
265
+ $this->writer->write('<</Length ' . strlen($toUni) . '>>');
266
+ $this->writer->stream($toUni);
267
+ $this->writer->write('endobj');
268
+
269
+ // Font file
270
+ $this->writer->object();
271
+ $this->writer->write('<</Length ' . strlen($fontstream));
272
+ $this->writer->write('/Filter /FlateDecode');
273
+ $this->writer->write('/Length1 ' . $ttfontsize);
274
+ $this->writer->write('>>');
275
+ $this->writer->stream($fontstream);
276
+ $this->writer->write('endobj');
277
+ } // foreach subset
278
+ unset($ttf);
279
+
280
+ } elseif ($type === 'TTF') { // TrueType embedded SUBSETS or FULL
281
+
282
+ $this->mpdf->fonts[$k]['n'] = $this->mpdf->n + 1;
283
+
284
+ if ($asSubset) {
285
+ $ssfaid = 'A';
286
+ $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor);
287
+ $fontname = 'MPDFA' . $ssfaid . '+' . $font['name'];
288
+ $subset = $font['subset'];
289
+ unset($subset[0]);
290
+ $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset, $font['TTCfontID'], $this->mpdf->debugfonts, $font['useOTL']);
291
+ $ttfontsize = strlen($ttfontstream);
292
+ $fontstream = gzcompress($ttfontstream);
293
+ $codeToGlyph = $ttf->codeToGlyph;
294
+ unset($codeToGlyph[0]);
295
+ } else {
296
+ $fontname = $font['name'];
297
+ }
298
+
299
+ // Type0 Font
300
+ // A composite font - a font composed of other fonts, organized hierarchically
301
+ $this->writer->object();
302
+ $this->writer->write('<</Type /Font');
303
+ $this->writer->write('/Subtype /Type0');
304
+ $this->writer->write('/BaseFont /' . $fontname . '');
305
+ $this->writer->write('/Encoding /Identity-H');
306
+ $this->writer->write('/DescendantFonts [' . ($this->mpdf->n + 1) . ' 0 R]');
307
+ $this->writer->write('/ToUnicode ' . ($this->mpdf->n + 2) . ' 0 R');
308
+ $this->writer->write('>>');
309
+ $this->writer->write('endobj');
310
+
311
+ // CIDFontType2
312
+ // A CIDFont whose glyph descriptions are based on TrueType font technology
313
+ $this->writer->object();
314
+ $this->writer->write('<</Type /Font');
315
+ $this->writer->write('/Subtype /CIDFontType2');
316
+ $this->writer->write('/BaseFont /' . $fontname . '');
317
+ $this->writer->write('/CIDSystemInfo ' . ($this->mpdf->n + 2) . ' 0 R');
318
+ $this->writer->write('/FontDescriptor ' . ($this->mpdf->n + 3) . ' 0 R');
319
+
320
+ if (isset($font['desc']['MissingWidth'])) {
321
+ $this->writer->write('/DW ' . $font['desc']['MissingWidth'] . '');
322
+ }
323
+
324
+ if (!$asSubset && $this->fontCache->has($font['fontkey'] . '.cw')) {
325
+ $w = $this->fontCache->load($font['fontkey'] . '.cw');
326
+ $this->writer->write($w);
327
+ } else {
328
+ $this->writeTTFontWidths($font, $asSubset, ($asSubset ? $ttf->maxUni : 0));
329
+ }
330
+
331
+ $this->writer->write('/CIDToGIDMap ' . ($this->mpdf->n + 4) . ' 0 R');
332
+ $this->writer->write('>>');
333
+ $this->writer->write('endobj');
334
+
335
+ // ToUnicode
336
+ $this->writer->object();
337
+ $toUni = "/CIDInit /ProcSet findresource begin\n";
338
+ $toUni .= "12 dict begin\n";
339
+ $toUni .= "begincmap\n";
340
+ $toUni .= "/CIDSystemInfo\n";
341
+ $toUni .= "<</Registry (Adobe)\n";
342
+ $toUni .= "/Ordering (UCS)\n";
343
+ $toUni .= "/Supplement 0\n";
344
+ $toUni .= ">> def\n";
345
+ $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
346
+ $toUni .= "/CMapType 2 def\n";
347
+ $toUni .= "1 begincodespacerange\n";
348
+ $toUni .= "<0000> <FFFF>\n";
349
+ $toUni .= "endcodespacerange\n";
350
+ $toUni .= "1 beginbfrange\n";
351
+ $toUni .= "<0000> <FFFF> <0000>\n";
352
+ $toUni .= "endbfrange\n";
353
+ $toUni .= "endcmap\n";
354
+ $toUni .= "CMapName currentdict /CMap defineresource pop\n";
355
+ $toUni .= "end\n";
356
+ $toUni .= "end\n";
357
+
358
+ $this->writer->write('<</Length ' . strlen($toUni) . '>>');
359
+ $this->writer->stream($toUni);
360
+ $this->writer->write('endobj');
361
+
362
+ // CIDSystemInfo dictionary
363
+ $this->writer->object();
364
+ $this->writer->write('<</Registry (Adobe)');
365
+ $this->writer->write('/Ordering (UCS)');
366
+ $this->writer->write('/Supplement 0');
367
+ $this->writer->write('>>');
368
+ $this->writer->write('endobj');
369
+
370
+ // Font descriptor
371
+ $this->writer->object();
372
+ $this->writer->write('<</Type /FontDescriptor');
373
+ $this->writer->write('/FontName /' . $fontname);
374
+
375
+ foreach ($font['desc'] as $kd => $v) {
376
+ if ($asSubset && $kd === 'Flags') {
377
+ $v |= 4;
378
+ $v &= ~32;
379
+ } // SYMBOLIC font flag
380
+ $this->writer->write(' /' . $kd . ' ' . $v);
381
+ }
382
+
383
+ if ($font['panose']) {
384
+ $this->writer->write(' /Style << /Panose <' . $font['panose'] . '> >>');
385
+ }
386
+
387
+ if ($asSubset) {
388
+ $this->writer->write('/FontFile2 ' . ($this->mpdf->n + 2) . ' 0 R');
389
+ } elseif ($font['fontkey']) {
390
+ // obj ID of a stream containing a TrueType font program
391
+ $this->writer->write('/FontFile2 ' . $this->mpdf->FontFiles[$font['fontkey']]['n'] . ' 0 R');
392
+ }
393
+
394
+ $this->writer->write('>>');
395
+ $this->writer->write('endobj');
396
+
397
+ // Embed CIDToGIDMap
398
+ // A specification of the mapping from CIDs to glyph indices
399
+ if ($asSubset) {
400
+ $cidtogidmap = str_pad('', 256 * 256 * 2, "\x00");
401
+ foreach ($codeToGlyph as $cc => $glyph) {
402
+ $cidtogidmap[$cc * 2] = chr($glyph >> 8);
403
+ $cidtogidmap[$cc * 2 + 1] = chr($glyph & 0xFF);
404
+ }
405
+ $cidtogidmap = gzcompress($cidtogidmap);
406
+ } else {
407
+ // First see if there is a cached CIDToGIDMapfile
408
+ if ($this->fontCache->has($font['fontkey'] . '.cgm')) {
409
+ $cidtogidmap = $this->fontCache->load($font['fontkey'] . '.cgm');
410
+ } else {
411
+ $ttf = new TTFontFile($this->fontCache, $this->fontDescriptor);
412
+ $charToGlyph = $ttf->getCTG($font['ttffile'], $font['TTCfontID'], $this->mpdf->debugfonts, $font['useOTL']);
413
+ $cidtogidmap = str_pad('', 256 * 256 * 2, "\x00");
414
+ foreach ($charToGlyph as $cc => $glyph) {
415
+ $cidtogidmap[$cc * 2] = chr($glyph >> 8);
416
+ $cidtogidmap[$cc * 2 + 1] = chr($glyph & 0xFF);
417
+ }
418
+ unset($ttf);
419
+ $cidtogidmap = gzcompress($cidtogidmap);
420
+ $this->fontCache->binaryWrite($font['fontkey'] . '.cgm', $cidtogidmap);
421
+ }
422
+ }
423
+ $this->writer->object();
424
+ $this->writer->write('<</Length ' . strlen($cidtogidmap) . '');
425
+ $this->writer->write('/Filter /FlateDecode');
426
+ $this->writer->write('>>');
427
+ $this->writer->stream($cidtogidmap);
428
+ $this->writer->write('endobj');
429
+
430
+ // Font file
431
+ if ($asSubset) {
432
+ $this->writer->object();
433
+ $this->writer->write('<</Length ' . strlen($fontstream));
434
+ $this->writer->write('/Filter /FlateDecode');
435
+ $this->writer->write('/Length1 ' . $ttfontsize);
436
+ $this->writer->write('>>');
437
+ $this->writer->stream($fontstream);
438
+ $this->writer->write('endobj');
439
+ unset($ttf);
440
+ }
441
+ } else {
442
+ throw new \Mpdf\MpdfException(sprintf('Unsupported font type: %s (%s)', $type, $name));
443
+ }
444
+ }
445
+ }
446
+
447
+ private function writeTTFontWidths(&$font, $asSubset, $maxUni) // _putTTfontwidths
448
+ {
449
+ if ($asSubset && $this->fontCache->has($font['fontkey'] . '.cw127.php')) {
450
+ include $this->fontCache->tempFilename($font['fontkey'] . '.cw127.php');
451
+ $startcid = 128;
452
+ } else {
453
+ $rangeid = 0;
454
+ $range = [];
455
+ $prevcid = -2;
456
+ $prevwidth = -1;
457
+ $interval = false;
458
+ $startcid = 1;
459
+ }
460
+ if ($asSubset) {
461
+ $cwlen = $maxUni + 1;
462
+ } else {
463
+ $cwlen = (strlen($font['cw']) / 2);
464
+ }
465
+
466
+ // for each character
467
+ for ($cid = $startcid; $cid < $cwlen; $cid++) {
468
+ if ($cid == 128 && $asSubset && (!$this->fontCache->has($font['fontkey'] . '.cw127.php'))) {
469
+ $cw127 = '<?php' . "\n";
470
+ $cw127 .= '$rangeid=' . $rangeid . ";\n";
471
+ $cw127 .= '$prevcid=' . $prevcid . ";\n";
472
+ $cw127 .= '$prevwidth=' . $prevwidth . ";\n";
473
+ if ($interval) {
474
+ $cw127 .= '$interval=true' . ";\n";
475
+ } else {
476
+ $cw127 .= '$interval=false' . ";\n";
477
+ }
478
+ $cw127 .= '$range=' . var_export($range, true) . ";\n";
479
+ $this->fontCache->write($font['fontkey'] . '.cw127.php', $cw127);
480
+ }
481
+
482
+ $character1 = isset($font['cw'][$cid * 2]) ? $font['cw'][$cid * 2] : '';
483
+ $character2 = isset($font['cw'][$cid * 2 + 1]) ? $font['cw'][$cid * 2 + 1] : '';
484
+
485
+ if ($character1 === "\00" && $character2 === "\00") {
486
+ continue;
487
+ }
488
+
489
+ $width = (ord($character1) << 8) + ord($character2);
490
+
491
+ if ($width === 65535) {
492
+ $width = 0;
493
+ }
494
+
495
+ if ($asSubset && $cid > 255 && (!isset($font['subset'][$cid]) || !$font['subset'][$cid])) {
496
+ continue;
497
+ }
498
+
499
+ if ($asSubset && $cid > 0xFFFF) {
500
+ continue;
501
+ } // mPDF 6
502
+
503
+ if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
504
+ if ($cid === ($prevcid + 1)) {
505
+ // consecutive CID
506
+ if ($width === $prevwidth) {
507
+ if ($width === $range[$rangeid][0]) {
508
+ $range[$rangeid][] = $width;
509
+ } else {
510
+ array_pop($range[$rangeid]);
511
+ // new range
512
+ $rangeid = $prevcid;
513
+ $range[$rangeid] = [];
514
+ $range[$rangeid][] = $prevwidth;
515
+ $range[$rangeid][] = $width;
516
+ }
517
+ $interval = true;
518
+ $range[$rangeid]['interval'] = true;
519
+ } else {
520
+ if ($interval) {
521
+ // new range
522
+ $rangeid = $cid;
523
+ $range[$rangeid] = [];
524
+ $range[$rangeid][] = $width;
525
+ } else {
526
+ $range[$rangeid][] = $width;
527
+ }
528
+ $interval = false;
529
+ }
530
+ } else {
531
+ // new range
532
+ $rangeid = $cid;
533
+ $range[$rangeid] = [];
534
+ $range[$rangeid][] = $width;
535
+ $interval = false;
536
+ }
537
+ $prevcid = $cid;
538
+ $prevwidth = $width;
539
+ }
540
+ }
541
+ $w = $this->writeFontRanges($range);
542
+ $this->writer->write($w);
543
+ if (!$asSubset) {
544
+ $this->fontCache->binaryWrite($font['fontkey'] . '.cw', $w);
545
+ }
546
+ }
547
+
548
+ private function writeFontRanges(&$range) // _putfontranges
549
+ {
550
+ // optimize ranges
551
+ $prevk = -1;
552
+ $nextk = -1;
553
+ $prevint = false;
554
+ foreach ($range as $k => $ws) {
555
+ $cws = count($ws);
556
+ if (($k == $nextk) and ( !$prevint) and ( (!isset($ws['interval'])) or ( $cws < 4))) {
557
+ if (isset($range[$k]['interval'])) {
558
+ unset($range[$k]['interval']);
559
+ }
560
+ $range[$prevk] = array_merge($range[$prevk], $range[$k]);
561
+ unset($range[$k]);
562
+ } else {
563
+ $prevk = $k;
564
+ }
565
+ $nextk = $k + $cws;
566
+ if (isset($ws['interval'])) {
567
+ if ($cws > 3) {
568
+ $prevint = true;
569
+ } else {
570
+ $prevint = false;
571
+ }
572
+ unset($range[$k]['interval']);
573
+ --$nextk;
574
+ } else {
575
+ $prevint = false;
576
+ }
577
+ }
578
+ // output data
579
+ $w = '';
580
+ foreach ($range as $k => $ws) {
581
+ if (count(array_count_values($ws)) === 1) {
582
+ // interval mode is more compact
583
+ $w .= ' ' . $k . ' ' . ($k + count($ws) - 1) . ' ' . $ws[0];
584
+ } else {
585
+ // range mode
586
+ $w .= ' ' . $k . ' [ ' . implode(' ', $ws) . ' ]' . "\n";
587
+ }
588
+ }
589
+ return '/W [' . $w . ' ]';
590
+ }
591
+
592
+ private function writeFontWidths(&$font, $cidoffset = 0) // _putfontwidths
593
+ {
594
+ ksort($font['cw']);
595
+ unset($font['cw'][65535]);
596
+ $rangeid = 0;
597
+ $range = [];
598
+ $prevcid = -2;
599
+ $prevwidth = -1;
600
+ $interval = false;
601
+ // for each character
602
+ foreach ($font['cw'] as $cid => $width) {
603
+ $cid -= $cidoffset;
604
+ if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
605
+ if ($cid === ($prevcid + 1)) {
606
+ // consecutive CID
607
+ if ($width === $prevwidth) {
608
+ if ($width === $range[$rangeid][0]) {
609
+ $range[$rangeid][] = $width;
610
+ } else {
611
+ array_pop($range[$rangeid]);
612
+ // new range
613
+ $rangeid = $prevcid;
614
+ $range[$rangeid] = [];
615
+ $range[$rangeid][] = $prevwidth;
616
+ $range[$rangeid][] = $width;
617
+ }
618
+ $interval = true;
619
+ $range[$rangeid]['interval'] = true;
620
+ } else {
621
+ if ($interval) {
622
+ // new range
623
+ $rangeid = $cid;
624
+ $range[$rangeid] = [];
625
+ $range[$rangeid][] = $width;
626
+ } else {
627
+ $range[$rangeid][] = $width;
628
+ }
629
+ $interval = false;
630
+ }
631
+ } else {
632
+ // new range
633
+ $rangeid = $cid;
634
+ $range[$rangeid] = [];
635
+ $range[$rangeid][] = $width;
636
+ $interval = false;
637
+ }
638
+ $prevcid = $cid;
639
+ $prevwidth = $width;
640
+ }
641
+ }
642
+ $this->writer->write($this->writeFontRanges($range));
643
+ }
644
+
645
+ // from class PDF_Chinese CJK EXTENSIONS
646
+ public function writeType0(&$font) // _putType0
647
+ {
648
+ // Type0
649
+ $this->writer->write('/Subtype /Type0');
650
+ $this->writer->write('/BaseFont /' . $font['name'] . '-' . $font['CMap']);
651
+ $this->writer->write('/Encoding /' . $font['CMap']);
652
+ $this->writer->write('/DescendantFonts [' . ($this->mpdf->n + 1) . ' 0 R]');
653
+ $this->writer->write('>>');
654
+ $this->writer->write('endobj');
655
+ // CIDFont
656
+ $this->writer->object();
657
+ $this->writer->write('<</Type /Font');
658
+ $this->writer->write('/Subtype /CIDFontType0');
659
+ $this->writer->write('/BaseFont /' . $font['name']);
660
+
661
+ $cidinfo = '/Registry ' . $this->writer->string('Adobe');
662
+ $cidinfo .= ' /Ordering ' . $this->writer->string($font['registry']['ordering']);
663
+ $cidinfo .= ' /Supplement ' . $font['registry']['supplement'];
664
+ $this->writer->write('/CIDSystemInfo <<' . $cidinfo . '>>');
665
+
666
+ $this->writer->write('/FontDescriptor ' . ($this->mpdf->n + 1) . ' 0 R');
667
+ if (isset($font['MissingWidth'])) {
668
+ $this->writer->write('/DW ' . $font['MissingWidth'] . '');
669
+ }
670
+ $this->writeFontWidths($font, 31);
671
+ $this->writer->write('>>');
672
+ $this->writer->write('endobj');
673
+
674
+ // Font descriptor
675
+ $this->writer->object();
676
+ $s = '<</Type /FontDescriptor /FontName /' . $font['name'];
677
+ foreach ($font['desc'] as $k => $v) {
678
+ if ($k !== 'Style') {
679
+ $s .= ' /' . $k . ' ' . $v . '';
680
+ }
681
+ }
682
+ $this->writer->write($s . '>>');
683
+ $this->writer->write('endobj');
684
+ }
685
+
686
+ }
vendor/mpdf/mpdf/src/Writer/FormWriter.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf\Writer;
4
+
5
+ use Mpdf\Strict;
6
+
7
+ use Mpdf\Mpdf;
8
+
9
+ final class FormWriter
10
+ {
11
+
12
+ use Strict;
13
+
14
+ /**
15
+ * @var \Mpdf\Mpdf
16
+ */
17
+ private $mpdf;
18
+
19
+ /**
20
+ * @var \Mpdf\Writer\BaseWriter
21
+ */
22
+ private $writer;
23
+
24
+ public function __construct(Mpdf $mpdf, BaseWriter $writer)
25
+ {
26
+ $this->mpdf = $mpdf;
27
+ $this->writer = $writer;
28
+ }
29
+
30
+ public function writeFormObjects() // _putformobjects
31
+ {
32
+ foreach ($this->mpdf->formobjects as $file => $info) {
33
+
34
+ $this->writer->object();
35
+
36
+ $this->mpdf->formobjects[$file]['n'] = $this->mpdf->n;
37
+
38
+ $this->writer->write('<</Type /XObject');
39
+ $this->writer->write('/Subtype /Form');
40
+ $this->writer->write('/Group ' . ($this->mpdf->n + 1) . ' 0 R');
41
+ $this->writer->write('/BBox [' . $info['x'] . ' ' . $info['y'] . ' ' . ($info['w'] + $info['x']) . ' ' . ($info['h'] + $info['y']) . ']');
42
+
43
+ if ($this->mpdf->compress) {
44
+ $this->writer->write('/Filter /FlateDecode');
45
+ }
46
+
47
+ $data = $this->mpdf->compress ? gzcompress($info['data']) : $info['data'];
48
+ $this->writer->write('/Length ' . strlen($data) . '>>');
49
+ $this->writer->stream($data);
50
+
51
+ unset($this->mpdf->formobjects[$file]['data']);
52
+
53
+ $this->writer->write('endobj');
54
+
55
+ // Required for SVG transparency (opacity) to work
56
+ $this->writer->object();
57
+ $this->writer->write('<</Type /Group');
58
+ $this->writer->write('/S /Transparency');
59
+ $this->writer->write('>>');
60
+ $this->writer->write('endobj');
61
+ }
62
+ }
63
+
64
+ public function writeFormXObjects() // _putformxobjects
65
+ {
66
+ $filter = $this->mpdf->compress ? '/Filter /FlateDecode ' : '';
67
+
68
+ reset($this->mpdf->tpls);
69
+
70
+ foreach ($this->mpdf->tpls as $tplidx => $tpl) {
71
+
72
+ $p = $this->mpdf->compress ? gzcompress($tpl['buffer']) : $tpl['buffer'];
73
+
74
+ $this->writer->object();
75
+ $this->mpdf->tpls[$tplidx]['n'] = $this->mpdf->n;
76
+ $this->writer->write('<<' . $filter . '/Type /XObject');
77
+ $this->writer->write('/Subtype /Form');
78
+ $this->writer->write('/FormType 1');
79
+
80
+ // Left/Bottom/Right/Top
81
+ $this->writer->write(
82
+ sprintf(
83
+ '/BBox [%.2F %.2F %.2F %.2F]',
84
+ $tpl['box']['x'] * Mpdf::SCALE,
85
+ $tpl['box']['y'] * Mpdf::SCALE,
86
+ ($tpl['box']['x'] + $tpl['box']['w']) * Mpdf::SCALE,
87
+ ($tpl['box']['y'] + $tpl['box']['h']) * Mpdf::SCALE
88
+ )
89
+ );
90
+
91
+ if (isset($tpl['box'])) {
92
+ $this->writer->write(
93
+ sprintf(
94
+ '/Matrix [1 0 0 1 %.5F %.5F]',
95
+ -$tpl['box']['x'] * Mpdf::SCALE,
96
+ -$tpl['box']['y'] * Mpdf::SCALE
97
+ )
98
+ );
99
+ }
100
+
101
+ $this->writer->write('/Resources ');
102
+
103
+ if (isset($tpl['resources'])) {
104
+
105
+ $this->mpdf->current_parser = $tpl['parser'];
106
+ $this->mpdf->pdf_write_value($tpl['resources']);
107
+
108
+ } else {
109
+
110
+ $this->writer->write('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
111
+
112
+ if (isset($this->_res['tpl'][$tplidx]['fonts']) && count($this->mpdf->_res['tpl'][$tplidx]['fonts'])) {
113
+ $this->writer->write('/Font <<');
114
+ foreach ($this->mpdf->_res['tpl'][$tplidx]['fonts'] as $font) {
115
+ $this->writer->write('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R');
116
+ }
117
+ $this->writer->write('>>');
118
+ }
119
+
120
+ if ((isset($this->mpdf->_res['tpl'][$tplidx]['images']) && count($this->mpdf->_res['tpl'][$tplidx]['images'])) ||
121
+ (isset($this->mpdf->_res['tpl'][$tplidx]['tpls']) && count($this->mpdf->_res['tpl'][$tplidx]['tpls']))) {
122
+
123
+ $this->writer->write('/XObject <<');
124
+
125
+ if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->mpdf->_res['tpl'][$tplidx]['images'])) {
126
+ foreach ($this->mpdf->_res['tpl'][$tplidx]['images'] as $image) {
127
+ $this->writer->write('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R');
128
+ }
129
+ }
130
+
131
+ if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->mpdf->_res['tpl'][$tplidx]['tpls'])) {
132
+ foreach ($this->mpdf->_res['tpl'][$tplidx]['tpls'] as $i => $itpl) {
133
+ $this->writer->write($this->mpdf->tplprefix . $i . ' ' . $itpl['n'] . ' 0 R');
134
+ }
135
+ }
136
+
137
+ $this->writer->write('>>');
138
+ }
139
+
140
+ $this->writer->write('>>');
141
+ }
142
+
143
+ $this->writer->write('/Length ' . strlen($p) . ' >>');
144
+ $this->writer->stream($p);
145
+ $this->writer->write('endobj');
146
+ }
147
+ }
148
+
149
+ }
vendor/mpdf/mpdf/src/Writer/ImageWriter.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf\Writer;
4
+
5
+ use Mpdf\Strict;
6
+ use Mpdf\Mpdf;
7
+
8
+ final class ImageWriter
9
+ {
10
+
11
+ use Strict;
12
+
13
+ /**
14
+ * @var \Mpdf\Mpdf
15
+ */
16
+ private $mpdf;
17
+
18
+ /**
19
+ * @var \Mpdf\Writer\BaseWriter
20
+ */
21
+ private $writer;
22
+
23
+ public function __construct(Mpdf $mpdf, BaseWriter $writer)
24
+ {
25
+ $this->mpdf = $mpdf;
26
+ $this->writer = $writer;
27
+ }
28
+
29
+ public function writeImages()
30
+ {
31
+ $filter = $this->mpdf->compress ? '/Filter /FlateDecode ' : '';
32
+
33
+ foreach ($this->mpdf->images as $file => $info) {
34
+
35
+ $this->writer->object();
36
+
37
+ $this->mpdf->images[$file]['n'] = $this->mpdf->n;
38
+
39
+ $this->writer->write('<</Type /XObject');
40
+ $this->writer->write('/Subtype /Image');
41
+ $this->writer->write('/Width ' . $info['w']);
42
+ $this->writer->write('/Height ' . $info['h']);
43
+
44
+ if (isset($info['interpolation']) && $info['interpolation']) {
45
+ $this->writer->write('/Interpolate true'); // mPDF 6 - image interpolation shall be performed by a conforming reader
46
+ }
47
+
48
+ if (isset($info['masked'])) {
49
+ $this->writer->write('/SMask ' . ($this->mpdf->n - 1) . ' 0 R');
50
+ }
51
+
52
+ // set color space
53
+ $icc = false;
54
+ if (isset($info['icc']) && ( $info['icc'] !== false)) {
55
+ // ICC Colour Space
56
+ $icc = true;
57
+ $this->writer->write('/ColorSpace [/ICCBased ' . ($this->mpdf->n + 1) . ' 0 R]');
58
+ } elseif ($info['cs'] === 'Indexed') {
59
+ if ($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace === 3)) {
60
+ throw new \Mpdf\MpdfException('PDFA1-b and PDFX/1-a files do not permit using mixed colour space (' . $file . ').');
61
+ }
62
+ $this->writer->write('/ColorSpace [/Indexed /DeviceRGB ' . (strlen($info['pal']) / 3 - 1) . ' ' . ($this->mpdf->n + 1) . ' 0 R]');
63
+ } else {
64
+ $this->writer->write('/ColorSpace /' . $info['cs']);
65
+ if ($info['cs'] === 'DeviceCMYK') {
66
+ if ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace !== 3) {
67
+ throw new \Mpdf\MpdfException('PDFA1-b does not permit Images using mixed colour space (' . $file . ').');
68
+ }
69
+ if ($info['type'] === 'jpg') {
70
+ $this->writer->write('/Decode [1 0 1 0 1 0 1 0]');
71
+ }
72
+ } elseif (($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace === 3)) && $info['cs'] === 'DeviceRGB') {
73
+ throw new \Mpdf\MpdfException('PDFA1-b and PDFX/1-a files do not permit using mixed colour space (' . $file . ').');
74
+ }
75
+ }
76
+
77
+ $this->writer->write('/BitsPerComponent ' . $info['bpc']);
78
+
79
+ if (isset($info['f']) && $info['f']) {
80
+ $this->writer->write('/Filter /' . $info['f']);
81
+ }
82
+
83
+ if (isset($info['parms'])) {
84
+ $this->writer->write($info['parms']);
85
+ }
86
+
87
+ if (isset($info['trns']) && is_array($info['trns'])) {
88
+ $trns = '';
89
+ $maskCount = count($info['trns']);
90
+ for ($i = 0; $i < $maskCount; $i++) {
91
+ $trns .= $info['trns'][$i] . ' ' . $info['trns'][$i] . ' ';
92
+ }
93
+ $this->writer->write('/Mask [' . $trns . ']');
94
+ }
95
+
96
+ $this->writer->write('/Length ' . strlen($info['data']) . '>>');
97
+ $this->writer->stream($info['data']);
98
+
99
+ unset($this->mpdf->images[$file]['data']);
100
+
101
+ $this->writer->write('endobj');
102
+
103
+ if ($icc) { // ICC colour profile
104
+ $this->writer->object();
105
+ $icc = $this->mpdf->compress ? gzcompress($info['icc']) : $info['icc'];
106
+ $this->writer->write('<</N ' . $info['ch'] . ' ' . $filter . '/Length ' . strlen($icc) . '>>');
107
+ $this->writer->stream($icc);
108
+ $this->writer->write('endobj');
109
+ } elseif ($info['cs'] === 'Indexed') { // Palette
110
+ $this->writer->object();
111
+ $pal = $this->mpdf->compress ? gzcompress($info['pal']) : $info['pal'];
112
+ $this->writer->write('<<' . $filter . '/Length ' . strlen($pal) . '>>');
113
+ $this->writer->stream($pal);
114
+ $this->writer->write('endobj');
115
+ }
116
+ }
117
+ }
118
+
119
+ }
vendor/mpdf/mpdf/src/Writer/JavaScriptWriter.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf\Writer;
4
+
5
+ use Mpdf\Strict;
6
+ use Mpdf\Mpdf;
7
+
8
+ final class JavaScriptWriter
9
+ {
10
+
11
+ use Strict;
12
+
13
+ /**
14
+ * @var \Mpdf\Mpdf
15
+ */
16
+ private $mpdf;
17
+
18
+ /**
19
+ * @var \Mpdf\Writer\BaseWriter
20
+ */
21
+ private $writer;
22
+
23
+ public function __construct(Mpdf $mpdf, BaseWriter $writer)
24
+ {
25
+ $this->mpdf = $mpdf;
26
+ $this->writer = $writer;
27
+ }
28
+
29
+ public function writeJavascript() // _putjavascript
30
+ {
31
+ $this->writer->object();
32
+ $this->mpdf->n_js = $this->mpdf->n;
33
+ $this->writer->write('<<');
34
+ $this->writer->write('/Names [(EmbeddedJS) ' . (1 + $this->mpdf->n) . ' 0 R ]');
35
+ $this->writer->write('>>');
36
+ $this->writer->write('endobj');
37
+
38
+ $this->writer->object();
39
+ $this->writer->write('<<');
40
+ $this->writer->write('/S /JavaScript');
41
+ $this->writer->write('/JS ' . $this->writer->string($this->mpdf->js));
42
+ $this->writer->write('>>');
43
+ $this->writer->write('endobj');
44
+ }
45
+
46
+ }
vendor/mpdf/mpdf/src/Writer/MetadataWriter.php ADDED
@@ -0,0 +1,820 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Mpdf\Writer;
4
+
5
+ use Mpdf\Strict;
6
+
7
+ use Mpdf\Form;
8
+ use Mpdf\Mpdf;
9
+ use Mpdf\Pdf\Protection;
10
+ use Mpdf\Utils\PdfDate;
11
+
12
+ use Psr\Log\LoggerInterface;
13
+
14
+ class MetadataWriter implements \Psr\Log\LoggerAwareInterface
15
+ {
16
+
17
+ use Strict;
18
+
19
+ /**
20
+ * @var \Mpdf\Mpdf
21
+ */
22
+ private $mpdf;
23
+
24
+ /**
25
+ * @var \Mpdf\Writer\BaseWriter
26
+ */
27
+ private $writer;
28
+
29
+ /**
30
+ * @var \Mpdf\Form
31
+ */
32
+ private $form;
33
+
34
+ /**
35
+ * @var \Mpdf\Pdf\Protection
36
+ */
37
+ private $protection;
38
+
39
+ /**
40
+ * @var \Psr\Log\LoggerInterface
41
+ */
42
+ private $logger;
43
+
44
+ public function __construct(Mpdf $mpdf, BaseWriter $writer, Form $form, Protection $protection, LoggerInterface $logger)
45
+ {
46
+ $this->mpdf = $mpdf;
47
+ $this->writer = $writer;
48
+ $this->form = $form;
49
+ $this->protection = $protection;
50
+ $this->logger = $logger;
51
+ }
52
+
53
+ public function writeMetadata() // _putmetadata
54
+ {
55
+ $this->writer->object();
56
+ $this->mpdf->MetadataRoot = $this->mpdf->n;
57
+ $Producer = 'mPDF ' . Mpdf::VERSION;
58
+ $z = date('O'); // +0200
59
+ $offset = substr($z, 0, 3) . ':' . substr($z, 3, 2);
60
+ $CreationDate = date('Y-m-d\TH:i:s') . $offset; // 2006-03-10T10:47:26-05:00 2006-06-19T09:05:17Z
61
+ $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0x0fff) | 0x4000, random_int(0, 0x3fff) | 0x8000, random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff));
62
+
63
+
64
+ $m = '<?xpacket begin="' . chr(239) . chr(187) . chr(191) . '" id="W5M0MpCehiHzreSzNTczkc9d"?>' . "\n"; // begin = FEFF BOM
65
+ $m .= ' <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="3.1-701">' . "\n";
66
+ $m .= ' <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">' . "\n";
67
+ $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">' . "\n";
68
+ $m .= ' <pdf:Producer>' . $Producer . '</pdf:Producer>' . "\n";
69
+ if (!empty($this->mpdf->keywords)) {
70
+ $m .= ' <pdf:Keywords>' . $this->mpdf->keywords . '</pdf:Keywords>' . "\n";
71
+ }
72
+ $m .= ' </rdf:Description>' . "\n";
73
+
74
+ $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:xmp="http://ns.adobe.com/xap/1.0/">' . "\n";
75
+ $m .= ' <xmp:CreateDate>' . $CreationDate . '</xmp:CreateDate>' . "\n";
76
+ $m .= ' <xmp:ModifyDate>' . $CreationDate . '</xmp:ModifyDate>' . "\n";
77
+ $m .= ' <xmp:MetadataDate>' . $CreationDate . '</xmp:MetadataDate>' . "\n";
78
+ if (!empty($this->mpdf->creator)) {
79
+ $m .= ' <xmp:CreatorTool>' . $this->mpdf->creator . '</xmp:CreatorTool>' . "\n";
80
+ }
81
+ $m .= ' </rdf:Description>' . "\n";
82
+
83
+ // DC elements
84
+ $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:dc="http://purl.org/dc/elements/1.1/">' . "\n";
85
+ $m .= ' <dc:format>application/pdf</dc:format>' . "\n";
86
+ if (!empty($this->mpdf->title)) {
87
+ $m .= ' <dc:title>
88
+ <rdf:Alt>
89
+ <rdf:li xml:lang="x-default">' . $this->mpdf->title . '</rdf:li>
90
+ </rdf:Alt>
91
+ </dc:title>' . "\n";
92
+ }
93
+ if (!empty($this->mpdf->keywords)) {
94
+ $m .= ' <dc:subject>
95
+ <rdf:Bag>
96
+ <rdf:li>' . $this->mpdf->keywords . '</rdf:li>
97
+ </rdf:Bag>
98
+ </dc:subject>' . "\n";
99
+ }
100
+ if (!empty($this->mpdf->subject)) {
101
+ $m .= ' <dc:description>
102
+ <rdf:Alt>
103
+ <rdf:li xml:lang="x-default">' . $this->mpdf->subject . '</rdf:li>
104
+ </rdf:Alt>
105
+ </dc:description>' . "\n";
106
+ }
107
+ if (!empty($this->mpdf->author)) {
108
+ $m .= ' <dc:creator>
109
+ <rdf:Seq>
110
+ <rdf:li>' . $this->mpdf->author . '</rdf:li>
111
+ </rdf:Seq>
112
+ </dc:creator>' . "\n";
113
+ }
114
+ $m .= ' </rdf:Description>' . "\n";
115
+
116
+ if (!empty($this->mpdf->additionalXmpRdf)) {
117
+ $m .= $this->mpdf->additionalXmpRdf;
118
+ }
119
+
120
+ // This bit is specific to PDFX-1a
121
+ if ($this->mpdf->PDFX) {
122
+ $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/" pdfx:Apag_PDFX_Checkup="1.3" pdfx:GTS_PDFXConformance="PDF/X-1a:2003" pdfx:GTS_PDFXVersion="PDF/X-1:2003"/>' . "\n";
123
+ } // This bit is specific to PDFA-1b
124
+ elseif ($this->mpdf->PDFA) {
125
+
126
+ if (strpos($this->mpdf->PDFAversion, '-') === false) {
127
+ throw new \Mpdf\MpdfException(sprintf('PDFA version (%s) is not valid. (Use: 1-B, 3-B, etc.)', $this->mpdf->PDFAversion));
128
+ }
129
+
130
+ list($part, $conformance) = explode('-', strtoupper($this->mpdf->PDFAversion));
131
+ $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" >' . "\n";
132
+ $m .= ' <pdfaid:part>' . $part . '</pdfaid:part>' . "\n";
133
+ $m .= ' <pdfaid:conformance>' . $conformance . '</pdfaid:conformance>' . "\n";
134
+ if ($part === '1' && $conformance === 'B') {
135
+ $m .= ' <pdfaid:amd>2005</pdfaid:amd>' . "\n";
136
+ }
137
+ $m .= ' </rdf:Description>' . "\n";
138
+ }
139
+
140
+ $m .= ' <rdf:Description rdf:about="uuid:' . $uuid . '" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">' . "\n";
141
+ $m .= ' <xmpMM:DocumentID>uuid:' . $uuid . '</xmpMM:DocumentID>' . "\n";
142
+ $m .= ' </rdf:Description>' . "\n";
143
+ $m .= ' </rdf:RDF>' . "\n";
144
+ $m .= ' </x:xmpmeta>' . "\n";
145
+ $m .= str_repeat(str_repeat(' ', 100) . "\n", 20); // 2-4kB whitespace padding required
146
+ $m .= '<?xpacket end="w"?>'; // "r" read only
147
+ $this->writer->write('<</Type/Metadata/Subtype/XML/Length ' . strlen($m) . '>>');
148
+ $this->writer->stream($m);
149
+ $this->writer->write('endobj');
150
+ }
151
+
152
+ public function writeInfo() // _putinfo
153
+ {
154
+ $this->writer->write('/Producer ' . $this->writer->utf16BigEndianTextString('mPDF ' . $this->getVersionString()));
155
+
156
+ if (!empty($this->mpdf->title)) {
157
+ $this->writer->write('/Title ' . $this->writer->utf16BigEndianTextString($this->mpdf->title));
158
+ }
159
+
160
+ if (!empty($this->mpdf->subject)) {
161
+ $this->writer->write('/Subject ' . $this->writer->utf16BigEndianTextString($this->mpdf->subject));
162
+ }
163
+
164
+ if (!empty($this->mpdf->author)) {
165
+ $this->writer->write('/Author ' . $this->writer->utf16BigEndianTextString($this->mpdf->author));
166
+ }
167
+
168
+ if (!empty($this->mpdf->keywords)) {
169
+ $this->writer->write('/Keywords ' . $this->writer->utf16BigEndianTextString($this->mpdf->keywords));
170
+ }
171
+
172
+ if (!empty($this->mpdf->creator)) {
173
+ $this->writer->write('/Creator ' . $this->writer->utf16BigEndianTextString($this->mpdf->creator));
174
+ }
175
+
176
+ foreach ($this->mpdf->customProperties as $key => $value) {
177
+ $this->writer->write('/' . $key . ' ' . $this->writer->utf16BigEndianTextString($value));
178
+ }
179
+
180
+ $z = date('O'); // +0200
181
+ $offset = substr($z, 0, 3) . "'" . substr($z, 3, 2) . "'";
182
+ $this->writer->write('/CreationDate ' . $this->writer->string(date('YmdHis') . $offset));
183
+ $this->writer->write('/ModDate ' . $this->writer->string(date('YmdHis') . $offset));
184
+ if ($this->mpdf->PDFX) {
185
+ $this->writer->write('/Trapped/False');
186
+ $this->writer->write('/GTS_PDFXVersion(PDF/X-1a:2003)');
187
+ }
188
+ }
189
+
190
+ public function writeOutputIntent() // _putoutputintent
191
+ {
192
+ $this->writer->object();
193
+ $this->mpdf->OutputIntentRoot = $this->mpdf->n;
194
+ $this->writer->write('<</Type /OutputIntent');
195
+
196
+ $ICCProfile = str_replace('_', ' ', basename($this->mpdf->ICCProfile, '.icc'));
197
+
198
+ if ($this->mpdf->PDFA) {
199
+ $this->writer->write('/S /GTS_PDFA1');
200
+ if ($this->mpdf->ICCProfile) {
201
+ $this->writer->write('/Info (' . $ICCProfile . ')');
202
+ $this->writer->write('/OutputConditionIdentifier (Custom)');
203
+ $this->writer->write('/OutputCondition ()');
204
+ } else {
205
+ $this->writer->write('/Info (sRGB IEC61966-2.1)');
206
+ $this->writer->write('/OutputConditionIdentifier (sRGB IEC61966-2.1)');
207
+ $this->writer->write('/OutputCondition ()');
208
+ }
209
+ $this->writer->write('/DestOutputProfile ' . ($this->mpdf->n + 1) . ' 0 R');
210
+ } elseif ($this->mpdf->PDFX) { // always a CMYK profile
211
+ $this->writer->write('/S /GTS_PDFX');
212
+ if ($this->mpdf->ICCProfile) {
213
+ $this->writer->write('/Info (' . $ICCProfile . ')');
214
+ $this->writer->write('/OutputConditionIdentifier (Custom)');
215
+ $this->writer->write('/OutputCondition ()');
216
+ $this->writer->write('/DestOutputProfile ' . ($this->mpdf->n + 1) . ' 0 R');
217
+ } else {
218
+ $this->writer->write('/Info (CGATS TR 001)');
219
+ $this->writer->write('/OutputConditionIdentifier (CGATS TR 001)');
220
+ $this->writer->write('/OutputCondition (CGATS TR 001 (SWOP))');
221
+ $this->writer->write('/RegistryName (http://www.color.org)');
222
+ }
223
+ }
224
+ $this->writer->write('>>');
225
+ $this->writer->write('endobj');
226
+
227
+ if ($this->mpdf->PDFX && !$this->mpdf->ICCProfile) {
228
+ return;
229
+ }
230
+
231
+ $this->writer->object();
232
+
233
+ if ($this->mpdf->ICCProfile) {
234
+ if (!file_exists($this->mpdf->ICCProfile)) {
235
+ throw new \Mpdf\MpdfException(sprintf('Unable to find ICC profile "%s"', $this->mpdf->ICCProfile));
236
+ }
237
+ $s = file_get_contents($this->mpdf->ICCProfile);
238
+ } else {
239
+ $s = file_get_contents(__DIR__ . '/../../data/iccprofiles/sRGB_IEC61966-2-1.icc');
240
+ }
241
+
242
+ if ($this->mpdf->compress) {
243
+ $s = gzcompress($s);
244
+ }
245
+
246
+ $this->writer->write('<<');
247
+
248
+ if ($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace === 3)) {
249
+ $this->writer->write('/N 4');
250
+ } else {
251
+ $this->writer->write('/N 3');
252
+ }
253
+
254
+ if ($this->mpdf->compress) {
255
+ $this->writer->write('/Filter /FlateDecode ');
256
+ }
257
+
258
+ $this->writer->write('/Length ' . strlen($s) . '>>');
259
+ $this->writer->stream($s);
260
+ $this->writer->write('endobj');
261
+ }
262
+
263
+ public function writeAssociatedFiles() // _putAssociatedFiles
264
+ {
265
+ if (!function_exists('gzcompress')) {
266
+ throw new \Mpdf\MpdfException('ext-zlib is required for compression of associated files');
267
+ }
268
+
269
+ // for each file, we create the spec object + the stream object
270
+ foreach ($this->mpdf->associatedFiles as $k => $file) {
271
+ // spec
272
+ $this->writer->object();
273
+ $this->mpdf->associatedFiles[$k]['_root'] = $this->mpdf->n; // we store the root ref of object for future reference (e.g. /EmbeddedFiles catalog)
274
+ $this->writer->write('<</F ' . $this->writer->string($file['name']));
275
+ if ($file['description']) {
276
+ $this->writer->write('/Desc ' . $this->writer->string($file['description']));
277
+ }
278
+ $this->writer->write('/Type /Filespec');
279
+ $this->writer->write('/EF <<');
280
+ $this->writer->write('/F ' . ($this->mpdf->n + 1) . ' 0 R');
281
+ $this->writer->write('/UF ' . ($this->mpdf->n + 1) . ' 0 R');
282
+ $this->writer->write('>>');
283
+ if ($file['AFRelationship']) {
284
+ $this->writer->write('/AFRelationship /' . $file['AFRelationship']);
285
+ }
286
+ $this->writer->write('/UF ' . $this->writer->string($file['name']));
287
+ $this->writer->write('>>');
288
+ $this->writer->write('endobj');
289
+
290
+ $fileContent = null;
291
+ if (isset($file['path'])) {
292
+ $fileContent = @file_get_contents($file['path']);
293
+ } elseif (isset($file['content'])) {
294
+ $fileContent = $file['content'];
295
+ }
296
+
297
+ if (!$fileContent) {
298
+ throw new \Mpdf\MpdfException(sprintf('Cannot access associated file - %s', $file['path']));
299
+ }
300
+
301
+ $filestream = gzcompress($fileContent);
302
+ $this->writer->object();
303
+ $this->writer->write('<</Type /EmbeddedFile');
304
+ if ($file['mime']) {
305
+ $this->writer->write('/Subtype /' . $this->writer->escapeSlashes($file['mime']));
306
+ }
307
+ $this->writer->write('/Length '.strlen($filestream));
308
+ $this->writer->write('/Filter /FlateDecode');
309
+ if (isset($file['path'])) {
310
+ $this->writer->write('/Params <</ModDate '.$this->writer->string('D:' . PdfDate::format(filemtime($file['path']))).' >>');
311
+ } else {
312
+ $this->writer->write('/Params <</ModDate '.$this->writer->string('D:' . PdfDate::format(time())).' >>');
313
+ }
314
+
315
+ $this->writer->write('>>');
316
+ $this->writer->stream($filestream);
317
+ $this->writer->write('endobj');
318
+ }
319
+
320
+ // AF array
321
+ $this->writer->object();
322
+ $refs = [];
323
+ foreach ($this->mpdf->associatedFiles as $file) {
324
+ $refs[] = '' . $file['_root'] . ' 0 R';
325
+ }
326
+ $this->writer->write('[' . implode(' ', $refs) . ']');
327
+ $this->writer->write('endobj');
328
+
329
+ $this->mpdf->associatedFilesRoot = $this->mpdf->n;
330
+ }
331
+
332
+ public function writeCatalog() //_putcatalog
333
+ {
334
+ $this->writer->write('/Type /Catalog');
335
+ $this->writer->write('/Pages 1 0 R');
336
+
337
+ if ($this->mpdf->ZoomMode === 'fullpage') {
338
+ $this->writer->write('/OpenAction [3 0 R /Fit]');
339
+ } elseif ($this->mpdf->ZoomMode === 'fullwidth') {
340
+ $this->writer->write('/OpenAction [3 0 R /FitH null]');
341
+ } elseif ($this->mpdf->ZoomMode === 'real') {
342
+ $this->writer->write('/OpenAction [3 0 R /XYZ null null 1]');
343
+ } elseif (!is_string($this->mpdf->ZoomMode)) {
344
+ $this->writer->write('/OpenAction [3 0 R /XYZ null null ' . ($this->mpdf->ZoomMode / 100) . ']');
345
+ } else {
346
+ $this->writer->write('/OpenAction [3 0 R /XYZ null null null]');
347
+ }
348
+
349
+ if ($this->mpdf->LayoutMode === 'single') {
350
+ $this->writer->write('/PageLayout /SinglePage');
351
+ } elseif ($this->mpdf->LayoutMode === 'continuous') {
352
+ $this->writer->write('/PageLayout /OneColumn');
353
+ } elseif ($this->mpdf->LayoutMode === 'twoleft') {
354
+ $this->writer->write('/PageLayout /TwoColumnLeft');
355
+ } elseif ($this->mpdf->LayoutMode === 'tworight') {
356
+ $this->writer->write('/PageLayout /TwoColumnRight');
357
+ } elseif ($this->mpdf->LayoutMode === 'two') {
358
+ if ($this->mpdf->mirrorMargins) {
359
+ $this->writer->write('/PageLayout /TwoColumnRight');
360
+ } else {
361
+ $this->writer->write('/PageLayout /TwoColumnLeft');
362
+ }
363
+ }
364
+
365
+ // Bookmarks
366
+ if (count($this->mpdf->BMoutlines) > 0) {
367
+ $this->writer->write('/Outlines ' . $this->mpdf->OutlineRoot . ' 0 R');
368
+ $this->writer->write('/PageMode /UseOutlines');
369
+ }
370
+
371
+ // Fullscreen
372
+ if (is_int(strpos($this->mpdf->DisplayPreferences, 'FullScreen'))) {
373
+ $this->writer->write('/PageMode /FullScreen');
374
+ }
375
+
376
+ // Metadata
377
+ if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
378
+ $this->writer->write('/Metadata ' . $this->mpdf->MetadataRoot . ' 0 R');
379
+ }
380
+
381
+ // OutputIntents
382
+ if ($this->mpdf->PDFA || $this->mpdf->PDFX || $this->mpdf->ICCProfile) {
383
+ $this->writer->write('/OutputIntents [' . $this->mpdf->OutputIntentRoot . ' 0 R]');
384
+ }
385
+
386
+ // Associated files
387
+ if ($this->mpdf->associatedFilesRoot) {
388
+ $this->writer->write('/AF '. $this->mpdf->associatedFilesRoot .' 0 R');
389
+
390
+ $names = [];
391
+ foreach ($this->mpdf->associatedFiles as $file) {
392
+ $names[] = $this->writer->string($file['name']) . ' ' . $file['_root'] . ' 0 R';
393
+ }
394
+ $this->writer->write('/Names << /EmbeddedFiles << /Names [' . implode(' ', $names) . '] >> >>');
395
+ }
396
+
397
+ // Forms
398
+ if (count($this->form->forms) > 0) {
399
+ $this->form->_putFormsCatalog();
400
+ }
401
+
402
+ if ($this->mpdf->js !== null) {
403
+ $this->writer->write('/Names << /JavaScript ' . $this->mpdf->n_js . ' 0 R >> ');
404
+ }
405
+
406
+ if ($this->mpdf->DisplayPreferences || $this->mpdf->directionality === 'rtl' || $this->mpdf->mirrorMargins) {
407
+
408
+ $this->writer->write('/ViewerPreferences<<');
409
+
410
+ if (is_int(strpos($this->mpdf->DisplayPreferences, 'HideMenubar'))) {
411
+ $this->writer->write('/HideMenubar true');
412
+ }
413
+
414
+ if (is_int(strpos($this->mpdf->DisplayPreferences, 'HideToolbar'))) {
415
+ $this->writer->write('/HideToolbar true');
416
+ }
417
+
418
+ if (is_int(strpos($this->mpdf->DisplayPreferences, 'HideWindowUI'))) {
419
+ $this->writer->write('/HideWindowUI true');
420
+ }
421
+
422
+ if (is_int(strpos($this->mpdf->DisplayPreferences, 'DisplayDocTitle'))) {
423
+ $this->writer->write('/DisplayDocTitle true');
424
+ }
425
+
426
+ if (is_int(strpos($this->mpdf->DisplayPreferences, 'CenterWindow'))) {
427
+ $this->writer->write('/CenterWindow true');
428
+ }
429
+
430
+ if (is_int(strpos($this->mpdf->DisplayPreferences, 'FitWindow'))) {
431
+ $this->writer->write('/FitWindow true');
432
+ }
433
+
434
+ // PrintScaling is PDF 1.6 spec.
435
+ if (!$this->mpdf->PDFA && !$this->mpdf->PDFX && is_int(strpos($this->mpdf->DisplayPreferences, 'NoPrintScaling'))) {
436
+ $this->writer->write('/PrintScaling /None');
437
+ }
438
+
439
+ if ($this->mpdf->directionality === 'rtl') {
440
+ $this->writer->write('/Direction /R2L');
441
+ }
442
+
443
+ // Duplex is PDF 1.7 spec.
444
+ if ($this->mpdf->mirrorMargins && !$this->mpdf->PDFA && !$this->mpdf->PDFX) {
445
+ // if ($this->mpdf->DefOrientation=='P') $this->writer->write('/Duplex /DuplexFlipShortEdge');
446
+ $this->writer->write('/Duplex /DuplexFlipLongEdge'); // PDF v1.7+
447
+ }
448
+
449
+ $this->writer->write('>>');
450
+ }
451
+
452
+ if ($this->mpdf->open_layer_pane && ($this->mpdf->hasOC || count($this->mpdf->layers))) {
453
+ $this->writer->write('/PageMode /UseOC');
454
+ }
455
+
456
+ if ($this->mpdf->hasOC || count($this->mpdf->layers)) {
457
+ $p = $v = $h = $l = $loff = $lall = $as = '';
458
+ if ($this->mpdf->hasOC) {
459
+ if (($this->mpdf->hasOC & 1) === 1) {
460
+ $p = $this->mpdf->n_ocg_print . ' 0 R';
461
+ }
462
+ if (($this->mpdf->hasOC & 2) === 2) {
463
+ $v = $this->mpdf->n_ocg_view . ' 0 R';
464
+ }
465
+ if (($this->mpdf->hasOC & 4) === 4) {
466
+ $h = $this->mpdf->n_ocg_hidden . ' 0 R';
467
+ }
468
+ $as = "<</Event /Print /OCGs [$p $v $h] /Category [/Print]>> <</Event /View /OCGs [$p $v $h] /Category [/View]>>";
469
+ }
470
+
471
+ if (count($this->mpdf->layers)) {
472
+ foreach ($this->mpdf->layers as $k => $layer) {
473
+ if (strtolower($this->mpdf->layerDetails[$k]['state']) === 'hidden') {
474
+ $loff .= $layer['n'] . ' 0 R ';
475
+ } else {
476
+ $l .= $layer['n'] . ' 0 R ';
477
+ }
478
+ $lall .= $layer['n'] . ' 0 R ';
479
+ }
480
+ }
481
+ $this->writer->write("/OCProperties <</OCGs [$p $v $h $lall] /D <</ON [$p $l] /OFF [$v $h $loff] ");
482
+ $this->writer->write("/Order [$v $p $h $lall] ");
483
+ if ($as) {
484
+ $this->writer->write("/AS [$as] ");
485
+ }
486
+ $this->writer->write('>>>>');
487
+ }
488
+ }
489
+
490
+ /**
491
+ * @since 5.7.2
492
+ */
493
+ public function writeAnnotations() // _putannots
494
+ {
495
+ $nb = $this->mpdf->page;
496
+
497
+ for ($n = 1; $n <= $nb; $n++) {
498
+
499
+ if (isset($this->mpdf->PageLinks[$n]) || isset($this->mpdf->PageAnnots[$n]) || count($this->form->forms) > 0) {
500
+
501
+ $wPt = $this->mpdf->pageDim[$n]['w'] * Mpdf::SCALE;
502
+ $hPt = $this->mpdf->pageDim[$n]['h'] * Mpdf::SCALE;
503
+
504
+ // Links
505
+ if (isset($this->mpdf->PageLinks[$n])) {
506
+
507
+ foreach ($this->mpdf->PageLinks[$n] as $key => $pl) {
508
+
509
+ $this->writer->object();
510
+ $annot = '';
511
+
512
+ $rect = sprintf('%.3F %.3F %.3F %.3F', $pl[0], $pl[1], $pl[0] + $pl[2], $pl[1] - $pl[3]);
513
+
514
+ $annot .= '<</Type /Annot /Subtype /Link /Rect [' . $rect . ']';
515
+ // Removed as causing undesired effects in Chrome PDF viewer https://github.com/mpdf/mpdf/issues/283
516
+ // $annot .= ' /Contents ' . $this->writer->utf16BigEndianTextString($pl[4]);
517
+ $annot .= ' /NM ' . $this->writer->string(sprintf('%04u-%04u', $n, $key));
518
+ $annot .= ' /M ' . $this->writer->string('D:' . date('YmdHis'));
519
+
520
+ $annot .= ' /Border [0 0 0]';
521
+
522
+ // Use this (instead of /Border) to specify border around link
523
+
524
+ // $annot .= ' /BS <</W 1'; // Width on points; 0 = no line
525
+ // $annot .= ' /S /D'; // style - [S]olid, [D]ashed, [B]eveled, [I]nset, [U]nderline
526
+ // $annot .= ' /D [3 2]'; // Dash array - if dashed
527
+ // $annot .= ' >>';
528
+ // $annot .= ' /C [1 0 0]'; // Color RGB
529
+
530
+ if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
531
+ $annot .= ' /F 28';
532
+ }
533
+
534
+ if (strpos($pl[4], '@') === 0) {
535
+
536
+ $p = substr($pl[4], 1);
537
+ // $h=isset($this->mpdf->OrientationChanges[$p]) ? $wPt : $hPt;
538
+ $htarg = $this->mpdf->pageDim[$p]['h'] * Mpdf::SCALE;
539
+ $annot .= sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>', 1 + 2 * $p, $htarg);
540
+
541
+ } elseif (is_string($pl[4])) {
542
+
543
+ $annot .= ' /A <</S /URI /URI ' . $this->writer->string($pl[4]) . '>> >>';
544
+
545
+ } else {
546
+
547
+ $l = $this->mpdf->links[$pl[4]];
548
+ // may not be set if #link points to non-existent target
549
+ if (isset($this->mpdf->pageDim[$l[0]]['h'])) {
550
+ $htarg = $this->mpdf->pageDim[$l[0]]['h'] * Mpdf::SCALE;
551
+ } else {
552
+ $htarg = $this->mpdf->h * Mpdf::SCALE;
553
+ } // doesn't really matter
554
+
555
+ $annot .= sprintf(' /Dest [%d 0 R /XYZ 0 %.3F null]>>', 1 + 2 * $l[0], $htarg - $l[1] * Mpdf::SCALE);
556
+ }
557
+
558
+ $this->writer->write($annot);
559
+ $this->writer->write('endobj');
560
+
561
+ }
562
+ }
563
+
564
+ /* -- ANNOTATIONS -- */
565
+ if (isset($this->mpdf->PageAnnots[$n])) {
566
+
567
+ foreach ($this->mpdf->PageAnnots[$n] as $key => $pl) {
568
+
569
+ $fileAttachment = (bool) $pl['opt']['file'];
570
+
571
+ if ($fileAttachment && !$this->mpdf->allowAnnotationFiles) {
572
+ $this->logger->warning('Embedded files for annotations have to be allowed explicitly with "allowAnnotationFiles" config key');
573
+ $fileAttachment = false;
574
+ }
575
+
576
+ $this->writer->object();
577
+
578
+ $annot = '';
579
+ $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER);
580
+ $x = $pl['x'];
581
+
582
+ if ($this->mpdf->annotMargin != 0 || $x == 0 || $x < 0) { // Odd page, intentional non-strict comparison
583
+ $x = ($wPt / Mpdf::SCALE) - $this->mpdf->annotMargin;
584
+ }
585
+
586
+ $w = $h = 0;
587
+ $a = $x * Mpdf::SCALE;
588
+ $b = $hPt - ($pl['y'] * Mpdf::SCALE);
589
+
590
+ $annot .= '<</Type /Annot ';
591
+
592
+ if ($fileAttachment) {
593
+ $annot .= '/Subtype /FileAttachment ';
594
+ // Need to set a size for FileAttachment icons
595
+ if ($pl['opt']['icon'] === 'Paperclip') {
596
+ $w = 8.235;
597
+ $h = 20;
598
+ } elseif ($pl['opt']['icon'] === 'Tag') {
599
+ $w = 20;
600
+ $h = 16;
601
+ } elseif ($pl['opt']['icon'] === 'Graph') {
602
+ $w = 20;
603
+ $h = 20;
604
+ } else {
605
+ $w = 14;
606
+ $h = 20;
607
+ }
608
+
609
+ // PushPin
610
+ $f = $pl['opt']['file'];
611
+ $f = preg_replace('/^.*\//', '', $f);
612
+ $f = preg_replace('/[^a-zA-Z0-9._]/', '', $f);
613
+
614
+ $annot .= '/FS <</Type /Filespec /F (' . $f . ')';
615
+ $annot .= '/EF <</F ' . ($this->mpdf->n + 1) . ' 0 R>>';
616
+ $annot .= '>>';
617
+
618
+ } else {
619
+ $annot .= '/Subtype /Text';
620
+ $w = 20;
621
+ $h = 20; // mPDF 6
622
+ }
623
+
624
+ $rect = sprintf('%.3F %.3F %.3F %.3F', $a, $b - $h, $a + $w, $b);
625
+ $annot .= ' /Rect [' . $rect . ']';
626
+
627
+ // contents = description of file in free text
628
+ $annot .= ' /Contents ' . $this->writer->utf16BigEndianTextString($pl['txt']);
629
+
630
+ $annot .= ' /NM ' . $this->writer->string(sprintf('%04u-%04u', $n, 2000 + $key));
631
+ $annot .= ' /M ' . $this->writer->string('D:' . date('YmdHis'));
632
+ $annot .= ' /CreationDate ' . $this->writer->string('D:' . date('YmdHis'));
633
+ $annot .= ' /Border [0 0 0]';
634
+
635
+ if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
636
+ $annot .= ' /F 28';
637
+ $annot .= ' /CA 1';
638
+ } elseif ($pl['opt']['ca'] > 0) {
639
+ $annot .= ' /CA ' . $pl['opt']['ca'];
640
+ }
641
+
642
+ $annotcolor = ' /C [';
643
+ if (isset($pl['opt']['c']) && $pl['opt']['c']) {
644
+ $col = $pl['opt']['c'];
645
+ if ($col{0} == 3 || $col{0} == 5) {
646
+ $annotcolor .= sprintf('%.3F %.3F %.3F', ord($col{1}) / 255, ord($col{2}) / 255, ord($col{3}) / 255);
647
+ } elseif ($col{0} == 1) {
648
+ $annotcolor .= sprintf('%.3F', ord($col{1}) / 255);
649
+ } elseif ($col{0} == 4 || $col{0} == 6) {
650
+ $annotcolor .= sprintf('%.3F %.3F %.3F %.3F', ord($col{1}) / 100, ord($col{2}) / 100, ord($col{3}) / 100, ord($col{4}) / 100);
651
+ } else {
652
+ $annotcolor .= '1 1 0';
653
+ }
654
+ } else {
655
+ $annotcolor .= '1 1 0';
656
+ }
657
+ $annotcolor .= ']';
658
+ $annot .= $annotcolor;
659
+
660
+ // Usually Author
661
+ // Use as Title for fileattachment
662
+ if (isset($pl['opt']['t']) && is_string($pl['opt']['t'])) {
663
+ $annot .= ' /T ' . $this->writer->utf16BigEndianTextString($pl['opt']['t']);
664
+ }
665
+
666
+ if ($fileAttachment) {
667
+ $iconsapp = ['Paperclip', 'Graph', 'PushPin', 'Tag'];
668
+ } else {
669
+ $iconsapp = ['Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph'];
670
+ }
671
+
672
+ if (isset($pl['opt']['icon']) && in_array($pl['opt']['icon'], $iconsapp)) {
673
+ $annot .= ' /Name /' . $pl['opt']['icon'];
674
+ } elseif ($fileAttachment) {
675
+ $annot .= ' /Name /PushPin';
676
+ } else {
677
+ $annot .= ' /Name /Note';
678
+ }
679
+
680
+ if (!$fileAttachment) {
681
+ // Subj is PDF 1.5 spec.
682
+ if (!$this->mpdf->PDFA && !$this->mpdf->PDFX && isset($pl['opt']['subj'])) {
683
+ $annot .= ' /Subj ' . $this->writer->utf16BigEndianTextString($pl['opt']['subj']);
684
+ }
685
+ if (!empty($pl['opt']['popup'])) {
686
+ $annot .= ' /Open true';
687
+ $annot .= ' /Popup ' . ($this->mpdf->n + 1) . ' 0 R';
688
+ } else {
689
+ $annot .= ' /Open false';
690
+ }
691
+ }
692
+
693
+ $annot .= ' /P ' . $pl['pageobj'] . ' 0 R';
694
+ $annot .= '>>';
695
+ $this->writer->write($annot);
696
+ $this->writer->write('endobj');
697
+
698
+ if ($fileAttachment) {
699
+
700
+ $file = @file_get_contents($pl['opt']['file']);
701
+ if (!$file) {
702
+ throw new \Mpdf\MpdfException('mPDF Error: Cannot access file attachment - ' . $pl['opt']['file']);
703
+ }
704
+
705
+ $filestream = gzcompress($file);
706
+ $this->writer->object();
707
+ $this->writer->write('<</Type /EmbeddedFile');
708
+ $this->writer->write('/Length ' . strlen($filestream));
709
+ $this->writer->write('/Filter /FlateDecode');
710
+ $this->writer->write('>>');
711
+ $this->writer->stream($filestream);
712
+ $this->writer->write('endobj');
713
+
714
+ } elseif (!empty($pl['opt']['popup'])) {
715
+ $this->writer->object();
716
+ $annot = '';
717
+ if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][0])) {
718
+ $x = $pl['opt']['popup'][0] * Mpdf::SCALE;
719
+ } else {
720
+ $x = $pl['x'] * Mpdf::SCALE;
721
+ }
722
+ if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][1])) {
723
+ $y = $hPt - ($pl['opt']['popup'][1] * Mpdf::SCALE);
724
+ } else {
725
+ $y = $hPt - ($pl['y'] * Mpdf::SCALE);
726
+ }
727
+ if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][2])) {
728
+ $w = $pl['opt']['popup'][2] * Mpdf::SCALE;
729
+ } else {
730
+ $w = 180;
731
+ }
732
+ if (is_array($pl['opt']['popup']) && isset($pl['opt']['popup'][3])) {
733
+ $h = $pl['opt']['popup'][3] * Mpdf::SCALE;
734
+ } else {
735
+ $h = 120;
736
+ }
737
+ $rect = sprintf('%.3F %.3F %.3F %.3F', $x, $y - $h, $x + $w, $y);
738
+ $annot .= '<</Type /Annot /Subtype /Popup /Rect [' . $rect . ']';
739
+ $annot .= ' /M ' . $this->writer->string('D:' . date('YmdHis'));
740
+ if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
741
+ $annot .= ' /F 28';
742
+ }
743
+ $annot .= ' /Parent ' . ($this->mpdf->n - 1) . ' 0 R';
744
+ $annot .= '>>';
745
+ $this->writer->write($annot);
746
+ $this->writer->write('endobj');
747
+ }
748
+ }
749
+ }
750
+
751
+ // Active Forms
752
+ if (count($this->form->forms) > 0) {
753
+ $this->form->_putFormItems($n, $hPt);
754
+ }
755
+ }
756
+ }
757
+
758
+ // Active Forms - Radio Button Group entries
759
+ // Output Radio Button Group form entries (radio_on_obj_id already determined)
760
+ if (count($this->form->form_radio_groups)) {
761
+ $this->form->_putRadioItems($n);
762
+ }
763
+ }
764
+
765
+ public function writeEncryption() // _putencryption
766
+ {
767
+ $this->writer->write('/Filter /Standard');
768
+ if ($this->protection->getUseRC128Encryption()) {
769
+ $this->writer->write('/V 2');
770
+ $this->writer->write('/R 3');
771
+ $this->writer->write('/Length 128');
772
+ } else {
773
+ $this->writer->write('/V 1');
774
+ $this->writer->write('/R 2');
775
+ }
776
+ $this->writer->write('/O (' . $this->writer->escape($this->protection->getOValue()) . ')');
777
+ $this->writer->write('/U (' . $this->writer->escape($this->protection->getUValue()) . ')');
778
+ $this->writer->write('/P ' . $this->protection->getPValue());
779
+ }
780
+
781
+ public function writeTrailer() // _puttrailer
782
+ {
783
+ $this->writer->write('/Size ' . ($this->mpdf->n + 1));
784
+ $this->writer->write('/Root ' . $this->mpdf->n . ' 0 R');
785
+ $this->writer->write('/Info ' . $this->mpdf->InfoRoot . ' 0 R');
786
+
787
+ if ($this->mpdf->encrypted) {
788
+ $this->writer->write('/Encrypt ' . $this->mpdf->enc_obj_id . ' 0 R');
789
+ $this->writer->write('/ID [<' . $this->protection->getUniqid() . '> <' . $this->protection->getUniqid() . '>]');
790
+ } else {
791
+ $uniqid = md5(time() . $this->mpdf->buffer);
792
+ $this->writer->write('/ID [<' . $uniqid . '> <' . $uniqid . '>]');
793
+ }
794
+ }
795
+
796
+ pu