Version Description
- Minor bug fixes.
Download this release
Release Info
Developer | sitewit |
Plugin | Google Ads & Marketing by Kliken |
Version | 1.0.2 |
Comparing to | |
See all releases |
Version 1.0.2
- assets/admin-script.js +15 -0
- changelog.txt +11 -0
- classes/class-helper.php +428 -0
- classes/class-message.php +83 -0
- classes/class-plugin.php +299 -0
- classes/class-rest-misc-controller.php +132 -0
- classes/class-rest-orders-controller.php +66 -0
- classes/class-rest-products-controller.php +129 -0
- classes/class-wc-integration.php +145 -0
- classes/class-wc-rest-products-controller-compat.php +23 -0
- kliken-marketing-for-google.php +61 -0
- languages/kliken-marketing-for-google-de_CH.mo +0 -0
- languages/kliken-marketing-for-google-de_DE.mo +0 -0
- languages/kliken-marketing-for-google-es_ES.mo +0 -0
- languages/kliken-marketing-for-google-fr_FR.mo +0 -0
- languages/kliken-marketing-for-google-nl_NL.mo +0 -0
- languages/kliken-marketing-for-google.pot +193 -0
- pages/admin-style.php +92 -0
- pages/dashboard.php +93 -0
- pages/getstarted.php +54 -0
- pages/trackingscript.php +14 -0
- pages/transactionscript.php +39 -0
- readme.txt +59 -0
- uninstall.php +20 -0
- vendor/autoload.php +7 -0
- vendor/composer/ClassLoader.php +445 -0
- vendor/composer/LICENSE +56 -0
- vendor/composer/autoload_classmap.php +17 -0
- vendor/composer/autoload_namespaces.php +9 -0
- vendor/composer/autoload_psr4.php +9 -0
- vendor/composer/autoload_real.php +52 -0
- vendor/composer/autoload_static.php +27 -0
- vendor/composer/installed.json +1 -0
assets/admin-script.js
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready(function() {
|
2 |
+
// Only care about those notice messages with "data-message-name" attribute, and "is-dimissible" class
|
3 |
+
jQuery(".wrap").on("click", "div[data-message-name].is-dismissible button.notice-dismiss", function(event) {
|
4 |
+
event.preventDefault();
|
5 |
+
event.stopPropagation();
|
6 |
+
|
7 |
+
if (confirm(dimissibleNotice.confirmMessage)) {
|
8 |
+
jQuery.post( ajaxurl, {
|
9 |
+
action: dimissibleNotice.action,
|
10 |
+
message_name: jQuery(this).parent().attr('data-message-name'),
|
11 |
+
_ajax_nonce: dimissibleNotice.nonce
|
12 |
+
})
|
13 |
+
}
|
14 |
+
});
|
15 |
+
});
|
changelog.txt
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*** Google Ads for WooCommerce Changelog ***
|
2 |
+
|
3 |
+
2019-07-02 - version 1.0.2
|
4 |
+
* Minor bug fixes.
|
5 |
+
|
6 |
+
2019-04-02 - version 1.0.1
|
7 |
+
* Minor UI improvements.
|
8 |
+
* Minor bug fixes.
|
9 |
+
|
10 |
+
2019-02-20 - version 1.0.0
|
11 |
+
* First release.
|
classes/class-helper.php
ADDED
@@ -0,0 +1,428 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Helper class to provide some common functionalities
|
4 |
+
*
|
5 |
+
* @package Kliken Marketing for Google
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace Kliken\WcPlugin;
|
9 |
+
|
10 |
+
defined( 'ABSPATH' ) || exit;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Helper class
|
14 |
+
*/
|
15 |
+
class Helper {
|
16 |
+
/**
|
17 |
+
* Name of the option that WooCommerce will save the plugin settings into.
|
18 |
+
*
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
private static $_option_key = null;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* A wrapper around WC_Logger log method.
|
25 |
+
*
|
26 |
+
* @param string $level Log level.
|
27 |
+
* @param string $message Message to log.
|
28 |
+
* @param boolean $force Force logging without the need of WP_DEBUG mode.
|
29 |
+
*/
|
30 |
+
public static function wc_log( $level, $message, $force = false ) {
|
31 |
+
if ( ( WP_DEBUG || $force )
|
32 |
+
&& function_exists( 'wc_get_logger' )
|
33 |
+
&& $message
|
34 |
+
&& in_array( $level, [ 'debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency' ], true ) ) {
|
35 |
+
wc_get_logger()->log( $level, $message, [ 'source' => 'kliken-marketing-for-google' ] );
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Get plugin option key, because of WooCommerce Integration Settings API.
|
41 |
+
*
|
42 |
+
* @return string
|
43 |
+
*/
|
44 |
+
public static function get_option_key() {
|
45 |
+
if ( null === self::$_option_key ) {
|
46 |
+
if ( function_exists( 'wc' ) && class_exists( '\WC_Integration' ) ) {
|
47 |
+
self::$_option_key = ( new WC_Integration( false ) )->get_option_key();
|
48 |
+
} else {
|
49 |
+
// In the weird case when WooCommerce is not available.
|
50 |
+
self::$_option_key = 'woocommerce_kk_wcintegration_settings';
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
return self::$_option_key;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Get plugin options, being an integration with WooCommerce Settings API.
|
59 |
+
*
|
60 |
+
* @return array
|
61 |
+
*/
|
62 |
+
public static function get_plugin_options() {
|
63 |
+
return get_option( self::get_option_key(), [] );
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Check if provided id can be considered a valid account id.
|
68 |
+
* Should be an integer.
|
69 |
+
*
|
70 |
+
* @param mixed $id Account Id.
|
71 |
+
* @return boolean
|
72 |
+
*/
|
73 |
+
public static function is_valid_account_id( $id ) {
|
74 |
+
return ! empty( $id ) && ctype_digit( strval( $id ) );
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Check if the provided token can be considered a valid application token.
|
79 |
+
* Should be not empty, for now.
|
80 |
+
*
|
81 |
+
* @param string $token Application token.
|
82 |
+
* @return boolean
|
83 |
+
*/
|
84 |
+
public static function is_valid_app_token( $token ) {
|
85 |
+
$token = sanitize_text_field( $token );
|
86 |
+
return ! empty( $token );
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Check if current page is a page of the plugin, matching the provided page slug.
|
91 |
+
*
|
92 |
+
* @param string $page_slug Page slug.
|
93 |
+
* @return boolean
|
94 |
+
*/
|
95 |
+
public static function is_plugin_page( $page_slug = null ) {
|
96 |
+
global $pagenow;
|
97 |
+
|
98 |
+
if ( 'admin.php' !== $pagenow ) {
|
99 |
+
return false;
|
100 |
+
}
|
101 |
+
|
102 |
+
if ( null !== $page_slug ) {
|
103 |
+
return ( isset( $_GET['page'] ) && $page_slug === $_GET['page'] ); // WPCS: CSRF ok, input var ok.
|
104 |
+
} else {
|
105 |
+
return (
|
106 |
+
isset( $_GET['page'] ) && 'wc-settings' === $_GET['page']
|
107 |
+
&& isset( $_GET['tab'] ) && 'integration' === $_GET['tab']
|
108 |
+
&& isset( $_GET['section'] ) && KK_WC_INTEGRATION_PAGE_ID === $_GET['section']
|
109 |
+
); // WPCS: CSRF ok, input var ok.
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Get plugin page URL.
|
115 |
+
*/
|
116 |
+
public static function get_plugin_page() {
|
117 |
+
return 'admin.php?page=wc-settings&tab=integration§ion=' . KK_WC_INTEGRATION_PAGE_ID;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Get base64 encoded data url for the logo image.
|
122 |
+
*
|
123 |
+
* @return string
|
124 |
+
*/
|
125 |
+
public static function get_base64_icon() {
|
126 |
+
// phpcs:ignore
|
127 |
+
return 'data:image/svg+xml;base64,' . base64_encode( file_get_contents( KK_WC_PLUGIN_DIR . 'assets/logo-small.svg' ) );
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Get a list of supported languages (WP style) with a map to .NET style
|
132 |
+
*
|
133 |
+
* @return array
|
134 |
+
*/
|
135 |
+
public static function get_wl_supported_languages() {
|
136 |
+
return [
|
137 |
+
'en_US' => 'en',
|
138 |
+
'es_ES' => 'es',
|
139 |
+
'de_DE' => 'de',
|
140 |
+
'de_CH' => 'de-CH',
|
141 |
+
'fr_FR' => 'fr',
|
142 |
+
'nl_NL' => 'nl',
|
143 |
+
];
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Get locale of WordPress site/user, in .NET style.
|
148 |
+
* Default to English if not supported by the plugin.
|
149 |
+
*
|
150 |
+
* @return string
|
151 |
+
*/
|
152 |
+
public static function get_wl_locale() {
|
153 |
+
if ( function_exists( 'get_user_locale' ) ) {
|
154 |
+
$wp_locale = get_user_locale();
|
155 |
+
} else {
|
156 |
+
$wp_locale = get_locale();
|
157 |
+
}
|
158 |
+
|
159 |
+
$supported_langs = self::get_wl_supported_languages();
|
160 |
+
|
161 |
+
if ( array_key_exists( $wp_locale, $supported_langs ) ) {
|
162 |
+
return $supported_langs[ $wp_locale ];
|
163 |
+
}
|
164 |
+
|
165 |
+
return 'en';
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Get locale of WordPress site/user, with a postfix.
|
170 |
+
*
|
171 |
+
* @param string $postfix Postfix to be used. Defaults to "-".
|
172 |
+
* @return string
|
173 |
+
*/
|
174 |
+
public static function get_locale_postfix( $postfix = '-' ) {
|
175 |
+
if ( function_exists( 'get_user_locale' ) ) {
|
176 |
+
$wp_locale = get_user_locale();
|
177 |
+
} else {
|
178 |
+
$wp_locale = get_locale();
|
179 |
+
}
|
180 |
+
|
181 |
+
$supported_langs = self::get_wl_supported_languages();
|
182 |
+
|
183 |
+
if ( array_key_exists( $wp_locale, $supported_langs ) ) {
|
184 |
+
if ( 'en_US' === $wp_locale ) {
|
185 |
+
return '';
|
186 |
+
} else {
|
187 |
+
return $postfix . $wp_locale;
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
return '';
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Add SiteWit tracking script to page.
|
196 |
+
*/
|
197 |
+
public static function add_tracking_script() {
|
198 |
+
global $wp;
|
199 |
+
|
200 |
+
$saved_settings = self::get_plugin_options();
|
201 |
+
|
202 |
+
if ( ! self::is_valid_account_id( $saved_settings['account_id'] ) ) {
|
203 |
+
return;
|
204 |
+
}
|
205 |
+
|
206 |
+
// Check if is order received page.
|
207 |
+
if ( is_order_received_page() ) {
|
208 |
+
$order_id = isset( $wp->query_vars['order-received'] ) ? $wp->query_vars['order-received'] : 0;
|
209 |
+
$trans = self::build_transaction_data( $order_id );
|
210 |
+
|
211 |
+
if ( null !== $trans ) {
|
212 |
+
include_once KK_WC_PLUGIN_DIR . 'pages/transactionscript.php';
|
213 |
+
}
|
214 |
+
}
|
215 |
+
|
216 |
+
$account_id = $saved_settings['account_id'];
|
217 |
+
include_once KK_WC_PLUGIN_DIR . 'pages/trackingscript.php';
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Add Google Verification Token to page meta.
|
222 |
+
*/
|
223 |
+
public static function add_google_verification_token() {
|
224 |
+
$saved_settings = self::get_plugin_options();
|
225 |
+
|
226 |
+
// Sanitize the saved string again just in case.
|
227 |
+
$token = sanitize_text_field( $saved_settings['google_token'] );
|
228 |
+
|
229 |
+
if ( $token ) {
|
230 |
+
printf( '<!-- Kliken Google Site Verification Token Tag -->' );
|
231 |
+
printf( '<meta name="google-site-verification" content="%s" />', esc_attr( $token ) );
|
232 |
+
}
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Build transaction/order data preparing to be recorded by our tracking script
|
237 |
+
*
|
238 |
+
* @param int $order_id WooCommerce Order Id.
|
239 |
+
* @return array|null
|
240 |
+
*/
|
241 |
+
public static function build_transaction_data( $order_id ) {
|
242 |
+
// Get the order detail.
|
243 |
+
$order = wc_get_order( $order_id );
|
244 |
+
|
245 |
+
if ( ! $order ) {
|
246 |
+
return null;
|
247 |
+
}
|
248 |
+
|
249 |
+
// We don't care about these statuses.
|
250 |
+
$status = $order->get_status();
|
251 |
+
if ( 'cancelled' === $status || 'refunded' === $status || 'failed' === $status ) {
|
252 |
+
return null;
|
253 |
+
}
|
254 |
+
|
255 |
+
$transaction = [
|
256 |
+
'order_id' => $order_id,
|
257 |
+
'currency' => $order->get_currency(),
|
258 |
+
'affiliate' => null,
|
259 |
+
'sub_total' => $order->get_subtotal(),
|
260 |
+
'tax' => $order->get_total_tax(),
|
261 |
+
'city' => $order->get_billing_city(),
|
262 |
+
'state' => $order->get_billing_state(),
|
263 |
+
'country' => $order->get_billing_country(),
|
264 |
+
'total' => $order->get_total(),
|
265 |
+
'items' => [],
|
266 |
+
];
|
267 |
+
|
268 |
+
$order_items = $order->get_items();
|
269 |
+
|
270 |
+
// Cache category info, because in the order, there might be multiple items under same category.
|
271 |
+
$category_cache = [];
|
272 |
+
|
273 |
+
foreach ( $order_items as $index => $item ) {
|
274 |
+
$product = $item->get_product();
|
275 |
+
|
276 |
+
if ( ! $product ) continue;
|
277 |
+
|
278 |
+
$product_categories = $product->get_category_ids();
|
279 |
+
$category_name = '';
|
280 |
+
|
281 |
+
foreach ( $product_categories as $index => $id ) {
|
282 |
+
if ( array_key_exists( $id, $category_cache ) ) {
|
283 |
+
$category_name = $category_cache[ $id ];
|
284 |
+
} else {
|
285 |
+
$term = get_term_by( 'id', $id, 'product_cat' );
|
286 |
+
if ( $term ) {
|
287 |
+
$category_name = $term->name;
|
288 |
+
$category_cache[ $id ] = $category_name;
|
289 |
+
}
|
290 |
+
}
|
291 |
+
}
|
292 |
+
|
293 |
+
array_push(
|
294 |
+
$transaction['items'], [
|
295 |
+
'sku' => $product->get_sku(),
|
296 |
+
'name' => $product->get_name(),
|
297 |
+
'category' => $category_name,
|
298 |
+
'price' => $product->get_price(),
|
299 |
+
'quantity' => $item->get_quantity(),
|
300 |
+
]
|
301 |
+
);
|
302 |
+
}
|
303 |
+
|
304 |
+
return $transaction;
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Build the WooCommerce authorization URL
|
309 |
+
* Doc: https://woocommerce.github.io/woocommerce-rest-api-docs/#rest-api-keys
|
310 |
+
*
|
311 |
+
* @param int $account_id Account Id.
|
312 |
+
* @param string $application_token Application Token.
|
313 |
+
* @return string|null
|
314 |
+
*/
|
315 |
+
public static function build_authorization_url( $account_id, $application_token ) {
|
316 |
+
if ( empty( $account_id ) || empty( $application_token ) ) {
|
317 |
+
return null;
|
318 |
+
}
|
319 |
+
|
320 |
+
$authorization_url = get_site_url() . '/wc-auth/v1/authorize'
|
321 |
+
. '?app_name=' . rawurlencode( 'Google Ads for WooCommerce' )
|
322 |
+
. '&scope=read_write'
|
323 |
+
. '&user_id=' . base64_encode( $account_id . ':' . $application_token )
|
324 |
+
. '&return_url=' . rawurlencode( 'bit.ly/2OweS8h' ) // This links back to woo.kliken.com. We just need to do this to shorten the link because some WordPress hostings seem to dislike long links.
|
325 |
+
. '&callback_url=' . rawurlencode( KK_WC_AUTH_CALLBACK_URL );
|
326 |
+
|
327 |
+
return $authorization_url;
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* Build sign up link.
|
332 |
+
*/
|
333 |
+
public static function build_signup_link() {
|
334 |
+
$current_user = wp_get_current_user();
|
335 |
+
|
336 |
+
return sprintf(
|
337 |
+
KK_WC_WOOKLIKEN_BASE_URL . 'auth/woo/?u=%s&n=%s&e=%s&t=%s&return=%s',
|
338 |
+
rawurlencode( get_site_url() ),
|
339 |
+
rawurlencode( $current_user->display_name ),
|
340 |
+
rawurlencode( $current_user->user_email ),
|
341 |
+
wp_create_nonce( KK_WC_ACTION_SAVE_ACCOUNT ),
|
342 |
+
get_admin_url() . 'admin.php?action=' . KK_WC_ACTION_SAVE_ACCOUNT
|
343 |
+
);
|
344 |
+
}
|
345 |
+
|
346 |
+
/**
|
347 |
+
* Save account information.
|
348 |
+
*
|
349 |
+
* @param int $account_id Account Id.
|
350 |
+
* @param string $application_token Application Token.
|
351 |
+
* @return string|null WooCommerce authorization URL to redirect to after saving account info.
|
352 |
+
*/
|
353 |
+
public static function save_account_info( $account_id, $application_token ) {
|
354 |
+
if ( self::is_valid_account_id( $account_id )
|
355 |
+
&& self::is_valid_app_token( $application_token )
|
356 |
+
) {
|
357 |
+
$saved_settings = self::get_plugin_options();
|
358 |
+
|
359 |
+
$google_token = '';
|
360 |
+
if ( ! empty( $saved_settings['google_token'] ) ) {
|
361 |
+
$google_token = $saved_settings['google_token'];
|
362 |
+
}
|
363 |
+
|
364 |
+
update_option(
|
365 |
+
self::get_option_key(), [
|
366 |
+
'account_id' => intval( $account_id ),
|
367 |
+
'app_token' => sanitize_text_field( $application_token ),
|
368 |
+
'google_token' => $google_token,
|
369 |
+
]
|
370 |
+
);
|
371 |
+
|
372 |
+
return self::build_authorization_url( $account_id, $application_token );
|
373 |
+
}
|
374 |
+
|
375 |
+
return null;
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Redirect to WooCommerce Authorization page if needed.
|
380 |
+
*/
|
381 |
+
public static function check_redirect_for_wc_auth() {
|
382 |
+
// Bail if activating from network, or bulk.
|
383 |
+
if ( is_network_admin() ) {
|
384 |
+
return;
|
385 |
+
}
|
386 |
+
|
387 |
+
// If WooCommerce is not available/active, don't bother.
|
388 |
+
if ( ! function_exists( 'wc' ) ) {
|
389 |
+
return;
|
390 |
+
}
|
391 |
+
|
392 |
+
$authorization_url = get_site_transient( KK_WC_TRANSIENT_AUTH_REDIRECT );
|
393 |
+
|
394 |
+
if ( ! empty( $authorization_url ) ) {
|
395 |
+
delete_site_transient( KK_WC_TRANSIENT_AUTH_REDIRECT );
|
396 |
+
|
397 |
+
if ( wp_safe_redirect( $authorization_url ) ) {
|
398 |
+
exit;
|
399 |
+
}
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
/**
|
404 |
+
* Get the formatted, clean, safe onboarding message.
|
405 |
+
*/
|
406 |
+
public static function get_onboarding_message() {
|
407 |
+
return sprintf(
|
408 |
+
wp_kses(
|
409 |
+
/* translators: %s: A hyperlink */
|
410 |
+
__( '<strong>Google Ads for WooCommerce plugin is almost ready.</strong> <a href="%s">Click here</a> to get started.', 'kliken-marketing-for-google' ),
|
411 |
+
[
|
412 |
+
'strong' => [],
|
413 |
+
'a' => [ 'href' => [] ],
|
414 |
+
]
|
415 |
+
), esc_url( self::get_plugin_page() )
|
416 |
+
);
|
417 |
+
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
* Get image link.
|
421 |
+
*
|
422 |
+
* @param string $image_base_name Base name of the image, without the extension.
|
423 |
+
* @param string $image_extension Extension of the image, including the ".".
|
424 |
+
*/
|
425 |
+
public static function get_image_link( $image_base_name, $image_extension ) {
|
426 |
+
return KK_WC_PLUGIN_URL . 'assets/' . $image_base_name . self::get_locale_postfix() . $image_extension;
|
427 |
+
}
|
428 |
+
}
|
classes/class-message.php
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Message class to provide shortcuts for display various types of WordPress admin notices
|
4 |
+
*
|
5 |
+
* @package Kliken WooCommerce Google Ads
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace Kliken\WcPlugin;
|
9 |
+
|
10 |
+
defined( 'ABSPATH' ) || exit;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Message class
|
14 |
+
*/
|
15 |
+
class Message {
|
16 |
+
/**
|
17 |
+
* Build a message to HTML code to be displayed on a page
|
18 |
+
*
|
19 |
+
* @param string $type Message type.
|
20 |
+
* @param string $message Message, translated, to show to user.
|
21 |
+
* @param string $message_name The name of the message. This is only used for message that will be permanently dismissible.
|
22 |
+
*/
|
23 |
+
private static function show_message( $type = 'info', $message = '', $message_name = '' ) {
|
24 |
+
$data_attr = $message_name ? 'data-message-name="' . $message_name . '"' : '';
|
25 |
+
|
26 |
+
// Do not escape the message here as it's already escaped.
|
27 |
+
// Mark this as XSS ok for PHPCodesniffer because the message MUST be escaped beforehand.
|
28 |
+
printf(
|
29 |
+
'<div class="notice notice-%1$s is-dismissible" %2$s><p>%3$s</p></div>',
|
30 |
+
esc_attr( $type ),
|
31 |
+
$data_attr,
|
32 |
+
$message
|
33 |
+
); // WPCS: XSS ok.
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Show an info message
|
38 |
+
*
|
39 |
+
* @param string $message Message, translated, to be displayed.
|
40 |
+
* @param string $message_name The name of the message. This is only used for message that will be permanently dismissible.
|
41 |
+
*/
|
42 |
+
public static function show_info( $message = '', $message_name = '' ) {
|
43 |
+
if ( $message ) {
|
44 |
+
self::show_message( 'info', $message, $message_name );
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Show a success message
|
50 |
+
*
|
51 |
+
* @param string $message Message, translated, to be displayed.
|
52 |
+
* @param string $message_name The name of the message. This is only used for message that will be permanently dismissible.
|
53 |
+
*/
|
54 |
+
public static function show_success( $message = '', $message_name = '' ) {
|
55 |
+
if ( $message ) {
|
56 |
+
self::show_message( 'success', $message, $message_name );
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Show a warning message
|
62 |
+
*
|
63 |
+
* @param string $message Message, translated, to be displayed.
|
64 |
+
* @param string $message_name The name of the message. This is only used for message that will be permanently dismissible.
|
65 |
+
*/
|
66 |
+
public static function show_warning( $message = '', $message_name = '' ) {
|
67 |
+
if ( $message ) {
|
68 |
+
self::show_message( 'warning', $message, $message_name );
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Show an error message
|
74 |
+
*
|
75 |
+
* @param string $message Message, translated, to be displayed.
|
76 |
+
* @param string $message_name The name of the message. This is only used for message that will be permanently dismissible.
|
77 |
+
*/
|
78 |
+
public static function show_error( $message = '', $message_name = '' ) {
|
79 |
+
if ( $message ) {
|
80 |
+
self::show_message( 'error', $message, $message_name );
|
81 |
+
}
|
82 |
+
}
|
83 |
+
}
|
classes/class-plugin.php
ADDED
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Main plugin class to bootstrap everything else
|
4 |
+
*
|
5 |
+
* @package Kliken Marketing for Google
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace Kliken\WcPlugin;
|
9 |
+
|
10 |
+
defined( 'ABSPATH' ) || exit;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Plugin class
|
14 |
+
*/
|
15 |
+
class Plugin {
|
16 |
+
|
17 |
+
const ALREADY_BOOTSTRAPED = 1;
|
18 |
+
const DEPENDENCIES_UNSATISFIED = 2;
|
19 |
+
const DISMISS_POSTFIX = '_dismissed';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Flag to indicate the plugin has been boostrapped.
|
23 |
+
*
|
24 |
+
* @var bool
|
25 |
+
*/
|
26 |
+
private $_bootstrapped = false;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Try to register important hooks, with main stuff inside "plugins_loaded"
|
30 |
+
* so we can have checks for requirements/dependencies.
|
31 |
+
*/
|
32 |
+
public function maybe_run() {
|
33 |
+
register_activation_hook( KK_WC_PLUGIN_FILE, [ $this, 'activate' ] );
|
34 |
+
|
35 |
+
add_action( 'plugins_loaded', [ $this, 'bootstrap' ] );
|
36 |
+
|
37 |
+
add_filter( 'plugin_action_links_' . plugin_basename( KK_WC_PLUGIN_FILE ), [ $this, 'plugin_action_links' ] );
|
38 |
+
add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
|
39 |
+
|
40 |
+
if ( is_admin() ) {
|
41 |
+
add_action( 'wp_ajax_' . KK_WC_ACTION_DISMISS_NOTICE, [ $this, 'ajax_dismiss_notice' ] );
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Bootstrap the execution of the plugin.
|
47 |
+
*
|
48 |
+
* @throws \Exception Throw an exception if the plugin has been called before.
|
49 |
+
*/
|
50 |
+
public function bootstrap() {
|
51 |
+
try {
|
52 |
+
load_plugin_textdomain( 'kliken-marketing-for-google', false, KK_WC_PLUGIN_REL_PATH . '/languages' );
|
53 |
+
|
54 |
+
if ( $this->_bootstrapped ) {
|
55 |
+
throw new \Exception( __( 'Google Ads for WooCommerce plugin can only be called once', 'kliken-marketing-for-google' ), self::ALREADY_BOOTSTRAPED );
|
56 |
+
}
|
57 |
+
|
58 |
+
$this->check_dependencies();
|
59 |
+
$this->run();
|
60 |
+
|
61 |
+
$this->_bootstrapped = true;
|
62 |
+
} catch ( \Exception $e ) {
|
63 |
+
if ( in_array( $e->getCode(), [ self::ALREADY_BOOTSTRAPED, self::DEPENDENCIES_UNSATISFIED ] ) ) {
|
64 |
+
set_site_transient( KK_WC_BOOTSTRAP_MESSAGE, $e->getMessage(), MONTH_IN_SECONDS );
|
65 |
+
}
|
66 |
+
|
67 |
+
add_action( 'admin_notices', [ $this, 'show_bootstrap_message' ] );
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Run when the plugin is activated.
|
73 |
+
*/
|
74 |
+
public function activate() {
|
75 |
+
$saved_settings = Helper::get_plugin_options();
|
76 |
+
if ( empty( $saved_settings ) ) {
|
77 |
+
update_option( Helper::get_option_key(), [
|
78 |
+
'account_id' => 0,
|
79 |
+
'app_token' => '',
|
80 |
+
'google_token' => '',
|
81 |
+
] );
|
82 |
+
|
83 |
+
$has_account_id = false;
|
84 |
+
} else {
|
85 |
+
$has_account_id = Helper::is_valid_account_id( $saved_settings['account_id'] );
|
86 |
+
}
|
87 |
+
|
88 |
+
if ( ! $has_account_id ) {
|
89 |
+
// Try to find account id baked into the plugin zip.
|
90 |
+
$config_path = KK_WC_PLUGIN_DIR . 'config.php';
|
91 |
+
if ( file_exists( $config_path ) ) {
|
92 |
+
include_once $config_path;
|
93 |
+
|
94 |
+
// $kk_account_id and $kk_app_token are defined in the config file.
|
95 |
+
$authorization_url = Helper::save_account_info( $kk_account_id, $kk_app_token );
|
96 |
+
|
97 |
+
// Remove the file.
|
98 |
+
unlink( $config_path ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink
|
99 |
+
|
100 |
+
// Here we need to know if after activation we need to redirect to the WooCommerce Auth page or not.
|
101 |
+
if ( ! empty( $authorization_url ) ) {
|
102 |
+
set_site_transient( KK_WC_TRANSIENT_AUTH_REDIRECT, $authorization_url, MINUTE_IN_SECONDS );
|
103 |
+
}
|
104 |
+
} else {
|
105 |
+
// Seems to not have account info, we will try to show onboarding message, for a month, at top.
|
106 |
+
set_site_transient( KK_WC_WELCOME_MESSAGE, true, MONTH_IN_SECONDS );
|
107 |
+
}
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Add more links to plugin's "row" in the WordPress' plugin list,
|
113 |
+
* for more actions that user can do.
|
114 |
+
*
|
115 |
+
* @param array $links A list of links already registered.
|
116 |
+
* @return array
|
117 |
+
*/
|
118 |
+
public function plugin_action_links( $links ) {
|
119 |
+
$plugin_links = [];
|
120 |
+
|
121 |
+
if ( function_exists( 'wc' ) ) {
|
122 |
+
$plugin_links[] = '<a href="' . esc_url( Helper::get_plugin_page() ) . '">' . __( 'Dashboard', 'kliken-marketing-for-google' ) . '</a>';
|
123 |
+
}
|
124 |
+
|
125 |
+
$plugin_links[] = '<a href="https://kliken.com/contact/">' . __( 'Support', 'kliken-marketing-for-google' ) . '</a>';
|
126 |
+
|
127 |
+
return array_merge( $plugin_links, $links );
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Show bootstrap (warning) message if needed.
|
132 |
+
*/
|
133 |
+
public function show_bootstrap_message() {
|
134 |
+
$message = get_site_transient( KK_WC_BOOTSTRAP_MESSAGE );
|
135 |
+
|
136 |
+
if ( ! empty( $message )
|
137 |
+
&& false === get_option( KK_WC_BOOTSTRAP_MESSAGE . self::DISMISS_POSTFIX, false )
|
138 |
+
&& current_user_can( 'manage_options' ) ) {
|
139 |
+
Message::show_warning( $message, 'bsmessage' );
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Show onboarding (info) message if needed.
|
145 |
+
*/
|
146 |
+
public function show_onboarding_message() {
|
147 |
+
$settings = Helper::get_plugin_options();
|
148 |
+
|
149 |
+
if ( false !== get_site_transient( KK_WC_WELCOME_MESSAGE, false )
|
150 |
+
&& false === get_option( KK_WC_WELCOME_MESSAGE . self::DISMISS_POSTFIX, false )
|
151 |
+
&& current_user_can( 'manage_options' ) && ! Helper::is_plugin_page()
|
152 |
+
&& ! Helper::is_valid_account_id( $settings['account_id'] ) ) {
|
153 |
+
Message::show_info( Helper::get_onboarding_message(), 'welcome' );
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Add a new integration to WooCommerce.
|
159 |
+
*
|
160 |
+
* @param array $integrations List of integrations.
|
161 |
+
* @return array
|
162 |
+
*/
|
163 |
+
public function woocommerce_integrations( $integrations ) {
|
164 |
+
$integrations[] = '\\Kliken\\WcPlugin\\WC_Integration';
|
165 |
+
|
166 |
+
return $integrations;
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Add Tracking Script and Google Verification Token to site's header if available.
|
171 |
+
*/
|
172 |
+
public function wp_head() {
|
173 |
+
// Inject Google verification token.
|
174 |
+
Helper::add_google_verification_token();
|
175 |
+
|
176 |
+
// Inject tracking script.
|
177 |
+
Helper::add_tracking_script();
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Register custom REST API endpoints for WooCommerce.
|
182 |
+
*/
|
183 |
+
public function rest_api_init() {
|
184 |
+
( new REST_Misc_Controller() )->register_routes();
|
185 |
+
( new REST_Products_Controller() )->register_routes();
|
186 |
+
( new REST_Orders_Controller() )->register_routes();
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Stuff to do during admin initialization.
|
191 |
+
*/
|
192 |
+
public function admin_init() {
|
193 |
+
Helper::check_redirect_for_wc_auth();
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Enqueue script(s) needed for admin pages.
|
198 |
+
*/
|
199 |
+
public function admin_enqueue_scripts() {
|
200 |
+
wp_enqueue_script( 'kk-admin-script', KK_WC_PLUGIN_URL . 'assets/admin-script.js', [ 'jquery' ] );
|
201 |
+
|
202 |
+
wp_localize_script(
|
203 |
+
'kk-admin-script',
|
204 |
+
'dimissibleNotice',
|
205 |
+
[
|
206 |
+
'action' => KK_WC_ACTION_DISMISS_NOTICE,
|
207 |
+
'nonce' => wp_create_nonce( KK_WC_ACTION_DISMISS_NOTICE ),
|
208 |
+
'confirmMessage' => esc_html__( 'This will dismiss the message permanently. Are you sure?', 'kliken-marketing-for-google' ),
|
209 |
+
]
|
210 |
+
);
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Action to save account information after signing up.
|
215 |
+
*/
|
216 |
+
public function save_account() {
|
217 |
+
if ( ! isset( $_GET['t'] ) || ! wp_verify_nonce( sanitize_key( $_GET['t'] ), KK_WC_ACTION_SAVE_ACCOUNT ) ) { // WPCS: input var ok.
|
218 |
+
wp_nonce_ays( KK_WC_ACTION_SAVE_ACCOUNT );
|
219 |
+
}
|
220 |
+
|
221 |
+
// Default to redirect back to dashboard page.
|
222 |
+
$url = Helper::get_plugin_page();
|
223 |
+
|
224 |
+
if ( isset( $_GET['maid'], $_GET['appt'] ) ) { // WPCS: input var ok.
|
225 |
+
// Once account info is saved, we will have to do WooCommerce API Authorization again.
|
226 |
+
$authorization_url = Helper::save_account_info(
|
227 |
+
sanitize_text_field( wp_unslash( $_GET['maid'] ) ), // WPCS: input var ok.
|
228 |
+
sanitize_text_field( wp_unslash( $_GET['appt'] ) ) // WPCS: input var ok.
|
229 |
+
);
|
230 |
+
|
231 |
+
if ( $authorization_url ) {
|
232 |
+
$url = $authorization_url;
|
233 |
+
}
|
234 |
+
}
|
235 |
+
|
236 |
+
if ( $url ) {
|
237 |
+
wp_safe_redirect( $url );
|
238 |
+
exit;
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Action to handle AJAX request to permanently dismiss a notice.
|
244 |
+
*/
|
245 |
+
public function ajax_dismiss_notice() {
|
246 |
+
check_ajax_referer( KK_WC_ACTION_DISMISS_NOTICE );
|
247 |
+
|
248 |
+
if ( isset( $_POST['message_name'] ) ) { // WPCS: input var ok.
|
249 |
+
$message_name = sanitize_key( $_POST['message_name'] ); // WPCS: input var ok.
|
250 |
+
|
251 |
+
switch ( $message_name ) {
|
252 |
+
case 'welcome':
|
253 |
+
update_option( KK_WC_WELCOME_MESSAGE . self::DISMISS_POSTFIX, true );
|
254 |
+
break;
|
255 |
+
case 'bsmessage':
|
256 |
+
update_option( KK_WC_BOOTSTRAP_MESSAGE . self::DISMISS_POSTFIX, true );
|
257 |
+
delete_site_transient( KK_WC_BOOTSTRAP_MESSAGE );
|
258 |
+
break;
|
259 |
+
}
|
260 |
+
}
|
261 |
+
|
262 |
+
wp_die();
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Check if the dependencies of the plugin are satisfied.
|
267 |
+
* Here we need WooCommerce 3.0 or above, to be installed, and active.
|
268 |
+
*
|
269 |
+
* @throws \Exception Throw an exception if the dependency is not satisfied.
|
270 |
+
*/
|
271 |
+
private function check_dependencies() {
|
272 |
+
if ( ! function_exists( 'wc' ) ) {
|
273 |
+
throw new \Exception( __( 'Google Ads for WooCommerce requires WooCommerce to be activated', 'kliken-marketing-for-google' ), self::DEPENDENCIES_UNSATISFIED );
|
274 |
+
}
|
275 |
+
|
276 |
+
$required_woo_version = '3.0';
|
277 |
+
if ( version_compare( wc()->version, $required_woo_version, '<' ) ) {
|
278 |
+
/* translators: %s: Version number of WooCommerce required to run plugin. Do not translate. */
|
279 |
+
throw new \Exception( sprintf( __( 'Google Ads for WooCommerce requires WooCommerce version %s or greater', 'kliken-marketing-for-google' ), $required_woo_version ), self::DEPENDENCIES_UNSATISFIED );
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Main running point of the plugins. Responsible for hooking into different parts of WordPress and WooCommerce.
|
285 |
+
*/
|
286 |
+
private function run() {
|
287 |
+
add_filter( 'woocommerce_integrations', [ $this, 'woocommerce_integrations' ] );
|
288 |
+
add_action( 'wp_head', [ $this, 'wp_head' ] );
|
289 |
+
add_action( 'rest_api_init', [ $this, 'rest_api_init' ] );
|
290 |
+
add_action( 'admin_init', [ $this, 'admin_init' ] );
|
291 |
+
add_action( 'admin_notices', [ $this, 'show_onboarding_message' ] );
|
292 |
+
|
293 |
+
// Additional admin actions registered for handling requests.
|
294 |
+
if ( is_admin() ) {
|
295 |
+
// Handle request to save account info coming back from Kliken sign up page.
|
296 |
+
add_action( 'admin_action_' . KK_WC_ACTION_SAVE_ACCOUNT, [ $this, 'save_account' ] );
|
297 |
+
}
|
298 |
+
}
|
299 |
+
}
|
classes/class-rest-misc-controller.php
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* REST controller for miscellaneous endpoints.
|
4 |
+
*
|
5 |
+
* @package Kliken Marketing for Google
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace Kliken\WcPlugin;
|
9 |
+
|
10 |
+
defined( 'ABSPATH' ) || exit;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* REST API Misc controller class.
|
14 |
+
*
|
15 |
+
* @extends WC_REST_CRUD_Controller
|
16 |
+
*/
|
17 |
+
class REST_Misc_Controller extends \WC_REST_CRUD_Controller {
|
18 |
+
/**
|
19 |
+
* Endpoint namespace.
|
20 |
+
*
|
21 |
+
* @var string
|
22 |
+
*/
|
23 |
+
protected $namespace = 'wc-kliken/v1';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Register the routes we need.
|
27 |
+
*/
|
28 |
+
public function register_routes() {
|
29 |
+
register_rest_route(
|
30 |
+
$this->namespace, '/google-token', [
|
31 |
+
[
|
32 |
+
'methods' => \WP_REST_Server::CREATABLE,
|
33 |
+
'callback' => [ $this, 'save_google_token' ],
|
34 |
+
'permission_callback' => function() {
|
35 |
+
return current_user_can( 'manage_options' );
|
36 |
+
},
|
37 |
+
],
|
38 |
+
]
|
39 |
+
);
|
40 |
+
|
41 |
+
register_rest_route(
|
42 |
+
$this->namespace, '/shipping/wc-services', [
|
43 |
+
[
|
44 |
+
'methods' => \WP_REST_Server::READABLE,
|
45 |
+
'callback' => [ $this, 'get_wc_services_shipping_methods' ],
|
46 |
+
'permission_callback' => [ $this, 'get_shipping_methods_permissions_check' ],
|
47 |
+
],
|
48 |
+
]
|
49 |
+
);
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Save Google Verification Token to database so we can later on display it as a header's meta.
|
54 |
+
*
|
55 |
+
* @param WP_REST_Request $request Full details about the request.
|
56 |
+
* @return WP_Error|WP_REST_Response
|
57 |
+
*/
|
58 |
+
public function save_google_token( $request ) {
|
59 |
+
// If we know more about Google's token specifications, we can have more strict rules
|
60 |
+
// For now, just sanitize the token as a text string (no tags, no simple injections).
|
61 |
+
$token = sanitize_text_field( $request->get_param( 'token' ) );
|
62 |
+
if ( ! $token ) {
|
63 |
+
return new \WP_Error( 'rest_bad_request', __( 'Invalid Data', 'kliken-marketing-for-google' ), [ 'status' => 400 ] );
|
64 |
+
}
|
65 |
+
|
66 |
+
$saved_settings = Helper::get_plugin_options();
|
67 |
+
$saved_settings['google_token'] = $token;
|
68 |
+
|
69 |
+
// Save the token to database.
|
70 |
+
update_option( Helper::get_option_key(), $saved_settings );
|
71 |
+
|
72 |
+
// But WP_REST_Response is only available since 4.4?
|
73 |
+
return new \WP_REST_Response( null, 201 );
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Get shipping services associated with a WooCommerce Services Carrier shipping method.
|
78 |
+
* Because for some reason, WooCommerce does not return that with their API endpoints.
|
79 |
+
*
|
80 |
+
* @param WP_REST_Request $request Full details about the request.
|
81 |
+
* @return WP_Error|WP_REST_Response
|
82 |
+
*/
|
83 |
+
public function get_wc_services_shipping_methods( $request ) {
|
84 |
+
$id = (int) $request['id'];
|
85 |
+
$carrier_name = $request['carrier'];
|
86 |
+
|
87 |
+
// Get the option from database.
|
88 |
+
$data = get_option( "woocommerce_wc_services_{$carrier_name}_{$id}_form_settings" );
|
89 |
+
|
90 |
+
if ( ! $data || empty( $data ) || empty( $data->services ) ) {
|
91 |
+
return new \WP_Error( 'no_wc_services', __( 'Invalid Data', 'kliken-marketing-for-google' ), [ 'status' => 404 ] );
|
92 |
+
}
|
93 |
+
|
94 |
+
$carrier_services = [];
|
95 |
+
|
96 |
+
foreach ( $data->services as $key => $service ) {
|
97 |
+
if ( true !== $service['enabled'] ) {
|
98 |
+
continue;
|
99 |
+
}
|
100 |
+
|
101 |
+
array_push(
|
102 |
+
$carrier_services, [
|
103 |
+
'service_name' => $service['id'],
|
104 |
+
'adjustment' => $service['adjustment'],
|
105 |
+
'adjustment_type' => $service['adjustment_type'],
|
106 |
+
]
|
107 |
+
);
|
108 |
+
}
|
109 |
+
|
110 |
+
$response = rest_ensure_response(
|
111 |
+
[
|
112 |
+
'carrier_name' => $data->title,
|
113 |
+
'carrier_services' => $carrier_services,
|
114 |
+
]
|
115 |
+
);
|
116 |
+
|
117 |
+
return $response;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Check whether a given request has permission to view shipping methods.
|
122 |
+
*
|
123 |
+
* @param WP_REST_Request $request Full details about the request.
|
124 |
+
* @return WP_Error|boolean
|
125 |
+
*/
|
126 |
+
public function get_shipping_methods_permissions_check( $request ) {
|
127 |
+
if ( ! wc_rest_check_manager_permissions( 'shipping_methods', 'read' ) ) {
|
128 |
+
return new \WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'kliken-marketing-for-google' ), [ 'status' => rest_authorization_required_code() ] );
|
129 |
+
}
|
130 |
+
return true;
|
131 |
+
}
|
132 |
+
}
|
classes/class-rest-orders-controller.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* REST controller for getting orders, extending of what WooCommerce
|
4 |
+
* does not provide at the moment.
|
5 |
+
*
|
6 |
+
* @package Kliken Marketing for Google
|
7 |
+
*/
|
8 |
+
|
9 |
+
namespace Kliken\WcPlugin;
|
10 |
+
|
11 |
+
defined( 'ABSPATH' ) || exit;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* REST API Orders controller class.
|
15 |
+
*
|
16 |
+
* @extends WC_REST_Orders_Controller
|
17 |
+
*/
|
18 |
+
class REST_Orders_Controller extends \WC_REST_Orders_Controller {
|
19 |
+
/**
|
20 |
+
* Endpoint namespace.
|
21 |
+
*
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected $namespace = 'wc-kliken/v1';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Register the routes for products.
|
28 |
+
*/
|
29 |
+
public function register_routes() {
|
30 |
+
register_rest_route(
|
31 |
+
$this->namespace, '/orders/modified', [
|
32 |
+
[
|
33 |
+
'methods' => \WP_REST_Server::READABLE,
|
34 |
+
'callback' => [ $this, 'get_items' ],
|
35 |
+
'permission_callback' => [ $this, 'get_items_permissions_check' ],
|
36 |
+
],
|
37 |
+
]
|
38 |
+
);
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Prepare objects query to get modified orders.
|
43 |
+
*
|
44 |
+
* @since 3.0.0
|
45 |
+
* @param WP_REST_Request $request Full details about the request.
|
46 |
+
* @return array
|
47 |
+
*/
|
48 |
+
protected function prepare_objects_query( $request ) {
|
49 |
+
$args = parent::prepare_objects_query( $request );
|
50 |
+
|
51 |
+
// Reset the date query to look up post_modified column instead.
|
52 |
+
if ( ! empty( $args['date_query'] ) ) {
|
53 |
+
if ( isset( $request['before'] ) ) {
|
54 |
+
$args['date_query'][0]['column'] = 'post_modified';
|
55 |
+
$args['date_query'][0]['before'] = $request['before'];
|
56 |
+
}
|
57 |
+
|
58 |
+
if ( isset( $request['after'] ) ) {
|
59 |
+
$args['date_query'][0]['column'] = 'post_modified';
|
60 |
+
$args['date_query'][0]['after'] = $request['after'];
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
return $args;
|
65 |
+
}
|
66 |
+
}
|
classes/class-rest-products-controller.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* REST controller for getting products, extending of what WooCommerce
|
4 |
+
* does not provide at the moment.
|
5 |
+
*
|
6 |
+
* @package Kliken Marketing for Google
|
7 |
+
*/
|
8 |
+
|
9 |
+
namespace Kliken\WcPlugin;
|
10 |
+
|
11 |
+
defined( 'ABSPATH' ) || exit;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* REST API Products controller class.
|
15 |
+
*
|
16 |
+
* @extends WC_REST_Products_Controller_Compat
|
17 |
+
*/
|
18 |
+
class REST_Products_Controller extends WC_REST_Products_Controller_Compat {
|
19 |
+
/**
|
20 |
+
* Endpoint namespace.
|
21 |
+
*
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected $namespace = 'wc-kliken/v1';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Register the routes for products.
|
28 |
+
*/
|
29 |
+
public function register_routes() {
|
30 |
+
register_rest_route(
|
31 |
+
$this->namespace, '/products/modified', [
|
32 |
+
[
|
33 |
+
'methods' => \WP_REST_Server::READABLE,
|
34 |
+
'callback' => [ $this, 'get_items' ],
|
35 |
+
'permission_callback' => [ $this, 'get_items_permissions_check' ],
|
36 |
+
],
|
37 |
+
]
|
38 |
+
);
|
39 |
+
|
40 |
+
register_rest_route(
|
41 |
+
$this->namespace, '/products/deleted', [
|
42 |
+
[
|
43 |
+
'methods' => \WP_REST_Server::READABLE,
|
44 |
+
'callback' => [ $this, 'get_deleted_products' ],
|
45 |
+
'permission_callback' => [ $this, 'get_items_permissions_check' ],
|
46 |
+
],
|
47 |
+
]
|
48 |
+
);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Get deleted/trashed products.
|
53 |
+
*
|
54 |
+
* @param WP_REST_Request $request Full details about the request.
|
55 |
+
* @return WP_Error|WP_REST_Response
|
56 |
+
*/
|
57 |
+
public function get_deleted_products( $request ) {
|
58 |
+
$page = intval( $request['page'] );
|
59 |
+
$per_page = intval( $request['per_page'] );
|
60 |
+
|
61 |
+
$query_args = [
|
62 |
+
'fields' => 'ids', // We only need post ids for this.
|
63 |
+
'post_type' => $this->post_type,
|
64 |
+
'post_status' => 'trash',
|
65 |
+
'ignore_sticky_posts' => true,
|
66 |
+
'paged' => 0 === $page ? 1 : $page,
|
67 |
+
'posts_per_page' => 0 === $per_page ? 100 : $per_page,
|
68 |
+
'orderby' => 'modified',
|
69 |
+
'order' => 'ASC',
|
70 |
+
];
|
71 |
+
|
72 |
+
$query_args['date_query'] = [];
|
73 |
+
// Set before into date query. Date query must be specified as an array of an array.
|
74 |
+
if ( isset( $request['before'] ) ) {
|
75 |
+
$query_args['date_query'][0]['column'] = 'post_modified';
|
76 |
+
$query_args['date_query'][0]['before'] = $request['before'];
|
77 |
+
}
|
78 |
+
|
79 |
+
// Set after into date query. Date query must be specified as an array of an array.
|
80 |
+
if ( isset( $request['after'] ) ) {
|
81 |
+
$query_args['date_query'][0]['column'] = 'post_modified';
|
82 |
+
$query_args['date_query'][0]['after'] = $request['after'];
|
83 |
+
}
|
84 |
+
|
85 |
+
$query = new \WP_Query();
|
86 |
+
$result = $query->query( $query_args );
|
87 |
+
|
88 |
+
$total_posts = $query->found_posts;
|
89 |
+
if ( $total_posts < 1 ) {
|
90 |
+
// Out-of-bounds, run the query again without LIMIT for total count.
|
91 |
+
unset( $query_args['paged'] );
|
92 |
+
$count_query = new \WP_Query();
|
93 |
+
$count_query->query( $query_args );
|
94 |
+
$total_posts = $count_query->found_posts;
|
95 |
+
}
|
96 |
+
|
97 |
+
$response = rest_ensure_response( $result );
|
98 |
+
$response->header( 'X-WP-Total', (int) $total_posts );
|
99 |
+
$response->header( 'X-WP-TotalPages', (int) ceil( $total_posts / (int) $query_args['posts_per_page'] ) );
|
100 |
+
|
101 |
+
return $response;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Prepare objects query to get modified products.
|
106 |
+
*
|
107 |
+
* @since 3.0.0
|
108 |
+
* @param WP_REST_Request $request Full details about the request.
|
109 |
+
* @return array
|
110 |
+
*/
|
111 |
+
protected function prepare_objects_query( $request ) {
|
112 |
+
$args = parent::prepare_objects_query( $request );
|
113 |
+
|
114 |
+
// Reset the date query to look up post_modified column instead.
|
115 |
+
if ( ! empty( $args['date_query'] ) ) {
|
116 |
+
if ( isset( $request['before'] ) ) {
|
117 |
+
$args['date_query'][0]['column'] = 'post_modified';
|
118 |
+
$args['date_query'][0]['before'] = $request['before'];
|
119 |
+
}
|
120 |
+
|
121 |
+
if ( isset( $request['after'] ) ) {
|
122 |
+
$args['date_query'][0]['column'] = 'post_modified';
|
123 |
+
$args['date_query'][0]['after'] = $request['after'];
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
return $args;
|
128 |
+
}
|
129 |
+
}
|
classes/class-wc-integration.php
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Integration class to hook plugin settings into WooCommerce's Settings Integration tab
|
4 |
+
*
|
5 |
+
* @package Kliken Marketing for Google
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace Kliken\WcPlugin;
|
9 |
+
|
10 |
+
defined( 'ABSPATH' ) || exit;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* WooCommerce Integration class
|
14 |
+
*/
|
15 |
+
class WC_Integration extends \WC_Integration {
|
16 |
+
/**
|
17 |
+
* Constructor. Default to also init.
|
18 |
+
*
|
19 |
+
* @param boolean $init If class initialization is also needed.
|
20 |
+
*/
|
21 |
+
public function __construct( $init = true ) {
|
22 |
+
global $woocommerce;
|
23 |
+
|
24 |
+
$this->id = KK_WC_INTEGRATION_PAGE_ID;
|
25 |
+
$this->method_title = __( 'Google Ads for WooCommerce', 'kliken-marketing-for-google' ); // This is for the sub-section text.
|
26 |
+
|
27 |
+
if ( true === $init ) {
|
28 |
+
// Load the settings.
|
29 |
+
$this->init_form_fields();
|
30 |
+
$this->init_settings();
|
31 |
+
|
32 |
+
$this->account_id = $this->get_option( 'account_id' );
|
33 |
+
$this->app_token = $this->get_option( 'app_token' );
|
34 |
+
|
35 |
+
// Action to save the options.
|
36 |
+
add_action( 'woocommerce_update_options_integration_' . $this->id, [ $this, 'process_admin_options' ] );
|
37 |
+
add_filter( 'woocommerce_settings_api_sanitized_fields_' . $this->id, [ $this, 'sanitize_settings' ] );
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Initialize integration settings form fields.
|
43 |
+
*/
|
44 |
+
public function init_form_fields() {
|
45 |
+
$this->form_fields = [
|
46 |
+
'account_id' => [
|
47 |
+
'title' => __( 'Account Id', 'kliken-marketing-for-google' ),
|
48 |
+
'type' => 'text',
|
49 |
+
'default' => '',
|
50 |
+
],
|
51 |
+
'app_token' => [
|
52 |
+
'title' => __( 'Application Token', 'kliken-marketing-for-google' ),
|
53 |
+
'type' => 'text',
|
54 |
+
'default' => '',
|
55 |
+
],
|
56 |
+
'google_token' => [
|
57 |
+
'title' => __( 'Google Verification Token', 'kliken-marketing-for-google' ),
|
58 |
+
'type' => 'text',
|
59 |
+
'default' => '',
|
60 |
+
],
|
61 |
+
'guide_link' => [
|
62 |
+
'type' => 'desc',
|
63 |
+
'description' => '<a href="https://support.sitewit.com/hc/en-us/articles/360016107933-WooCommerce-Advanced-Options" target="_blank" rel="noopener noreferrer">' . __( 'What are these options?', 'kliken-marketing-for-google' ) . '</a>',
|
64 |
+
'desc_tip' => '',
|
65 |
+
],
|
66 |
+
];
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Display "options" area.
|
71 |
+
*/
|
72 |
+
public function admin_options() {
|
73 |
+
Helper::check_redirect_for_wc_auth();
|
74 |
+
|
75 |
+
// So this is the way WordPress hide the save button *facepalming*.
|
76 |
+
$GLOBALS['hide_save_button'] = true;
|
77 |
+
|
78 |
+
include_once KK_WC_PLUGIN_DIR . 'pages/admin-style.php';
|
79 |
+
|
80 |
+
if ( Helper::is_valid_account_id( $this->settings['account_id'] )
|
81 |
+
&& Helper::is_valid_app_token( $this->settings['app_token'] )
|
82 |
+
) {
|
83 |
+
// Already have account info. Show dashboard.
|
84 |
+
include_once KK_WC_PLUGIN_DIR . 'pages/dashboard.php';
|
85 |
+
} else {
|
86 |
+
// Show sign up form.
|
87 |
+
include_once KK_WC_PLUGIN_DIR . 'pages/getstarted.php';
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Generate HTML code for "desc" field.
|
93 |
+
* This is a custom field for display a descriptive info line alongside other fields.
|
94 |
+
*
|
95 |
+
* @param string $key Field key.
|
96 |
+
* @param array $data Field data.
|
97 |
+
*/
|
98 |
+
public function generate_desc_html( $key, $data ) {
|
99 |
+
ob_start();
|
100 |
+
?>
|
101 |
+
<tr valign="top">
|
102 |
+
<th scope="row" class="titledesc" style="padding: 0;">
|
103 |
+
</th>
|
104 |
+
<td class="forminp" style="padding: 0 0 0 10px;">
|
105 |
+
<fieldset>
|
106 |
+
<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
|
107 |
+
</fieldset>
|
108 |
+
</td>
|
109 |
+
</tr>
|
110 |
+
<?php
|
111 |
+
return ob_get_clean();
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Sanitize setting values before saving to the database
|
116 |
+
*
|
117 |
+
* @param array $settings Array of fields setting values being submitted.
|
118 |
+
* @return array
|
119 |
+
*/
|
120 |
+
public function sanitize_settings( $settings ) {
|
121 |
+
// Validate account id as an integer.
|
122 |
+
$settings['account_id'] = intval( $settings['account_id'] );
|
123 |
+
|
124 |
+
// Sanitize token.
|
125 |
+
$settings['app_token'] = sanitize_text_field( $settings['app_token'] );
|
126 |
+
|
127 |
+
// Sanitize google verification token.
|
128 |
+
$settings['google_token'] = sanitize_text_field( $settings['google_token'] );
|
129 |
+
|
130 |
+
if ( 0 === $settings['account_id'] || '' === $settings['app_token'] ) {
|
131 |
+
// No (valid) values were entered, we should show onboarding/welcome message.
|
132 |
+
set_site_transient( KK_WC_WELCOME_MESSAGE, true, MONTH_IN_SECONDS );
|
133 |
+
} elseif ( intval( $this->account_id ) !== $settings['account_id']
|
134 |
+
|| $settings['app_token'] !== $this->app_token
|
135 |
+
) {
|
136 |
+
// If the values changed, we want to redirect them to the WooCommerce Authorization page immediately after save.
|
137 |
+
$authorization_url = Helper::build_authorization_url( $settings['account_id'], $settings['app_token'] );
|
138 |
+
if ( ! empty( $authorization_url ) ) {
|
139 |
+
set_site_transient( KK_WC_TRANSIENT_AUTH_REDIRECT, $authorization_url, MINUTE_IN_SECONDS );
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
return $settings;
|
144 |
+
}
|
145 |
+
}
|
classes/class-wc-rest-products-controller-compat.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Adapter class to provide compatibility to WooCommerce version < 3.5.0, when
|
4 |
+
* the version 3 of WooCommerce REST API was introduced.
|
5 |
+
*
|
6 |
+
* @package Kliken Marketing for Google
|
7 |
+
*/
|
8 |
+
|
9 |
+
namespace Kliken\WcPlugin;
|
10 |
+
|
11 |
+
defined( 'ABSPATH' ) || exit;
|
12 |
+
|
13 |
+
if ( class_exists( '\WC_REST_Products_V2_Controller' ) ) {
|
14 |
+
/**
|
15 |
+
* WooCommerce at > v2. We still try to extend from the v2 of the class.
|
16 |
+
*/
|
17 |
+
class WC_REST_Products_Controller_Compat extends \WC_REST_Products_V2_Controller { }
|
18 |
+
} else {
|
19 |
+
/**
|
20 |
+
* WooCommerce at v2. This might become legacy soon.
|
21 |
+
*/
|
22 |
+
class WC_REST_Products_Controller_Compat extends \WC_REST_Products_Controller { }
|
23 |
+
}
|
kliken-marketing-for-google.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
Plugin Name: Google Ads for WooCommerce
|
4 |
+
Plugin URI: https://woo.kliken.com/
|
5 |
+
Description: The automated Google Shopping solution to get your products found on Google, and grow your WooCommerce Store!
|
6 |
+
Version: 1.0.2
|
7 |
+
Author: Kliken
|
8 |
+
Author URI: http://kliken.com/
|
9 |
+
Developer: Kliken
|
10 |
+
Developer URI: http://kliken.com/
|
11 |
+
Text Domain: kliken-marketing-for-google
|
12 |
+
Domain path: /languages
|
13 |
+
|
14 |
+
WC requires at least: 3.0
|
15 |
+
WC tested up to: 3.9
|
16 |
+
|
17 |
+
License: GNU General Public License v3.0
|
18 |
+
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
19 |
+
|
20 |
+
@package Kliken Marketing for Google
|
21 |
+
*/
|
22 |
+
|
23 |
+
defined( 'ABSPATH' ) || exit;
|
24 |
+
|
25 |
+
define( 'KK_WC_PLUGIN_FILE', __FILE__ );
|
26 |
+
define( 'KK_WC_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
27 |
+
define( 'KK_WC_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
28 |
+
define( 'KK_WC_PLUGIN_REL_PATH', basename( dirname( __FILE__ ) ) );
|
29 |
+
define( 'KK_WC_AFFILIATE_ID', '82E7B644-DB42-40E9-9EDF-6FD10A4BAFB3' );
|
30 |
+
define( 'KK_WC_WOOKLIKEN_BASE_URL', 'https://woo.kliken.com/' );
|
31 |
+
define( 'KK_WC_AUTH_CALLBACK_URL', 'https://app.mysite-analytics.com/WebHooks/WooCommerceAuth/' );
|
32 |
+
define( 'KK_WC_AUTH_APP_NAME', 'Google Ads for WooCommerce' );
|
33 |
+
|
34 |
+
define( 'KK_WC_INTEGRATION_PAGE_ID', 'kk_wcintegration' );
|
35 |
+
|
36 |
+
define( 'KK_WC_ACTION_SAVE_ACCOUNT', 'kkwc_saveaccount' );
|
37 |
+
define( 'KK_WC_ACTION_DISMISS_NOTICE', 'kkwc_dismissnotice' );
|
38 |
+
define( 'KK_WC_ACTION_CHECK_ACCOUNT', 'kkwc_checkaccount' );
|
39 |
+
|
40 |
+
define( 'KK_WC_TRANSIENT_AUTH_REDIRECT', 'kk_wc_activation_redirect' );
|
41 |
+
|
42 |
+
define( 'KK_WC_WELCOME_MESSAGE', 'kk_wc_welcome_message' );
|
43 |
+
define( 'KK_WC_BOOTSTRAP_MESSAGE', 'kk_wc_bootstrap_message' );
|
44 |
+
|
45 |
+
require 'vendor/autoload.php';
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Starting point. Try to initiate the main instance of the plugin.
|
49 |
+
*/
|
50 |
+
function kk_wc_plugin() {
|
51 |
+
static $plugin;
|
52 |
+
|
53 |
+
if ( ! isset( $plugin ) ) {
|
54 |
+
$plugin = new \Kliken\WcPlugin\Plugin();
|
55 |
+
}
|
56 |
+
|
57 |
+
return $plugin;
|
58 |
+
}
|
59 |
+
|
60 |
+
// Adopt this nice method from WooCommerce.
|
61 |
+
kk_wc_plugin()->maybe_run();
|
languages/kliken-marketing-for-google-de_CH.mo
ADDED
Binary file
|
languages/kliken-marketing-for-google-de_DE.mo
ADDED
Binary file
|
languages/kliken-marketing-for-google-es_ES.mo
ADDED
Binary file
|
languages/kliken-marketing-for-google-fr_FR.mo
ADDED
Binary file
|
languages/kliken-marketing-for-google-nl_NL.mo
ADDED
Binary file
|
languages/kliken-marketing-for-google.pot
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (C) 2020 Kliken
|
2 |
+
# This file is distributed under the GNU General Public License v3.0.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"Project-Id-Version: Google Ads for WooCommerce 1.0.2\n"
|
6 |
+
"Report-Msgid-Bugs-To: http://www.sitewit.com/contact/\n"
|
7 |
+
"POT-Creation-Date: 2020-02-18 16:30:32+00:00\n"
|
8 |
+
"MIME-Version: 1.0\n"
|
9 |
+
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
+
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n"
|
12 |
+
"Last-Translator: SiteWit <wordpress@sitewit.com>\n"
|
13 |
+
"Language-Team: SiteWit <wordpress@sitewit.com>\n"
|
14 |
+
"Language: en\n"
|
15 |
+
"Plural-Forms: nplurals=2; plural=n !=\n"
|
16 |
+
"X-Poedit-Country: United States\n"
|
17 |
+
"X-Poedit-SourceCharset: UTF-8\n"
|
18 |
+
"X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;"
|
19 |
+
"_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;"
|
20 |
+
"esc_html_x:1,2c;\n"
|
21 |
+
"X-Poedit-Basepath: ../\n"
|
22 |
+
"X-Poedit-SearchPath-0: .\n"
|
23 |
+
"X-Poedit-Bookmarks: \n"
|
24 |
+
"X-Textdomain-Support: yes\n"
|
25 |
+
"X-Generator: grunt-wp-i18n1.0.2\n"
|
26 |
+
|
27 |
+
#. translators: %s: A hyperlink
|
28 |
+
#: classes/class-helper.php:410
|
29 |
+
msgid ""
|
30 |
+
"<strong>Google Ads for WooCommerce plugin is almost ready.</strong> <a href="
|
31 |
+
"\"%s\">Click here</a> to get started."
|
32 |
+
msgstr ""
|
33 |
+
|
34 |
+
#: classes/class-plugin.php:55
|
35 |
+
msgid "Google Ads for WooCommerce plugin can only be called once"
|
36 |
+
msgstr ""
|
37 |
+
|
38 |
+
#: classes/class-plugin.php:122
|
39 |
+
msgid "Dashboard"
|
40 |
+
msgstr ""
|
41 |
+
|
42 |
+
#: classes/class-plugin.php:125
|
43 |
+
msgid "Support"
|
44 |
+
msgstr ""
|
45 |
+
|
46 |
+
#: classes/class-plugin.php:208
|
47 |
+
msgid "This will dismiss the message permanently. Are you sure?"
|
48 |
+
msgstr ""
|
49 |
+
|
50 |
+
#: classes/class-plugin.php:273
|
51 |
+
msgid "Google Ads for WooCommerce requires WooCommerce to be activated"
|
52 |
+
msgstr ""
|
53 |
+
|
54 |
+
#. translators: %s: Version number of WooCommerce required to run plugin. Do
|
55 |
+
#. not translate.
|
56 |
+
#: classes/class-plugin.php:279
|
57 |
+
msgid "Google Ads for WooCommerce requires WooCommerce version %s or greater"
|
58 |
+
msgstr ""
|
59 |
+
|
60 |
+
#: classes/class-rest-misc-controller.php:63
|
61 |
+
#: classes/class-rest-misc-controller.php:91
|
62 |
+
msgid "Invalid Data"
|
63 |
+
msgstr ""
|
64 |
+
|
65 |
+
#: classes/class-rest-misc-controller.php:128
|
66 |
+
msgid "Sorry, you cannot list resources."
|
67 |
+
msgstr ""
|
68 |
+
|
69 |
+
#. Plugin Name of the plugin/theme
|
70 |
+
msgid "Google Ads for WooCommerce"
|
71 |
+
msgstr ""
|
72 |
+
|
73 |
+
#: classes/class-wc-integration.php:47
|
74 |
+
msgid "Account Id"
|
75 |
+
msgstr ""
|
76 |
+
|
77 |
+
#: classes/class-wc-integration.php:52
|
78 |
+
msgid "Application Token"
|
79 |
+
msgstr ""
|
80 |
+
|
81 |
+
#: classes/class-wc-integration.php:57
|
82 |
+
msgid "Google Verification Token"
|
83 |
+
msgstr ""
|
84 |
+
|
85 |
+
#: classes/class-wc-integration.php:63
|
86 |
+
msgid "What are these options?"
|
87 |
+
msgstr ""
|
88 |
+
|
89 |
+
#: pages/dashboard.php:15
|
90 |
+
msgid "Launch Google Shopping ads and get your products found online easily."
|
91 |
+
msgstr ""
|
92 |
+
|
93 |
+
#: pages/dashboard.php:26
|
94 |
+
msgid "Your store is connected."
|
95 |
+
msgstr ""
|
96 |
+
|
97 |
+
#: pages/dashboard.php:28
|
98 |
+
msgid "Your WooCommerce store is connected to your Kliken account."
|
99 |
+
msgstr ""
|
100 |
+
|
101 |
+
#: pages/dashboard.php:34
|
102 |
+
msgid "Campaign Dashboard"
|
103 |
+
msgstr ""
|
104 |
+
|
105 |
+
#: pages/dashboard.php:36
|
106 |
+
msgid "Open your dashboard to review your campaign's performance"
|
107 |
+
msgstr ""
|
108 |
+
|
109 |
+
#: pages/dashboard.php:41
|
110 |
+
msgid "Create a New Google Shopping Campaign"
|
111 |
+
msgstr ""
|
112 |
+
|
113 |
+
#: pages/dashboard.php:43
|
114 |
+
msgid ""
|
115 |
+
"Build a campaign in a few minutes, and sell to customers as they search for "
|
116 |
+
"your products on Google."
|
117 |
+
msgstr ""
|
118 |
+
|
119 |
+
#: pages/dashboard.php:48
|
120 |
+
msgid "Manage Campaigns"
|
121 |
+
msgstr ""
|
122 |
+
|
123 |
+
#: pages/dashboard.php:50
|
124 |
+
msgid ""
|
125 |
+
"Make changes to your active campaigns, purchase one you built, or reinstate "
|
126 |
+
"your cancelled campaigns."
|
127 |
+
msgstr ""
|
128 |
+
|
129 |
+
#: pages/dashboard.php:56
|
130 |
+
msgid "Advanced Options"
|
131 |
+
msgstr ""
|
132 |
+
|
133 |
+
#: pages/dashboard.php:67
|
134 |
+
msgid "Enable Edit"
|
135 |
+
msgstr ""
|
136 |
+
|
137 |
+
#: pages/dashboard.php:68
|
138 |
+
msgid "Save Changes"
|
139 |
+
msgstr ""
|
140 |
+
|
141 |
+
#: pages/dashboard.php:72
|
142 |
+
msgid "Authorize API Access"
|
143 |
+
msgstr ""
|
144 |
+
|
145 |
+
#: pages/getstarted.php:30
|
146 |
+
msgid "Launch Google Shopping Ads and get your products found online easily."
|
147 |
+
msgstr ""
|
148 |
+
|
149 |
+
#: pages/getstarted.php:41
|
150 |
+
msgid "Increase sales and revenue with Google Shopping Ads"
|
151 |
+
msgstr ""
|
152 |
+
|
153 |
+
#: pages/getstarted.php:43
|
154 |
+
msgid "Use this WooCommerce and Google Ads integration to:"
|
155 |
+
msgstr ""
|
156 |
+
|
157 |
+
#: pages/getstarted.php:45
|
158 |
+
msgid "Find more customers on Google"
|
159 |
+
msgstr ""
|
160 |
+
|
161 |
+
#: pages/getstarted.php:46
|
162 |
+
msgid "Automate bidding to maximize sales for your marketing budget"
|
163 |
+
msgstr ""
|
164 |
+
|
165 |
+
#: pages/getstarted.php:47
|
166 |
+
msgid "Keep your marketing and store in sync"
|
167 |
+
msgstr ""
|
168 |
+
|
169 |
+
#: pages/getstarted.php:48
|
170 |
+
msgid "Create perfect shopping campaigns in minutes"
|
171 |
+
msgstr ""
|
172 |
+
|
173 |
+
#: pages/getstarted.php:51
|
174 |
+
msgid "Get Started"
|
175 |
+
msgstr ""
|
176 |
+
|
177 |
+
#. Plugin URI of the plugin/theme
|
178 |
+
msgid "https://woo.kliken.com/"
|
179 |
+
msgstr ""
|
180 |
+
|
181 |
+
#. Description of the plugin/theme
|
182 |
+
msgid ""
|
183 |
+
"The automated Google Shopping solution to get your products found on Google, "
|
184 |
+
"and grow your WooCommerce Store!"
|
185 |
+
msgstr ""
|
186 |
+
|
187 |
+
#. Author of the plugin/theme
|
188 |
+
msgid "Kliken"
|
189 |
+
msgstr ""
|
190 |
+
|
191 |
+
#. Author URI of the plugin/theme
|
192 |
+
msgid "http://kliken.com/"
|
193 |
+
msgstr ""
|
pages/admin-style.php
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<style>
|
2 |
+
.kk-wrapper {
|
3 |
+
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
|
4 |
+
font-size: 13pt;
|
5 |
+
font-style: normal;
|
6 |
+
font-variant: normal;
|
7 |
+
}
|
8 |
+
|
9 |
+
.kk-wrapper h1 {
|
10 |
+
font-size: 18pt!important;
|
11 |
+
font-weight: bold!important;
|
12 |
+
}
|
13 |
+
|
14 |
+
.kk-wrapper h2 {
|
15 |
+
font-size: 17pt!important;
|
16 |
+
}
|
17 |
+
|
18 |
+
.kk-wrapper p {
|
19 |
+
font-size: 13pt;
|
20 |
+
}
|
21 |
+
|
22 |
+
.kk-wrapper .subhdr {
|
23 |
+
font-size: 14pt;
|
24 |
+
}
|
25 |
+
|
26 |
+
.kk-wrapper ul {
|
27 |
+
list-style-type: disc;
|
28 |
+
margin: 16pt 16pt 38pt 16pt;
|
29 |
+
}
|
30 |
+
|
31 |
+
.kk-wrapper .kk-box {
|
32 |
+
max-width: 825px;
|
33 |
+
margin-top: 20pt;
|
34 |
+
}
|
35 |
+
|
36 |
+
.kk-wrapper .kk-box-header {
|
37 |
+
border: 1px solid #cccccc;
|
38 |
+
background-color: #f6f6f6;
|
39 |
+
}
|
40 |
+
|
41 |
+
.kk-wrapper .kk-box-content {
|
42 |
+
background-color: white;
|
43 |
+
border: 1px solid #cccccc;
|
44 |
+
padding: 30px;
|
45 |
+
}
|
46 |
+
|
47 |
+
.kk-wrapper .sub-heading {
|
48 |
+
font-size: 14pt;
|
49 |
+
text-decoration: none;
|
50 |
+
font-weight: bold;
|
51 |
+
margin-top: 10px;
|
52 |
+
color: #4883af!important;
|
53 |
+
}
|
54 |
+
|
55 |
+
.kk-wrapper .sub-note {
|
56 |
+
margin-top: 0;
|
57 |
+
}
|
58 |
+
|
59 |
+
.kk-wrapper .kk-img-container {
|
60 |
+
margin: 20px;
|
61 |
+
}
|
62 |
+
|
63 |
+
.kk-wrapper .kk-google-img {
|
64 |
+
height: 40px;
|
65 |
+
display: block;
|
66 |
+
margin-bottom: -5px;
|
67 |
+
}
|
68 |
+
|
69 |
+
.kk-wrapper .kk-poweredby-img {
|
70 |
+
margin-left: 65px;
|
71 |
+
}
|
72 |
+
|
73 |
+
.kk-wrapper .kk-link {
|
74 |
+
margin-top: 30px;
|
75 |
+
}
|
76 |
+
|
77 |
+
.kk-wrapper summary {
|
78 |
+
margin-top: 25px;
|
79 |
+
margin-bottom: 10px;
|
80 |
+
color: #4883af!important;
|
81 |
+
cursor: pointer;
|
82 |
+
}
|
83 |
+
|
84 |
+
.kk-wrapper summary:focus {
|
85 |
+
outline: none;
|
86 |
+
}
|
87 |
+
|
88 |
+
.kk-wrapper .input-text.regular-input {
|
89 |
+
width: 100%!important;
|
90 |
+
max-width: 400px!important;
|
91 |
+
}
|
92 |
+
</style>
|
pages/dashboard.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Dashboard page.
|
4 |
+
*
|
5 |
+
* @package Kliken Marketing for Google
|
6 |
+
*/
|
7 |
+
|
8 |
+
defined( 'ABSPATH' ) || exit;
|
9 |
+
|
10 |
+
?>
|
11 |
+
|
12 |
+
<div class="wrap kk-wrapper">
|
13 |
+
<h2><?php esc_html_e( 'Google Ads for WooCommerce', 'kliken-marketing-for-google' ); ?></h2>
|
14 |
+
|
15 |
+
<p><?php esc_html_e( 'Launch Google Shopping ads and get your products found online easily.', 'kliken-marketing-for-google' ); ?></p>
|
16 |
+
|
17 |
+
<div class="kk-box">
|
18 |
+
<div class="kk-box-header">
|
19 |
+
<div class="kk-img-container">
|
20 |
+
<img src="https://d9hhrg4mnvzow.cloudfront.net/start.kliken.com/woo/40c24363-googleheader-logo.svg" alt="Google Logo" height="40" class="kk-google-img">
|
21 |
+
<img src="https://d9hhrg4mnvzow.cloudfront.net/start.kliken.com/woo/1ab26a95-powderedbykliken_03600c03500c000000.png" alt="Powered by Kliken" class="kk-poweredby-img">
|
22 |
+
</div>
|
23 |
+
</div>
|
24 |
+
|
25 |
+
<div class="kk-box-content">
|
26 |
+
<h1><?php esc_html_e( 'Your store is connected.', 'kliken-marketing-for-google' ); ?></h1>
|
27 |
+
|
28 |
+
<p class="subhdr"><?php esc_html_e( 'Your WooCommerce store is connected to your Kliken account.', 'kliken-marketing-for-google' ); ?></p>
|
29 |
+
|
30 |
+
<hr>
|
31 |
+
|
32 |
+
<div class="kk-link">
|
33 |
+
<a class="sub-heading" href="<?php echo esc_url( KK_WC_WOOKLIKEN_BASE_URL . 'smb/shopping/dashboard' ); ?>">
|
34 |
+
<?php esc_html_e( 'Campaign Dashboard', 'kliken-marketing-for-google' ); ?>
|
35 |
+
</a>
|
36 |
+
<p class="sub-note"><?php esc_html_e( 'Open your dashboard to review your campaign\'s performance', 'kliken-marketing-for-google' ); ?></p>
|
37 |
+
</div>
|
38 |
+
|
39 |
+
<div class="kk-link">
|
40 |
+
<a class="sub-heading" href="<?php echo esc_url( KK_WC_WOOKLIKEN_BASE_URL . 'smb/shopping/create' ); ?>">
|
41 |
+
<?php esc_html_e( 'Create a New Google Shopping Campaign', 'kliken-marketing-for-google' ); ?>
|
42 |
+
</a>
|
43 |
+
<p class="sub-note"><?php esc_html_e( 'Build a campaign in a few minutes, and sell to customers as they search for your products on Google.', 'kliken-marketing-for-google' ); ?></p>
|
44 |
+
</div>
|
45 |
+
|
46 |
+
<div class="kk-link">
|
47 |
+
<a class="sub-heading" href="<?php echo esc_url( KK_WC_WOOKLIKEN_BASE_URL . 'smb/shopping/manage' ); ?>">
|
48 |
+
<?php esc_html_e( 'Manage Campaigns', 'kliken-marketing-for-google' ); ?>
|
49 |
+
</a>
|
50 |
+
<p class="sub-note"><?php esc_html_e( 'Make changes to your active campaigns, purchase one you built, or reinstate your cancelled campaigns.', 'kliken-marketing-for-google' ); ?></p>
|
51 |
+
</div>
|
52 |
+
|
53 |
+
<hr>
|
54 |
+
|
55 |
+
<details class="primer advanced-settings">
|
56 |
+
<summary><?php esc_html_e( 'Advanced Options', 'kliken-marketing-for-google' ); ?></summary>
|
57 |
+
|
58 |
+
<div>
|
59 |
+
<input type="hidden" name="section" value="<?php echo esc_attr( $this->id ); ?>" />
|
60 |
+
</div>
|
61 |
+
<table class="form-table">
|
62 |
+
<?php
|
63 |
+
// NOTE: these methods are only available if this file is included within a WC_Integration extended class.
|
64 |
+
$this->generate_settings_html( $this->get_form_fields() ); // WPCS: XSS ok.
|
65 |
+
?>
|
66 |
+
</table>
|
67 |
+
<button type="button" class="button button-default" id="enable-settings-edit"><?php esc_html_e( 'Enable Edit', 'kliken-marketing-for-google' ); ?></button>
|
68 |
+
<button type="submit" class="button-primary woocommerce-save-button" name="save" id="submit" value="Save changes"><?php esc_html_e( 'Save Changes', 'kliken-marketing-for-google' ); ?></button>
|
69 |
+
|
70 |
+
<hr>
|
71 |
+
<a href="<?php echo esc_url( \Kliken\WcPlugin\Helper::build_authorization_url( $this->account_id, $this->app_token ) ); ?>">
|
72 |
+
<button type="button" class="button button-primary" id="authorize-api-access"><?php esc_html_e( 'Authorize API Access', 'kliken-marketing-for-google' ); ?></button>
|
73 |
+
</a>
|
74 |
+
</details>
|
75 |
+
</div>
|
76 |
+
</div>
|
77 |
+
</div>
|
78 |
+
|
79 |
+
<script>
|
80 |
+
jQuery(document).ready(function() {
|
81 |
+
// Disable setting inputs, and hide submit button
|
82 |
+
jQuery(".advanced-settings input[type=text]").prop("disabled", true);
|
83 |
+
jQuery("#submit").prop("disabled", true).hide();
|
84 |
+
|
85 |
+
jQuery("#enable-settings-edit").click(function() {
|
86 |
+
jQuery(".advanced-settings input[type=text]").prop("disabled", false);
|
87 |
+
jQuery("#submit").prop("disabled", false).show();
|
88 |
+
|
89 |
+
// Hide the button itself
|
90 |
+
jQuery(this).hide();
|
91 |
+
});
|
92 |
+
});
|
93 |
+
</script>
|
pages/getstarted.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Get started page.
|
4 |
+
*
|
5 |
+
* @package Kliken Marketing for Google
|
6 |
+
*/
|
7 |
+
|
8 |
+
defined( 'ABSPATH' ) || exit;
|
9 |
+
|
10 |
+
?>
|
11 |
+
|
12 |
+
<style>
|
13 |
+
#getstarted_btn {
|
14 |
+
background-color: #ff6600;
|
15 |
+
color: #fff;
|
16 |
+
padding: 10px 20px;
|
17 |
+
font-size: 14px;
|
18 |
+
text-decoration: none;
|
19 |
+
font-family: "Lato",sans-serif;
|
20 |
+
line-height: 35px;
|
21 |
+
font-weight: 700;
|
22 |
+
letter-spacing: 2px !important;
|
23 |
+
text-transform: uppercase;
|
24 |
+
}
|
25 |
+
</style>
|
26 |
+
|
27 |
+
<div class="wrap kk-wrapper">
|
28 |
+
<h2><?php esc_html_e( 'Google Ads for WooCommerce', 'kliken-marketing-for-google' ); ?></h2>
|
29 |
+
|
30 |
+
<p><?php esc_html_e( 'Launch Google Shopping Ads and get your products found online easily.', 'kliken-marketing-for-google' ); ?></p>
|
31 |
+
|
32 |
+
<div class="kk-box">
|
33 |
+
<div class="kk-box-header">
|
34 |
+
<div class="kk-img-container">
|
35 |
+
<img src="https://d9hhrg4mnvzow.cloudfront.net/start.kliken.com/woo/40c24363-googleheader-logo.svg" alt="Google Logo" height="40" class="kk-google-img">
|
36 |
+
<img src="https://d9hhrg4mnvzow.cloudfront.net/start.kliken.com/woo/1ab26a95-powderedbykliken_03600c03500c000000.png" alt="Powered by Kliken" class="kk-poweredby-img">
|
37 |
+
</div>
|
38 |
+
</div>
|
39 |
+
|
40 |
+
<div class="kk-box-content">
|
41 |
+
<h1><?php esc_html_e( 'Increase sales and revenue with Google Shopping Ads', 'kliken-marketing-for-google' ); ?></h1>
|
42 |
+
|
43 |
+
<p class="subhdr"><?php esc_html_e( 'Use this WooCommerce and Google Ads integration to:', 'kliken-marketing-for-google' ); ?></h5>
|
44 |
+
<ul>
|
45 |
+
<li><?php esc_html_e( 'Find more customers on Google', 'kliken-marketing-for-google' ); ?></li>
|
46 |
+
<li><?php esc_html_e( 'Automate bidding to maximize sales for your marketing budget', 'kliken-marketing-for-google' ); ?></li>
|
47 |
+
<li><?php esc_html_e( 'Keep your marketing and store in sync', 'kliken-marketing-for-google' ); ?></li>
|
48 |
+
<li><?php esc_html_e( 'Create perfect shopping campaigns in minutes', 'kliken-marketing-for-google' ); ?></li>
|
49 |
+
</ul>
|
50 |
+
|
51 |
+
<a id="getstarted_btn" href="<?php echo esc_url( \Kliken\WcPlugin\Helper::build_signup_link() ); ?>"><?php esc_html_e( 'Get Started', 'kliken-marketing-for-google' ); ?></a>
|
52 |
+
</div>
|
53 |
+
</div>
|
54 |
+
</div>
|
pages/trackingscript.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Contains JS script to include our main tracking script.
|
4 |
+
*
|
5 |
+
* @package Kliken Marketing for Google
|
6 |
+
*/
|
7 |
+
|
8 |
+
defined( 'ABSPATH' ) || exit;
|
9 |
+
|
10 |
+
?>
|
11 |
+
|
12 |
+
<script type="text/javascript">
|
13 |
+
var _swaMa=["<?php echo esc_attr( $account_id ); ?>"];"undefined"==typeof sw&&!function(e,s,a){function t(){for(;o[0]&&"loaded"==o[0][d];)i=o.shift(),i[w]=!c.parentNode.insertBefore(i,c)}for(var r,n,i,o=[],c=e.scripts[0],w="onreadystatechange",d="readyState";r=a.shift();)n=e.createElement(s),"async"in c?(n.async=!1,e.head.appendChild(n)):c[d]?(o.push(n),n[w]=t):e.write("<"+s+' src="'+r+'" defer></'+s+">"),n.src=r}(document,"script",["//analytics.sitewit.com/v3/"+_swaMa[0]+"/sw.js"]);
|
14 |
+
</script>
|
pages/transactionscript.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Contains JS script to register a transaction up on order received page.
|
4 |
+
*
|
5 |
+
* @package Kliken Marketing for Google
|
6 |
+
*/
|
7 |
+
|
8 |
+
defined( 'ABSPATH' ) || exit;
|
9 |
+
|
10 |
+
?>
|
11 |
+
|
12 |
+
<script type="text/javascript">
|
13 |
+
var swPreRegister = function() {
|
14 |
+
sw.gawCurrency = "<?php echo esc_attr( $trans['currency'] ); ?>";
|
15 |
+
|
16 |
+
var trans = sw.create_transaction(
|
17 |
+
"<?php echo esc_attr( $trans['order_id'] ); ?>",
|
18 |
+
"<?php echo esc_attr( $trans['affiliate'] ); ?>",
|
19 |
+
"<?php echo esc_attr( $trans['sub_total'] ); ?>",
|
20 |
+
"<?php echo esc_attr( $trans['tax'] ); ?>",
|
21 |
+
"<?php echo esc_attr( $trans['city'] ); ?>",
|
22 |
+
"<?php echo esc_attr( $trans['state'] ); ?>",
|
23 |
+
"<?php echo esc_attr( $trans['country'] ); ?>",
|
24 |
+
"<?php echo esc_attr( $trans['total'] ); ?>",
|
25 |
+
);
|
26 |
+
|
27 |
+
<?php foreach ( $trans['items'] as $index => $item ) : ?>
|
28 |
+
trans.add_item(
|
29 |
+
"<?php echo esc_attr( $item['sku'] ); ?>",
|
30 |
+
"<?php echo esc_attr( $item['name'] ); ?>",
|
31 |
+
"<?php echo esc_attr( $item['category'] ); ?>",
|
32 |
+
"<?php echo esc_attr( $item['price'] ); ?>",
|
33 |
+
"<?php echo esc_attr( $item['quantity'] ); ?>",
|
34 |
+
);
|
35 |
+
<?php endforeach; ?>
|
36 |
+
|
37 |
+
sw.hit.set_page("ORDER_CONFIRMATION");
|
38 |
+
};
|
39 |
+
</script>
|
readme.txt
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== Google Ads for WooCommerce ===
|
2 |
+
Contributors: sitewit
|
3 |
+
Tags: advertising, adwords, analytics, bing, google, leads, marketing, marketing platform, metrics, online advertising, online marketing, plugin, ppc, PPC, google shopping, shopping ads, product ads, ROI, conversions
|
4 |
+
Requires at least: 4.4
|
5 |
+
Tested up to: 5.3
|
6 |
+
Requires PHP: 5.6
|
7 |
+
Stable tag: 1.0.2
|
8 |
+
License: GPLv3 or later License
|
9 |
+
URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
+
|
11 |
+
Google Shopping Ads are the most effective way to advertise your Woo store and increase sales and revenue.
|
12 |
+
|
13 |
+
|
14 |
+
== Description ==
|
15 |
+
In a few simple steps, generate a fully optimized Google Shopping Ads campaign. Select what categories you want to advertise and we automatically generate smart Google Shopping feeds, automate bidding to maximize your return on advertising spend, and measure conversions and sales for your marketing.
|
16 |
+
|
17 |
+
= Benefits =
|
18 |
+
|
19 |
+
* Find more customers on Google when they are searching for your products.
|
20 |
+
* Get the most out of your marketing through our automated bidding which maximizes sales for your marketing budget.
|
21 |
+
* Keep your marketing and store in sync, ensuring you only market products that are in inventory and keeping the Google campaigns and Woo store in sync automatically.
|
22 |
+
* Create perfect shopping campaigns in minutes using best practices to maximize effectiveness, including smart product feeds and advanced bidding by product.
|
23 |
+
|
24 |
+
= How does it work? =
|
25 |
+
|
26 |
+
1. Start building a campaign. No credit card necessary to build your marketing campaign.
|
27 |
+
2. Select the geographical location you want to target.
|
28 |
+
3. Select what store categories you want to advertise.
|
29 |
+
4. Select a budget.
|
30 |
+
5. Purchase your campaign and start marketing on Google Shopping
|
31 |
+
|
32 |
+
No long term contract, you can cancel at any time.
|
33 |
+
|
34 |
+
Google Ads for WooCommerce is the easiest, lowest risk way to advertise your Woo store on Google Shopping and is brought to you by Kliken in collaboration with WooCommerce and Google, working together to bring you the best Google Ads experience fully integrated into your WooCommerce store, optimized to maximize your online sales.
|
35 |
+
|
36 |
+
|
37 |
+
== Frequently Asked Questions ==
|
38 |
+
|
39 |
+
= How does billing work? =
|
40 |
+
Your Google Shopping campaign is billed monthly to help keep your product ads online. You will be billed the same amount each time for the package level you choose. This way you know the exact costs of your campaign each month.
|
41 |
+
|
42 |
+
= How do I cancel my subscription? =
|
43 |
+
The Google Shopping campaign is a contract free service. You can cancel your subscription at anytime from the Google Shopping app under the Manage section. When a campaign is cancelled, it will continue to run the remainder of the billed month, or until it has used the remaining Google Ads balance.
|
44 |
+
|
45 |
+
= What is the Kliken Fee? =
|
46 |
+
This is our monthly fee for creating, managing, and optimizing all aspects of your Google Shopping campaign.
|
47 |
+
|
48 |
+
|
49 |
+
== Changelog ==
|
50 |
+
|
51 |
+
= 1.0.2 =
|
52 |
+
* Minor bug fixes.
|
53 |
+
|
54 |
+
= 1.0.1 =
|
55 |
+
* Minor UI improvements.
|
56 |
+
* Minor bug fixes.
|
57 |
+
|
58 |
+
= 1.0.0 =
|
59 |
+
* First release.
|
uninstall.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Uninstall script.
|
4 |
+
*
|
5 |
+
* @package Kliken Marketing for Google
|
6 |
+
*/
|
7 |
+
|
8 |
+
defined( 'ABSPATH' ) || exit;
|
9 |
+
|
10 |
+
defined( 'WP_UNINSTALL_PLUGIN' ) || exit;
|
11 |
+
|
12 |
+
delete_option( 'kk_wc_settings' );
|
13 |
+
delete_option( 'woocommerce_kk_wcintegration_settings' );
|
14 |
+
|
15 |
+
delete_site_transient( 'kk_wc_activation_redirect' );
|
16 |
+
|
17 |
+
delete_site_transient( 'kk_wc_welcome_message' );
|
18 |
+
delete_option( 'kk_wc_welcome_message_dismissed' );
|
19 |
+
delete_site_transient( 'kk_wc_bootstrap_message' );
|
20 |
+
delete_option( 'kk_wc_bootstrap_message_dismissed' );
|
vendor/autoload.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload.php @generated by Composer
|
4 |
+
|
5 |
+
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
+
|
7 |
+
return ComposerAutoloaderInit8d05e6ff15e07dd67db7d411953e0c56::getLoader();
|
vendor/composer/ClassLoader.php
ADDED
@@ -0,0 +1,445 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* This file is part of Composer.
|
5 |
+
*
|
6 |
+
* (c) Nils Adermann <naderman@naderman.de>
|
7 |
+
* Jordi Boggiano <j.boggiano@seld.be>
|
8 |
+
*
|
9 |
+
* For the full copyright and license information, please view the LICENSE
|
10 |
+
* file that was distributed with this source code.
|
11 |
+
*/
|
12 |
+
|
13 |
+
namespace Composer\Autoload;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
17 |
+
*
|
18 |
+
* $loader = new \Composer\Autoload\ClassLoader();
|
19 |
+
*
|
20 |
+
* // register classes with namespaces
|
21 |
+
* $loader->add('Symfony\Component', __DIR__.'/component');
|
22 |
+
* $loader->add('Symfony', __DIR__.'/framework');
|
23 |
+
*
|
24 |
+
* // activate the autoloader
|
25 |
+
* $loader->register();
|
26 |
+
*
|
27 |
+
* // to enable searching the include path (eg. for PEAR packages)
|
28 |
+
* $loader->setUseIncludePath(true);
|
29 |
+
*
|
30 |
+
* In this example, if you try to use a class in the Symfony\Component
|
31 |
+
* namespace or one of its children (Symfony\Component\Console for instance),
|
32 |
+
* the autoloader will first look for the class under the component/
|
33 |
+
* directory, and it will then fallback to the framework/ directory if not
|
34 |
+
* found before giving up.
|
35 |
+
*
|
36 |
+
* This class is loosely based on the Symfony UniversalClassLoader.
|
37 |
+
*
|
38 |
+
* @author Fabien Potencier <fabien@symfony.com>
|
39 |
+
* @author Jordi Boggiano <j.boggiano@seld.be>
|
40 |
+
* @see http://www.php-fig.org/psr/psr-0/
|
41 |
+
* @see http://www.php-fig.org/psr/psr-4/
|
42 |
+
*/
|
43 |
+
class ClassLoader
|
44 |
+
{
|
45 |
+
// PSR-4
|
46 |
+
private $prefixLengthsPsr4 = array();
|
47 |
+
private $prefixDirsPsr4 = array();
|
48 |
+
private $fallbackDirsPsr4 = array();
|
49 |
+
|
50 |
+
// PSR-0
|
51 |
+
private $prefixesPsr0 = array();
|
52 |
+
private $fallbackDirsPsr0 = array();
|
53 |
+
|
54 |
+
private $useIncludePath = false;
|
55 |
+
private $classMap = array();
|
56 |
+
private $classMapAuthoritative = false;
|
57 |
+
private $missingClasses = array();
|
58 |
+
private $apcuPrefix;
|
59 |
+
|
60 |
+
public function getPrefixes()
|
61 |
+
{
|
62 |
+
if (!empty($this->prefixesPsr0)) {
|
63 |
+
return call_user_func_array('array_merge', $this->prefixesPsr0);
|
64 |
+
}
|
65 |
+
|
66 |
+
return array();
|
67 |
+
}
|
68 |
+
|
69 |
+
public function getPrefixesPsr4()
|
70 |
+
{
|
71 |
+
return $this->prefixDirsPsr4;
|
72 |
+
}
|
73 |
+
|
74 |
+
public function getFallbackDirs()
|
75 |
+
{
|
76 |
+
return $this->fallbackDirsPsr0;
|
77 |
+
}
|
78 |
+
|
79 |
+
public function getFallbackDirsPsr4()
|
80 |
+
{
|
81 |
+
return $this->fallbackDirsPsr4;
|
82 |
+
}
|
83 |
+
|
84 |
+
public function getClassMap()
|
85 |
+
{
|
86 |
+
return $this->classMap;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @param array $classMap Class to filename map
|
91 |
+
*/
|
92 |
+
public function addClassMap(array $classMap)
|
93 |
+
{
|
94 |
+
if ($this->classMap) {
|
95 |
+
$this->classMap = array_merge($this->classMap, $classMap);
|
96 |
+
} else {
|
97 |
+
$this->classMap = $classMap;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Registers a set of PSR-0 directories for a given prefix, either
|
103 |
+
* appending or prepending to the ones previously set for this prefix.
|
104 |
+
*
|
105 |
+
* @param string $prefix The prefix
|
106 |
+
* @param array|string $paths The PSR-0 root directories
|
107 |
+
* @param bool $prepend Whether to prepend the directories
|
108 |
+
*/
|
109 |
+
public function add($prefix, $paths, $prepend = false)
|
110 |
+
{
|
111 |
+
if (!$prefix) {
|
112 |
+
if ($prepend) {
|
113 |
+
$this->fallbackDirsPsr0 = array_merge(
|
114 |
+
(array) $paths,
|
115 |
+
$this->fallbackDirsPsr0
|
116 |
+
);
|
117 |
+
} else {
|
118 |
+
$this->fallbackDirsPsr0 = array_merge(
|
119 |
+
$this->fallbackDirsPsr0,
|
120 |
+
(array) $paths
|
121 |
+
);
|
122 |
+
}
|
123 |
+
|
124 |
+
return;
|
125 |
+
}
|
126 |
+
|
127 |
+
$first = $prefix[0];
|
128 |
+
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
129 |
+
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
130 |
+
|
131 |
+
return;
|
132 |
+
}
|
133 |
+
if ($prepend) {
|
134 |
+
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
135 |
+
(array) $paths,
|
136 |
+
$this->prefixesPsr0[$first][$prefix]
|
137 |
+
);
|
138 |
+
} else {
|
139 |
+
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
140 |
+
$this->prefixesPsr0[$first][$prefix],
|
141 |
+
(array) $paths
|
142 |
+
);
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Registers a set of PSR-4 directories for a given namespace, either
|
148 |
+
* appending or prepending to the ones previously set for this namespace.
|
149 |
+
*
|
150 |
+
* @param string $prefix The prefix/namespace, with trailing '\\'
|
151 |
+
* @param array|string $paths The PSR-4 base directories
|
152 |
+
* @param bool $prepend Whether to prepend the directories
|
153 |
+
*
|
154 |
+
* @throws \InvalidArgumentException
|
155 |
+
*/
|
156 |
+
public function addPsr4($prefix, $paths, $prepend = false)
|
157 |
+
{
|
158 |
+
if (!$prefix) {
|
159 |
+
// Register directories for the root namespace.
|
160 |
+
if ($prepend) {
|
161 |
+
$this->fallbackDirsPsr4 = array_merge(
|
162 |
+
(array) $paths,
|
163 |
+
$this->fallbackDirsPsr4
|
164 |
+
);
|
165 |
+
} else {
|
166 |
+
$this->fallbackDirsPsr4 = array_merge(
|
167 |
+
$this->fallbackDirsPsr4,
|
168 |
+
(array) $paths
|
169 |
+
);
|
170 |
+
}
|
171 |
+
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
172 |
+
// Register directories for a new namespace.
|
173 |
+
$length = strlen($prefix);
|
174 |
+
if ('\\' !== $prefix[$length - 1]) {
|
175 |
+
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
176 |
+
}
|
177 |
+
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
178 |
+
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
179 |
+
} elseif ($prepend) {
|
180 |
+
// Prepend directories for an already registered namespace.
|
181 |
+
$this->prefixDirsPsr4[$prefix] = array_merge(
|
182 |
+
(array) $paths,
|
183 |
+
$this->prefixDirsPsr4[$prefix]
|
184 |
+
);
|
185 |
+
} else {
|
186 |
+
// Append directories for an already registered namespace.
|
187 |
+
$this->prefixDirsPsr4[$prefix] = array_merge(
|
188 |
+
$this->prefixDirsPsr4[$prefix],
|
189 |
+
(array) $paths
|
190 |
+
);
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Registers a set of PSR-0 directories for a given prefix,
|
196 |
+
* replacing any others previously set for this prefix.
|
197 |
+
*
|
198 |
+
* @param string $prefix The prefix
|
199 |
+
* @param array|string $paths The PSR-0 base directories
|
200 |
+
*/
|
201 |
+
public function set($prefix, $paths)
|
202 |
+
{
|
203 |
+
if (!$prefix) {
|
204 |
+
$this->fallbackDirsPsr0 = (array) $paths;
|
205 |
+
} else {
|
206 |
+
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Registers a set of PSR-4 directories for a given namespace,
|
212 |
+
* replacing any others previously set for this namespace.
|
213 |
+
*
|
214 |
+
* @param string $prefix The prefix/namespace, with trailing '\\'
|
215 |
+
* @param array|string $paths The PSR-4 base directories
|
216 |
+
*
|
217 |
+
* @throws \InvalidArgumentException
|
218 |
+
*/
|
219 |
+
public function setPsr4($prefix, $paths)
|
220 |
+
{
|
221 |
+
if (!$prefix) {
|
222 |
+
$this->fallbackDirsPsr4 = (array) $paths;
|
223 |
+
} else {
|
224 |
+
$length = strlen($prefix);
|
225 |
+
if ('\\' !== $prefix[$length - 1]) {
|
226 |
+
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
227 |
+
}
|
228 |
+
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
229 |
+
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
230 |
+
}
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Turns on searching the include path for class files.
|
235 |
+
*
|
236 |
+
* @param bool $useIncludePath
|
237 |
+
*/
|
238 |
+
public function setUseIncludePath($useIncludePath)
|
239 |
+
{
|
240 |
+
$this->useIncludePath = $useIncludePath;
|
241 |
+
}
|
242 |
+
|
243 |
+
/**
|
244 |
+
* Can be used to check if the autoloader uses the include path to check
|
245 |
+
* for classes.
|
246 |
+
*
|
247 |
+
* @return bool
|
248 |
+
*/
|
249 |
+
public function getUseIncludePath()
|
250 |
+
{
|
251 |
+
return $this->useIncludePath;
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Turns off searching the prefix and fallback directories for classes
|
256 |
+
* that have not been registered with the class map.
|
257 |
+
*
|
258 |
+
* @param bool $classMapAuthoritative
|
259 |
+
*/
|
260 |
+
public function setClassMapAuthoritative($classMapAuthoritative)
|
261 |
+
{
|
262 |
+
$this->classMapAuthoritative = $classMapAuthoritative;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Should class lookup fail if not found in the current class map?
|
267 |
+
*
|
268 |
+
* @return bool
|
269 |
+
*/
|
270 |
+
public function isClassMapAuthoritative()
|
271 |
+
{
|
272 |
+
return $this->classMapAuthoritative;
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
277 |
+
*
|
278 |
+
* @param string|null $apcuPrefix
|
279 |
+
*/
|
280 |
+
public function setApcuPrefix($apcuPrefix)
|
281 |
+
{
|
282 |
+
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* The APCu prefix in use, or null if APCu caching is not enabled.
|
287 |
+
*
|
288 |
+
* @return string|null
|
289 |
+
*/
|
290 |
+
public function getApcuPrefix()
|
291 |
+
{
|
292 |
+
return $this->apcuPrefix;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Registers this instance as an autoloader.
|
297 |
+
*
|
298 |
+
* @param bool $prepend Whether to prepend the autoloader or not
|
299 |
+
*/
|
300 |
+
public function register($prepend = false)
|
301 |
+
{
|
302 |
+
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
303 |
+
}
|
304 |
+
|
305 |
+
/**
|
306 |
+
* Unregisters this instance as an autoloader.
|
307 |
+
*/
|
308 |
+
public function unregister()
|
309 |
+
{
|
310 |
+
spl_autoload_unregister(array($this, 'loadClass'));
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Loads the given class or interface.
|
315 |
+
*
|
316 |
+
* @param string $class The name of the class
|
317 |
+
* @return bool|null True if loaded, null otherwise
|
318 |
+
*/
|
319 |
+
public function loadClass($class)
|
320 |
+
{
|
321 |
+
if ($file = $this->findFile($class)) {
|
322 |
+
includeFile($file);
|
323 |
+
|
324 |
+
return true;
|
325 |
+
}
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* Finds the path to the file where the class is defined.
|
330 |
+
*
|
331 |
+
* @param string $class The name of the class
|
332 |
+
*
|
333 |
+
* @return string|false The path if found, false otherwise
|
334 |
+
*/
|
335 |
+
public function findFile($class)
|
336 |
+
{
|
337 |
+
// class map lookup
|
338 |
+
if (isset($this->classMap[$class])) {
|
339 |
+
return $this->classMap[$class];
|
340 |
+
}
|
341 |
+
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
342 |
+
return false;
|
343 |
+
}
|
344 |
+
if (null !== $this->apcuPrefix) {
|
345 |
+
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
346 |
+
if ($hit) {
|
347 |
+
return $file;
|
348 |
+
}
|
349 |
+
}
|
350 |
+
|
351 |
+
$file = $this->findFileWithExtension($class, '.php');
|
352 |
+
|
353 |
+
// Search for Hack files if we are running on HHVM
|
354 |
+
if (false === $file && defined('HHVM_VERSION')) {
|
355 |
+
$file = $this->findFileWithExtension($class, '.hh');
|
356 |
+
}
|
357 |
+
|
358 |
+
if (null !== $this->apcuPrefix) {
|
359 |
+
apcu_add($this->apcuPrefix.$class, $file);
|
360 |
+
}
|
361 |
+
|
362 |
+
if (false === $file) {
|
363 |
+
// Remember that this class does not exist.
|
364 |
+
$this->missingClasses[$class] = true;
|
365 |
+
}
|
366 |
+
|
367 |
+
return $file;
|
368 |
+
}
|
369 |
+
|
370 |
+
private function findFileWithExtension($class, $ext)
|
371 |
+
{
|
372 |
+
// PSR-4 lookup
|
373 |
+
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
374 |
+
|
375 |
+
$first = $class[0];
|
376 |
+
if (isset($this->prefixLengthsPsr4[$first])) {
|
377 |
+
$subPath = $class;
|
378 |
+
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
379 |
+
$subPath = substr($subPath, 0, $lastPos);
|
380 |
+
$search = $subPath.'\\';
|
381 |
+
if (isset($this->prefixDirsPsr4[$search])) {
|
382 |
+
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
383 |
+
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
384 |
+
if (file_exists($file = $dir . $pathEnd)) {
|
385 |
+
return $file;
|
386 |
+
}
|
387 |
+
}
|
388 |
+
}
|
389 |
+
}
|
390 |
+
}
|
391 |
+
|
392 |
+
// PSR-4 fallback dirs
|
393 |
+
foreach ($this->fallbackDirsPsr4 as $dir) {
|
394 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
395 |
+
return $file;
|
396 |
+
}
|
397 |
+
}
|
398 |
+
|
399 |
+
// PSR-0 lookup
|
400 |
+
if (false !== $pos = strrpos($class, '\\')) {
|
401 |
+
// namespaced class name
|
402 |
+
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
403 |
+
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
404 |
+
} else {
|
405 |
+
// PEAR-like class name
|
406 |
+
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
407 |
+
}
|
408 |
+
|
409 |
+
if (isset($this->prefixesPsr0[$first])) {
|
410 |
+
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
411 |
+
if (0 === strpos($class, $prefix)) {
|
412 |
+
foreach ($dirs as $dir) {
|
413 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
414 |
+
return $file;
|
415 |
+
}
|
416 |
+
}
|
417 |
+
}
|
418 |
+
}
|
419 |
+
}
|
420 |
+
|
421 |
+
// PSR-0 fallback dirs
|
422 |
+
foreach ($this->fallbackDirsPsr0 as $dir) {
|
423 |
+
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
424 |
+
return $file;
|
425 |
+
}
|
426 |
+
}
|
427 |
+
|
428 |
+
// PSR-0 include paths.
|
429 |
+
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
430 |
+
return $file;
|
431 |
+
}
|
432 |
+
|
433 |
+
return false;
|
434 |
+
}
|
435 |
+
}
|
436 |
+
|
437 |
+
/**
|
438 |
+
* Scope isolated include.
|
439 |
+
*
|
440 |
+
* Prevents access to $this/self from included files.
|
441 |
+
*/
|
442 |
+
function includeFile($file)
|
443 |
+
{
|
444 |
+
include $file;
|
445 |
+
}
|
vendor/composer/LICENSE
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
2 |
+
Upstream-Name: Composer
|
3 |
+
Upstream-Contact: Jordi Boggiano <j.boggiano@seld.be>
|
4 |
+
Source: https://github.com/composer/composer
|
5 |
+
|
6 |
+
Files: *
|
7 |
+
Copyright: 2016, Nils Adermann <naderman@naderman.de>
|
8 |
+
2016, Jordi Boggiano <j.boggiano@seld.be>
|
9 |
+
License: Expat
|
10 |
+
|
11 |
+
Files: src/Composer/Util/TlsHelper.php
|
12 |
+
Copyright: 2016, Nils Adermann <naderman@naderman.de>
|
13 |
+
2016, Jordi Boggiano <j.boggiano@seld.be>
|
14 |
+
2013, Evan Coury <me@evancoury.com>
|
15 |
+
License: Expat and BSD-2-Clause
|
16 |
+
|
17 |
+
License: BSD-2-Clause
|
18 |
+
Redistribution and use in source and binary forms, with or without modification,
|
19 |
+
are permitted provided that the following conditions are met:
|
20 |
+
.
|
21 |
+
* Redistributions of source code must retain the above copyright notice,
|
22 |
+
this list of conditions and the following disclaimer.
|
23 |
+
.
|
24 |
+
* Redistributions in binary form must reproduce the above copyright notice,
|
25 |
+
this list of conditions and the following disclaimer in the documentation
|
26 |
+
and/or other materials provided with the distribution.
|
27 |
+
.
|
28 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
29 |
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
30 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
31 |
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
32 |
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
33 |
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
34 |
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
35 |
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
36 |
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
37 |
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38 |
+
|
39 |
+
License: Expat
|
40 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
41 |
+
of this software and associated documentation files (the "Software"), to deal
|
42 |
+
in the Software without restriction, including without limitation the rights
|
43 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
44 |
+
copies of the Software, and to permit persons to whom the Software is furnished
|
45 |
+
to do so, subject to the following conditions:
|
46 |
+
.
|
47 |
+
The above copyright notice and this permission notice shall be included in all
|
48 |
+
copies or substantial portions of the Software.
|
49 |
+
.
|
50 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
51 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
52 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
53 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
54 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
55 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
56 |
+
THE SOFTWARE.
|
vendor/composer/autoload_classmap.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_classmap.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
'Kliken\\WcPlugin\\Helper' => $baseDir . '/classes/class-helper.php',
|
10 |
+
'Kliken\\WcPlugin\\Message' => $baseDir . '/classes/class-message.php',
|
11 |
+
'Kliken\\WcPlugin\\Plugin' => $baseDir . '/classes/class-plugin.php',
|
12 |
+
'Kliken\\WcPlugin\\REST_Misc_Controller' => $baseDir . '/classes/class-rest-misc-controller.php',
|
13 |
+
'Kliken\\WcPlugin\\REST_Orders_Controller' => $baseDir . '/classes/class-rest-orders-controller.php',
|
14 |
+
'Kliken\\WcPlugin\\REST_Products_Controller' => $baseDir . '/classes/class-rest-products-controller.php',
|
15 |
+
'Kliken\\WcPlugin\\WC_Integration' => $baseDir . '/classes/class-wc-integration.php',
|
16 |
+
'Kliken\\WcPlugin\\WC_REST_Products_Controller_Compat' => $baseDir . '/classes/class-wc-rest-products-controller-compat.php',
|
17 |
+
);
|
vendor/composer/autoload_namespaces.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_namespaces.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
);
|
vendor/composer/autoload_psr4.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_psr4.php @generated by Composer
|
4 |
+
|
5 |
+
$vendorDir = dirname(dirname(__FILE__));
|
6 |
+
$baseDir = dirname($vendorDir);
|
7 |
+
|
8 |
+
return array(
|
9 |
+
);
|
vendor/composer/autoload_real.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_real.php @generated by Composer
|
4 |
+
|
5 |
+
class ComposerAutoloaderInit8d05e6ff15e07dd67db7d411953e0c56
|
6 |
+
{
|
7 |
+
private static $loader;
|
8 |
+
|
9 |
+
public static function loadClassLoader($class)
|
10 |
+
{
|
11 |
+
if ('Composer\Autoload\ClassLoader' === $class) {
|
12 |
+
require __DIR__ . '/ClassLoader.php';
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
public static function getLoader()
|
17 |
+
{
|
18 |
+
if (null !== self::$loader) {
|
19 |
+
return self::$loader;
|
20 |
+
}
|
21 |
+
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit8d05e6ff15e07dd67db7d411953e0c56', 'loadClassLoader'), true, true);
|
23 |
+
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit8d05e6ff15e07dd67db7d411953e0c56', 'loadClassLoader'));
|
25 |
+
|
26 |
+
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
+
if ($useStaticLoader) {
|
28 |
+
require_once __DIR__ . '/autoload_static.php';
|
29 |
+
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInit8d05e6ff15e07dd67db7d411953e0c56::getInitializer($loader));
|
31 |
+
} else {
|
32 |
+
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
+
foreach ($map as $namespace => $path) {
|
34 |
+
$loader->set($namespace, $path);
|
35 |
+
}
|
36 |
+
|
37 |
+
$map = require __DIR__ . '/autoload_psr4.php';
|
38 |
+
foreach ($map as $namespace => $path) {
|
39 |
+
$loader->setPsr4($namespace, $path);
|
40 |
+
}
|
41 |
+
|
42 |
+
$classMap = require __DIR__ . '/autoload_classmap.php';
|
43 |
+
if ($classMap) {
|
44 |
+
$loader->addClassMap($classMap);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
$loader->register(true);
|
49 |
+
|
50 |
+
return $loader;
|
51 |
+
}
|
52 |
+
}
|
vendor/composer/autoload_static.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// autoload_static.php @generated by Composer
|
4 |
+
|
5 |
+
namespace Composer\Autoload;
|
6 |
+
|
7 |
+
class ComposerStaticInit8d05e6ff15e07dd67db7d411953e0c56
|
8 |
+
{
|
9 |
+
public static $classMap = array (
|
10 |
+
'Kliken\\WcPlugin\\Helper' => __DIR__ . '/../..' . '/classes/class-helper.php',
|
11 |
+
'Kliken\\WcPlugin\\Message' => __DIR__ . '/../..' . '/classes/class-message.php',
|
12 |
+
'Kliken\\WcPlugin\\Plugin' => __DIR__ . '/../..' . '/classes/class-plugin.php',
|
13 |
+
'Kliken\\WcPlugin\\REST_Misc_Controller' => __DIR__ . '/../..' . '/classes/class-rest-misc-controller.php',
|
14 |
+
'Kliken\\WcPlugin\\REST_Orders_Controller' => __DIR__ . '/../..' . '/classes/class-rest-orders-controller.php',
|
15 |
+
'Kliken\\WcPlugin\\REST_Products_Controller' => __DIR__ . '/../..' . '/classes/class-rest-products-controller.php',
|
16 |
+
'Kliken\\WcPlugin\\WC_Integration' => __DIR__ . '/../..' . '/classes/class-wc-integration.php',
|
17 |
+
'Kliken\\WcPlugin\\WC_REST_Products_Controller_Compat' => __DIR__ . '/../..' . '/classes/class-wc-rest-products-controller-compat.php',
|
18 |
+
);
|
19 |
+
|
20 |
+
public static function getInitializer(ClassLoader $loader)
|
21 |
+
{
|
22 |
+
return \Closure::bind(function () use ($loader) {
|
23 |
+
$loader->classMap = ComposerStaticInit8d05e6ff15e07dd67db7d411953e0c56::$classMap;
|
24 |
+
|
25 |
+
}, null, ClassLoader::class);
|
26 |
+
}
|
27 |
+
}
|
vendor/composer/installed.json
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
[]
|