Rename WordPress plugin from Dutchie Menus to Crawlsy Menus v1.3.0
- Renamed plugin to avoid WordPress.org naming conflict causing false update notifications - Added /downloads static route to serve plugin zip file - Updated all CSS classes from dutchie- to crawlsy- prefix - Added plugin zip to backend/public/downloads for hosting - Plugin available at: https://dispos.crawlsy.com/downloads/crawlsy-menus-1.3.0.zip 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
294
wordpress-plugin/crawlsy-menus.php
Normal file
294
wordpress-plugin/crawlsy-menus.php
Normal file
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Crawlsy Menus
|
||||
* Plugin URI: https://creationshop.io
|
||||
* Description: Display cannabis product menus from Crawlsy with Elementor integration
|
||||
* Version: 1.3.0
|
||||
* Author: Creationshop
|
||||
* Author URI: https://creationshop.io
|
||||
* License: GPL v2 or later
|
||||
* Text Domain: crawlsy-menus
|
||||
* Requires PHP: 7.4
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
define('CRAWLSY_MENUS_VERSION', '1.3.0');
|
||||
define('CRAWLSY_MENUS_API_URL', 'https://dispos.crawlsy.com/api');
|
||||
define('CRAWLSY_MENUS_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||
define('CRAWLSY_MENUS_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||||
|
||||
/**
|
||||
* Main Plugin Class
|
||||
*/
|
||||
class Crawlsy_Menus_Plugin {
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
public static function instance() {
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
add_action('plugins_loaded', [$this, 'init']);
|
||||
add_action('elementor/widgets/register', [$this, 'register_elementor_widgets']);
|
||||
add_action('admin_menu', [$this, 'add_admin_menu']);
|
||||
add_action('admin_init', [$this, 'register_settings']);
|
||||
add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts']);
|
||||
}
|
||||
|
||||
public function init() {
|
||||
// Initialize plugin
|
||||
load_plugin_textdomain('crawlsy-menus', false, dirname(plugin_basename(__FILE__)) . '/languages');
|
||||
|
||||
// Register shortcodes (keeping backward compatible shortcode names)
|
||||
add_shortcode('crawlsy_products', [$this, 'products_shortcode']);
|
||||
add_shortcode('crawlsy_product', [$this, 'single_product_shortcode']);
|
||||
// Legacy shortcode support
|
||||
add_shortcode('dutchie_products', [$this, 'products_shortcode']);
|
||||
add_shortcode('dutchie_product', [$this, 'single_product_shortcode']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Elementor Widgets
|
||||
*/
|
||||
public function register_elementor_widgets($widgets_manager) {
|
||||
require_once CRAWLSY_MENUS_PLUGIN_DIR . 'widgets/product-grid.php';
|
||||
require_once CRAWLSY_MENUS_PLUGIN_DIR . 'widgets/single-product.php';
|
||||
|
||||
$widgets_manager->register(new \Crawlsy_Menus_Product_Grid_Widget());
|
||||
$widgets_manager->register(new \Crawlsy_Menus_Single_Product_Widget());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Scripts and Styles
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
wp_enqueue_style(
|
||||
'crawlsy-menus-styles',
|
||||
CRAWLSY_MENUS_PLUGIN_URL . 'assets/css/crawlsy-menus.css',
|
||||
[],
|
||||
CRAWLSY_MENUS_VERSION
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'crawlsy-menus-script',
|
||||
CRAWLSY_MENUS_PLUGIN_URL . 'assets/js/crawlsy-menus.js',
|
||||
['jquery'],
|
||||
CRAWLSY_MENUS_VERSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Admin Menu
|
||||
*/
|
||||
public function add_admin_menu() {
|
||||
add_menu_page(
|
||||
'Crawlsy Menus',
|
||||
'Crawlsy Menus',
|
||||
'manage_options',
|
||||
'crawlsy-menus',
|
||||
[$this, 'admin_page'],
|
||||
'dashicons-products',
|
||||
30
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Plugin Settings
|
||||
*/
|
||||
public function register_settings() {
|
||||
register_setting('crawlsy_menus_settings', 'crawlsy_api_token');
|
||||
|
||||
// Migrate old setting if exists
|
||||
$old_token = get_option('dutchie_api_token');
|
||||
if ($old_token && !get_option('crawlsy_api_token')) {
|
||||
update_option('crawlsy_api_token', $old_token);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin Page
|
||||
*/
|
||||
public function admin_page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1>Crawlsy Menus Settings</h1>
|
||||
<p>Version <?php echo CRAWLSY_MENUS_VERSION; ?> by <a href="https://creationshop.io" target="_blank">Creationshop</a></p>
|
||||
|
||||
<form method="post" action="options.php">
|
||||
<?php settings_fields('crawlsy_menus_settings'); ?>
|
||||
<?php do_settings_sections('crawlsy_menus_settings'); ?>
|
||||
|
||||
<table class="form-table">
|
||||
<tr>
|
||||
<th scope="row"><label for="crawlsy_api_token">API Token</label></th>
|
||||
<td>
|
||||
<input type="password" id="crawlsy_api_token" name="crawlsy_api_token"
|
||||
value="<?php echo esc_attr(get_option('crawlsy_api_token')); ?>"
|
||||
class="regular-text" />
|
||||
<p class="description">Your authentication token from the admin dashboard. The token includes your store configuration.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?php submit_button(); ?>
|
||||
</form>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Test Connection</h2>
|
||||
<button type="button" id="test-api-connection" class="button">Test API Connection</button>
|
||||
<div id="api-test-result" style="margin-top: 10px;"></div>
|
||||
|
||||
<script>
|
||||
jQuery(document).ready(function($) {
|
||||
$('#test-api-connection').on('click', function() {
|
||||
var apiUrl = '<?php echo CRAWLSY_MENUS_API_URL; ?>';
|
||||
var apiToken = $('#crawlsy_api_token').val();
|
||||
|
||||
$('#api-test-result').html('<p>Testing connection...</p>');
|
||||
|
||||
$.ajax({
|
||||
url: apiUrl + '/auth/me',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + apiToken
|
||||
},
|
||||
success: function(response) {
|
||||
$('#api-test-result').html(
|
||||
'<div class="notice notice-success"><p><strong>Success!</strong> Connected as: ' +
|
||||
response.user.email + '</p></div>'
|
||||
);
|
||||
},
|
||||
error: function(xhr) {
|
||||
$('#api-test-result').html(
|
||||
'<div class="notice notice-error"><p><strong>Error:</strong> ' +
|
||||
(xhr.responseJSON?.error || 'Connection failed') + '</p></div>'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Products Shortcode
|
||||
*/
|
||||
public function products_shortcode($atts) {
|
||||
$atts = shortcode_atts([
|
||||
'category_id' => '',
|
||||
'limit' => 12,
|
||||
'columns' => 3,
|
||||
'in_stock' => 'true'
|
||||
], $atts);
|
||||
|
||||
$products = $this->fetch_products($atts);
|
||||
|
||||
if (!$products) {
|
||||
return '<p>No products found.</p>';
|
||||
}
|
||||
|
||||
ob_start();
|
||||
include CRAWLSY_MENUS_PLUGIN_DIR . 'templates/product-grid.php';
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Single Product Shortcode
|
||||
*/
|
||||
public function single_product_shortcode($atts) {
|
||||
$atts = shortcode_atts([
|
||||
'id' => 0
|
||||
], $atts);
|
||||
|
||||
if (!$atts['id']) {
|
||||
return '<p>Product ID required.</p>';
|
||||
}
|
||||
|
||||
$product = $this->fetch_product($atts['id']);
|
||||
|
||||
if (!$product) {
|
||||
return '<p>Product not found.</p>';
|
||||
}
|
||||
|
||||
ob_start();
|
||||
include CRAWLSY_MENUS_PLUGIN_DIR . 'templates/single-product.php';
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch Products from API
|
||||
*/
|
||||
public function fetch_products($args = []) {
|
||||
$api_token = get_option('crawlsy_api_token');
|
||||
|
||||
if (!$api_token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$query_args = http_build_query($args);
|
||||
$url = CRAWLSY_MENUS_API_URL . '/products?' . $query_args;
|
||||
|
||||
$response = wp_remote_get($url, [
|
||||
'headers' => [
|
||||
'Authorization' => 'Bearer ' . $api_token
|
||||
],
|
||||
'timeout' => 30
|
||||
]);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$body = wp_remote_retrieve_body($response);
|
||||
$data = json_decode($body, true);
|
||||
|
||||
return $data['products'] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch Single Product from API
|
||||
*/
|
||||
public function fetch_product($id) {
|
||||
$api_token = get_option('crawlsy_api_token');
|
||||
|
||||
if (!$api_token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$url = CRAWLSY_MENUS_API_URL . '/products/' . intval($id);
|
||||
|
||||
$response = wp_remote_get($url, [
|
||||
'headers' => [
|
||||
'Authorization' => 'Bearer ' . $api_token
|
||||
],
|
||||
'timeout' => 30
|
||||
]);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$body = wp_remote_retrieve_body($response);
|
||||
$data = json_decode($body, true);
|
||||
|
||||
return $data['product'] ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize Plugin
|
||||
function crawlsy_menus() {
|
||||
return Crawlsy_Menus_Plugin::instance();
|
||||
}
|
||||
|
||||
crawlsy_menus();
|
||||
Reference in New Issue
Block a user