PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.3.5
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.3.5
2.4.3 2.4.4 2.4.2 2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 All 60 releases
easy-invoice / includes / Shortcodes / ShortcodeManager.php

ShortcodeManager.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.3.5, at includes/Shortcodes/ShortcodeManager.php

208 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Shortcode Manager for Easy Invoice Free
4 *
5 * Manages shortcodes for invoice and quote URLs
6 *
7 * @package EasyInvoice
8 * @subpackage Shortcodes
9 * @since 2.0.0
10 */
11
12 namespace EasyInvoice\Shortcodes;
13
14 if (!defined('ABSPATH')) {
15 exit;
16 }
17
18 /**
19 * ShortcodeManager Class
20 */
21 class ShortcodeManager {
22
23 /**
24 * Constructor
25 */
26 public function __construct() {
27 // Register shortcodes
28 add_shortcode('easy_invoice_url', [$this, 'renderInvoiceUrl']);
29 add_shortcode('easy_quote_url', [$this, 'renderQuoteUrl']);
30
31 // Add shortcode info to help tab
32 add_action('admin_head', [$this, 'addShortcodeHelp']);
33 }
34
35 /**
36 * Render invoice URL shortcode
37 *
38 * @param array $atts Shortcode attributes
39 * @return string Rendered shortcode
40 */
41 public function renderInvoiceUrl($atts) {
42 $atts = shortcode_atts([
43 'id' => 0,
44 'number' => '',
45 'text' => '',
46 'class' => 'easy-invoice-url',
47 'target' => '_blank'
48 ], $atts, 'easy_invoice_url');
49
50 // Get invoice by ID or number
51 $invoice = null;
52 if (!empty($atts['id'])) {
53 $invoice = \EasyInvoice\Providers\InvoiceServiceProvider::getInvoiceRepository()->find($atts['id']);
54 } elseif (!empty($atts['number'])) {
55 $invoice = \EasyInvoice\Providers\InvoiceServiceProvider::getInvoiceRepository()->findByNumber($atts['number']);
56 }
57
58 if (!$invoice) {
59 return '<span class="easy-invoice-error">' . __('Invoice not found', 'easy-invoice') . '</span>';
60 }
61
62 $url = get_permalink($invoice->getId());
63 // Only use secure link if enabled in settings and available
64 $secure_links_enabled = get_option('easy_invoice_pro_enable_secure_links', 'no') === 'yes';
65 if ($secure_links_enabled && class_exists('\EasyInvoicePro\Addons\SecureLinks\Controllers\PermalinkController')) {
66 $secure_url = \EasyInvoicePro\Addons\SecureLinks\Controllers\PermalinkController::getInvoiceSecureLinkUrl($invoice->getId());
67 if ($secure_url) {
68 $url = $secure_url;
69 }
70 }
71
72 // SECURITY: attach a per-invoice access token so recipients of
73 // this shortcode-rendered URL can submit manual payments. See
74 // EmailManager::getInvoiceReplacements for full rationale and
75 // PaymentController::submitManualPayment for the gate.
76 $invoice_access_token = \EasyInvoice\Controllers\InvoiceController::invoiceAccessToken((int) $invoice->getId());
77 if ($invoice_access_token !== '' && $url) {
78 $url = add_query_arg('ik', $invoice_access_token, $url);
79 }
80
81 $text = !empty($atts['text']) ? $atts['text'] : $invoice->getNumber();
82 $class = esc_attr($atts['class']);
83 $target = esc_attr($atts['target']);
84
85 return sprintf(
86 '<a href="%s" class="%s" target="%s">%s</a>',
87 esc_url($url),
88 $class,
89 $target,
90 esc_html($text)
91 );
92 }
93
94 /**
95 * Render quote URL shortcode
96 *
97 * @param array $atts Shortcode attributes
98 * @return string Rendered shortcode
99 */
100 public function renderQuoteUrl($atts) {
101 $atts = shortcode_atts([
102 'id' => 0,
103 'number' => '',
104 'text' => '',
105 'class' => 'easy-quote-url',
106 'target' => '_blank'
107 ], $atts, 'easy_quote_url');
108
109 // Get quote by ID or number
110 $quote = null;
111 if (!empty($atts['id'])) {
112 $quote = \EasyInvoice\Providers\QuoteServiceProvider::getQuoteRepository()->find($atts['id']);
113 } elseif (!empty($atts['number'])) {
114 $quote = \EasyInvoice\Providers\QuoteServiceProvider::getQuoteRepository()->findByNumber($atts['number']);
115 }
116
117 if (!$quote) {
118 return '<span class="easy-invoice-error">' . __('Quote not found', 'easy-invoice') . '</span>';
119 }
120
121 $url = get_permalink($quote->getId());
122 $secure_links_enabled = get_option('easy_invoice_pro_enable_secure_links', 'no') === 'yes';
123 if ($secure_links_enabled && class_exists('\EasyInvoicePro\Addons\SecureLinks\Controllers\PermalinkController')) {
124 $secure_url = \EasyInvoicePro\Addons\SecureLinks\Controllers\PermalinkController::getQuoteSecureLinkUrl($quote->getId());
125 if ($secure_url) {
126 $url = $secure_url;
127 }
128 }
129
130 // SECURITY (CVE-2026-9021): attach per-quote access token so any
131 // recipient of this URL can render the Accept/Decline UI on the
132 // public single-quote page. See EmailManager::getQuoteReplacements
133 // for full rationale.
134 $quote_access_token = \EasyInvoice\Controllers\QuoteController::quoteAccessToken((int) $quote->getId());
135 if ($quote_access_token !== '' && $url) {
136 $url = add_query_arg('qk', $quote_access_token, $url);
137 }
138
139 $text = !empty($atts['text']) ? $atts['text'] : $quote->getNumber();
140 $class = esc_attr($atts['class']);
141 $target = esc_attr($atts['target']);
142
143 return sprintf(
144 '<a href="%s" class="%s" target="%s">%s</a>',
145 esc_url($url),
146 $class,
147 $target,
148 esc_html($text)
149 );
150 }
151
152 /**
153 * Add shortcode help to the help tab
154 */
155 public function addShortcodeHelp() {
156 $screen = get_current_screen();
157
158 if ($screen && ($screen->id === 'easy-invoice_page_easy-invoice-settings' || $screen->id === 'edit-easy_invoice')) {
159 $screen->add_help_tab([
160 'id' => 'easy-invoice-shortcodes',
161 'title' => __('Shortcodes', 'easy-invoice'),
162 'content' => $this->getShortcodeHelpContent()
163 ]);
164 }
165 }
166
167 /**
168 * Get shortcode help content
169 *
170 * @return string Help content
171 */
172 private function getShortcodeHelpContent() {
173 $content = '<h2>' . __('Available Shortcodes', 'easy-invoice') . '</h2>';
174
175 $content .= '<h3><code>[easy_invoice_url]</code></h3>';
176 $content .= '<p>' . __('Displays a link to an invoice.', 'easy-invoice') . '</p>';
177 $content .= '<h4>' . __('Attributes:', 'easy-invoice') . '</h4>';
178 $content .= '<ul>';
179 $content .= '<li><code>id</code> - ' . __('Invoice ID (required if number is not provided)', 'easy-invoice') . '</li>';
180 $content .= '<li><code>number</code> - ' . __('Invoice number (required if id is not provided)', 'easy-invoice') . '</li>';
181 $content .= '<li><code>text</code> - ' . __('Link text (default: invoice number)', 'easy-invoice') . '</li>';
182 $content .= '<li><code>class</code> - ' . __('CSS class for the link (default: easy-invoice-url)', 'easy-invoice') . '</li>';
183 $content .= '<li><code>target</code> - ' . __('Link target (default: _blank)', 'easy-invoice') . '</li>';
184 $content .= '</ul>';
185 $content .= '<h4>' . __('Examples:', 'easy-invoice') . '</h4>';
186 $content .= '<pre><code>[easy_invoice_url id="123" text="View Invoice"]</code></pre>';
187 $content .= '<pre><code>[easy_invoice_url number="INV-001" text="Click here to view"]</code></pre>';
188
189 $content .= '<hr>';
190
191 $content .= '<h3><code>[easy_quote_url]</code></h3>';
192 $content .= '<p>' . __('Displays a link to a quote.', 'easy-invoice') . '</p>';
193 $content .= '<h4>' . __('Attributes:', 'easy-invoice') . '</h4>';
194 $content .= '<ul>';
195 $content .= '<li><code>id</code> - ' . __('Quote ID (required if number is not provided)', 'easy-invoice') . '</li>';
196 $content .= '<li><code>number</code> - ' . __('Quote number (required if id is not provided)', 'easy-invoice') . '</li>';
197 $content .= '<li><code>text</code> - ' . __('Link text (default: quote number)', 'easy-invoice') . '</li>';
198 $content .= '<li><code>class</code> - ' . __('CSS class for the link (default: easy-quote-url)', 'easy-invoice') . '</li>';
199 $content .= '<li><code>target</code> - ' . __('Link target (default: _blank)', 'easy-invoice') . '</li>';
200 $content .= '</ul>';
201 $content .= '<h4>' . __('Examples:', 'easy-invoice') . '</h4>';
202 $content .= '<pre><code>[easy_quote_url id="456" text="View Quote"]</code></pre>';
203 $content .= '<pre><code>[easy_quote_url number="QT-001" text="Click here to view"]</code></pre>';
204
205 return $content;
206 }
207 }
208