PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.3.4
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.3.4
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 2.1.15 2.1.16 2.1.2 All 57 releases
easy-invoice / includes / Shortcodes / ShortcodeManager.php

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

198 lines 7.9 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 $text = !empty($atts['text']) ? $atts['text'] : $invoice->getNumber();
72 $class = esc_attr($atts['class']);
73 $target = esc_attr($atts['target']);
74
75 return sprintf(
76 '<a href="%s" class="%s" target="%s">%s</a>',
77 esc_url($url),
78 $class,
79 $target,
80 esc_html($text)
81 );
82 }
83
84 /**
85 * Render quote URL shortcode
86 *
87 * @param array $atts Shortcode attributes
88 * @return string Rendered shortcode
89 */
90 public function renderQuoteUrl($atts) {
91 $atts = shortcode_atts([
92 'id' => 0,
93 'number' => '',
94 'text' => '',
95 'class' => 'easy-quote-url',
96 'target' => '_blank'
97 ], $atts, 'easy_quote_url');
98
99 // Get quote by ID or number
100 $quote = null;
101 if (!empty($atts['id'])) {
102 $quote = \EasyInvoice\Providers\QuoteServiceProvider::getQuoteRepository()->find($atts['id']);
103 } elseif (!empty($atts['number'])) {
104 $quote = \EasyInvoice\Providers\QuoteServiceProvider::getQuoteRepository()->findByNumber($atts['number']);
105 }
106
107 if (!$quote) {
108 return '<span class="easy-invoice-error">' . __('Quote not found', 'easy-invoice') . '</span>';
109 }
110
111 $url = get_permalink($quote->getId());
112 $secure_links_enabled = get_option('easy_invoice_pro_enable_secure_links', 'no') === 'yes';
113 if ($secure_links_enabled && class_exists('\EasyInvoicePro\Addons\SecureLinks\Controllers\PermalinkController')) {
114 $secure_url = \EasyInvoicePro\Addons\SecureLinks\Controllers\PermalinkController::getQuoteSecureLinkUrl($quote->getId());
115 if ($secure_url) {
116 $url = $secure_url;
117 }
118 }
119
120 // SECURITY (CVE-2026-9021): attach per-quote access token so any
121 // recipient of this URL can render the Accept/Decline UI on the
122 // public single-quote page. See EmailManager::getQuoteReplacements
123 // for full rationale.
124 $quote_access_token = \EasyInvoice\Controllers\QuoteController::quoteAccessToken((int) $quote->getId());
125 if ($quote_access_token !== '' && $url) {
126 $url = add_query_arg('qk', $quote_access_token, $url);
127 }
128
129 $text = !empty($atts['text']) ? $atts['text'] : $quote->getNumber();
130 $class = esc_attr($atts['class']);
131 $target = esc_attr($atts['target']);
132
133 return sprintf(
134 '<a href="%s" class="%s" target="%s">%s</a>',
135 esc_url($url),
136 $class,
137 $target,
138 esc_html($text)
139 );
140 }
141
142 /**
143 * Add shortcode help to the help tab
144 */
145 public function addShortcodeHelp() {
146 $screen = get_current_screen();
147
148 if ($screen && ($screen->id === 'easy-invoice_page_easy-invoice-settings' || $screen->id === 'edit-easy_invoice')) {
149 $screen->add_help_tab([
150 'id' => 'easy-invoice-shortcodes',
151 'title' => __('Shortcodes', 'easy-invoice'),
152 'content' => $this->getShortcodeHelpContent()
153 ]);
154 }
155 }
156
157 /**
158 * Get shortcode help content
159 *
160 * @return string Help content
161 */
162 private function getShortcodeHelpContent() {
163 $content = '<h2>' . __('Available Shortcodes', 'easy-invoice') . '</h2>';
164
165 $content .= '<h3><code>[easy_invoice_url]</code></h3>';
166 $content .= '<p>' . __('Displays a link to an invoice.', 'easy-invoice') . '</p>';
167 $content .= '<h4>' . __('Attributes:', 'easy-invoice') . '</h4>';
168 $content .= '<ul>';
169 $content .= '<li><code>id</code> - ' . __('Invoice ID (required if number is not provided)', 'easy-invoice') . '</li>';
170 $content .= '<li><code>number</code> - ' . __('Invoice number (required if id is not provided)', 'easy-invoice') . '</li>';
171 $content .= '<li><code>text</code> - ' . __('Link text (default: invoice number)', 'easy-invoice') . '</li>';
172 $content .= '<li><code>class</code> - ' . __('CSS class for the link (default: easy-invoice-url)', 'easy-invoice') . '</li>';
173 $content .= '<li><code>target</code> - ' . __('Link target (default: _blank)', 'easy-invoice') . '</li>';
174 $content .= '</ul>';
175 $content .= '<h4>' . __('Examples:', 'easy-invoice') . '</h4>';
176 $content .= '<pre><code>[easy_invoice_url id="123" text="View Invoice"]</code></pre>';
177 $content .= '<pre><code>[easy_invoice_url number="INV-001" text="Click here to view"]</code></pre>';
178
179 $content .= '<hr>';
180
181 $content .= '<h3><code>[easy_quote_url]</code></h3>';
182 $content .= '<p>' . __('Displays a link to a quote.', 'easy-invoice') . '</p>';
183 $content .= '<h4>' . __('Attributes:', 'easy-invoice') . '</h4>';
184 $content .= '<ul>';
185 $content .= '<li><code>id</code> - ' . __('Quote ID (required if number is not provided)', 'easy-invoice') . '</li>';
186 $content .= '<li><code>number</code> - ' . __('Quote number (required if id is not provided)', 'easy-invoice') . '</li>';
187 $content .= '<li><code>text</code> - ' . __('Link text (default: quote number)', 'easy-invoice') . '</li>';
188 $content .= '<li><code>class</code> - ' . __('CSS class for the link (default: easy-quote-url)', 'easy-invoice') . '</li>';
189 $content .= '<li><code>target</code> - ' . __('Link target (default: _blank)', 'easy-invoice') . '</li>';
190 $content .= '</ul>';
191 $content .= '<h4>' . __('Examples:', 'easy-invoice') . '</h4>';
192 $content .= '<pre><code>[easy_quote_url id="456" text="View Quote"]</code></pre>';
193 $content .= '<pre><code>[easy_quote_url number="QT-001" text="Click here to view"]</code></pre>';
194
195 return $content;
196 }
197 }
198