From ae1aa22606355bac3ab5c548791ea00780cf0dd9 Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Mon, 30 Sep 2024 15:26:39 +0300
Subject: [PATCH 01/67] Reapply "[ #1079 ] - class to handle uploads"
This reverts commit c5a96d6d2e2f9ecdef3378ee13a3157ca1ba5bfb.
---
.../admin/class-modula-gallery-upload.php | 58 +++++++++++++++++++
includes/class-modula.php | 3 +-
2 files changed, 60 insertions(+), 1 deletion(-)
create mode 100644 includes/admin/class-modula-gallery-upload.php
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
new file mode 100644
index 00000000..3d8b29f3
--- /dev/null
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -0,0 +1,58 @@
+
Date: Mon, 30 Sep 2024 15:26:42 +0300
Subject: [PATCH 02/67] Reapply "[ #1060 ] - user rights check function"
This reverts commit ca5f0a562301b31967f83912ea6ddfb25143eb56.
---
includes/admin/class-modula-gallery-upload.php | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index 3d8b29f3..cb0c2422 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -53,6 +53,22 @@ public static function get_instance() {
return self::$instance;
}
+
+ /**
+ * Check if the user has the rights to upload files
+ *
+ * @return bool
+ *
+ * @since 2.10.3
+ */
+ public function check_user_upload_rights() {
+ // Check if the user has the rights to upload files and edit posts.
+ if ( ! current_user_can( 'upload_files' ) || ! current_user_can( 'edit_posts' ) ) {
+ return false;
+ }
+
+ return true;
+ }
}
Modula_Gallery_Upload::get_instance();
From adb013f44a4c4b3864218708409e0cafc37a9099 Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Mon, 30 Sep 2024 15:26:46 +0300
Subject: [PATCH 03/67] Reapply "[ #1065 ] - default location for media
browser"
This reverts commit 4ce9befdef0f446b6b5f16ac837c20a5e81da924.
---
includes/admin/class-modula-gallery-upload.php | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index cb0c2422..e97e9977 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -36,6 +36,7 @@ class Modula_Gallery_Upload {
* @since 2.10.3
*/
private function __construct() {
+ add_action( 'admin_init', array( $this, 'set_default_browser_dir' ), 15 );
}
/**
@@ -69,6 +70,16 @@ public function check_user_upload_rights() {
return true;
}
+
+ /**
+ * Set the default directory for the media browser. By default, it's the uploads directory.
+ *
+ * @return void
+ */
+ public function set_default_browser_dir() {
+ $uploads = wp_upload_dir();
+ $this->default_dir = apply_filters( 'modula_gallery_upload_default_dir', $uploads['basedir'] );
+ }
}
Modula_Gallery_Upload::get_instance();
From f41da47d32dbd9e79ed9f61b683edb14e3d29e25 Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Mon, 30 Sep 2024 15:27:32 +0300
Subject: [PATCH 04/67] version bump; changelog update;
---
Modula.php | 4 ++--
package.json | 2 +-
readme.txt | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Modula.php b/Modula.php
index 32752283..bf9b12e5 100644
--- a/Modula.php
+++ b/Modula.php
@@ -4,7 +4,7 @@
* Plugin URI: https://wp-modula.com/
* Description: Modula is the most powerful, user-friendly WordPress gallery plugin. Add galleries, masonry grids and more in a few clicks.
* Author: WPChill
-* Version: 2.10.2
+* Version: 2.10.3
* Author URI: https://www.wpchill.com/
* License: GPLv3 or later
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -47,7 +47,7 @@
* @since 2.0.2
*/
-define( 'MODULA_LITE_VERSION', '2.10.2' );
+define( 'MODULA_LITE_VERSION', '2.10.3' );
define( 'MODULA_PATH', plugin_dir_path( __FILE__ ) );
define( 'MODULA_URL', plugin_dir_url( __FILE__ ) );
defined( 'MODULA_PRO_STORE_URL' ) || define( 'MODULA_PRO_STORE_URL', 'https://wp-modula.com' );
diff --git a/package.json b/package.json
index f9695033..4cccf3f8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "modula-best-grid-gallery",
- "version": "2.10.2",
+ "version": "2.10.3",
"description": "Modula Image Gallery build tools",
"author": "WPChill",
"license": "GPL-2.0-or-later",
diff --git a/readme.txt b/readme.txt
index 66274770..62eee4cc 100644
--- a/readme.txt
+++ b/readme.txt
@@ -4,7 +4,7 @@ Tags: best gallery plugin, image gallery, video gallery, free gallery, wordpress
Requires at least: 5.3
Tested up to: 6.6
Requires PHP: 5.6
-Stable tag: 2.10.2
+Stable tag: 2.10.3
License: GNU General Public License v3.0 or later
The WordPress gallery plugin that's highly customizable & you can use to impress your clients. Create beautiful image galleries in minutes.
From 6dd251dc802813e58beedcca40a7ff5521960558 Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Mon, 30 Sep 2024 16:14:06 +0300
Subject: [PATCH 05/67] version bump; [ #1048 ] - create Upload from folder
button
---
Modula.php | 4 +--
.../admin/class-modula-gallery-upload.php | 28 +++++++++++++++----
2 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/Modula.php b/Modula.php
index bf9b12e5..b52679f7 100644
--- a/Modula.php
+++ b/Modula.php
@@ -4,7 +4,7 @@
* Plugin URI: https://wp-modula.com/
* Description: Modula is the most powerful, user-friendly WordPress gallery plugin. Add galleries, masonry grids and more in a few clicks.
* Author: WPChill
-* Version: 2.10.3
+* Version: 2.11.0
* Author URI: https://www.wpchill.com/
* License: GPLv3 or later
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -47,7 +47,7 @@
* @since 2.0.2
*/
-define( 'MODULA_LITE_VERSION', '2.10.3' );
+define( 'MODULA_LITE_VERSION', '2.11.0' );
define( 'MODULA_PATH', plugin_dir_path( __FILE__ ) );
define( 'MODULA_URL', plugin_dir_url( __FILE__ ) );
defined( 'MODULA_PRO_STORE_URL' ) || define( 'MODULA_PRO_STORE_URL', 'https://wp-modula.com' );
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index e97e9977..d37c94fb 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -9,7 +9,7 @@
* Handles the fast gallery creation from uploaded .zip file
* or from a choosen folder with images that reside on the server
*
- * @since 2.10.3
+ * @since 2.11.0
*/
class Modula_Gallery_Upload {
@@ -19,7 +19,7 @@ class Modula_Gallery_Upload {
*
* @var Modula_Gallery_Upload
*
- * @since 2.10.3
+ * @since 2.11.0
*/
public static $instance = null;
@@ -33,10 +33,13 @@ class Modula_Gallery_Upload {
/**
* Class constructor
*
- * @since 2.10.3
+ * @since 2.11.0
*/
private function __construct() {
+ // Set the default directory for the media browser
add_action( 'admin_init', array( $this, 'set_default_browser_dir' ), 15 );
+ // Add the Browser button
+ add_action( 'modula_gallery_media_select_option', array( $this, 'add_folder_browser_button' ), 15 );
}
/**
@@ -44,7 +47,7 @@ private function __construct() {
*
* @return Modula_Gallery_Upload
*
- * @since 2.10.3
+ * @since 2.11.0
*/
public static function get_instance() {
@@ -60,7 +63,7 @@ public static function get_instance() {
*
* @return bool
*
- * @since 2.10.3
+ * @since 2.11.0
*/
public function check_user_upload_rights() {
// Check if the user has the rights to upload files and edit posts.
@@ -80,6 +83,21 @@ public function set_default_browser_dir() {
$uploads = wp_upload_dir();
$this->default_dir = apply_filters( 'modula_gallery_upload_default_dir', $uploads['basedir'] );
}
+
+ /**
+ * Output the Upload from folder button
+ *
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function add_folder_browser_button() {
+ ?>
+
+
+
+
Date: Tue, 1 Oct 2024 11:46:35 +0300
Subject: [PATCH 06/67] [ #1050 ] - folder browser implementation
---
assets/js/admin/modula-gallery-upload.js | 40 +++
.../admin/class-modula-gallery-upload.php | 324 ++++++++++++++++++
2 files changed, 364 insertions(+)
create mode 100644 assets/js/admin/modula-gallery-upload.js
create mode 100644 includes/admin/class-modula-gallery-upload.php
diff --git a/assets/js/admin/modula-gallery-upload.js b/assets/js/admin/modula-gallery-upload.js
new file mode 100644
index 00000000..4bbb641d
--- /dev/null
+++ b/assets/js/admin/modula-gallery-upload.js
@@ -0,0 +1,40 @@
+// Browse for file class
+class ModulaBrowseForFile {
+ postID = 0;
+ constructor() {
+ const instance = this;
+ // Add user actions
+ instance.add_actions();
+ instance.postID = document.getElementById( 'post_ID' ).value;
+ }
+ add_actions() {
+ const instance = this,
+ modulaFileBrowserButton = document.getElementById(
+ 'modula-uploader-folder-browser'
+ );
+ modulaFileBrowserButton.addEventListener( 'click', function ( e ) {
+ // Prevent default action
+ e.preventDefault();
+
+ window.send_to_editor = window.send_to_browse_file_url;
+
+ tb_show(
+ modulaGalleryUpload.browseFolder,
+ 'media-upload.php?post_id=' +
+ instance.postID +
+ '&type=modula_file_browser&from=wpdlm01&TB_iframe=true'
+ );
+
+ return false;
+ } );
+ }
+ browserModal( url ) {}
+}
+
+document.addEventListener( 'DOMContentLoaded', function () {
+ window.send_to_browse_file_url = function ( html ) {
+ tb_remove();
+ window.send_to_editor = window.send_to_editor_default;
+ };
+ new ModulaBrowseForFile();
+} );
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
new file mode 100644
index 00000000..ab77f300
--- /dev/null
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -0,0 +1,324 @@
+default_dir = apply_filters( 'modula_gallery_upload_default_dir', $uploads['basedir'] );
+ }
+
+ /**
+ * Output the Upload from folder button.
+ *
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function add_folder_browser_button() {
+ ?>
+
+
+
+ $folder . '/' . $file,
+ );
+ }
+
+ return $dlm_files;
+ }
+
+ /**
+ * Multi-byte-safe pathinfo replacement.
+ *
+ * @param $filepath
+ *
+ * @return mixed
+ *
+ * @since 2.11.0
+ */
+ public function mb_pathinfo( $filepath ) {
+ $ret = array();
+ preg_match(
+ '%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im',
+ $filepath,
+ $m
+ );
+ if ( isset( $m[1] ) ) {
+ $ret['dirname'] = $m[1];
+ }
+ if ( isset( $m[2] ) ) {
+ $ret['basename'] = $m[2];
+ }
+ if ( isset( $m[5] ) ) {
+ $ret['extension'] = $m[5];
+ }
+ if ( isset( $m[3] ) ) {
+ $ret['filename'] = $m[3];
+ }
+
+ return $ret;
+ }
+
+ /**
+ * List browser files
+ *
+ * @access public
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function ajax_list_files() {
+ // Check Nonce
+ check_ajax_referer( 'list-files', 'security' );
+
+ // Check user rights
+ if ( ! $this->check_user_upload_rights() ) {
+ die();
+ }
+
+ if ( ! isset( $_POST['path'] ) ) {
+ die();
+ }
+
+ $path = sanitize_text_field( wp_unslash( $_POST['path'] ) );
+ // List all files
+ $files = $this->list_files( $path );
+ foreach ( $files as $found_file ) {
+ // Multi-byte-safe pathinfo
+ $file = $this->mb_pathinfo( $found_file['path'] );
+ echo '' . esc_html( $file['basename'] ) . ' ';
+ }
+
+ die();
+ }
+
+ /**
+ * Media browser, for the folder upload functionality
+ *
+ * @access public
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function media_browser() {
+ // If we have paths, show them in the file browser
+ if ( ! empty( $this->default_dir ) ) {
+ echo '' . esc_html__( 'Modula folder browser', 'modula-best-grid-gallery' ) . ' ';
+ // print_emoji_styles is deprecated and triggers a PHP warning.
+ remove_action( 'admin_print_styles', 'print_emoji_styles' );
+ do_action( 'admin_print_styles' ); // phpcs:ignore
+ do_action( 'admin_print_scripts' ); // phpcs:ignore
+ do_action( 'admin_head' ); // phpcs:ignore
+ // re-add print_emoji_styles.
+ add_action( 'admin_print_styles', 'print_emoji_styles' );
+
+ echo ' ';
+
+ echo '';
+ // Cycle through paths and list files.
+ // Get files based on path.
+ $files = $this->list_files( $this->default_dir, 1 );
+ if ( ! empty( $files ) ) {
+ // Cycle through files.
+ foreach ( $files as $found_file ) {
+ $file = pathinfo( $found_file['path'] );
+ echo '' . esc_html( $file['basename'] ) . ' ';
+ }
+ }
+ echo ' ';
+ ?>
+
+ ';
+ }
+ }
+
+ /**
+ * Enqueue required admin scripts
+ *
+ * @param string $hook The current admin page
+ * @return void
+ */
+ public function enqueue_scripts( $hook ) {
+ if ( 'post.php' !== $hook && 'post-new.php' !== $hook ) {
+ return;
+ }
+ $current_screen = get_current_screen();
+ if ( 'modula-gallery' !== $current_screen->post_type ) {
+ return;
+ }
+ // Enqueue the gallery upload script
+ wp_enqueue_script( 'modula-gallery-upload', MODULA_URL . 'assets/js/admin/modula-gallery-upload.js', array( 'jquery', 'media-upload' ), MODULA_LITE_VERSION, true );
+ // Localize the script
+ wp_localize_script(
+ 'modula-gallery-upload',
+ 'modulaGalleryUpload',
+ array(
+ 'browseFolder' => __( 'Browse for a folder', 'modula-best-grid-gallery' ),
+ )
+ );
+ wp_enqueue_style( 'media-upload' );
+ wp_enqueue_style( 'thickbox' );
+ }
+}
+
+Modula_Gallery_Upload::get_instance();
From 31c57913d5e77a46a0b55f4ad2527a76fc51e08a Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Tue, 1 Oct 2024 14:05:41 +0300
Subject: [PATCH 07/67] [ #1049 ] - folder browser modal
---
assets/css/admin/modula-browser.css | 30 +++++++
.../admin/class-modula-gallery-upload.php | 87 ++++++++++---------
2 files changed, 74 insertions(+), 43 deletions(-)
create mode 100644 assets/css/admin/modula-browser.css
diff --git a/assets/css/admin/modula-browser.css b/assets/css/admin/modula-browser.css
new file mode 100644
index 00000000..836d233d
--- /dev/null
+++ b/assets/css/admin/modula-browser.css
@@ -0,0 +1,30 @@
+ul.modula_file_browser {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ background-color: aliceblue;
+ padding:15px;
+}
+
+ul.modula_file_browser li {
+ list-style-type: none;
+}
+
+ul.modula_file_browser li a{
+ text-decoration: none;
+ color:#2271b1;
+}
+
+ul.modula_file_browser li a::before {
+ content: "\f139";
+ font-family: dashicons;
+ margin-right: 5px;
+}
+
+ul.modula_file_browser li.folder_open > a::before {
+ content: "\f140";
+}
+
+#modula_create_gallery {
+ margin-top:30px;
+}
\ No newline at end of file
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index ab77f300..2817e2d6 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -211,7 +211,7 @@ public function ajax_list_files() {
foreach ( $files as $found_file ) {
// Multi-byte-safe pathinfo
$file = $this->mb_pathinfo( $found_file['path'] );
- echo '' . esc_html( $file['basename'] ) . ' ';
+ echo '' . esc_html( $file['basename'] ) . ' ';
}
die();
@@ -228,7 +228,10 @@ public function ajax_list_files() {
public function media_browser() {
// If we have paths, show them in the file browser
if ( ! empty( $this->default_dir ) ) {
- echo '' . esc_html__( 'Modula folder browser', 'modula-best-grid-gallery' ) . ' ';
+ $this->enqueue_browser_scripts();
+ echo '';
+ echo '' . esc_html__( 'Modula folder browser', 'modula-best-grid-gallery' ) . ' ';
+ echo ' ';
// print_emoji_styles is deprecated and triggers a PHP warning.
remove_action( 'admin_print_styles', 'print_emoji_styles' );
do_action( 'admin_print_styles' ); // phpcs:ignore
@@ -236,9 +239,8 @@ public function media_browser() {
do_action( 'admin_head' ); // phpcs:ignore
// re-add print_emoji_styles.
add_action( 'admin_print_styles', 'print_emoji_styles' );
-
- echo ' ';
-
+ echo '';
+ echo '' . esc_html__( 'Select a folder to upload images from', 'modula-best-grid-gallery' ) . '
';
echo '';
- ?>
-
- ' . esc_html__( 'Create gallery from folders', 'modula-best-grid-gallery' ) . '';
+ do_action( 'admin_print_footer_styles' ); // phpcs:ignore
+ do_action( 'admin_print_footer_scripts' ); // phpcs:ignore
+ do_action( 'admin_footer' ); // phpcs:ignore
+ echo '';
echo '';
}
}
@@ -314,11 +284,42 @@ public function enqueue_scripts( $hook ) {
'modulaGalleryUpload',
array(
'browseFolder' => __( 'Browse for a folder', 'modula-best-grid-gallery' ),
+ 'noSubfolders' => __( 'No subfolders found', 'modula-best-grid-gallery' ),
+ 'security' => wp_create_nonce( 'list-files' ),
+ 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
)
);
wp_enqueue_style( 'media-upload' );
wp_enqueue_style( 'thickbox' );
}
+
+ /**
+ * Enqueue browser scripts
+ *
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function enqueue_browser_scripts() {
+ // Enqueue Modula browser styles.
+ wp_enqueue_style( 'modula-browser', MODULA_URL . 'assets/css/admin/modula-browser.css', array(), MODULA_LITE_VERSION );
+ // Enqueue Dashicons.
+ wp_enqueue_style( 'dashicons' );
+ // Enqueue buttons styles.
+ wp_enqueue_style( 'buttons' );
+ // Enqueue the Modula Gallery Upload script.
+ wp_enqueue_script( 'modula-gallery-upload', MODULA_URL . 'assets/js/admin/modula-gallery-upload.js', array( 'jquery', 'media-upload' ), MODULA_LITE_VERSION, true );
+ // Localize the script
+ wp_localize_script(
+ 'modula-gallery-upload',
+ 'modulaGalleryUpload',
+ array(
+ 'browseFolder' => __( 'Browse for a folder', 'modula-best-grid-gallery' ),
+ 'noSubfolders' => __( 'No subfolders found', 'modula-best-grid-gallery' ),
+ 'security' => wp_create_nonce( 'list-files' ),
+ )
+ );
+ }
}
Modula_Gallery_Upload::get_instance();
From 95c84bed81c7bfb559d05b2c0374f465c7cf084b Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Wed, 2 Oct 2024 08:42:21 +0300
Subject: [PATCH 08/67] [ #1050 ] - folder navigation
---
assets/js/admin/modula-gallery-upload.js | 104 +++++++++++++++---
.../admin/class-modula-gallery-upload.php | 77 ++++++-------
2 files changed, 130 insertions(+), 51 deletions(-)
diff --git a/assets/js/admin/modula-gallery-upload.js b/assets/js/admin/modula-gallery-upload.js
index 4bbb641d..1027ed16 100644
--- a/assets/js/admin/modula-gallery-upload.js
+++ b/assets/js/admin/modula-gallery-upload.js
@@ -1,34 +1,112 @@
// Browse for file class
class ModulaBrowseForFile {
postID = 0;
+ /**
+ * Constructor
+ *
+ * @since 2.11.0
+ */
constructor() {
const instance = this;
// Add user actions
instance.add_actions();
- instance.postID = document.getElementById( 'post_ID' ).value;
+ instance.postObject = document.getElementById( 'post_ID' );
+ if ( instance.postObject ) {
+ instance.postID = instance.postObject.value;
+ }
}
+ /**
+ * Add actions
+ *
+ * @snice 2.11.0
+ */
add_actions() {
const instance = this,
modulaFileBrowserButton = document.getElementById(
'modula-uploader-folder-browser'
);
- modulaFileBrowserButton.addEventListener( 'click', function ( e ) {
- // Prevent default action
- e.preventDefault();
+ if ( modulaFileBrowserButton ) {
+ modulaFileBrowserButton.addEventListener( 'click', function ( e ) {
+ // Prevent default action
+ e.preventDefault();
- window.send_to_editor = window.send_to_browse_file_url;
+ window.send_to_editor = window.send_to_browse_file_url;
- tb_show(
- modulaGalleryUpload.browseFolder,
- 'media-upload.php?post_id=' +
- instance.postID +
- '&type=modula_file_browser&from=wpdlm01&TB_iframe=true'
- );
+ tb_show(
+ modulaGalleryUpload.browseFolder,
+ 'media-upload.php?post_id=' +
+ instance.postID +
+ '&type=modula_file_browser&from=wpdlm01&TB_iframe=true'
+ );
- return false;
+ return false;
+ } );
+ }
+ }
+ /**
+ * File browser
+ *
+ * @since 2.11.0
+ */
+ fileBrowser() {
+ const instance = this;
+ // Event delegation - listens for clicks on dynamically added elements
+ document.body.addEventListener( 'click', function ( e ) {
+ if ( e.target && e.target.matches( '.modula_file_browser a' ) ) {
+ e.preventDefault();
+ // Code to handle the click event on the dynamically added element
+ instance.addFolderClick( e.target );
+ }
} );
}
- browserModal( url ) {}
+ /**
+ * Add folder click
+ *
+ * @param {*} folderLink
+ * @returns
+ *
+ * @since 2.11.0
+ */
+ addFolderClick( folderLink ) {
+ const instance = this,
+ $link = jQuery( folderLink ),
+ $parent = $link.closest( 'li' ),
+ $input = $parent.find( 'input[type="checkbox"]' ),
+ $inputChecked = $input.is( ':checked' );
+
+ if ( $parent.is( '.folder_open' ) ) {
+ $parent.find( 'ul' ).remove();
+ $parent.removeClass( 'folder_open' );
+ } else {
+ $link.after( '' );
+ var data = {
+ action: 'modula_list_files',
+ path: $link.attr( 'data-path' ),
+ security: modulaGalleryUpload.security,
+ 'input-checked': $inputChecked,
+ };
+
+ jQuery.post(
+ modulaGalleryUpload.ajaxUrl,
+ data,
+ function ( response ) {
+ $parent.addClass( 'folder_open' );
+
+ if ( response ) {
+ $parent.find( '.load_tree' ).html( response );
+ } else {
+ $parent
+ .find( '.load_tree' )
+ .html( modulaGalleryUpload.noSubFolders );
+ }
+ $parent
+ .find( '.load_tree' )
+ .removeClass( 'load_tree loading' );
+ }
+ );
+ }
+ return false;
+ }
}
document.addEventListener( 'DOMContentLoaded', function () {
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index ab77f300..b90c8b61 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -204,6 +204,10 @@ public function ajax_list_files() {
if ( ! isset( $_POST['path'] ) ) {
die();
}
+ $checked = false;
+ if ( ! empty( $_POST['input-checked'] ) && 'true' === $_POST['input-checked'] ) {
+ $checked = true;
+ }
$path = sanitize_text_field( wp_unslash( $_POST['path'] ) );
// List all files
@@ -211,7 +215,7 @@ public function ajax_list_files() {
foreach ( $files as $found_file ) {
// Multi-byte-safe pathinfo
$file = $this->mb_pathinfo( $found_file['path'] );
- echo '' . esc_html( $file['basename'] ) . ' ';
+ echo '' . esc_html( $file['basename'] ) . ' ';
}
die();
@@ -251,43 +255,11 @@ public function media_browser() {
}
}
echo '';
- ?>
-
- ' . esc_html__( 'Create gallery from folders', 'modula-best-grid-gallery' ) . '';
+ do_action( 'admin_print_footer_styles' ); // phpcs:ignore
+ do_action( 'admin_print_footer_scripts' ); // phpcs:ignore
+ do_action( 'admin_footer' ); // phpcs:ignore
+ echo '';
echo '';
}
}
@@ -319,6 +291,35 @@ public function enqueue_scripts( $hook ) {
wp_enqueue_style( 'media-upload' );
wp_enqueue_style( 'thickbox' );
}
+
+ /**
+ * Enqueue browser scripts
+ *
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function enqueue_browser_scripts() {
+ // Enqueue Modula browser styles.
+ wp_enqueue_style( 'modula-browser', MODULA_URL . 'assets/css/admin/modula-browser.css', array(), MODULA_LITE_VERSION );
+ // Enqueue Dashicons.
+ wp_enqueue_style( 'dashicons' );
+ // Enqueue buttons styles.
+ wp_enqueue_style( 'buttons' );
+ // Enqueue the Modula Gallery Upload script.
+ wp_enqueue_script( 'modula-gallery-upload', MODULA_URL . 'assets/js/admin/modula-gallery-upload.js', array( 'jquery', 'media-upload' ), MODULA_LITE_VERSION, true );
+ // Localize the script
+ wp_localize_script(
+ 'modula-gallery-upload',
+ 'modulaGalleryUpload',
+ array(
+ 'browseFolder' => __( 'Browse for a folder', 'modula-best-grid-gallery' ),
+ 'noSubfolders' => __( 'No subfolders found', 'modula-best-grid-gallery' ),
+ 'security' => wp_create_nonce( 'list-files' ),
+ 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
+ )
+ );
+ }
}
Modula_Gallery_Upload::get_instance();
From a71b15411c0742304758a26eea1e0acd5d42dee1 Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Wed, 2 Oct 2024 11:38:25 +0300
Subject: [PATCH 09/67] [ #1056 ] - folders validation
---
assets/js/admin/modula-gallery-upload.js | 79 +++++++++++++
.../admin/class-modula-gallery-upload.php | 105 ++++++++++++++----
2 files changed, 162 insertions(+), 22 deletions(-)
diff --git a/assets/js/admin/modula-gallery-upload.js b/assets/js/admin/modula-gallery-upload.js
index 1027ed16..139675c0 100644
--- a/assets/js/admin/modula-gallery-upload.js
+++ b/assets/js/admin/modula-gallery-upload.js
@@ -58,6 +58,7 @@ class ModulaBrowseForFile {
instance.addFolderClick( e.target );
}
} );
+ instance.foldersValidation();
}
/**
* Add folder click
@@ -107,6 +108,84 @@ class ModulaBrowseForFile {
}
return false;
}
+ /**
+ * Validate folders
+ *
+ * @since 2.11.0
+ */
+ foldersValidation() {
+ const instance = this,
+ modulaSendFoldersButton = document.getElementById(
+ 'modula_create_gallery'
+ );
+
+ modulaSendFoldersButton.addEventListener( 'click', function ( e ) {
+ e.preventDefault();
+ const checkedInputsEl = document.querySelectorAll(
+ 'input[type="checkbox"]:checked'
+ ),
+ checkedInputs = Array.from( checkedInputsEl ),
+ paths = checkedInputs.map( ( input ) => input.value );
+ const response = instance.checkPaths( paths );
+ if ( ! response ) {
+ // Sed error message
+ }
+ // Send the images folders paths to be added to be validated
+ } );
+ }
+ /**
+ * Check paths
+ *
+ * @param {*} paths
+ * @returns
+ *
+ * @since 2.11.0
+ */
+ checkPaths( paths ) {
+ const instance = this;
+ let ajaxResponse = false;
+ if ( paths.length === 0 ) {
+ return false;
+ }
+ var xhr = new XMLHttpRequest();
+ var params = new URLSearchParams();
+ // Set the request parameters.
+ params.append( 'action', 'modula_check_paths' );
+ params.append( 'paths', paths );
+ params.append( 'security', modulaGalleryUpload.security );
+ // Set request to admin-ajax.php.
+ xhr.open( 'POST', modulaGalleryUpload.ajaxUrl, true );
+ // Set the content type for a POST request.
+ xhr.setRequestHeader(
+ 'Content-Type',
+ 'application/x-www-form-urlencoded'
+ );
+ // Define what happens on successful data submission.
+ xhr.onload = function () {
+ if ( xhr.status >= 200 && xhr.status < 400 ) {
+ ajaxResponse = JSON.parse( xhr.response );
+ if ( ajaxResponse.success ) {
+ // Send success message and number of valid paths found.
+
+ } else {
+ // Send error message
+ }
+ } else {
+ // Send error message
+ }
+ };
+
+ // Define what happens in case of an error.
+ xhr.onerror = function () {
+ console.error( 'Request failed' );
+ // Send error message
+ };
+
+ // Send the request with parameters.
+ xhr.send( params.toString() );
+ // Return the response.
+ return xhr.response;
+ }
}
document.addEventListener( 'DOMContentLoaded', function () {
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index ae16bcfa..1654a90c 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -43,9 +43,11 @@ private function __construct() {
// Create the media browser.
add_action( 'media_upload_modula_file_browser', array( $this, 'media_browser' ) );
// AJAX list files.
- add_action( 'wp_ajax_modula_list_files', array( $this, 'ajax_list_files' ) );
+ add_action( 'wp_ajax_modula_list_files', array( $this, 'ajax_list_folders' ) );
// Add required scripts.
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
+ // AJAX check paths.
+ add_action( 'wp_ajax_modula_check_paths', array( $this, 'ajax_check_paths' ) );
}
/**
@@ -102,14 +104,13 @@ public function set_default_browser_dir() {
public function add_folder_browser_button() {
?>
-
+
check_folder( $folder ) ) {
return false;
}
@@ -138,18 +130,18 @@ public function list_files( $folder = '' ) {
// By default, the sorted order is alphabetical in ascending order
$files = array_diff( scandir( $folder ), array( '..', '.' ) );
- $dlm_files = array();
+ $modula_folders = array();
foreach ( $files as $file ) {
if ( ! is_dir( $folder . '/' . $file ) ) {
continue;
}
- $dlm_files[] = array(
+ $modula_folders[] = array(
'path' => $folder . '/' . $file,
);
}
- return $dlm_files;
+ return $modula_folders;
}
/**
@@ -185,14 +177,14 @@ public function mb_pathinfo( $filepath ) {
}
/**
- * List browser files
+ * List browser folders
*
* @access public
* @return void
*
* @since 2.11.0
*/
- public function ajax_list_files() {
+ public function ajax_list_folders() {
// Check Nonce
check_ajax_referer( 'list-files', 'security' );
@@ -211,7 +203,7 @@ public function ajax_list_files() {
$path = sanitize_text_field( wp_unslash( $_POST['path'] ) );
// List all files
- $files = $this->list_files( $path );
+ $files = $this->list_folders( $path );
foreach ( $files as $found_file ) {
// Multi-byte-safe pathinfo
$file = $this->mb_pathinfo( $found_file['path'] );
@@ -248,7 +240,7 @@ public function media_browser() {
echo '';
// Cycle through paths and list files.
// Get files based on path.
- $files = $this->list_files( $this->default_dir, 1 );
+ $files = $this->list_folders( $this->default_dir, 1 );
if ( ! empty( $files ) ) {
// Cycle through files.
foreach ( $files as $found_file ) {
@@ -325,6 +317,75 @@ public function enqueue_browser_scripts() {
)
);
}
+
+ /**
+ * Paths validation
+ *
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function ajax_check_paths() {
+ // Check Nonce
+ check_ajax_referer( 'list-files', 'security' );
+
+ // Check user rights
+ if ( ! $this->check_user_upload_rights() ) {
+ wp_send_json_error( __( 'You do not have the rights to upload files.', 'modula-best-grid-gallery' ) );
+ }
+
+ if ( ! isset( $_POST['paths'] ) ) {
+ wp_send_json_error( __( 'No paths were provided.', 'modula-best-grid-gallery' ) );
+ }
+
+ $paths = wp_unslash( $_POST['paths'] );
+ $folders = array();
+ if ( is_array( $paths ) ) {
+ $paths = array_map( 'sanitize_text_field', $paths );
+ foreach ( $paths as $path ) {
+ if ( $this->check_folder( $path ) ) {
+ // Retrieve the files here.
+ $files[] = $path;
+ }
+ }
+ } else {
+ $paths = sanitize_text_field( $paths );
+ if ( $this->check_folder( $paths ) ) {
+ // Retrieve the files here.
+ $folders[] = $paths;
+ }
+ }
+
+ // If no valid paths were provided, return an error
+ if ( empty( $folders ) ) {
+ wp_send_json_error( __( 'No valid paths were provided.', 'modula-best-grid-gallery' ) );
+ }
+ // Return the files
+ wp_send_json_success( $folders );
+ }
+
+ /**
+ * Check for empty or non folders
+ *
+ * @param string $folder
+ * @return void
+ */
+ public function check_folder( $folder ) {
+ // If no folder is specified, return false
+ if ( empty( $folder ) ) {
+ return false;
+ }
+ // If not dir, return false
+ if ( ! is_dir( $folder ) ) {
+ return false;
+ }
+ // If the folder does not exist, return false
+ $files_folders = scandir( $folder );
+ if ( ! $files_folders ) {
+ return false;
+ }
+ return true;
+ }
}
Modula_Gallery_Upload::get_instance();
From 64950e0970eafcd3f7c50141d1b391669e28e714 Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Thu, 3 Oct 2024 09:07:20 +0300
Subject: [PATCH 10/67] [ #1057 ] - files validation
---
assets/js/admin/modula-gallery-upload.js | 170 ++++++++++++------
.../admin/class-modula-gallery-upload.php | 130 +++++++++++++-
2 files changed, 243 insertions(+), 57 deletions(-)
diff --git a/assets/js/admin/modula-gallery-upload.js b/assets/js/admin/modula-gallery-upload.js
index 139675c0..f61d1f3b 100644
--- a/assets/js/admin/modula-gallery-upload.js
+++ b/assets/js/admin/modula-gallery-upload.js
@@ -58,7 +58,7 @@ class ModulaBrowseForFile {
instance.addFolderClick( e.target );
}
} );
- instance.foldersValidation();
+ instance.foldersFilesValidation();
}
/**
* Add folder click
@@ -113,25 +113,38 @@ class ModulaBrowseForFile {
*
* @since 2.11.0
*/
- foldersValidation() {
+ foldersFilesValidation() {
const instance = this,
modulaSendFoldersButton = document.getElementById(
'modula_create_gallery'
);
- modulaSendFoldersButton.addEventListener( 'click', function ( e ) {
- e.preventDefault();
- const checkedInputsEl = document.querySelectorAll(
- 'input[type="checkbox"]:checked'
- ),
- checkedInputs = Array.from( checkedInputsEl ),
- paths = checkedInputs.map( ( input ) => input.value );
- const response = instance.checkPaths( paths );
- if ( ! response ) {
- // Sed error message
+ modulaSendFoldersButton.addEventListener(
+ 'click',
+ async function ( e ) {
+ e.preventDefault();
+ const checkedInputsEl = document.querySelectorAll(
+ 'input[type="checkbox"]:checked'
+ ),
+ checkedInputs = Array.from( checkedInputsEl ),
+ paths = checkedInputs.map( ( input ) => input.value );
+ const responsePaths = await instance.checkPaths( paths );
+ if ( ! responsePaths ) {
+ // Send error message
+
+ return;
+ }
+ const responseFiles =
+ await instance.filesValidation( responsePaths );
+
+ if ( ! responseFiles ) {
+ // Send error message
+
+ return;
+ }
+ // Import the files in the Media Library
}
- // Send the images folders paths to be added to be validated
- } );
+ );
}
/**
* Check paths
@@ -141,50 +154,101 @@ class ModulaBrowseForFile {
*
* @since 2.11.0
*/
- checkPaths( paths ) {
- const instance = this;
- let ajaxResponse = false;
+ async checkPaths( paths ) {
if ( paths.length === 0 ) {
return false;
}
- var xhr = new XMLHttpRequest();
- var params = new URLSearchParams();
- // Set the request parameters.
- params.append( 'action', 'modula_check_paths' );
- params.append( 'paths', paths );
- params.append( 'security', modulaGalleryUpload.security );
- // Set request to admin-ajax.php.
- xhr.open( 'POST', modulaGalleryUpload.ajaxUrl, true );
- // Set the content type for a POST request.
- xhr.setRequestHeader(
- 'Content-Type',
- 'application/x-www-form-urlencoded'
- );
- // Define what happens on successful data submission.
- xhr.onload = function () {
- if ( xhr.status >= 200 && xhr.status < 400 ) {
- ajaxResponse = JSON.parse( xhr.response );
- if ( ajaxResponse.success ) {
- // Send success message and number of valid paths found.
-
- } else {
- // Send error message
+
+ const $params = {
+ action: 'modula_check_paths',
+ paths: paths,
+ security: modulaGalleryUpload.security,
+ },
+ instance = this;
+ const ajaxResponse = await instance.ajaxCall( $params ),
+ response = await JSON.parse( ajaxResponse );
+ if ( response.success ) {
+ return response.data;
+ } else {
+ return false;
+ }
+ }
+ /**
+ * Files validation
+ *
+ * @param {*} paths
+ *
+ * @since 2.11.0
+ */
+ async filesValidation( paths ) {
+ if ( 0 === paths.length ) {
+ return false;
+ }
+ const $params = {
+ action: 'modula_check_files',
+ paths: paths,
+ security: modulaGalleryUpload.security,
+ },
+ instance = this;
+
+ const ajaxResponse = await instance.ajaxCall( $params ),
+ response = await JSON.parse( ajaxResponse );
+
+ return response;
+ }
+ /**
+ * AJAX request
+ * @param {*} $params
+ * @param {*} $callback
+ * @returns
+ *
+ * @since 2.11.0
+ */
+ async ajaxCall( $params ) {
+ return new Promise( ( resolve, reject ) => {
+ // Create a new XMLHttpRequest object.
+ var xhr = new XMLHttpRequest();
+ var params = new URLSearchParams();
+ // Set the request parameters.
+ if ( $params ) {
+ // Loop through the parameters and append them to the URLSearchParams object.
+ for ( let key in $params ) {
+ if ( ! $params.hasOwnProperty( key ) ) {
+ continue;
+ }
+ params.append( key, $params[ key ] );
}
- } else {
- // Send error message
}
- };
-
- // Define what happens in case of an error.
- xhr.onerror = function () {
- console.error( 'Request failed' );
- // Send error message
- };
-
- // Send the request with parameters.
- xhr.send( params.toString() );
- // Return the response.
- return xhr.response;
+ // Set request to admin-ajax.php.
+ xhr.open( 'POST', modulaGalleryUpload.ajaxUrl, true );
+ // Set the content type for a POST request.
+ xhr.setRequestHeader(
+ 'Content-Type',
+ 'application/x-www-form-urlencoded'
+ );
+ // Detect when the request is complete
+ xhr.onreadystatechange = function () {
+ if ( xhr.readyState === 4 ) {
+ // 4 means request is done
+ if ( xhr.status === 200 ) {
+ // 200 is a successful status
+ resolve( xhr.response );
+ } else {
+ // Handle error if necessary
+ reject( xhr.response );
+ }
+ }
+ };
+
+ // Define what happens in case of an error.
+ xhr.onerror = function () {
+ console.error( 'Request failed' );
+ // Send error message
+ };
+
+ // Send the request with parameters.
+ xhr.send( params.toString() );
+ } );
}
}
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index 1654a90c..3a6c7bc5 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -48,6 +48,8 @@ private function __construct() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
// AJAX check paths.
add_action( 'wp_ajax_modula_check_paths', array( $this, 'ajax_check_paths' ) );
+ // AJAX check files from paths.
+ add_action( 'wp_ajax_modula_check_files', array( $this, 'ajax_check_files' ) );
}
/**
@@ -239,7 +241,7 @@ public function media_browser() {
echo '' . esc_html__( 'Select a folder to upload images from', 'modula-best-grid-gallery' ) . '
';
echo '';
// Cycle through paths and list files.
- // Get files based on path.
+ // Get folders based on path.
$files = $this->list_folders( $this->default_dir, 1 );
if ( ! empty( $files ) ) {
// Cycle through files.
@@ -344,14 +346,14 @@ public function ajax_check_paths() {
$paths = array_map( 'sanitize_text_field', $paths );
foreach ( $paths as $path ) {
if ( $this->check_folder( $path ) ) {
- // Retrieve the files here.
- $files[] = $path;
+ // Add folder path to the array
+ $folders[] = $path;
}
}
} else {
$paths = sanitize_text_field( $paths );
if ( $this->check_folder( $paths ) ) {
- // Retrieve the files here.
+ // Add folder path to the array
$folders[] = $paths;
}
}
@@ -386,6 +388,126 @@ public function check_folder( $folder ) {
}
return true;
}
+
+ /**
+ * Returns a listing of all files in the specified folder.
+ *
+ * @param string $folder
+ * @return array|bool
+ *
+ * @since 2.11.0
+ */
+ public function get_files( $folder ) {
+
+ // A listing of all files and dirs in $folder, excepting . and ..
+ // By default, the sorted order is alphabetical in ascending order
+ $files = array_diff( scandir( $folder ), array( '..', '.' ) );
+
+ $modula_files = array();
+ foreach ( $files as $file ) {
+ if ( is_dir( $folder . '/' . $file ) ) {
+ continue;
+ }
+ $file_path = $folder . '/' . $file;
+ if ( ! $this->check_file( $file_path ) ) {
+ continue;
+ }
+ $modula_files[] = $file_path;
+ }
+
+ return $modula_files;
+ }
+
+ /**
+ * Define allowed mime types for the gallery upload
+ *
+ * @return array
+ *
+ * @since 2.11.0
+ */
+ public function define_allowed_mime_types() {
+ // Define the allowed mime types.
+ $allowed_mime_types = array(
+ 'jpg|jpeg|jpe' => 'image/jpeg',
+ 'png' => 'image/png',
+ 'gif' => 'image/gif',
+ 'bmp' => 'image/bmp',
+ 'tiff' => 'image/tiff',
+ 'tif' => 'image/tiff',
+ 'webp' => 'image/webp',
+ );
+
+ // Get WP's default allowed mime types.
+ $wp_allowed_mime_types = get_allowed_mime_types();
+ // Get mime types that are present in the default allowed mime types and the ones we defined.
+ $allowed_mime_types = array_intersect_key( $allowed_mime_types, $wp_allowed_mime_types );
+
+ return apply_filters( 'modula_gallery_upload_allowed_mime_types', $allowed_mime_types );
+ }
+
+ /**
+ * File validation
+ *
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function ajax_check_files() {
+ // Check Nonce
+ check_ajax_referer( 'list-files', 'security' );
+
+ // Check user rights
+ if ( ! $this->check_user_upload_rights() ) {
+ wp_send_json_error( __( 'You do not have the rights to upload files.', 'modula-best-grid-gallery' ) );
+ }
+
+ if ( ! isset( $_POST['paths'] ) || empty( $_POST['paths'] ) ) {
+ wp_send_json_error( __( 'No paths were provided.', 'modula-best-grid-gallery' ) );
+ }
+
+ $paths = wp_unslash( $_POST['paths'] );
+ $files = array();
+
+ if ( is_array( $paths ) ) {
+ $paths = array_map( 'sanitize_text_field', $paths );
+ // Cycle through paths and get files.
+ foreach ( $paths as $path ) {
+ $files = array_merge( $files, $this->get_files( $path ) );
+ }
+ } else {
+ $paths = sanitize_text_field( $paths );
+ $files = $this->get_files( $paths );
+ }
+
+ // If no valid paths were provided, return an error
+ if ( empty( $files ) ) {
+ wp_send_json_error( __( 'No valid files were provided.', 'modula-best-grid-gallery' ) );
+ }
+ // Return the files
+ wp_send_json_success( $files );
+ }
+
+ /**
+ * File validation
+ *
+ * @param string $file
+ * @return bool
+ *
+ * @since 2.11.0
+ */
+ public function check_file( $file ) {
+ // Check if the file exists
+ if ( ! file_exists( $file ) ) {
+ return false;
+ }
+ // Check file mime type
+ $allowed_mime_types = $this->define_allowed_mime_types();
+ $file_info = wp_check_filetype( $file, $allowed_mime_types );
+ if ( ! $file_info || ! $file_info['ext'] || ! $file_info['type'] ) {
+ return false;
+ }
+ return true;
+ }
}
Modula_Gallery_Upload::get_instance();
From 7af9a7516495a175633f960c72e008ce9f855ce7 Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Thu, 3 Oct 2024 13:37:51 +0300
Subject: [PATCH 11/67] [ #1051 ] - import files to media library
---
assets/js/admin/modula-gallery-upload.js | 37 ++++++++++++
.../admin/class-modula-gallery-upload.php | 60 +++++++++++++++++++
2 files changed, 97 insertions(+)
diff --git a/assets/js/admin/modula-gallery-upload.js b/assets/js/admin/modula-gallery-upload.js
index f61d1f3b..1f1b9927 100644
--- a/assets/js/admin/modula-gallery-upload.js
+++ b/assets/js/admin/modula-gallery-upload.js
@@ -143,6 +143,7 @@ class ModulaBrowseForFile {
return;
}
// Import the files in the Media Library
+ instance.importFiles( responseFiles.data );
}
);
}
@@ -250,6 +251,42 @@ class ModulaBrowseForFile {
xhr.send( params.toString() );
} );
}
+ /**
+ * Import files
+ *
+ * @param {*} files
+ * @since 2.11.0
+ */
+ async importFiles( files ) {
+ const instance = this;
+ let filesArray = [];
+
+ // Cycle through the files and import them
+ for( let i = 0; i < files.length; i++ ) {
+ const file = files[ i ];
+ const $params = {
+ action: 'modula_import_file',
+ file: file,
+ security: modulaGalleryUpload.security,
+ };
+ const instance = this;
+ const ajaxResponse = await instance.ajaxCall( $params ),
+ response = await JSON.parse( ajaxResponse );
+ if ( response.success ) {
+ filesArray.push( response.data );
+ } else {
+ // Send error message
+
+ }
+ }
+
+ // Check if there are files to import
+ if ( filesArray.length > 0 ) {
+ // Update the gallery
+ //instance.updateGallery( filesArray );
+ }
+ }
+
}
document.addEventListener( 'DOMContentLoaded', function () {
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index 3a6c7bc5..81c77f98 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -50,6 +50,8 @@ private function __construct() {
add_action( 'wp_ajax_modula_check_paths', array( $this, 'ajax_check_paths' ) );
// AJAX check files from paths.
add_action( 'wp_ajax_modula_check_files', array( $this, 'ajax_check_files' ) );
+ // AJAX function to import images from a folder.
+ add_action( 'wp_ajax_modula_import_file', array( $this, 'ajax_import_file' ) );
}
/**
@@ -508,6 +510,64 @@ public function check_file( $file ) {
}
return true;
}
+
+ /**
+ * Import file from a folder to the media library
+ *
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function ajax_import_file() {
+ // Check Nonce
+ check_ajax_referer( 'list-files', 'security' );
+
+ // Check user rights
+ if ( ! $this->check_user_upload_rights() ) {
+ wp_send_json_error( __( 'You do not have the rights to upload files.', 'modula-best-grid-gallery' ) );
+ }
+
+ if ( ! isset( $_POST['file'] ) || empty( $_POST['file'] ) ) {
+ wp_send_json_error( __( 'No files were provided.', 'modula-best-grid-gallery' ) );
+ }
+
+ $file = wp_unslash( $_POST['file'] );
+ $attachment_id = $this->upload_image( $file );
+ if ( ! $attachment_id ) {
+ wp_send_json_error( __( 'The file could not be uploaded.', 'modula-best-grid-gallery' ) );
+ }
+ // Return the image ID
+ wp_send_json_success( $attachment_id );
+ }
+
+ /**
+ * Upload image to the media library
+ *
+ * @param string $file_path The path to the file
+ * @return int The attachment ID
+ *
+ * @since 2.11.0
+ */
+ public function upload_image( $file_path ) {
+ // Include the media functions file.
+ require_once ABSPATH . 'wp-admin/includes/image.php';
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ require_once ABSPATH . 'wp-admin/includes/media.php';
+ // Add the file to the media library.
+ $attachment_id = media_handle_sideload(
+ array(
+ 'name' => basename( $file_path ),
+ 'tmp_name' => $file_path,
+ ),
+ 0
+ );
+ // If the file was added successfully, return the attachment ID.
+ if ( is_wp_error( $attachment_id ) ) {
+ return false;
+ }
+ // Return the attachment ID.
+ return $attachment_id;
+ }
}
Modula_Gallery_Upload::get_instance();
From faf326e073a8295ac03600bca11fc2771534c968 Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Thu, 3 Oct 2024 15:23:41 +0300
Subject: [PATCH 12/67] [ #1058 ] - update gallery post meta
---
assets/js/admin/modula-gallery-upload.js | 41 ++++-
.../admin/class-modula-gallery-upload.php | 149 +++++++++++++++++-
2 files changed, 181 insertions(+), 9 deletions(-)
diff --git a/assets/js/admin/modula-gallery-upload.js b/assets/js/admin/modula-gallery-upload.js
index 1f1b9927..57f0b328 100644
--- a/assets/js/admin/modula-gallery-upload.js
+++ b/assets/js/admin/modula-gallery-upload.js
@@ -81,8 +81,9 @@ class ModulaBrowseForFile {
} else {
$link.after( '' );
var data = {
- action: 'modula_list_files',
+ action: 'modula_list_folders',
path: $link.attr( 'data-path' ),
+ postID: instance.postID,
security: modulaGalleryUpload.security,
'input-checked': $inputChecked,
};
@@ -259,10 +260,10 @@ class ModulaBrowseForFile {
*/
async importFiles( files ) {
const instance = this;
- let filesArray = [];
+ let filesIDs = [];
// Cycle through the files and import them
- for( let i = 0; i < files.length; i++ ) {
+ for ( let i = 0; i < files.length; i++ ) {
const file = files[ i ];
const $params = {
action: 'modula_import_file',
@@ -273,20 +274,44 @@ class ModulaBrowseForFile {
const ajaxResponse = await instance.ajaxCall( $params ),
response = await JSON.parse( ajaxResponse );
if ( response.success ) {
- filesArray.push( response.data );
+ filesIDs.push( response.data );
} else {
// Send error message
-
}
}
// Check if there are files to import
- if ( filesArray.length > 0 ) {
+ if ( filesIDs.length > 0 ) {
// Update the gallery
- //instance.updateGallery( filesArray );
+ instance.updateGallery( filesIDs );
+ }
+ }
+
+ /**
+ * Update gallery
+ *
+ * @param {*} ids
+ * @since 2.11.0
+ */
+ async updateGallery( $ids ) {
+ const instance = this;
+ instance.postID = document.getElementById( 'post_ID' ).value;
+
+ const $params = {
+ action: 'modula_add_images_ids',
+ ids: JSON.stringify( $ids ),
+ galleryID: instance.postID,
+ security: modulaGalleryUpload.security,
+ };
+
+ const ajaxResponse = await instance.ajaxCall( $params ),
+ response = await JSON.parse( ajaxResponse );
+
+ if ( response.success ) {
+ // Update the gallery
+ //instance.updateGalleryView( response.data );
}
}
-
}
document.addEventListener( 'DOMContentLoaded', function () {
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index 81c77f98..f847efc6 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -43,7 +43,7 @@ private function __construct() {
// Create the media browser.
add_action( 'media_upload_modula_file_browser', array( $this, 'media_browser' ) );
// AJAX list files.
- add_action( 'wp_ajax_modula_list_files', array( $this, 'ajax_list_folders' ) );
+ add_action( 'wp_ajax_modula_list_folders', array( $this, 'ajax_list_folders' ) );
// Add required scripts.
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
// AJAX check paths.
@@ -52,6 +52,8 @@ private function __construct() {
add_action( 'wp_ajax_modula_check_files', array( $this, 'ajax_check_files' ) );
// AJAX function to import images from a folder.
add_action( 'wp_ajax_modula_import_file', array( $this, 'ajax_import_file' ) );
+ // AJAX function to update the gallery modula-images post meta.
+ add_action( 'wp_ajax_modula_add_images_ids', array( $this, 'ajax_modula_add_images_ids' ) );
}
/**
@@ -240,6 +242,7 @@ public function media_browser() {
// re-add print_emoji_styles.
add_action( 'admin_print_styles', 'print_emoji_styles' );
echo '';
+ echo ' ';
echo '' . esc_html__( 'Select a folder to upload images from', 'modula-best-grid-gallery' ) . '
';
echo '';
// Cycle through paths and list files.
@@ -568,6 +571,150 @@ public function upload_image( $file_path ) {
// Return the attachment ID.
return $attachment_id;
}
+
+ /**
+ * Update the gallery modula-images post meta
+ *
+ * @return void
+ *
+ * @since 2.11.0
+ */
+ public function ajax_modula_add_images_ids() {
+ // Check Nonce
+ check_ajax_referer( 'list-files', 'security' );
+
+ // Check user rights
+ if ( ! $this->check_user_upload_rights() ) {
+ wp_send_json_error( __( 'You do not have the rights to upload files.', 'modula-best-grid-gallery' ) );
+ }
+
+ if ( ! isset( $_POST['galleryID'] ) || empty( $_POST['galleryID'] ) ) {
+ wp_send_json_error( __( 'No gallery ID was provided.', 'modula-best-grid-gallery' ) );
+ }
+
+ if ( ! isset( $_POST['ids'] ) || empty( $_POST['ids'] ) ) {
+ wp_send_json_error( __( 'No images were provided.', 'modula-best-grid-gallery' ) );
+ }
+
+ $gallery_id = absint( $_POST['galleryID'] );
+ $images = wp_unslash( $_POST['ids'] );
+ $images = explode( ',', $images );
+ $modula_images = array();
+
+ // Cycle through images and sanitize them
+ foreach ( $images as $image_id ) {
+ $attachment = get_post( $image_id );
+ $image = array(
+ 'id' => absint( $image_id ),
+ 'alt' => sanitize_text_field( get_post_meta( $image_id, '_wp_attachment_image_alt', true ) ),
+ 'title' => sanitize_text_field( $attachment->post_title ),
+ 'description' => wp_filter_post_kses( $attachment->post_content ),
+ 'halign' => 'center',
+ 'valign' => 'middle',
+ 'link' => '',
+ 'target' => '',
+ 'width' => 2,
+ 'height' => 2,
+ 'filters' => '',
+ );
+ $modula_images[ $image_id ] = $this->sanitize_image( $image );
+ }
+
+ // Update the gallery modula-images post meta
+ update_post_meta( $gallery_id, 'modula-images', $modula_images );
+
+ // Return the image ID
+ wp_send_json_success( __( 'Images added successfully.', 'modula-best-grid-gallery' ) );
+ }
+
+ /**
+ * Image sanitization function
+ *
+ * @param array $image
+ * @return array
+ *
+ * @since 2.11.0
+ */
+ private function sanitize_image( $image ) {
+
+ $new_image = array();
+
+ // This list will not contain id because we save our images based on image id.
+ $image_attributes = apply_filters(
+ 'modula_gallery_image_attributes',
+ array(
+ 'id',
+ 'alt',
+ 'title',
+ 'description',
+ 'halign',
+ 'valign',
+ 'link',
+ 'target',
+ 'width',
+ 'height',
+ 'togglelightbox',
+ 'hide_title',
+ )
+ );
+
+ foreach ( $image_attributes as $attribute ) {
+ if ( isset( $image[ $attribute ] ) ) {
+ switch ( $attribute ) {
+ case 'alt':
+ $new_image[ $attribute ] = sanitize_text_field( $image[ $attribute ] );
+ break;
+ case 'width':
+ case 'height':
+ $new_image[ $attribute ] = absint( $image[ $attribute ] );
+ break;
+ case 'title':
+ case 'description':
+ $new_image[ $attribute ] = wp_filter_post_kses( $image[ $attribute ] );
+ break;
+ case 'link':
+ $new_image[ $attribute ] = esc_url_raw( $image[ $attribute ] );
+ break;
+ case 'target':
+ if ( isset( $image[ $attribute ] ) ) {
+ $new_image[ $attribute ] = absint( $image[ $attribute ] );
+ } else {
+ $new_image[ $attribute ] = 0;
+ }
+ break;
+ case 'togglelightbox':
+ case 'hide_title':
+ if ( isset( $image[ $attribute ] ) ) {
+ $new_image[ $attribute ] = absint( $image[ $attribute ] );
+ } else {
+ $new_image[ $attribute ] = 0;
+ }
+ break;
+ case 'halign':
+ if ( in_array( $image[ $attribute ], array( 'left', 'right', 'center' ) ) ) {
+ $new_image[ $attribute ] = $image[ $attribute ];
+ } else {
+ $new_image[ $attribute ] = 'center';
+ }
+ break;
+ case 'valign':
+ if ( in_array( $image[ $attribute ], array( 'top', 'bottom', 'middle' ) ) ) {
+ $new_image[ $attribute ] = $image[ $attribute ];
+ } else {
+ $new_image[ $attribute ] = 'middle';
+ }
+ break;
+ default:
+ $new_image[ $attribute ] = apply_filters( 'modula_image_field_sanitization', sanitize_text_field( $image[ $attribute ] ), $image[ $attribute ], $attribute );
+ break;
+ }
+ } else {
+ $new_image[ $attribute ] = '';
+ }
+ }
+
+ return $new_image;
+ }
}
Modula_Gallery_Upload::get_instance();
From af8a74620769bc743c526ce978d3870f9bc4660c Mon Sep 17 00:00:00 2001
From: Razvan Aldea <44024114+razvanaldea89@users.noreply.github.com>
Date: Fri, 4 Oct 2024 13:50:16 +0300
Subject: [PATCH 13/67] [ #1074 ] - import progress
---
assets/css/admin/modula-browser.css | 23 +++
assets/js/admin/modula-gallery-upload.js | 187 ++++++++++++++++--
.../admin/class-modula-gallery-upload.php | 63 +++---
3 files changed, 226 insertions(+), 47 deletions(-)
diff --git a/assets/css/admin/modula-browser.css b/assets/css/admin/modula-browser.css
index 836d233d..2a9f8667 100644
--- a/assets/css/admin/modula-browser.css
+++ b/assets/css/admin/modula-browser.css
@@ -27,4 +27,27 @@ ul.modula_file_browser li.folder_open > a::before {
#modula_create_gallery {
margin-top:30px;
+}
+
+#modula-progress {
+ display:block;
+ width:100%;
+ margin-top:30px;
+}
+
+#modula-progress .modula-progress-text {
+ margin-top: 30px;
+ font-size: 14px;
+ color: #555;
+ font-style: italic;
+}
+
+#modula-progress .modula-progress-bar {
+ width: 0px;
+ height: 20px;
+ background-color: blue;
+ margin-top: 30px;
+ position: relative;
+ border-radius: 3px;
+ transition: width 0.3s ease;
}
\ No newline at end of file
diff --git a/assets/js/admin/modula-gallery-upload.js b/assets/js/admin/modula-gallery-upload.js
index 57f0b328..6a5e0589 100644
--- a/assets/js/admin/modula-gallery-upload.js
+++ b/assets/js/admin/modula-gallery-upload.js
@@ -1,6 +1,22 @@
+// Load the translations
+const { __ } = wp.i18n;
+
// Browse for file class
class ModulaBrowseForFile {
+ /**
+ * Post ID
+ *
+ * @since 2.11.0
+ */
postID = 0;
+
+ /**
+ * The progress class
+ *
+ * @since 2.11.0
+ */
+ progressClass = false;
+
/**
* Constructor
*
@@ -124,25 +140,46 @@ class ModulaBrowseForFile {
'click',
async function ( e ) {
e.preventDefault();
+ instance.progressClass.changeText(
+ modulaGalleryUpload.startFolderValidation
+ );
const checkedInputsEl = document.querySelectorAll(
'input[type="checkbox"]:checked'
),
checkedInputs = Array.from( checkedInputsEl ),
paths = checkedInputs.map( ( input ) => input.value );
const responsePaths = await instance.checkPaths( paths );
- if ( ! responsePaths ) {
+ if ( ! responsePaths.success ) {
// Send error message
-
+ instance.progressClass.changeText( responsePaths.data );
return;
}
- const responseFiles =
- await instance.filesValidation( responsePaths );
+ instance.progressClass.changeText(
+ __( 'Found ', 'modula-best-grid-gallery' ) +
+ responsePaths.data.length +
+ __(
+ ' folders. Starting files validation...',
+ 'modula-best-grid-gallery'
+ )
+ );
+ const responseFiles = await instance.filesValidation(
+ responsePaths.data
+ );
- if ( ! responseFiles ) {
+ if ( ! responseFiles.success ) {
// Send error message
-
+ instance.progressClass.changeText( responseFiles.data );
return;
}
+ instance.progressClass.changeText(
+ __( 'Found ', 'modula-best-grid-gallery' ) +
+ responseFiles.data.length +
+ __(
+ ' valid files. Starting importing the files...',
+ 'modula-best-grid-gallery'
+ )
+ );
+
// Import the files in the Media Library
instance.importFiles( responseFiles.data );
}
@@ -158,7 +195,10 @@ class ModulaBrowseForFile {
*/
async checkPaths( paths ) {
if ( paths.length === 0 ) {
- return false;
+ return {
+ success: false,
+ data: modulaGalleryUpload.noFoldersSelected,
+ };
}
const $params = {
@@ -169,11 +209,7 @@ class ModulaBrowseForFile {
instance = this;
const ajaxResponse = await instance.ajaxCall( $params ),
response = await JSON.parse( ajaxResponse );
- if ( response.success ) {
- return response.data;
- } else {
- return false;
- }
+ return response;
}
/**
* Files validation
@@ -183,9 +219,6 @@ class ModulaBrowseForFile {
* @since 2.11.0
*/
async filesValidation( paths ) {
- if ( 0 === paths.length ) {
- return false;
- }
const $params = {
action: 'modula_check_files',
paths: paths,
@@ -261,19 +294,25 @@ class ModulaBrowseForFile {
async importFiles( files ) {
const instance = this;
let filesIDs = [];
-
+ instance.progressClass.update( 0.3, files.length );
// Cycle through the files and import them
for ( let i = 0; i < files.length; i++ ) {
+ instance.progressClass.changeText(
+ __( 'Importing file ', 'modula-best-grid-gallery' ) +
+ ( i + 1 ) +
+ __( ' of ', 'modula-best-grid-gallery' ) +
+ files.length
+ );
const file = files[ i ];
const $params = {
action: 'modula_import_file',
file: file,
security: modulaGalleryUpload.security,
};
- const instance = this;
const ajaxResponse = await instance.ajaxCall( $params ),
response = await JSON.parse( ajaxResponse );
if ( response.success ) {
+ instance.progressClass.update( i + 1, files.length );
filesIDs.push( response.data );
} else {
// Send error message
@@ -282,8 +321,20 @@ class ModulaBrowseForFile {
// Check if there are files to import
if ( filesIDs.length > 0 ) {
- // Update the gallery
- instance.updateGallery( filesIDs );
+ instance.progressClass.changeText(
+ __( 'Imported ', 'modula-best-grid-gallery' ) +
+ filesIDs.length +
+ __( ' files.', 'modula-best-grid-gallery' )
+ );
+ // Wait for 2 seconds before updating the gallery.
+ setTimeout( function () {
+ instance.progressClass.hideBar();
+ instance.progressClass.changeText(
+ modulaGalleryUpload.updatingGallery
+ );
+ // Update the gallery
+ instance.updateGallery( filesIDs );
+ }, 2000 );
}
}
@@ -310,10 +361,108 @@ class ModulaBrowseForFile {
if ( response.success ) {
// Update the gallery
//instance.updateGalleryView( response.data );
+ instance.progressClass.changeText(
+ modulaGalleryUpload.galleryUpdated
+ );
}
}
}
+class ModulaProgressBar {
+ /**
+ * Progress bar wrapper
+ *
+ * @since 2.11.0
+ */
+ wrapper = null;
+
+ /**
+ * Progress bar element
+ *
+ * @since 2.11.0
+ */
+ progressBar = 0;
+
+ /**
+ * Progress bar text
+ * Place where the info about the progress is displayed
+ *
+ * @since 2.11.0
+ */
+ progressText = '';
+
+ /**
+ * Progress bar progress
+ *
+ * @since 2.11.0
+ */
+ progress = 0;
+
+ /**
+ * Progress bar total
+ *
+ * @since 2.11.0
+ */
+ total = 0;
+
+ /**
+ * Constructor
+ *
+ * @since 2.11.0
+ */
+ constructor( el ) {
+ const instance = this;
+ instance.wrapper = document.getElementById( el );
+ // Create the progress bar element
+ instance.progressBar = document.createElement( 'div' );
+ instance.progressBar.className = 'modula-progress-bar';
+ // Create the progress text element
+ instance.progressText = document.createElement( 'div' );
+ instance.progressText.className = 'modula-progress-text';
+ }
+ /**
+ * Progress display
+ *
+ * @since 2.11.0
+ */
+ display() {
+ const instance = this;
+ instance.wrapper.appendChild( instance.progressText );
+ instance.wrapper.appendChild( instance.progressBar );
+ }
+ /**
+ * Update progress bar
+ *
+ * @since 2.11.0
+ */
+ update( progress, total ) {
+ const instance = this;
+ instance.progress = progress;
+ instance.total = total;
+ instance.progressBar.style.width = ( progress / total ) * 100 + '%';
+ }
+ /**
+ * Change text
+ *
+ * @param {*} text
+ *
+ * @since 2.11.0
+ */
+ changeText( text ) {
+ const instance = this;
+ instance.progressText.innerHTML = text;
+ }
+ /**
+ * Hide bar
+ *
+ * @since 2.11.0
+ */
+ hideBar() {
+ const instance = this;
+ instance.progressBar.style.display = 'none';
+ }
+}
+
document.addEventListener( 'DOMContentLoaded', function () {
window.send_to_browse_file_url = function ( html ) {
tb_remove();
diff --git a/includes/admin/class-modula-gallery-upload.php b/includes/admin/class-modula-gallery-upload.php
index f847efc6..91929dce 100644
--- a/includes/admin/class-modula-gallery-upload.php
+++ b/includes/admin/class-modula-gallery-upload.php
@@ -257,10 +257,11 @@ public function media_browser() {
}
echo ' ';
echo '' . esc_html__( 'Create gallery from folders', 'modula-best-grid-gallery' ) . ' ';
+ echo '
';
do_action( 'admin_print_footer_styles' ); // phpcs:ignore
do_action( 'admin_print_footer_scripts' ); // phpcs:ignore
do_action( 'admin_footer' ); // phpcs:ignore
- echo '';
+ echo '';
echo '