· 8 years ago · Feb 20, 2018, 11:44 AM
1<?php
2
3/*
4Plugin Name: Eurobank WooCommerce Payment Gateway
5Plugin URI: https://www.enartia.com
6Description: Eurobank Payment Gateway allows you to accept payment through various channels such as Maestro, Mastercard, AMex cards, Diners and Visa cards On your Woocommerce Powered Site.
7Version: 1.4.1
8Author: Enartia
9Author URI: https://www.enartia.com
10License: GPL-3.0+
11License URI: http://www.gnu.org/licenses/gpl-3.0.txt
12 */
13
14if (!defined('ABSPATH')) {
15 exit;
16}
17
18require_once plugin_dir_path(__FILE__) . 'encryption.php';
19add_action('plugins_loaded', 'woocommerce_eurobank_init', 0);
20
21function woocommerce_eurobank_init()
22{
23
24 if (!class_exists('WC_Payment_Gateway')) {
25 return;
26 }
27
28 load_plugin_textdomain('woocommerce-eurobank-payment-gateway', false, dirname(plugin_basename(__FILE__)) . '/languages/');
29
30 /**
31 * Gateway class
32 */
33 class WC_Eurobank_Gateway extends WC_Payment_Gateway
34 {
35
36 public function __construct()
37 {
38 global $woocommerce;
39
40 $this->id = 'eurobank_gateway';
41 $this->icon = apply_filters('eurobank_icon', plugins_url('img/eurobank.png', __FILE__));
42 $this->has_fields = true;
43 $this->notify_url = WC()->api_request_url('WC_Eurobank_Gateway');
44 $this->method_description = __('Eurobank Payment Gateway allows you to accept payment through various channels such as Maestro, Mastercard, AMex cards, Diners and Visa cards On your Woocommerce Powered Site.', 'woocommerce-eurobank-payment-gateway');
45 $this->redirect_page_id = $this->get_option('redirect_page_id');
46 $this->method_title = 'Eurobank Gateway';
47
48 // Load the form fields.
49 $this->init_form_fields();
50
51 global $wpdb;
52
53 if ($wpdb->get_var("SHOW TABLES LIKE '" . $wpdb->prefix . "eurobank_transactions'") === $wpdb->prefix . 'eurobank_transactions') {
54 // The database table exist
55 } else {
56 // Table does not exist
57 $query = 'CREATE TABLE IF NOT EXISTS ' . $wpdb->prefix . 'eurobank_transactions (id int(11) unsigned NOT NULL AUTO_INCREMENT, merch_ref varchar(50) not null, trans_ticket varchar(32) not null , timestamp datetime default null, PRIMARY KEY (id))';
58 $wpdb->query($query);
59 }
60
61 // Load the settings.
62 $this->init_settings();
63
64 // Define user set variables
65 $this->title = $this->get_option('title');
66 $this->description = $this->get_option('description');
67 $this->eb_PayMerchantId = $this->get_option('eb_PayMerchantId');
68 $this->eb_PayMerchantKey = $this->get_option('eb_PayMerchantKey');
69 $this->pb_installments = $this->get_option('pb_installments');
70 //Actions
71 add_action('woocommerce_receipt_eurobank_gateway', array($this, 'receipt_page'));
72 add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options'));
73
74 // Payment listener/API hook
75 add_action('woocommerce_api_wc_eurobank_gateway', array($this, 'check_eurobank_response'));
76 }
77
78 /**
79 * Admin Panel Options
80 * */
81 public function admin_options()
82 {
83 echo '<h3>' . __('Eurobank Gateway', 'woocommerce-eurobank-payment-gateway') . '</h3>';
84 echo '<p>' . __('Eurobank Gateway allows you to accept payment through various channels such as Maestro, Mastercard, AMex cards, Diners and Visa cards.', 'woocommerce-eurobank-payment-gateway') . '</p>';
85
86 echo '<table class="form-table">';
87 $this->generate_settings_html();
88 echo '</table>';
89 }
90
91 /**
92 * Initialise Gateway Settings Form Fields
93 * */
94 function init_form_fields()
95 {
96 $this->form_fields = array(
97 'enabled' => array(
98 'title' => __('Enable/Disable', 'woocommerce-eurobank-payment-gateway'),
99 'type' => 'checkbox',
100 'label' => __('Enable Eurobank Gateway', 'woocommerce-eurobank-payment-gateway'),
101 'description' => __('Enable or disable the gateway.', 'woocommerce-eurobank-payment-gateway'),
102 'desc_tip' => true,
103 'default' => 'yes',
104 ),
105 'title' => array('title' => __('Title', 'woocommerce-eurobank-payment-gateway'), 'type' => 'text',
106 'description' => __('This controls the title which the user sees during checkout.', 'woocommerce-eurobank-payment-gateway'), 'desc_tip' => false,
107 'default' => __('Eurobank Gateway', 'woocommerce-eurobank-payment-gateway')), 'description' => array('title' => __('Description', 'woocommerce-eurobank-payment-gateway'),
108 'type' => 'textarea', 'description' => __('This controls the description which the user sees during checkout.', 'woocommerce-eurobank-payment-gateway'),
109 'default' => __('Pay Via Eurobank: Accepts Mastercard, Visa cards and etc.', 'woocommerce-eurobank-payment-gateway')),
110 'eb_PayMerchantId' => array('title' => __('Eurobank Merchant ID', 'woocommerce-eurobank-payment-gateway'), 'type' => 'text',
111 'description' => __('Enter Your Eurobank Merchant ID', 'woocommerce-eurobank-payment-gateway'), 'default' => '', 'desc_tip' => true),
112 'eb_PayMerchantKey' => array('title' => __('Eurobank Merchant KEY', 'woocommerce-eurobank-payment-gateway'), 'type' => 'password',
113 'description' => __('Enter Your Eurobank Merchant KEY', 'woocommerce-eurobank-payment-gateway'), 'default' => '', 'desc_tip' => false),
114 'redirect_page_id' => array('title' => __('Return Page', 'woocommerce-eurobank-payment-gateway'), 'type' => 'select', 'options' => $this->pb_get_pages('Select Page'),
115 'description' => __('URL of success page', 'woocommerce-eurobank-payment-gateway')),
116 'pb_installments' => array(
117 'title' => __('Max Installments', 'woocommerce-eurobank-payment-gateway'),
118 'type' => 'select',
119 'options' => $this->pb_get_installments('Select Installments'),
120 'description' => __('1 to 24 Installments,1 for one time payment. You must contact Eurobank first', 'woocommerce-eurobank-payment-gateway'),
121 ),
122 );
123 }
124
125 public function get_option($key, $empty_value = null)
126 {
127 $option_value = parent::get_option($key, $empty_value);
128 if ($key == 'eb_PayMerchantKey') {
129 $decrypted = WC_Payment_Gateway_KeyEncryption::decrypt(base64_decode($option_value), substr(NONCE_KEY, 0, 32));
130 $option_value = $decrypted;
131 }
132 return $option_value;
133 }
134 function payment_fields()
135 {
136 if ($description = $this->get_description()) {
137 echo wpautop(wptexturize($description));
138 }
139 $installments = $this->pb_installments;
140 if ($installments > 1) {
141 $doseis_field = '<p class="form-row ">
142 <label for="' . esc_attr($this->id) . '-card-doseis">' . __('Choose Installments', 'woocommerce-piraeusbank-payment-gateway') . ' <span class="required">*</span></label>
143 <select id="' . esc_attr($this->id) . '-card-doseis" name="' . esc_attr($this->id) . '-card-doseis" class="input-select wc-credit-card-form-card-doseis">
144 ';
145 for ($i = 1; $i <= $installments; $i++) {
146 $doseis_field .= '<option value="' . $i . '">' . $i . '</option>';
147 }
148 $doseis_field .= '</select>
149 </p>';
150 echo $doseis_field;
151 }
152 }
153 public function validate_eb_PayMerchantKey_field($key, $value)
154 {
155 $encrypted = WC_Payment_Gateway_KeyEncryption::encrypt($value, substr(NONCE_KEY, 0, 32));
156 return base64_encode($encrypted);
157 }
158 function pb_get_installments($title = false, $indent = true)
159 {
160
161 for ($i = 1; $i <= 24; $i++) {
162 $installment_list[$i] = $i;
163 }
164 return $installment_list;
165 }
166 function pb_get_pages($title = false, $indent = true)
167 {
168 $wp_pages = get_pages('sort_column=menu_order');
169 $page_list = array();
170 if ($title) {
171 $page_list[] = $title;
172 }
173
174 foreach ($wp_pages as $page) {
175 $prefix = '';
176 // show indented child pages?
177 if ($indent) {
178 $has_parent = $page->post_parent;
179 while ($has_parent) {
180 $prefix .= ' - ';
181 $next_page = get_page($has_parent);
182 $has_parent = $next_page->post_parent;
183 }
184 }
185 // add to page list array array
186 $page_list[$page->ID] = $prefix . $page->post_title;
187 }
188 $page_list[-1] = __('Thank you page', 'woocommerce-eurobank-payment-gateway');
189 return $page_list;
190 }
191
192 function calculate_digest($input)
193 {
194 $digest = base64_encode(sha1(($input), true));
195 return $digest;
196 }
197
198 /**
199 * Generate the Eurobank Payment button link
200 * */
201 function generate_eurobank_form($order_id)
202 {
203 global $woocommerce;
204 global $wpdb;
205
206 $order = new WC_Order($order_id);
207 //echo $this->pb_authorize;
208
209 $installments = 1;
210 /* if ($this->pb_installments > 1) {
211 $installments = intval($order->get_total() / 30);
212 $installments = min($installments, $this->pb_installments);
213 } */
214 if (method_exists($order, 'get_meta')) {
215 $installments = $order->get_meta('_doseis');
216 if ($installments == '') {
217 $installments = 1;
218 }
219 } else {
220 $installments = get_post_meta($order_id, '_doseis', 1);
221 }
222
223 // store TranTicket in table
224 $wpdb->delete($wpdb->prefix . 'eurobank_transactions', array('merch_ref' => $order_id));
225 $wpdb->insert($wpdb->prefix . 'eurobank_transactions', array('trans_ticket' => $order_id, 'merch_ref' => $order_id, 'timestamp' => current_time('mysql', 1)));
226
227 //redirect to payment
228
229 wc_enqueue_js('
230 $.blockUI({
231 message: "' . esc_js(__('Thank you for your order. We are now redirecting you to Eurobank to make payment.', 'woocommerce-eurobank-payment-gateway')) . '",
232 baseZ: 99999,
233 overlayCSS:
234 {
235 background: "#fff",
236 opacity: 0.6
237 },
238 css: {
239 padding: "20px",
240 zindex: "9999999",
241 textAlign: "center",
242 color: "#555",
243 border: "3px solid #aaa",
244 backgroundColor:"#fff",
245 cursor: "wait",
246 lineHeight: "24px",
247 }
248 });
249 jQuery("#eb_payment_form").submit();
250 ');
251
252 $billing = $order->get_address();
253 if ($installments > 1) {
254 $form_data_array = array('mid' => esc_attr($this->eb_PayMerchantId), 'lang' => 'el', 'deviceCategory' => '0', 'orderid' => ($order_id), 'orderDesc' => 'Order #' . $order_id,
255 'orderAmount' => $order->get_total(), 'currency' => 'EUR', 'payerEmail' => $billing['email'],
256 'extInstallmentoffset' => 0, 'extInstallmentperiod' => $installments,
257 'confirmUrl' => get_site_url() . "/?wc-api=WC_Eurobank_Gateway&result=success",
258 'cancelUrl' => get_site_url() . "/?wc-api=WC_Eurobank_Gateway&result=failure");
259 } else {
260 $form_data_array = array('mid' => esc_attr($this->eb_PayMerchantId), 'lang' => 'el', 'deviceCategory' => '0', 'orderid' => ($order_id), 'orderDesc' => 'Order #' . $order_id,
261 'orderAmount' => $order->get_total(), 'currency' => 'EUR', 'payerEmail' => $billing['email'],
262 'confirmUrl' => get_site_url() . "/?wc-api=WC_Eurobank_Gateway&result=success",
263 'cancelUrl' => get_site_url() . "/?wc-api=WC_Eurobank_Gateway&result=failure");
264 }
265 $form_secret = $this->eb_PayMerchantKey;
266 $form_data = utf8_encode(implode("", $form_data_array)) . $form_secret;
267
268 $digest = $this->calculate_digest($form_data);
269
270 /* $send_it_2 = "https://euro.test.modirum.com/vpos/shophandlermpi";
271 if ($this -> test_mode != "yes") {
272 $send_it_2 = "https://vpos.eurocommerce.gr/vpos/shophandlermpi";
273 } */
274 $send_it_2 = "https://vpos.eurocommerce.gr/vpos/shophandlermpi";
275 $html = '<form action="' . esc_url($send_it_2) . '" method="post" id="eb_payment_form" target="_top" accept-charset="UTF-8">';
276 foreach ($form_data_array as $key => $value) {
277 $html .= '<input type="hidden" id="' . $key . '" name="' . $key . '" value="' . utf8_encode($value) . '"/>';
278 }
279 $html .= '<input type="hidden" id="digest" name="digest" value="' . esc_attr($digest) . '"/>';
280 $html .= '</form>';
281 return $html;
282 }
283
284 /**
285 * Process the payment and return the result
286 * */
287 function process_payment($order_id)
288 {
289
290 /*
291 get_permalink was used instead of $order->get_checkout_payment_url in redirect in order to have a fixed checkout page to provide to Eurobank
292 */
293
294 $order = new WC_Order($order_id);
295 $doseis = intval($_POST[esc_attr($this->id) . '-card-doseis']);
296 if ($doseis > 0) {
297 $this->generic_add_meta($order_id, '_doseis', $doseis);
298 }
299 return array('result' => 'success', 'redirect' => add_query_arg('order', $order->id, add_query_arg('key', $order->order_key, get_permalink(woocommerce_get_page_id('pay')))));
300 }
301
302 /**
303 * Output for the order received page.
304 * */
305 function receipt_page($order)
306 {
307 echo '<p>' . __('Thank you - your order is now pending payment. You should be automatically redirected to Eurobank Paycenter to make payment.', 'woocommerce-eurobank-payment-gateway') . '</p>';
308 echo $this->generate_eurobank_form($order);
309 }
310
311 /**
312 * Verify a successful Payment!
313 * */
314 function check_eurobank_response()
315 {
316
317 global $woocommerce;
318 global $wpdb;
319
320 //$post_data_keys=array('mid','orderid','status','orderAmount','digest');
321 $mid = $_POST['mid'];
322 $orderid = $_POST['orderid'];
323 $orderAmount = $_POST['orderAmount'];
324 $status = $_POST['status'];
325 $post_digest = $_POST['digest'];
326 $form_data = '';
327 foreach ($_POST as $k => $v) {
328 if (!in_array($k, array('_charset_', 'digest', 'submitButton'))) {
329 $form_data .= $_POST[$k];
330 }
331 }
332 $form_data .= $this->eb_PayMerchantKey;
333 $digest = $this->calculate_digest($form_data);
334 $order = new WC_Order($orderid);
335 if ($digest != $post_digest) {
336 $message = __('A technical problem occured. <br />The transaction wasn\'t successful, payment wasn\'t received.', 'woocommerce-eurobank-payment-gateway');
337 $message_type = 'error';
338 $pb_message = array('message' => $message, 'message_type' => $message_type);
339 $this->generic_add_meta($orderid, '_eurobank_message', $pb_message);
340 //Update the order status
341 $order->update_status('failed', 'DIGEST');
342 $checkout_url = $woocommerce->cart->get_checkout_url();
343 wp_redirect($checkout_url);
344 exit;
345 }
346 //AUTHORIZED, CAPTURED,CANCELED,REFUSED,ERROR
347 if (isset($_GET['result']) && ($_GET['result'] == 'success')) {
348
349 if ($status == 'ERROR') {
350 $message = __('A technical problem occured. <br />The transaction wasn\'t successful, payment wasn\'t received.', 'woocommerce-eurobank-payment-gateway');
351 $message_type = 'error';
352 $pb_message = array('message' => $message, 'message_type' => $message_type);
353 $this->generic_add_meta($orderid, '_eurobank_message', $pb_message);
354 //Update the order status
355 $order->update_status('failed', 'ERROR');
356 $checkout_url = $woocommerce->cart->get_checkout_url();
357 wp_redirect($checkout_url);
358 exit;
359 }
360
361 $paymentRef = $_POST['paymentRef'];
362 $txId = $_POST['txId'];
363 if ($status == 'CAPTURED') {
364
365 if ($order->status == 'processing') {
366
367 $order->add_order_note(__('Payment Via Eurobank Bank<br />Transaction ID: ', 'woocommerce-eurobank-payment-gateway') . $paymentRef);
368
369 //Add customer order note
370 $order->add_order_note(__('Payment Received.<br />Your order is currently being processed.<br />We will be shipping your order to you soon.<br />Eurobank Bank ID: ', 'woocommerce-eurobank-payment-gateway') . $paymentRef, 1);
371
372 // Reduce stock levels
373 $order->reduce_order_stock();
374
375 // Empty cart
376 WC()->cart->empty_cart();
377
378 $message = __('Thank you for shopping with us.<br />Your transaction was successful, payment was received.<br />Your order is currently being processed.', 'woocommerce-eurobank-payment-gateway');
379 $message_type = 'success';
380 } else {
381
382 if ($order->has_downloadable_item()) {
383
384 //Update order status
385 $order->update_status('completed', __('Payment received, your order is now complete.', 'woocommerce-eurobank-payment-gateway'));
386
387 //Add admin order note
388 $order->add_order_note(__('Payment Via Eurobank Bank<br />Transaction ID: ', 'woocommerce-eurobank-payment-gateway') . $paymentRef);
389
390 //Add customer order note
391 $order->add_order_note(__('Payment Received.<br />Your order is now complete.<br />Eurobank Transaction ID: ', 'woocommerce-eurobank-payment-gateway') . $paymentRef, 1);
392
393 $message = __('Thank you for shopping with us.<br />Your transaction was successful, payment was received.<br />Your order is now complete.', 'woocommerce-eurobank-payment-gateway');
394 $message_type = 'success';
395 } else {
396
397 //Update order status
398 $order->update_status('processing', __('Payment received, your order is currently being processed.', 'woocommerce-eurobank-payment-gateway'));
399
400 //Add admin order note
401 $order->add_order_note(__('Payment Via Eurobank Bank<br />Transaction ID: ', 'woocommerce-eurobank-payment-gateway') . $paymentRef);
402
403 //Add customer order note
404 $order->add_order_note(__('Payment Received.<br />Your order is currently being processed.<br />We will be shipping your order to you soon.<br />Eurobank Bank ID: ', 'woocommerce-eurobank-payment-gateway') . $paymentRef, 1);
405
406 $message = __('Thank you for shopping with us.<br />Your transaction was successful, payment was received.<br />Your order is currently being processed.', 'woocommerce-eurobank-payment-gateway');
407 $message_type = 'success';
408 }
409
410 $pb_message = array('message' => $message, 'message_type' => $message_type);
411
412 $this->generic_add_meta($orderid, '_eurobank_message', $pb_message);
413 // Reduce stock levels
414 $order->reduce_order_stock();
415 wc_add_notice($message, $message_type);
416 // Empty cart
417 WC()->cart->empty_cart();
418 }
419 } else if ($status == 'CANCELED') {
420 $checkout_url = $woocommerce->cart->get_checkout_url();
421 $message = __('Thank you for shopping with us. <br />However, the transaction wasn\'t successful, payment was cancelled.', 'woocommerce-eurobank-payment-gateway');
422 $message_type = 'notice';
423 wc_add_notice($message, $message_type);
424 //wp_redirect($checkout_url);
425 //exit ;
426 } else { //Failed Response codes
427 $message = __('Thank you for shopping with us. <br />However, the transaction wasn\'t successful, payment wasn\'t received.', 'woocommerce-eurobank-payment-gateway');
428 $message_type = 'error';
429 $pb_message = array('message' => $message, 'message_type' => $message_type);
430 $this->generic_add_meta($orderid, '_eurobank_message', $pb_message);
431 //wc_add_notice( $message, $message_type );
432 $order->update_status('failed', 'UNKNOWN');
433 }
434 }
435 if (isset($_GET['result']) && ($_GET['result'] == 'failure')) {
436
437 $order = new WC_Order($orderid);
438 $message = __('Thank you for shopping with us. <br />However, the transaction wasn\'t successful, payment wasn\'t received.', 'woocommerce-eurobank-payment-gateway');
439 $message_type = 'error';
440 // wc_add_notice( $message, $message_type );
441 $transaction_id = $_POST['txId'];
442
443 //Add Customer Order Note
444 $order->add_order_note($message . '<br />Eurobank Transaction ID: ' . $transaction_id, 1);
445
446 //Add Admin Order Note
447 $order->add_order_note($message . '<br />Eurobank Transaction ID: ' . $transaction_id . '');
448
449 //Update the order status
450 $order->update_status('failed', $_POST['message']);
451
452 $pb_message = array('message' => $message, 'message_type' => $message_type);
453
454 $this->generic_add_meta($orderid, '_eurobank_message', $pb_message);
455 }
456
457 if ($this->redirect_page_id == "-1") {
458 $redirect_url = $this->get_return_url($order);
459 } else {
460 $redirect_url = ($this->redirect_page_id == "" || $this->redirect_page_id == 0) ? $this->get_return_url($order) : get_permalink($this->redirect_page_id);
461 }
462 wp_redirect($redirect_url);
463
464 exit;
465 }
466
467 function generic_add_meta($orderid, $key, $value)
468 {
469 $order = new WC_Order($orderid);
470 if (method_exists($order, 'add_meta_data') && method_exists($order, 'save_meta_data')) {
471 $order->add_meta_data($key, $value, true);
472 $order->save_meta_data();
473 } else {
474 update_post_meta($orderid, $key, $value);
475 }
476 }
477
478 }
479
480 function eurobank_message()
481 {
482 $order_id = absint(get_query_var('order-received'));
483 $order = new WC_Order($order_id);
484 if (method_exists($order, 'get_payment_method')) {
485 $payment_method = $order->get_payment_method();
486 } else {
487 $payment_method = $order->payment_method;
488 }
489 if (is_order_received_page() && ('eurobank_gateway' == $payment_method)) {
490 if (method_exists($order, 'get_meta')) {
491 $eurobank_message = $order->get_meta('_eurobank_message', true);
492 } else {
493 $eurobank_message = get_post_meta($order_id, '_eurobank_message');
494 }
495 $message = $eurobank_message['message'];
496 $message_type = $eurobank_message['message_type'];
497 if (method_exists($order, 'delete_meta_data')) {
498 $order->delete_meta_data('_eurobank_message');
499 $order->save_meta_data();
500 } else {
501 delete_post_meta($order_id, '_eurobank_message');
502 }
503 if (!empty($eurobank_message)) {
504 wc_add_notice($message, $message_type);
505 }
506 }
507 }
508
509 add_action('wp', 'eurobank_message');
510
511 /**
512 * Add Eurobank Gateway to WC
513 * */
514 function woocommerce_add_eurobank_gateway($methods)
515 {
516 $methods[] = 'WC_Eurobank_Gateway';
517 return $methods;
518 }
519
520 add_filter('woocommerce_payment_gateways', 'woocommerce_add_eurobank_gateway');
521
522 /**
523 * Add Settings link to the plugin entry in the plugins menu for WC below 2.1
524 * */
525 if (version_compare(WOOCOMMERCE_VERSION, "2.1") <= 0) {
526
527 add_filter('plugin_action_links', 'eurobank_plugin_action_links', 10, 2);
528
529 function eurobank_plugin_action_links($links, $file)
530 {
531 static $this_plugin;
532
533 if (!$this_plugin) {
534 $this_plugin = plugin_basename(__FILE__);
535 }
536
537 if ($file == $this_plugin) {
538 $settings_link = '<a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=woocommerce_settings&tab=payment_gateways§ion=WC_eurobank_Gateway">Settings</a>';
539 array_unshift($links, $settings_link);
540 }
541 return $links;
542 }
543
544 }
545 /**
546 * Add Settings link to the plugin entry in the plugins menu for WC 2.1 and above
547 * */else {
548 add_filter('plugin_action_links', 'eurobank_plugin_action_links', 10, 2);
549
550 function eurobank_plugin_action_links($links, $file)
551 {
552 static $this_plugin;
553
554 if (!$this_plugin) {
555 $this_plugin = plugin_basename(__FILE__);
556 }
557
558 if ($file == $this_plugin) {
559 $settings_link = '<a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=WC_Eurobank_Gateway">Settings</a>';
560 array_unshift($links, $settings_link);
561 }
562 return $links;
563 }
564
565 }
566}