diff --git a/assets/css/admin-style.scss b/assets/css/admin-style.scss
index b7b2d5a2..c166e63d 100644
--- a/assets/css/admin-style.scss
+++ b/assets/css/admin-style.scss
@@ -168,8 +168,6 @@
}
}
-
-
// Fix select2 width in filter
.tablenav {
.wcsn_search_product,
@@ -184,14 +182,6 @@
}
}
-// Fix source meta field width.
-._serial_key_source_field {
- label {
- margin: 0;
- width: 100%;
- }
-}
-
// Status tab
.wcsn-tools-tab-status {
table {
diff --git a/assets/js/admin-product.js b/assets/js/admin-product.js
new file mode 100644
index 00000000..455974ae
--- /dev/null
+++ b/assets/js/admin-product.js
@@ -0,0 +1,19 @@
+/**
+ * WC Serial Numbers
+ * https://pluginever.com
+ *
+ * Copyright (c) 2014 PluginEver
+ * Licensed under the GPLv2+ license.
+ */
+jQuery( function ( $ ) {
+ /********** ADMIN:PRODUCT EDIT **********/
+ $(document.body)
+ .on('change', ':input[name="_serial_key_source"]', function(){
+ var source = $(this).val();
+ $('*[class*="wcsn_show_if_key_source__"]').hide();
+ $('.wcsn_show_if_key_source__' + source).show();
+ });
+
+ // Trigger change to show/hide fields on load.
+ $(':input[name="_serial_key_source"]').trigger('change');
+});
diff --git a/composer.json b/composer.json
index 31f0f532..095fea61 100644
--- a/composer.json
+++ b/composer.json
@@ -18,6 +18,10 @@
{
"url": "git@github.com:pluginever/framework-model.git",
"type": "github"
+ },
+ {
+ "type": "github",
+ "url": "git@github.com:byteever/bytekit-models.git"
}
],
"require": {
@@ -28,7 +32,8 @@
"coenjacobs/mozart": "^0.7.1",
"pluginever/framework-model": "dev-master",
"pluginever/framework-plugin": "dev-master",
- "pluginever/framework-settings": "dev-master"
+ "pluginever/framework-settings": "dev-master",
+ "byteever/bytekit-models": "dev-master"
},
"autoload": {
"psr-4": {
@@ -65,7 +70,8 @@
"packages": [
"pluginever/framework-plugin",
"pluginever/framework-settings",
- "pluginever/framework-model"
+ "pluginever/framework-model",
+ "byteever/bytekit-models"
]
}
}
diff --git a/composer.lock b/composer.lock
index f5970305..313d549e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "db0a4e2eed5394cfab48f679b98ec95b",
+ "content-hash": "26d152b97ff925db5e9dbb38b5fc65a8",
"packages": [],
"packages-dev": [
{
@@ -53,6 +53,102 @@
},
"time": "2024-06-28T06:59:58+00:00"
},
+ {
+ "name": "byteever/bytekit-models",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "git@github.com:byteever/bytekit-models.git",
+ "reference": "959c56d6fd9e7b8728349c43ab7ab38491744e36"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/byteever/bytekit-models/zipball/959c56d6fd9e7b8728349c43ab7ab38491744e36",
+ "reference": "959c56d6fd9e7b8728349c43ab7ab38491744e36",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0"
+ },
+ "require-dev": {
+ "byteever/byteever-sniffs": "dev-master",
+ "codeception/module-asserts": "^1.0",
+ "codeception/module-cli": "^1.0",
+ "codeception/module-db": "^1.0",
+ "codeception/module-filesystem": "^1.0",
+ "codeception/module-phpbrowser": "^1.0",
+ "codeception/module-rest": "^2.0",
+ "codeception/module-webdriver": "^1.0",
+ "codeception/util-universalframework": "^1.0",
+ "lucatume/wp-browser": "<3.5"
+ },
+ "default-branch": true,
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ByteKit\\Models\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "ByteKit\\Models\\Tests\\Supports\\": "tests/_support",
+ "ByteKit\\Models\\Tests\\Unit\\": "tests/unit",
+ "ByteKit\\Models\\Tests\\Functional\\": "tests/functional",
+ "ByteKit\\Models\\Tests\\Acceptance\\": "tests/acceptance",
+ "ByteKit\\Models\\Tests\\WPUnit\\": "tests/wpunit"
+ }
+ },
+ "scripts": {
+ "phpcs": [
+ "@php ./vendor/bin/phpcs --standard=phpcs.xml -s -v"
+ ],
+ "phpcbf": [
+ "@php ./vendor/bin/phpcbf --standard=phpcs.xml -v"
+ ],
+ "test:setup": [
+ "bash bin/install-test-env.sh"
+ ],
+ "test:build": [
+ "vendor/bin/codecept build"
+ ],
+ "test:wpunit": [
+ "vendor/bin/codecept run wpunit --"
+ ],
+ "test:functional": [
+ "vendor/bin/codecept run functional --"
+ ],
+ "test:acceptance": [
+ "vendor/bin/codecept run acceptance --"
+ ],
+ "test:gen:wpunit": [
+ "vendor/bin/codecept generate:wpunit wpunit"
+ ],
+ "test:gen:functional": [
+ "vendor/bin/codecept generate:wpunit functional"
+ ],
+ "test:gen:acceptance": [
+ "vendor/bin/codecept generate:acceptance acceptance"
+ ],
+ "test": [
+ "vendor/bin/codecept run wpunit"
+ ]
+ },
+ "license": [
+ "GPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Sultan Nasir Uddin",
+ "email": "manikdrmc@gmail.com"
+ }
+ ],
+ "description": "A package to manage models in WordPress.",
+ "support": {
+ "source": "https://github.com/byteever/bytekit-models/tree/master",
+ "issues": "https://github.com/byteever/bytekit-models/issues"
+ },
+ "time": "2024-09-30T12:55:35+00:00"
+ },
{
"name": "coenjacobs/mozart",
"version": "0.7.1",
@@ -1934,7 +2030,8 @@
"stability-flags": {
"pluginever/framework-model": 20,
"pluginever/framework-plugin": 20,
- "pluginever/framework-settings": 20
+ "pluginever/framework-settings": 20,
+ "byteever/bytekit-models": 20
},
"prefer-stable": true,
"prefer-lowest": false,
diff --git a/includes/Admin/ListTables/GeneratorsTable.php b/includes/Admin/ListTables/GeneratorsTable.php
new file mode 100644
index 00000000..cb1846b2
--- /dev/null
+++ b/includes/Admin/ListTables/GeneratorsTable.php
@@ -0,0 +1,406 @@
+ __( 'generator', 'wc-serial-numbers' ),
+ 'plural' => __( 'generators', 'wc-serial-numbers' ),
+ 'ajax' => false,
+ )
+ );
+
+ $this->base_url = admin_url( 'admin.php?page=wc-serial-numbers-generators' );
+ }
+
+ /**
+ * Prepare table data.
+ *
+ * @since 1.4.6
+ */
+ public function prepare_items() {
+ wp_verify_nonce( '_wpnonce' );
+ $per_page = $this->get_items_per_page( 'wcsn_stocks_per_page' );
+ $columns = $this->get_columns();
+ $hidden = array();
+ $sortable = $this->get_sortable_columns();
+ $this->_column_headers = array( $columns, $hidden, $sortable );
+ $current_page = $this->get_pagenum();
+ $orderby = isset( $_GET['orderby'] ) ? sanitize_key( $_GET['orderby'] ) : 'order_date';
+ $order = isset( $_GET['order'] ) ? sanitize_key( $_GET['order'] ) : 'desc';
+ $status = ( ! empty( $_GET['status'] ) ) ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : '';
+
+ $args = array(
+ 'limit' => $per_page,
+ 'page' => $current_page,
+ 'orderby' => $orderby,
+ 'order' => $order,
+ 'status' => $status,
+ );
+
+ /**
+ * Filter the query arguments for the list table.
+ *
+ * @param array $args An associative array of arguments.
+ *
+ * @since 1.0.0
+ */
+ $args = apply_filters( 'wc_serial_numbers_pro_generators_table_query_args', $args );
+
+ $args['no_found_rows'] = false;
+ $this->items = Generator::results( $args );
+ $this->total_count = Generator::count( $args );
+
+ $this->set_pagination_args(
+ array(
+ 'total_items' => $this->total_count,
+ 'per_page' => $per_page,
+ )
+ );
+ }
+
+ /**
+ * No items found text.
+ */
+ public function no_items() {
+ esc_html_e( 'No generators found.', 'wc-serial-numbers' );
+ }
+
+ /**
+ * Returns an associative array listing all the views that can be used with this table.
+ *
+ * @since 1.0.0
+ * @return string[] Array of views.
+ */
+ public function get_views() {
+ wp_verify_nonce( '_wpnonce' );
+ $current = ( ! empty( $_GET['status'] ) ) ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : '';
+ $status_links = array();
+ $statuses = array_merge(
+ array(
+ 'all' => __( 'All', 'wc-serial-numbers' ),
+ ),
+ Generator::get_statuses()
+ );
+
+ foreach ( $statuses as $status => $label ) {
+ $link = 'all' === $status ? $this->base_url : add_query_arg( 'status', $status, $this->base_url );
+ $args = 'all' === $status ? array() : array( 'status' => $status );
+ $count = Generator::count( $args );
+ $label = sprintf( '%s (%s)', esc_html( $label ), number_format_i18n( $count ) );
+
+ $status_links[ $status ] = array(
+ 'url' => $link,
+ 'label' => $label,
+ 'current' => $current === $status,
+ );
+ }
+
+ return $this->get_views_links( $status_links );
+ }
+
+ /**
+ * Process bulk action.
+ *
+ * @param string $doaction Action name.
+ *
+ * @since 1.4.6
+ */
+ public function process_bulk_actions( $doaction ) {
+ wp_verify_nonce( '_wpnonce' );
+ if ( $doaction ) {
+ if ( isset( $_REQUEST['id'] ) ) {
+ $ids = wp_parse_id_list( wp_unslash( $_REQUEST['id'] ) );
+ $doaction = ( - 1 !== $_REQUEST['action'] ) ? $_REQUEST['action'] : $_REQUEST['action2']; // phpcs:ignore
+ } elseif ( isset( $_REQUEST['ids'] ) ) {
+ $ids = array_map( 'absint', $_REQUEST['ids'] );
+ } elseif ( wp_get_referer() ) {
+ wp_safe_redirect( wp_get_referer() );
+ exit;
+ }
+
+ foreach ( $ids as $id ) { // Check the permissions on each.
+ $generator = Generator::find( $id );
+ if ( ! $generator ) {
+ continue;
+ }
+ switch ( $doaction ) {
+ case 'delete':
+ $generator->delete();
+ break;
+
+ case 'activate':
+ $generator->status = 'active';
+ $generator->save();
+ break;
+
+ case 'deactivate':
+ $generator->status = 'inactive';
+ $generator->save();
+ break;
+ }
+ }
+
+ wp_safe_redirect( wp_get_referer() );
+ exit;
+ }
+
+ parent::process_bulk_actions( $doaction );
+ }
+
+ /**
+ * Get bulk actions
+ *
+ * since 1.0.0
+ *
+ * @return array
+ */
+ public function get_bulk_actions() {
+ return array(
+ 'delete' => __( 'Delete', 'wc-serial-numbers' ),
+ 'activate' => __( 'Activate', 'wc-serial-numbers' ),
+ 'deactivate' => __( 'Deactivate', 'wc-serial-numbers' ),
+ );
+ }
+
+ /**
+ * since 1.0.0
+ *
+ * @return array
+ */
+ public function get_columns() {
+ $columns = array(
+ 'cb' => '',
+ 'name' => __( 'Name', 'wc-serial-numbers' ),
+ 'pattern' => __( 'Pattern', 'wc-serial-numbers' ),
+ 'validity_for' => __( 'Validity For', 'wc-serial-numbers' ),
+ 'activation_limit' => __( 'Activation Limit', 'wc-serial-numbers' ),
+ 'status' => __( 'Status', 'wc-serial-numbers' ),
+ );
+
+ return apply_filters( 'wc_serial_numbers_pro_generators_table_columns', $columns );
+ }
+
+ /**
+ * Get sortable columns.
+ *
+ * @since 1.0.0
+ * @return array
+ */
+ protected function get_sortable_columns() {
+ return apply_filters(
+ 'wc_serial_numbers_pro_generators_table_sortable_columns',
+ array(
+ 'name' => array( 'name', false ),
+ 'pattern' => array( 'pattern', false ),
+ 'valid_for' => array( 'valid_for', false ),
+ 'activation_limit' => array( 'activation_limit', false ),
+ 'status' => array( 'status', false ),
+ )
+ );
+ }
+
+ /**
+ * Gets the name of the primary column.
+ *
+ * @since 1.0.0
+ * @access protected
+ * @return string Name of the primary column.
+ */
+ protected function get_primary_column_name() {
+ return 'name';
+ }
+
+ /**
+ * Render the bulk edit checkbox
+ *
+ * @param Generator $item Item being rendered.
+ *
+ * @return string
+ */
+ protected function column_cb( $item ) {
+ return "";
+ }
+
+ /**
+ * Display name column.
+ *
+ * @param Generator $item Item being rendered.
+ *
+ * @since 1.0.0
+ * @return string
+ */
+ protected function column_name( $item ) {
+ return sprintf(
+ '%s',
+ esc_url( add_query_arg( 'edit', $item->id, $this->base_url ) ),
+ esc_html( $item->name )
+ );
+ }
+
+ /**
+ * Column pattern.
+ *
+ * @param Generator $item Item being rendered.
+ *
+ * @since 1.0.0
+ * @return string
+ */
+ public function column_pattern( $item ) {
+ return wp_kses_post( '' . esc_html( $item->pattern ) . '
' );
+ }
+
+ /**
+ * Column validity_for.
+ *
+ * @param Generator $item Item being rendered.
+ *
+ * @since 1.0.0
+ * @return string
+ */
+ protected function column_validity_for( $item ) {
+ if ( empty( $item->validity_for ) ) {
+ return esc_html__( 'Lifetime', 'wc-serial-numbers' );
+ }
+ if ( ! empty( $item->validity_for ) ) {
+ // translators: %d: number of days.
+ return sprintf( _nx( '%d day After Purchase', '%d days After Purchase', $item->validity_for, 'valid for days', 'wc-serial-numbers' ), $item->validity_for );
+ }
+
+ return '—';
+ }
+
+ /**
+ * Column activation_limit.
+ *
+ * @param Generator $item Item being rendered.
+ *
+ * @since 1.0.0
+ * @return string
+ */
+ protected function column_activation_limit( $item ) {
+ if ( empty( $item->activation_limit ) ) {
+ return esc_html__( 'Unlimited', 'wc-serial-numbers' );
+ }
+
+ if ( ! empty( $item->activation_limit ) ) {
+ return number_format( $item->activation_limit );
+ }
+
+ return esc_html( $item->activation_limit );
+ }
+
+ /**
+ * Column status.
+ *
+ * @param Generator $item Item being rendered.
+ *
+ * @since 1.0.0
+ * @return string
+ */
+ protected function column_status( $item ) {
+ return $item->get_status_html();
+ }
+
+ /**
+ * Generates and displays row actions links.
+ *
+ * @param Generator $item The object.
+ * @param string $column_name Current column name.
+ * @param string $primary Primary column name.
+ *
+ * @since 1.0.0
+ * @return string Row actions output.
+ */
+ protected function handle_row_actions( $item, $column_name, $primary ) {
+ if ( $primary !== $column_name ) {
+ return null;
+ }
+
+ $actions = array(
+ 'id' => sprintf( '#%d', esc_attr( $item->id ) ),
+ 'edit' => sprintf(
+ '%s',
+ esc_url( add_query_arg( 'edit', $item->id, $this->base_url ) ),
+ __( 'Edit', 'wc-serial-numbers' )
+ ),
+ 'delete' => sprintf(
+ '%s',
+ esc_url(
+ wp_nonce_url(
+ add_query_arg(
+ array(
+ 'action' => 'delete',
+ 'id' => $item->id,
+ ),
+ $this->base_url
+ ),
+ 'bulk-' . $this->_args['plural']
+ )
+ ),
+ __( 'Delete', 'wc-serial-numbers' )
+ ),
+ );
+ // based on the status, add activate or deactivate action.
+ if ( 'active' === $item->status ) {
+ $actions['deactivate'] = sprintf(
+ '%s',
+ esc_url(
+ wp_nonce_url(
+ add_query_arg(
+ array(
+ 'action' => 'deactivate',
+ 'id' => $item->id,
+ ),
+ $this->base_url
+ ),
+ 'bulk-' . $this->_args['plural']
+ )
+ ),
+ __( 'Deactivate', 'wc-serial-numbers' )
+ );
+ } else {
+ $actions['activate'] = sprintf(
+ '%s',
+ esc_url(
+ wp_nonce_url(
+ add_query_arg(
+ array(
+ 'action' => 'activate',
+ 'id' => $item->id,
+ ),
+ $this->base_url
+ ),
+ 'bulk-' . $this->_args['plural']
+ )
+ ),
+ __( 'Activate', 'wc-serial-numbers' )
+ );
+ }
+
+ return $this->row_actions( $actions );
+ }
+}
diff --git a/includes/Admin/Products.php b/includes/Admin/Products.php
index d80f988d..33487d78 100644
--- a/includes/Admin/Products.php
+++ b/includes/Admin/Products.php
@@ -21,6 +21,11 @@ public function __construct() {
add_action( 'admin_head', array( __CLASS__, 'print_style' ) );
add_filter( 'woocommerce_product_data_tabs', array( __CLASS__, 'product_data_tab' ) );
add_action( 'woocommerce_product_data_panels', array( __CLASS__, 'product_write_panel' ) );
+ add_action( 'wc_serial_numbers_product_options', array( __CLASS__, 'render_enable_sale_keys_options' ) );
+ add_action( 'wc_serial_numbers_product_options', array( __CLASS__, 'render_source_options' ) );
+ add_action( 'wc_serial_numbers_product_options', array( __CLASS__, 'render_key_options' ) );
+ add_action( 'wc_serial_numbers_product_options', array( __CLASS__, 'render_software_options' ) );
+ add_action( 'wc_serial_numbers_product_options', array( __CLASS__, 'render_pro_notice_options' ) );
add_filter( 'woocommerce_process_product_meta', array( __CLASS__, 'product_save_data' ) );
add_action( 'woocommerce_product_after_variable_attributes', array( __CLASS__, 'variable_product_content' ), 10, 3 );
}
@@ -38,10 +43,10 @@ public static function print_style() {
content: "\f112";
}
- ._serial_key_source_field label {
- margin: 0 !important;
- width: 100% !important;
- }
+ /*._serial_key_source_field label {*/
+ /* margin: 0 !important;*/
+ /* width: 100% !important;*/
+ /*}*/
.wc-serial-numbers-upgrade-box {
background: #f1f1f1;
@@ -103,100 +108,86 @@ public static function product_data_tab( $tabs ) {
* since 1.0.0
*/
public static function product_write_panel() {
- global $post, $woocommerce;
- ?>
-
%s %s
', + __( 'Want to sell keys for variable products?', 'wc-serial-numbers' ), + 'https://www.pluginever.com/plugins/woocommerce-serial-numbers-pro/?utm_source=product_page_license_area&utm_medium=link&utm_campaign=wc-serial-numbers&utm_content=Upgrade%20to%20Pro', + __( 'Upgrade to Pro', 'wc-serial-numbers' ), + ) + ); +} diff --git a/includes/Admin/views/products/product-selling-keys-options.php b/includes/Admin/views/products/product-selling-keys-options.php new file mode 100644 index 00000000..1a752ff7 --- /dev/null +++ b/includes/Admin/views/products/product-selling-keys-options.php @@ -0,0 +1,32 @@ +'; +// Enable selling keys. +woocommerce_wp_checkbox( + array( + 'id' => '_is_serial_number', + 'label' => __( 'Sell keys', 'wc-serial-numbers' ), + 'description' => __( 'Enable this if you are selling keys with this product.', 'wc-serial-numbers' ), + 'value' => get_post_meta( $product->get_id(), '_is_serial_number', true ), + 'wrapper_class' => '', + 'desc_tip' => false, + ) +); + +/** +* Action hook to add more product key options for selling keys. +* +* @since 3.0.0 +*/ +do_action( 'wc_serial_numbers_product_enable_selling_keys', $product ); + +echo ''; diff --git a/includes/Admin/views/products/product-software-options.php b/includes/Admin/views/products/product-software-options.php new file mode 100644 index 00000000..cd5d5645 --- /dev/null +++ b/includes/Admin/views/products/product-software-options.php @@ -0,0 +1,33 @@ +'; + +woocommerce_wp_text_input( + array( + 'id' => '_software_version', + 'label' => __( 'Software version', 'wc-serial-numbers' ), + 'description' => __( 'Version number for the software. Ignore if it\'s not a software.', 'wc-serial-numbers' ), + 'placeholder' => __( 'e.g. 1.0', 'wc-serial-numbers' ), + 'desc_tip' => true, + ) +); + +/** + * Action hook to add more software options. + * + * @param WC_Product $product Product object. + * + * @since 3.0.0 + */ +do_action( 'wc_serial_numbers_product_software_options', $product ); + +echo ''; diff --git a/includes/Admin/views/products/product-source-options.php b/includes/Admin/views/products/product-source-options.php new file mode 100644 index 00000000..7ffda7c4 --- /dev/null +++ b/includes/Admin/views/products/product-source-options.php @@ -0,0 +1,88 @@ +'; +$source = get_post_meta( $product->get_id(), '_serial_key_source', true ); +$sources = wcsn_get_key_sources(); + +// key source select field. +woocommerce_wp_select( + array( + 'id' => '_serial_key_source', + 'label' => __( 'Key Source', 'wc-serial-numbers' ), + 'value' => $source, + 'options' => $sources, + 'desc_tip' => true, + 'description' => __( 'Automatically generate keys or use preset keys.', 'wc-serial-numbers' ), + 'wrapper_class' => '_serial_key_source', + 'class' => 'wc-enhanced-select', + 'style' => 'width: 50%;', + ) +); + +// Selling & Generate keys using a generator. +$generators = Generator::results( array( 'status' => 'active' ) ); + +// Generate options. +$options = array( + '' => __( 'Default', 'wc-serial-numbers' ), +); +foreach ( $generators as $generator ) { + $options[ $generator->id ] = $generator->name; +} +woocommerce_wp_select( + array( + 'id' => '_generator_id', + 'label' => __( 'Key Generator', 'wc-serial-numbers' ), + 'description' => __( 'Select a specific key generator or leave empty to use default settings.', 'wc-serial-numbers' ), + 'options' => $options, + 'desc_tip' => true, + 'class' => 'wc-enhanced-select', + 'wrapper_class' => 'wcsn_show_if_key_source__automatic', + 'style' => 'width: 50%;', + ) +); + +// Generate sequential keys. +woocommerce_wp_checkbox( + array( + 'id' => '_wcsn_is_sequential', + 'label' => __( 'Sequential Keys', 'wc-serial-numbers' ), + 'description' => __( 'Generate keys in sequential order.', 'wc-serial-numbers' ), + 'value' => get_post_meta( $product->get_id(), '_wcsn_is_sequential', true ), + 'wrapper_class' => 'wcsn_show_if_key_source__automatic', + ) +); + +$stocks = wcsn_get_stocks_count(); +$stock = isset( $stocks[ $product->get_id() ] ) ? $stocks[ $product->get_id() ] : 0; +echo wp_kses_post( + sprintf( + ' ', + __( 'Preset Stock', 'wc-serial-numbers' ), + $stock, + _n( 'key available.', 'keys available.', $stock, 'wc-serial-numbers' ) + ) +); + +/** + * Action hook to add more product key options for key source. + * + * @param WC_Product $product Product object. + * + * @since 3.0.0 + */ +do_action( 'wc_serial_numbers_product_key_source_options', $product ); + + +echo ''; diff --git a/includes/Models/Generator.php b/includes/Models/Generator.php new file mode 100644 index 00000000..ba36cfbf --- /dev/null +++ b/includes/Models/Generator.php @@ -0,0 +1,209 @@ +get_object_type(); + } + + /** + * The table associated with the model. + * + * @since 2.0.0 + * @var string + */ + protected $table = 'wcsn_generators'; + + /** + * The table columns of the model. + * + * @since 2.0.0 + * @var array + */ + protected $columns = array( + 'id', + 'name', + 'pattern', + 'charset', + 'valid_for', + 'activation_limit', + 'status', + ); + + /** + * The model's attributes. + * + * @since 2.0.0 + * @var array + */ + protected $attributes = array( + 'pattern' => '####-####-####-####', + 'charset' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', + 'status' => 'active', + ); + + /** + * The attributes that should be cast. + * + * @since 2.0.0 + * @var array + */ + protected $casts = array( + 'name' => 'string', + 'pattern' => 'string', + 'charset' => 'string', + 'valid_for' => 'int', + 'activation_limit' => 'int', + 'status' => 'string', + ); + + /** + * Indicates if the model should be timestamped. + * + * @since 2.0.0 + * @var bool + */ + protected $has_timestamps = true; + + /** + * Get searchable attributes. + * + * @since 2.0.0 + * @var array + */ + protected $searchable = array( + 'name', + 'pattern', + 'charset', + 'status', + ); + + /** + * Get status options. + * + * @since 2.0.0 + * @return array + */ + public static function get_statuses() { + return array( + 'active' => __( 'Active', 'wc-serial-numbers' ), + 'inactive' => __( 'Inactive', 'wc-serial-numbers' ), + ); + } + + /* + |-------------------------------------------------------------------------- + | Accessors, Mutators & Relationships + |-------------------------------------------------------------------------- + | This section includes methods for accessing, modifying, and assisting with + | the model's properties. + | - Getters: Retrieve property values. + | - Setters: Update property values. + | - Relationships: Define relationships between models. + |-------------------------------------------------------------------------- + */ + + /** + * Set the status attribute. + * + * @param string $value Status value. + * + * @since 2.0.0 + * @return void + */ + public function set_status( $value ) { + $this->attributes['status'] = in_array( $value, array_keys( self::get_statuses() ), true ) ? $value : 'active'; + } + + /* + |-------------------------------------------------------------------------- + | CRUD Methods + |-------------------------------------------------------------------------- + | This section contains methods for creating, reading, updating, and deleting + | objects in the database. + |-------------------------------------------------------------------------- + */ + + /** + * Saves an object in the database. + * + * @since 2.0.0 + * @return true|\WP_Error True on success, WP_Error on failure. + */ + public function save() { + // pattern is required. + if ( empty( $this->name ) ) { + return new \WP_Error( 'missing-required', __( 'The generator name is required.', 'wc-serial-numbers' ) ); + } + // product_id is required. + if ( empty( $this->pattern ) ) { + return new \WP_Error( 'missing-required', __( 'The generator pattern is required.', 'wc-serial-numbers' ) ); + } + // type is required. + if ( empty( $this->charset ) ) { + return new \WP_Error( 'missing-required', __( 'The generator charset is required.', 'wc-serial-numbers' ) ); + } + + return parent::save(); + } + + /* + |-------------------------------------------------------------------------- + | Helper Methods + |-------------------------------------------------------------------------- + | This section contains utility methods that are not directly related to this + | object but can be used to support its functionality. + |-------------------------------------------------------------------------- + */ + + /** + * Get status label. + * + * @since 2.0.0 + * @return string + */ + public function get_status_label() { + $statuses = self::get_statuses(); + return isset( $statuses[ $this->status ] ) ? $statuses[ $this->status ] : ''; + } + + /** + * Get the key status html. + * + * @since 2.0.0 + * @return string + */ + public function get_status_html() { + return sprintf( '%s', esc_attr( $this->status ), esc_html( $this->get_status_label() ) ); + } +} diff --git a/languages/wc-serial-numbers.pot b/languages/wc-serial-numbers.pot index 60e8800c..45970a43 100644 --- a/languages/wc-serial-numbers.pot +++ b/languages/wc-serial-numbers.pot @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: WC Serial Numbers 2.0.6\n" "Report-Msgid-Bugs-To: https://pluginever.com/support\n" -"POT-Creation-Date: 2024-10-07 09:04:45+00:00\n" +"POT-Creation-Date: 2024-10-14 08:32:57+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -24,6 +24,90 @@ msgstr "" "X-Textdomain-Support: yes\n" "X-Generator: grunt-wp-i18n 1.0.3\n" +#: includes/Admin/ListTables/GeneratorsTable.php:30 +msgid "generator" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:31 +msgid "generators" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:89 +msgid "No generators found." +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:104 +#: src/Admin/ListTables/KeysTable.php:228 +msgid "All" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:183 +#: includes/Admin/ListTables/GeneratorsTable.php:364 +#: src/Admin/ListTables/ActivationsTable.php:164 +#: src/Admin/ListTables/ActivationsTable.php:239 +#: src/Admin/ListTables/KeysTable.php:336 +#: src/Admin/ListTables/KeysTable.php:428 src/Admin/views/html-edit-key.php:130 +msgid "Delete" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:184 +#: includes/Admin/ListTables/GeneratorsTable.php:400 +#: src/Admin/views/html-api-actions.php:175 src/Frontend/Shortcodes.php:157 +msgid "Activate" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:185 +#: includes/Admin/ListTables/GeneratorsTable.php:383 +#: src/Admin/views/html-api-actions.php:176 src/Frontend/Shortcodes.php:158 +msgid "Deactivate" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:197 +#: src/Admin/views/html-edit-generator.php:31 +#: src/Admin/views/html-edit-key.php:146 +msgid "Name" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:198 +#: src/Admin/views/html-edit-generator.php:45 +msgid "Pattern" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:199 +msgid "Validity For" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:200 +#: src/Deprecated/Functions.php:361 src/Functions/Template.php:52 +#: src/functions.php:1026 +msgid "Activation Limit" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:201 +#: includes/Admin/Orders.php:250 src/Admin/ListTables/KeysTable.php:360 +#: src/Admin/Menus.php:358 src/Admin/views/html-edit-generator.php:102 +#: src/Admin/views/html-edit-key.php:92 src/Functions/Template.php:78 +#: src/functions.php:1041 +msgid "Status" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:286 +#: includes/Admin/Orders.php:243 src/Admin/ListTables/KeysTable.php:532 +#: src/Functions/Template.php:63 src/functions.php:1037 +msgid "Lifetime" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:306 +#: includes/Admin/Orders.php:247 +msgid "Unlimited" +msgstr "" + +#: includes/Admin/ListTables/GeneratorsTable.php:348 +#: src/Admin/ListTables/KeysTable.php:427 +#: src/Admin/ListTables/StockTable.php:143 +msgid "Edit" +msgstr "" + #: includes/Admin/Orders.php:53 includes/Admin/Orders.php:166 msgid "Add serial keys" msgstr "" @@ -61,7 +145,7 @@ msgstr "" #: src/Admin/ListTables/KeysTable.php:349 #: src/Admin/views/html-api-actions.php:131 #: src/Admin/views/html-api-validation.php:134 src/Functions/Template.php:42 -#: src/functions.php:1015 +#: src/functions.php:1016 msgid "Key" msgstr "" @@ -69,118 +153,183 @@ msgstr "" msgid "Expire date" msgstr "" -#: includes/Admin/Orders.php:243 src/Admin/ListTables/KeysTable.php:532 -#: src/Functions/Template.php:63 src/functions.php:1036 -msgid "Lifetime" -msgstr "" - -#: includes/Admin/Orders.php:246 src/Admin/views/html-edit-key.php:67 +#: includes/Admin/Orders.php:246 src/Admin/views/html-edit-generator.php:87 +#: src/Admin/views/html-edit-key.php:67 msgid "Activation limit" msgstr "" -#: includes/Admin/Orders.php:247 -msgid "Unlimited" -msgstr "" - -#: includes/Admin/Orders.php:250 src/Admin/ListTables/KeysTable.php:360 -#: src/Admin/Menus.php:320 src/Admin/views/html-edit-key.php:92 -#: src/Functions/Template.php:78 src/functions.php:1040 -msgid "Status" -msgstr "" - #: includes/Admin/Orders.php:277 #. translators: %s is the item number. msgid "View Details" msgstr "" -#: includes/Admin/Products.php:92 includes/Admin/Products.php:315 -#: src/Admin/Admin.php:141 src/Admin/Menus.php:54 src/Admin/Menus.php:88 -#: src/Admin/Menus.php:89 src/Admin/Menus.php:433 +#: includes/Admin/Products.php:97 includes/Admin/Products.php:317 +#: src/Admin/Admin.php:151 src/Admin/Menus.php:56 src/Admin/Menus.php:90 +#: src/Admin/Menus.php:91 src/Admin/Menus.php:464 #: src/Functions/Template.php:226 msgid "Serial Numbers" msgstr "" -#: includes/Admin/Products.php:114 -msgid "Sell keys" +#: includes/Admin/Products.php:203 +msgid "" +"The free version of Serial Numbers for WooCommerce does not support product " +"variation." msgstr "" -#: includes/Admin/Products.php:115 -msgid "Enable this if you are selling keys with this product." +#: includes/Admin/Products.php:205 +#: includes/Admin/views/products/product-pro-notice-options.php:18 +#: src/Admin/Menus.php:227 +msgid "Upgrade to Pro" +msgstr "" + +#: includes/Admin/Products.php:222 +msgid "You do not have permission to save this data." +msgstr "" + +#: includes/Admin/Products.php:299 +msgid "Order missing serial numbers for this item." +msgstr "" + +#: includes/Admin/Requests.php:44 +msgid "You do not have permission to perform this action." +msgstr "" + +#: includes/Admin/Requests.php:81 +msgid "Key added successfully." msgstr "" -#: includes/Admin/Products.php:128 +#: includes/Admin/Requests.php:83 +msgid "Key updated successfully." +msgstr "" + +#: includes/Admin/Requests.php:102 +msgid "Error: Sorry, you are not allowed to do this." +msgstr "" + +#: includes/Admin/Requests.php:135 +msgid "Generator has been saved successfully." +msgstr "" + +#: includes/Admin/Requests.php:152 +msgid "You are not allowed, to use this." +msgstr "" + +#: includes/Admin/Requests.php:162 +msgid "Error: Please select a product." +msgstr "" + +#: includes/Admin/Requests.php:169 +msgid "Error: Please enter a quantity." +msgstr "" + +#: includes/Admin/Requests.php:196 +msgid "Could not generate any keys. Please check the generator settings." +msgstr "" + +#: includes/Admin/Requests.php:205 +#. Translators: %s: number of keys generated. +msgid "%s keys have been generated successfully." +msgstr "" + +#: includes/Admin/Requests.php:222 includes/Admin/Requests.php:285 +#: includes/Admin/Requests.php:360 +msgid "You do not have permission to access this endpoint." +msgstr "" + +#: includes/Admin/Requests.php:396 +#. translators: $1: customer name, $2 customer id, $3: customer email +msgid "%1$s (#%2$s - %3$s)" +msgstr "" + +#: includes/Admin/views/products/product-key-options.php:20 msgid "Delivery quantity" msgstr "" -#: includes/Admin/Products.php:129 +#: includes/Admin/views/products/product-key-options.php:21 msgid "Number of key(s) will be delivered per item. Available in PRO." msgstr "" -#: includes/Admin/Products.php:149 includes/Admin/Products.php:181 -msgid "Key source" +#: includes/Admin/views/products/product-pro-notice-options.php:16 +msgid "Want to sell keys for variable products?" msgstr "" -#: includes/Admin/Products.php:167 +#: includes/Admin/views/products/product-selling-keys-options.php:17 +msgid "Sell keys" +msgstr "" + +#: includes/Admin/views/products/product-selling-keys-options.php:18 +msgid "Enable this if you are selling keys with this product." +msgstr "" + +#: includes/Admin/views/products/product-software-options.php:17 msgid "Software version" msgstr "" -#: includes/Admin/Products.php:168 +#: includes/Admin/views/products/product-software-options.php:18 msgid "Version number for the software. Ignore if it's not a software." msgstr "" -#: includes/Admin/Products.php:169 +#: includes/Admin/views/products/product-software-options.php:19 msgid "e.g. 1.0" msgstr "" -#: includes/Admin/Products.php:183 -msgid "key available." -msgid_plural "keys available." -msgstr[0] "" -msgstr[1] "" +#: includes/Admin/views/products/product-source-options.php:22 +msgid "Key Source" +msgstr "" -#: includes/Admin/Products.php:191 -msgid "Want to sell keys for variable products?" +#: includes/Admin/views/products/product-source-options.php:26 +msgid "Automatically generate keys or use preset keys." msgstr "" -#: includes/Admin/Products.php:193 includes/Admin/Products.php:214 -#: src/Admin/Menus.php:189 -msgid "Upgrade to Pro" +#: includes/Admin/views/products/product-source-options.php:38 +msgid "Default" msgstr "" -#: includes/Admin/Products.php:212 -msgid "" -"The free version of Serial Numbers for WooCommerce does not support product " -"variation." +#: includes/Admin/views/products/product-source-options.php:46 +msgid "Key Generator" msgstr "" -#: includes/Admin/Products.php:231 -msgid "You do not have permission to save this data." +#: includes/Admin/views/products/product-source-options.php:47 +#: src/Admin/views/tools/general.php:57 +msgid "Select a specific key generator or leave empty to use default settings." msgstr "" -#: includes/Admin/Products.php:297 -msgid "Order missing serial numbers for this item." +#: includes/Admin/views/products/product-source-options.php:60 +msgid "Sequential Keys" msgstr "" -#: includes/Admin/Requests.php:42 -msgid "You do not have permission to perform this action." +#: includes/Admin/views/products/product-source-options.php:61 +msgid "Generate keys in sequential order." msgstr "" -#: includes/Admin/Requests.php:79 -msgid "Key added successfully." +#: includes/Admin/views/products/product-source-options.php:72 +msgid "Preset Stock" msgstr "" -#: includes/Admin/Requests.php:81 -msgid "Key updated successfully." +#: includes/Admin/views/products/product-source-options.php:74 +msgid "key available." +msgid_plural "keys available." +msgstr[0] "" +msgstr[1] "" + +#: includes/Models/Generator.php:119 src/Functions/Template.php:70 +msgid "Active" msgstr "" -#: includes/Admin/Requests.php:100 includes/Admin/Requests.php:163 -#: includes/Admin/Requests.php:238 -msgid "You do not have permission to access this endpoint." +#: includes/Models/Generator.php:120 +msgid "Inactive" msgstr "" -#: includes/Admin/Requests.php:274 -#. translators: $1: customer name, $2 customer id, $3: customer email -msgid "%1$s (#%2$s - %3$s)" +#: includes/Models/Generator.php:166 +msgid "The generator name is required." +msgstr "" + +#: includes/Models/Generator.php:170 +msgid "The generator pattern is required." +msgstr "" + +#: includes/Models/Generator.php:174 +msgid "The generator charset is required." msgstr "" #: lib/Lib/Model.php:424 @@ -212,7 +361,7 @@ msgstr "" msgid "More Plugins" msgstr "" -#: lib/Lib/Plugin.php:692 src/Admin/Menus.php:170 src/Admin/Menus.php:171 +#: lib/Lib/Plugin.php:692 src/Admin/Menus.php:208 src/Admin/Menus.php:209 msgid "Settings" msgstr "" @@ -248,42 +397,42 @@ msgstr "" msgid "Missing data." msgstr "" -#: src/Admin/Admin.php:65 +#: src/Admin/Admin.php:75 msgid "Search by product" msgstr "" -#: src/Admin/Admin.php:66 +#: src/Admin/Admin.php:76 msgid "Search by order" msgstr "" -#: src/Admin/Admin.php:67 +#: src/Admin/Admin.php:77 msgid "Search by customer" msgstr "" -#: src/Admin/Admin.php:68 +#: src/Admin/Admin.php:78 msgid "Show" msgstr "" -#: src/Admin/Admin.php:69 +#: src/Admin/Admin.php:79 msgid "Hide" msgstr "" -#: src/Admin/Admin.php:70 src/Frontend/Frontend.php:56 +#: src/Admin/Admin.php:80 src/Frontend/Frontend.php:56 msgid "Copied" msgstr "" -#: src/Admin/Admin.php:108 +#: src/Admin/Admin.php:118 #. translators: 1: Plugin name 2: WordPress msgid "" "Thank you for using %1$s! Share your appreciation with a five-star review " "%2$s." msgstr "" -#: src/Admin/Admin.php:110 +#: src/Admin/Admin.php:120 msgid "Thanks :)" msgstr "" -#: src/Admin/Admin.php:128 +#: src/Admin/Admin.php:138 #. translators: 1: Plugin version msgid "Version %s" msgstr "" @@ -293,8 +442,8 @@ msgstr "" msgid "Activation" msgstr "" -#: src/Admin/ListTables/ActivationsTable.php:40 src/Admin/Menus.php:119 -#: src/Admin/Menus.php:120 src/Admin/views/html-list-activations.php:18 +#: src/Admin/ListTables/ActivationsTable.php:40 src/Admin/Menus.php:157 +#: src/Admin/Menus.php:158 src/Admin/views/html-list-activations.php:18 msgid "Activations" msgstr "" @@ -308,13 +457,6 @@ msgstr "" msgid "Filter" msgstr "" -#: src/Admin/ListTables/ActivationsTable.php:164 -#: src/Admin/ListTables/ActivationsTable.php:239 -#: src/Admin/ListTables/KeysTable.php:336 -#: src/Admin/ListTables/KeysTable.php:428 src/Admin/views/html-edit-key.php:130 -msgid "Delete" -msgstr "" - #: src/Admin/ListTables/ActivationsTable.php:176 #: src/Admin/views/html-api-actions.php:141 src/Frontend/Shortcodes.php:146 msgid "Instance" @@ -360,7 +502,7 @@ msgid "Keys can have one of the following statuses:" msgstr "" #: src/Admin/ListTables/KeysTable.php:178 -#: src/Admin/ListTables/KeysTable.php:235 src/functions.php:46 +#: src/Admin/ListTables/KeysTable.php:235 src/functions.php:47 msgid "Available" msgstr "" @@ -369,7 +511,7 @@ msgid "This means the key is available for purchase." msgstr "" #: src/Admin/ListTables/KeysTable.php:183 -#: src/Admin/ListTables/KeysTable.php:242 src/functions.php:47 +#: src/Admin/ListTables/KeysTable.php:242 src/functions.php:48 msgid "Pending" msgstr "" @@ -379,7 +521,7 @@ msgstr "" #: src/Admin/ListTables/KeysTable.php:188 #: src/Admin/ListTables/KeysTable.php:249 -#: src/Admin/ListTables/StockTable.php:97 src/functions.php:48 +#: src/Admin/ListTables/StockTable.php:97 src/functions.php:49 msgid "Sold" msgstr "" @@ -389,7 +531,7 @@ msgstr "" #: src/Admin/ListTables/KeysTable.php:193 #: src/Admin/ListTables/KeysTable.php:256 src/Functions/Template.php:72 -#: src/functions.php:49 +#: src/functions.php:50 msgid "Expired" msgstr "" @@ -398,7 +540,7 @@ msgid "This means the key has expired and is no longer valid." msgstr "" #: src/Admin/ListTables/KeysTable.php:198 -#: src/Admin/ListTables/KeysTable.php:263 src/functions.php:50 +#: src/Admin/ListTables/KeysTable.php:263 src/functions.php:51 msgid "Cancelled" msgstr "" @@ -412,10 +554,6 @@ msgstr "" msgid "All keys." msgstr "" -#: src/Admin/ListTables/KeysTable.php:228 -msgid "All" -msgstr "" - #: src/Admin/ListTables/KeysTable.php:233 msgid "Available for sell." msgstr "" @@ -457,11 +595,6 @@ msgstr "" msgid "ID: %d" msgstr "" -#: src/Admin/ListTables/KeysTable.php:427 -#: src/Admin/ListTables/StockTable.php:143 -msgid "Edit" -msgstr "" - #: src/Admin/ListTables/KeysTable.php:522 #. translators: %1$s: validity, %2$s: validity. msgid "%s Day
+
+
+
+ ', '' ); ?>
+