PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.0
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 / Controllers / ClientController.php

ClientController.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.4.0, at includes/Controllers/ClientController.php

309 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Client Controller Class
4 *
5 * @package Easy_Invoice
6 * @subpackage Controllers
7 */
8
9 namespace EasyInvoice\Controllers;
10
11 use EasyInvoice\Providers\ClientServiceProvider;
12 use EasyInvoice\Providers\InvoiceServiceProvider;
13 use EasyInvoice\Providers\QuoteServiceProvider;
14 use EasyInvoice\Constants\PagesSlugs;
15
16 /**
17 * ClientController handles all client-related functionality
18 */
19 class ClientController extends BaseController {
20 /**
21 * Initialize the controller
22 */
23 public function init() {
24 // The `easy_invoice_delete_client` AJAX is owned by EasyInvoiceAjax, the
25 // same convention already used for `easy_invoice_search_clients` (see the
26 // tombstone in QuoteController::init). The duplicate registration that used
27 // to live here raced with EasyInvoiceAjax::deleteClient(): both handlers ran
28 // on one request and whichever replied first ended it, so which
29 // implementation won depended on bootstrap order.
30 //
31 // EasyInvoiceAjax::deleteClient() is the one to keep — it checks the
32 // `ei_manage_clients` capability, refuses to delete administrator accounts,
33 // and cleans up the client's invoices, quotes, and payments. The version
34 // below (::deleteClient) did none of that. Keep this tombstone so the
35 // registration doesn't get added back.
36 }
37
38 /**
39 * Display method implementation
40 *
41 * @param array $args Display arguments
42 */
43 public function display(array $args = []) {
44 $page = isset($args['page']) ? $args['page'] : '';
45
46 switch ($page) {
47 case PagesSlugs::CLIENTS:
48 $this->displayClientsPage();
49 break;
50
51 case PagesSlugs::CLIENT_EDIT:
52 $this->displayClientEditPage();
53 break;
54
55 case PagesSlugs::CLIENT_VIEW:
56 $this->displayClientViewPage();
57 break;
58
59 default:
60 $this->displayClientsPage();
61 break;
62 }
63 }
64
65 /**
66 * Display clients page
67 */
68 protected function displayClientsPage() {
69 // Pagination settings
70 $per_page = 20;
71 $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
72
73 // Get repository
74 $repository = ClientServiceProvider::getClientRepository();
75
76 // Get all clients first to calculate total
77 $all_clients = $repository->all();
78 $total_clients = count($all_clients);
79 $total_pages = ceil($total_clients / $per_page);
80
81 // Get paginated clients
82 $offset = ($current_page - 1) * $per_page;
83 $clients = array_slice($all_clients, $offset, $per_page);
84
85 // Initialize stats
86 $stats = [
87 'total_clients' => $total_clients,
88 'total_invoices' => 0,
89 'total_revenue' => [],
90 'pending_invoices' => 0
91 ];
92
93 // Calculate total revenue from all clients' invoices
94 // Revenue and counts from SQL over the persisted totals; this used to load
95 // every invoice on the site as a model to render three header cards.
96 $invoice_repository = InvoiceServiceProvider::getInvoiceRepository();
97 $paid = \EasyInvoice\Services\InvoiceTotalsCache::paidRevenue();
98 $revenue_by_currency = [];
99 foreach ($paid['revenue'] as $currency_code => $row) {
100 $revenue_by_currency[$currency_code] = [
101 'amount' => (float) $row['amount'],
102 'symbol' => $row['symbol'],
103 'currency_code' => $currency_code,
104 ];
105 }
106 $stats['total_revenue'] = $revenue_by_currency;
107 $stats['total_invoices'] = (int) $invoice_repository->count();
108 $stats['pending_invoices'] = (int) \EasyInvoice\Services\InvoiceTotalsCache::outstanding()['count'];
109
110 // Prepare template data with pagination
111 $template_data = [
112 'clients' => $clients,
113 'stats' => $stats,
114 'current_page' => $current_page,
115 'per_page' => $per_page,
116 'total_clients' => $total_clients,
117 'total_pages' => $total_pages
118 ];
119
120 // Display the template
121 $this->displayTemplate(
122 EASY_INVOICE_PLUGIN_DIR . 'templates/clients-page.php',
123 $template_data
124 );
125 }
126
127 /**
128 * Display client edit page
129 */
130 protected function displayClientEditPage() {
131 $check = $this->checkCapability('ei_manage_clients');
132 if (is_wp_error($check)) {
133 wp_die(esc_html($check->get_error_message()));
134 }
135
136 $client_id = isset($_GET['client_id']) ? intval($_GET['client_id']) : 0;
137
138 if ($client_id <= 0) {
139 wp_die(esc_html__('Invalid client ID', 'easy-invoice'));
140 }
141
142 // Get client from repository
143 $repository = ClientServiceProvider::getClientRepository();
144 $client = $repository->find($client_id);
145
146 if (!$client) {
147 wp_die(esc_html__('Client not found', 'easy-invoice'));
148 }
149
150 // Display the template
151 $this->displayTemplate(
152 EASY_INVOICE_PLUGIN_DIR . 'templates/client-edit-page.php',
153 ['client' => $client]
154 );
155 }
156
157 /**
158 * Display client view page
159 */
160 protected function displayClientViewPage() {
161 $check = $this->checkCapability('ei_view_clients');
162 if (is_wp_error($check)) {
163 wp_die(esc_html($check->get_error_message()));
164 }
165
166 $client_id = isset($_GET['client_id']) ? intval($_GET['client_id']) : 0;
167
168 if ($client_id <= 0) {
169 wp_die(esc_html__('Invalid client ID', 'easy-invoice'));
170 }
171
172 // Get client from repository
173 $repository = ClientServiceProvider::getClientRepository();
174 $client = $repository->find($client_id);
175
176 if (!$client) {
177 wp_die(esc_html__('Client not found', 'easy-invoice'));
178 }
179
180 // Get client invoices
181 $invoices = [];
182 $invoice_repository = InvoiceServiceProvider::getInvoiceRepository();
183
184 // Query invoices for this client
185 $args = array(
186 'post_type' => 'easy_invoice',
187 'post_status' => 'publish',
188 'meta_query' => array(
189 array(
190 'key' => '_easy_invoice_client_id',
191 'value' => $client_id,
192 'compare' => '='
193 )
194 ),
195 'posts_per_page' => -1,
196 'orderby' => 'date',
197 'order' => 'DESC'
198 );
199
200 $invoice_posts = get_posts($args);
201
202 foreach ($invoice_posts as $post) {
203 $invoice = $invoice_repository->find($post->ID);
204 if ($invoice) {
205 $invoices[] = array(
206 'id' => $invoice->getId(),
207 'title' => $invoice->getTitle() ?: $invoice->getNumber(),
208 'invoice_number' => $invoice->getNumber(),
209 'date' => $invoice->getIssueDate(),
210 'due_date' => $invoice->getDueDate(),
211 'amount' => $invoice->getTotal(),
212 'status' => $invoice->getStatus()
213 );
214 }
215 }
216
217 // Get client quotes
218 $quotes = [];
219 $quote_repository = QuoteServiceProvider::getQuoteRepository();
220
221 // Query quotes for this client
222 $quote_args = array(
223 'post_type' => 'easy_invoice_quote',
224 'post_status' => 'publish',
225 'meta_query' => array(
226 array(
227 'key' => '_easy_invoice_client_id',
228 'value' => $client_id,
229 'compare' => '='
230 )
231 ),
232 'posts_per_page' => -1,
233 'orderby' => 'date',
234 'order' => 'DESC'
235 );
236
237 $quote_posts = get_posts($quote_args);
238
239 foreach ($quote_posts as $post) {
240 $quote = $quote_repository->find($post->ID);
241 if ($quote) {
242 $quotes[] = array(
243 'id' => $quote->getId(),
244 'title' => $quote->getTitle() ?: $quote->getNumber(),
245 'quote_number' => $quote->getNumber(),
246 'date' => $quote->getIssueDate(),
247 'expiry_date' => $quote->getExpiryDate(),
248 'amount' => $quote->getTotal(),
249 'status' => $quote->getStatus()
250 );
251 }
252 }
253
254 // Get client role information
255 $user = get_user_by('ID', $client_id);
256 $client_role = $user ? $user->roles[0] ?? 'client' : 'client';
257
258 // Display the template
259 $this->displayTemplate(
260 EASY_INVOICE_PLUGIN_DIR . 'templates/client-view-page.php',
261 [
262 'client' => $client,
263 'invoices' => $invoices,
264 'quotes' => $quotes,
265 'client_role' => $client_role
266 ]
267 );
268 }
269
270 /**
271 * Get client stats
272 *
273 * @return array
274 */
275 public function getClientStats() {
276 $repository = ClientServiceProvider::getClientRepository();
277 $clients = $repository->all();
278
279 return [
280 'total_clients' => count($clients)
281 ];
282 }
283
284 /**
285 * Delete a client
286 */
287 public function deleteClient() {
288 if (!$this->handleAjaxSecurity(($_POST['nonce'] ?? ''))) {
289 return;
290 }
291
292 // Check client ID
293 if (!isset($_POST['client_id']) || empty($_POST['client_id'])) {
294 wp_send_json_error(array('message' => 'Invalid client ID'));
295 }
296
297 $client_id = intval($_POST['client_id']);
298
299 // Delete client
300 $repository = ClientServiceProvider::getClientRepository();
301 $result = $repository->delete($client_id);
302
303 if ($result) {
304 wp_send_json_success(array('message' => 'Client deleted successfully'));
305 } else {
306 wp_send_json_error(array('message' => 'Error deleting client'));
307 }
308 }
309 }