├── .editorconfig
├── .github
└── FUNDING.yml
├── .gitignore
├── .phpcs.xml
├── assets
├── index.css
└── index.js
├── build.sh
├── composer.json
├── install.sh
├── plugin.php
├── readme.md
├── readme.txt
├── src
├── Admin.php
├── License.php
├── Log.php
├── Modules
│ └── ModuleX
│ │ └── Init.php
├── Plugin.php
├── Schema.php
└── Traits
│ ├── AjaxRequest.php
│ ├── Api.php
│ ├── FileSystem.php
│ ├── Orm.php
│ └── Singleton.php
└── strings.php
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | [*]
7 | indent_style = tab
8 | indent_size = 4
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: dev_kabir
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: devkabir
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | composer.lock
3 | *.zip
4 | .idea
--------------------------------------------------------------------------------
/.phpcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Coding standard for Dev Kabir's Projects
4 |
5 | plugin.php
6 | src
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/assets/index.css:
--------------------------------------------------------------------------------
1 | div.notice {
2 | display: none !important;
3 | }
--------------------------------------------------------------------------------
/assets/index.js:
--------------------------------------------------------------------------------
1 | alert('Script Loaded')
2 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # Function to display progress messages
4 | progress_message() {
5 | local message="$1"
6 |
7 | # Define color codes
8 | local color_reset="\033[0m"
9 | local color_green="\033[32m"
10 |
11 | # Print the colorized message
12 | echo -e "[$(date +'%Y-%m-%d %H:%M:%S')] ${color_green}${message}${color_reset}"
13 | }
14 |
15 | # abort on errors
16 | set -e
17 |
18 | # prepare place for build.
19 | plugin_name="$(basename $PWD)"
20 | progress_message "Preparing build directory..."
21 | rm -rf ./"$plugin_name" ./"$plugin_name".zip
22 | mkdir ./"$plugin_name"
23 |
24 | # copy all files for production
25 | progress_message "Copying files for production..."
26 | cp -R ./composer.json ./*.php src assets readme.txt ./"$plugin_name"/ --parents
27 |
28 | # Install PHP dependencies
29 | progress_message "Installing PHP dependencies..."
30 | composer install --working-dir=./"$plugin_name" --no-dev
31 | rm ./"$plugin_name"/composer.json
32 |
33 | # Add index.php to every directory
34 | progress_message "Adding index.php to every directory..."
35 | find ./"$plugin_name" -type d -exec sh -c "echo ' {}/index.php" \;
36 |
37 | # Create zip archive
38 | progress_message "Creating zip archive..."
39 | # TODO: update zip path based on your OS.
40 | "C:\Program Files\7-Zip\7z.exe" a ./"$plugin_name".zip ./"$plugin_name"/*
41 |
42 | # Revert changes for production
43 | progress_message "Reverting changes..."
44 | rm -rf ./"$plugin_name"
45 |
46 | # Completion message
47 | progress_message "Build process completed successfully."
48 | exit
49 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "devkabir/your-plugin-name",
3 | "description": "A simple oop structure in the singleton pattern for a WordPress plugin.",
4 | "version": "1.0.0",
5 | "type": "project",
6 | "license": "GPL-2.0-or-later",
7 | "authors": [
8 | {
9 | "name": "Dev Kabir",
10 | "email": "dev.kabir01@gmail.com"
11 | }
12 | ],
13 | "minimum-stability": "dev",
14 | "prefer-stable": true,
15 | "require-dev": {
16 | "php-stubs/woocommerce-stubs": "^9.3",
17 | "php-stubs/wordpress-stubs": "^6.6",
18 | "wp-coding-standards/wpcs": "^3.0"
19 | },
20 | "scripts": {
21 | "lint": "phpcs src --standard=.phpcs.xml -s --report=source",
22 | "format": "phpcbf src --standard=.phpcs.xml -s --report=source",
23 | "post-create-project-cmd": [
24 | "bash ./install.sh"
25 | ]
26 | },
27 | "autoload": {
28 | "psr-4": {
29 | "PluginPackage\\": "src/"
30 | }
31 | },
32 | "config": {
33 | "allow-plugins": {
34 | "dealerdirect/phpcodesniffer-composer-installer": true
35 | },
36 | "platform-check": true,
37 | "optimize-autoloader": true,
38 | "sort-packages": true,
39 | "lock": false
40 | },
41 | "require": {
42 | "php": "^7.4 || ^8.0",
43 | "ext-json": "*"
44 | }
45 | }
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Function to display progress messages
4 | progress_message() {
5 | local message="$1"
6 |
7 | # Define color codes
8 | local color_reset="\033[0m"
9 | local color_green="\033[32m"
10 |
11 | # Print the colorized message
12 | echo -e "[$(date +'%Y-%m-%d %H:%M:%S')] ${color_green}${message}${color_reset}"
13 | }
14 |
15 | # abort on errors
16 | set -e
17 | progress_message "Replacing placeholders..."
18 | # Get the current directory name
19 | base=${PWD##*/}
20 | # Convert to Pascal case for namespace
21 | namespace=$(sed -E 's/(^|-)([a-zA-Z0-9])/\U\2/g' <<< "$base")
22 | # Convert to Title Case with spaces
23 | title=$(sed 's/-/ /g' <<< "$base")
24 | title=${title^}
25 | object=$(sed 's/-/_/g' <<< "$base")
26 |
27 | if [ -e "plugin.php" ]; then
28 | mv plugin.php "$base.php"
29 | fi
30 | # Search and replace "Your Plugin Name" with the current directory name in all PHP, JS, JSON, and HTML files except files in the vendor folder inside src directory
31 | find ./ -type f \( -name "*.php" -o -name "*.js" -o -name "*.json" -o -name "*.html" -o -name "*.txt" \) -not -path "./vendor/*" -not -path "./assets/node_modules/*" -execdir sed -i "s/Your Plugin Name/${title//\//\\/}/g" {} \;
32 | # Search and replace "your-plugin-name" with the current directory name in all PHP, JS, JSON, and HTML files except files in the vendor folder inside src directory
33 | find ./ -type f \( -name "*.php" -o -name "*.js" -o -name "*.json" -o -name "*.html" \) -not -path "./vendor/*" -not -path "./assets/node_modules/*" -execdir sed -i "s/your-plugin-name/${base//\//\\/}/g" {} \;
34 | # Search and replace "YourPluginName" with the current directory name in all PHP, JS, JSON, and HTML files except files in the vendor folder inside src directory
35 | find ./ -type f \( -name "*.php" -o -name "*.js" -o -name "*.json" -o -name "*.html" \) -not -path "./vendor/*" -not -path "./assets/node_modules/*" -execdir sed -i "s/PluginPackage/${namespace//\//\\/}/g" {} \;
36 | # Search and replace "your_plugin_name" with the current directory name in all PHP, JS, JSON, and HTML files except files in the vendor folder inside src directory
37 | find ./ -type f \( -name "*.php" -o -name "*.js" -o -name "*.json" -o -name "*.html" -o -name "*.ts" \) -not -path "./vendor/*" -not -path "./assets/node_modules/*" -execdir sed -i "s/your_plugin_name/${object//\//\\/}/g" {} \;
38 | # run composer dump-autoload
39 | progress_message "Running composer dump-autoload..."
40 | composer dump-autoload
41 | # delete this file
42 | progress_message "Deleting unnecessary files..."
43 | rm -rf ./.github
44 | rm ./readme.md
45 | rm ./install.sh
46 |
--------------------------------------------------------------------------------
/plugin.php:
--------------------------------------------------------------------------------
1 |
26 | ```
27 |
28 | 3. Replace `` with what you want to call your plugin.
29 | 4. Hit **Enter** and let it do its magic!
30 | 5. You’re ready to start creating something amazing for WordPress!
31 |
32 | Happy coding!
33 |
34 | ## Building Your Plugin (Creating a ZIP File)
35 |
36 | When you're done and want to share your plugin, follow these steps to make a ZIP file:
37 |
38 | 1. In your terminal, run the following command:
39 |
40 | ```bash
41 | ./build.sh
42 | ```
43 |
44 | 2. This command will create a **ZIP** file of your plugin, so you can upload it to WordPress or share it with others.
45 |
46 | ## Extra Plugins (Recommended)
47 |
48 | If you want some extra tools to help with debugging (fixing errors), you can use [Zero Debugger](https://github.com/devkabir/0-debugger).
49 |
50 | ## Want More? Check Out Other Branches.
51 |
52 | - [Vue based Admin Template](https://github.com/devkabir/wordpress-plugin/tree/vue-admin-template)
53 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | === Your Plugin Name ===
2 | Contributors: (this should be a list of wordpress.org userid's)
3 | Donate link: https://example.com/
4 | Tags: tag1, tag2
5 | Requires at least: 5.3
6 | Tested up to: 6.3.1
7 | Stable tag: 4.7
8 | Requires PHP: 7.1
9 | License: GPLv2 or later
10 | License URI: https://www.gnu.org/licenses/gpl-2.0.html
11 |
12 | Here is a short description of the plugin. This should be no more than 150 characters. No markup here.
13 |
14 | == Description ==
15 |
16 | This is the long description. No limit, and you can use Markdown (as well as in the following sections).
17 |
18 | List:
19 |
20 | * "Contributors" is a comma separated list of wordpress.org usernames
21 | * "Tags" is a comma separated list of tags that apply to the plugin
22 | * "Requires at least" is the lowest version that the plugin will work on
23 | * "Tested up to" is the highest version that you've *successfully used to test the plugin*
24 | * Stable tag must indicate the Subversion "tag" of the latest stable version
25 |
26 | If no stable tag is provided, your users may not get the correct version of your code.
27 |
28 | == Frequently Asked Questions ==
29 |
30 | = A question that someone might have =
31 |
32 | An answer to that question.
33 |
34 | = What about foo bar? =
35 |
36 | Answer to foo bar dilemma.
37 |
38 | == Screenshots ==
39 |
40 | 1. This screen shot description corresponds to screenshot-1.(png|jpg|jpeg|gif). Screenshots are stored in the /assets directory.
41 | 2. This is the second screen shot
42 |
43 | == Changelog ==
44 |
45 | = 1.0.0 - date =
46 | * Initial release
47 |
--------------------------------------------------------------------------------
/src/Admin.php:
--------------------------------------------------------------------------------
1 | Hello Dev!' );
51 | },
52 | );
53 | }
54 | );
55 | add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );
56 | // Fire modules.
57 | $this->modules();
58 | }
59 |
60 | /**
61 | * It initializes all the modules that are needed to run the plugin.
62 | *
63 | * @return void
64 | */
65 | public function modules() {
66 | // TODO: Add new modules here.
67 | ModuleX::init();
68 | }
69 | /**
70 | * It loads scripts based on plugin's mode, dev or prod.
71 | *
72 | * @return void
73 | */
74 | public function scripts(): void {
75 | wp_register_style( SLUG, plugins_url( 'assets/index.css', FILE ), array(), VERSION );
76 | wp_register_script( SLUG, plugins_url( 'assets/index.js', FILE ), array(), VERSION, true );
77 | wp_localize_script(
78 | SLUG,
79 | str_replace( '-', '_', SLUG ),
80 | array(
81 | 'security_token' => wp_create_nonce( 'wp_rest' ),
82 | 'strings' => $this->strings(),
83 | ),
84 | );
85 | }
86 |
87 | /**
88 | * It returns the sanitized i18n strings array for js templates.
89 | *
90 | * @return array The sanitized strings array.
91 | */
92 | private function strings() {
93 | $string = include plugin_dir_path( FILE ) . 'strings.php';
94 | return $this->sanitize_array( $string );
95 | }
96 |
97 | /**
98 | * Sanitizes all values in a multidimensional array recursively.
99 | *
100 | * @param array $data The array to sanitize.
101 | * @return array The sanitized array.
102 | */
103 | private function sanitize_array( array &$data ): array {
104 | foreach ( $data as &$value ) {
105 | if ( ! is_array( $value ) ) {
106 | $value = esc_attr( sanitize_text_field( $value ) );
107 | } else {
108 | $value = $this->sanitize_array( $value );
109 | }
110 | }
111 | unset( $value ); // Unset the reference to avoid potential bugs.
112 | return $data;
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/License.php:
--------------------------------------------------------------------------------
1 | $site_url,
38 | 'event' => $event,
39 | 'version' => VERSION,
40 | 'name' => SLUG,
41 | );
42 |
43 | $headers = array(
44 | 'user-agent' => SLUG . ';' . password_hash( $site_url, PASSWORD_BCRYPT ),
45 | 'Accept' => 'application/json',
46 | 'Content-Type' => 'application/json',
47 | 'Origin' => $site_url,
48 | 'Referer' => $site_url,
49 | 'Cache-Control' => 'no-cache',
50 | );
51 |
52 | $response = wp_remote_post(
53 | $this->api,
54 | array(
55 | 'timeout' => 30,
56 | 'redirection' => 5,
57 | 'httpversion' => '1.0',
58 | 'headers' => $headers,
59 | 'body' => wp_json_encode( $data ),
60 | 'sslverify' => false,
61 | 'cookies' => array(),
62 | )
63 | );
64 |
65 | if ( false === is_wp_error( $response ) && false === get_option( SLUG . '-license-key' ) ) {
66 | $response = wp_remote_retrieve_body( $response );
67 | update_option( SLUG . '-license-key', $response );
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/Log.php:
--------------------------------------------------------------------------------
1 | file( $type );
26 |
27 | if ( is_array( $message ) || is_object( $message ) || is_iterable( $message ) ) {
28 | $message = wp_json_encode( $message, JSON_PRETTY_PRINT );
29 | } else {
30 | $decoded = json_decode( $message, true );
31 | if ( json_last_error() === JSON_ERROR_NONE ) {
32 | $message = wp_json_encode( $decoded, JSON_PRETTY_PRINT );
33 | }
34 | }
35 | $date = sprintf( '[%s]::', gmdate( 'd-M-Y h:i:s A' ) );
36 | $message = $this->read( $type ) . PHP_EOL . $date . sanitize_textarea_field( $message );
37 |
38 | return $this->write_file( $file, $message );
39 | }
40 |
41 |
42 | /**
43 | * It's reading the log file and returning the content.
44 | *
45 | * @param string $type log type.
46 | *
47 | * @return string logs
48 | */
49 | public function read( string $type ) {
50 | $file = $this->file( $type );
51 |
52 | return $this->read_file( $file );
53 | }
54 |
55 |
56 | /**
57 | * It's deleting the log file.
58 | *
59 | * @param string $type log type.
60 | *
61 | * @return bool
62 | */
63 | public function delete( string $type ) {
64 | $file = $this->file( $type );
65 | return $this->delete_file( $file );
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Modules/ModuleX/Init.php:
--------------------------------------------------------------------------------
1 | create();
27 | }
28 |
29 | /**
30 | * Handle the plugin deactivation event.
31 | *
32 | * In this method you can add any code that needs to be executed when the plugin is deactivated. For example,
33 | * deleting tables, options, etc.
34 | *
35 | * @return void
36 | */
37 | public static function deactivate() {
38 | License::instance( 'deactivate' );
39 | Schema::instance()->truncate();
40 | }
41 |
42 | /**
43 | * Handle the plugin uninstall event.
44 | *
45 | * In this method you can add any code that needs to be executed when the plugin is uninstalled. For example,
46 | * deleting tables, options, etc.
47 | *
48 | * @return void
49 | */
50 | public static function uninstall() {
51 | License::instance( 'uninstall' );
52 | Schema::instance()->delete();
53 | }
54 |
55 | /**
56 | * Initialize the plugin by setting up necessary components.
57 | * This method is called automatically when the plugin is activated.
58 | *
59 | * @return void
60 | */
61 | public static function init() {
62 | if ( is_admin() ) {
63 | Admin::instance();
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Schema.php:
--------------------------------------------------------------------------------
1 | "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}table_name (
25 | id INT(11) NOT NULL AUTO_INCREMENT,
26 | column_name VARCHAR(255) NOT NULL,
27 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
28 | updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
29 | PRIMARY KEY (id)
30 | );",
31 | );
32 |
33 | foreach ( $tables as $sql ) {
34 | $wpdb->query( $sql );
35 | if ( ! empty( $wpdb->last_error ) ) {
36 | Log::instance()->write(
37 | 'error',
38 | array(
39 | 'error' => $wpdb->last_error,
40 | 'query' => $sql,
41 | )
42 | );
43 | break;
44 | }
45 | }
46 | }
47 |
48 | /**
49 | * Delete tables in database.
50 | *
51 | * @return void
52 | */
53 | public function delete() {
54 | global $wpdb;
55 |
56 | $tables = array(
57 | 'table_name' => "DROP TABLE IF EXISTS {$wpdb->prefix}table_name",
58 | );
59 |
60 | foreach ( $tables as $sql ) {
61 | $wpdb->query( $sql );
62 | if ( ! empty( $wpdb->last_error ) ) {
63 | Log::instance()->write(
64 | 'error',
65 | array(
66 | 'error' => $wpdb->last_error,
67 | 'query' => $sql,
68 | )
69 | );
70 | break;
71 | }
72 | }
73 | }
74 |
75 | /**
76 | * Truncate tables in database.
77 | *
78 | * @return void
79 | */
80 | public function truncate() {
81 | global $wpdb;
82 |
83 | $tables = array(
84 | 'table_name' => "TRUNCATE TABLE {$wpdb->prefix}table_name",
85 | );
86 |
87 | foreach ( $tables as $sql ) {
88 | $wpdb->query( $sql );
89 | if ( ! empty( $wpdb->last_error ) ) {
90 | Log::instance()->write(
91 | 'error',
92 | array(
93 | 'error' => $wpdb->last_error,
94 | 'query' => $sql,
95 | )
96 | );
97 | break;
98 | }
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Traits/AjaxRequest.php:
--------------------------------------------------------------------------------
1 | errors = $message;
41 | return $this;
42 | }
43 | /**
44 | * Sets the data in the response array.
45 | *
46 | * @param mixed $data The data to be set.
47 | * @return self Returns the current object.
48 | */
49 | private function set_data( $data ): self {
50 | $this->response = $data;
51 |
52 | return $this;
53 | }
54 |
55 | /**
56 | * Serve data to AJAX request.
57 | */
58 | private function serve(): void {
59 | if ( empty( $this->errors ) ) {
60 | wp_send_json_success( $this->response );
61 | }
62 | wp_send_json_error( $this->errors );
63 | }
64 |
65 | /**
66 | * Verify and validate AJAX request.
67 | *
68 | * @param array $fields The fields to verify.
69 | * @param string $key The key to use for verification. Default is 'data'.
70 | */
71 | private function verify( array $fields = array(), string $key = 'data' ): void {
72 | check_ajax_referer( SLUG, 'security_token' );
73 | $this->response = array();
74 | $this->errors = array();
75 | if ( ! empty( $fields ) ) {
76 | // Will sanitized data before use.
77 | $un_slashed = array_map( 'wp_unslash', $_REQUEST[ $key ] ?? array() ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
78 | $data = array_column( $un_slashed, 'value', 'name' );
79 | $filtered = array_filter(
80 | $data,
81 | function ( $value, $key ) {
82 | switch ( $key ) {
83 | case 'email':
84 | return sanitize_email( $value );
85 | case 'comment':
86 | case 'message':
87 | return sanitize_textarea_field( $value );
88 | default:
89 | return sanitize_text_field( $value );
90 | }
91 | },
92 | ARRAY_FILTER_USE_BOTH
93 | );
94 | $this->data = $this->extract_data( $filtered, $fields );
95 | }
96 | }
97 |
98 | /**
99 | * Extracts data from an array using the given keys.
100 | *
101 | * @param array $sanitized The array from which to extract data.
102 | * @param array $keys The keys to use for extraction.
103 | *
104 | * @return array The extracted data.
105 | */
106 | public function extract_data( array $sanitized, array $keys ): array {
107 | return array_intersect_key( $sanitized, array_flip( $keys ) );
108 | }
109 |
110 | /**
111 | * Generate AJAX action for based on logged-in users.
112 | *
113 | * @param string $action The action to register.
114 | */
115 | public function action( string $action ): string {
116 | if ( is_user_logged_in() ) {
117 | return sprintf( 'wp_ajax_%s-%s', SLUG, $action );
118 | }
119 | return sprintf( 'wp_ajax_nopriv_%s-%s', SLUG, $action );
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/Traits/Api.php:
--------------------------------------------------------------------------------
1 | true,
27 | 'message' => '',
28 | 'data' => array(),
29 | );
30 |
31 |
32 | /**
33 | * Retrieves the URL for the API endpoint.
34 | *
35 | * @return string The URL for the API endpoint.
36 | */
37 | public static function get_url() {
38 | return get_rest_url() . self::$namespace . '/' . self::$route;
39 | }
40 |
41 |
42 | /**
43 | * Check if a given request has access to get data from custom table
44 | *
45 | * @return WP_Error|bool
46 | */
47 | public function options_permissions_check() {
48 | if ( ! current_user_can( 'manage_options' ) ) {
49 | return new WP_Error(
50 | 'rest_forbidden',
51 | __( 'Sorry, you are not allowed to use this endpoint', 'your-plugin-name' ),
52 | array( 'status' => rest_authorization_required_code() )
53 | );
54 | }
55 |
56 | return true;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Traits/FileSystem.php:
--------------------------------------------------------------------------------
1 | get_dir() . $type . '.' . $extension;
22 | }
23 |
24 |
25 | /**
26 | * Initialize the WP file system.
27 | *
28 | * @return mixed
29 | */
30 | private function load_filesystem() {
31 | global $wp_filesystem;
32 |
33 | if ( empty( $wp_filesystem ) ) {
34 | require_once ABSPATH . '/wp-admin/includes/file.php';
35 | WP_Filesystem();
36 | }
37 | }
38 | /**
39 | * Retrieves the directory path for the message files.
40 | *
41 | * @return string The directory path for the message files.
42 | * @global \WP_Filesystem_Direct $wp_filesystem
43 | */
44 | private function get_dir(): string {
45 | $this->load_filesystem();
46 | global $wp_filesystem;
47 | $upload_dir = wp_upload_dir();
48 | $message_dir = $upload_dir['basedir'] . '/' . SLUG . '-files/';
49 | if ( ! file_exists( $message_dir ) ) {
50 | $wp_filesystem->mkdir( $message_dir );
51 | }
52 |
53 | return $message_dir;
54 | }
55 |
56 | /**
57 | * Reads the contents of a file.
58 | *
59 | * @param string $path The path to the file to read.
60 | *
61 | * @return string|false The contents of the file, or false if the file does not exist.
62 | * @global \WP_Filesystem_Direct $wp_filesystem
63 | */
64 | private function read_file( $path ) {
65 | $this->load_filesystem();
66 | global $wp_filesystem;
67 | if ( ! file_exists( $path ) ) {
68 | return false;
69 | }
70 | $this->load_filesystem();
71 | return $wp_filesystem->get_contents( $path );
72 | }
73 |
74 | /**
75 | * Writes the given content to the given file.
76 | *
77 | * @param string $path The path to the file to write to.
78 | * @param string $content The content to write to the file.
79 | *
80 | * @return bool True on success, false on failure.
81 | * @global \WP_Filesystem_Direct $wp_filesystem
82 | */
83 | private function write_file( $path, $content ) {
84 | $this->load_filesystem();
85 | global $wp_filesystem;
86 | return $wp_filesystem->put_contents( $path, $content );
87 | }
88 |
89 | /**
90 | * Deletes the given file.
91 | *
92 | * @param string $path The path to the file to delete.
93 | *
94 | * @return bool True on success, false on failure.
95 | * @global \WP_Filesystem_Direct $wp_filesystem
96 | */
97 | private function delete_file( $path ) {
98 | $this->load_filesystem();
99 | global $wp_filesystem;
100 | if ( ! file_exists( $path ) ) {
101 | return false;
102 | }
103 | return $wp_filesystem->delete( $path );
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/Traits/Orm.php:
--------------------------------------------------------------------------------
1 | prefix . self::$table;
19 | }
20 |
21 | /**
22 | * Insert a new record into the database.
23 | *
24 | * @param array $data Associative array of column data to insert.
25 | * @return array Array of success status and ID of inserted record.
26 | */
27 | public static function insert( array $data ): array {
28 | global $wpdb;
29 | $table_name = self::get_table_name();
30 | $wpdb->insert( $table_name, $data );
31 | if ( empty( $wpdb->last_error ) ) {
32 | return array(
33 | 'success' => true,
34 | 'id' => $wpdb->insert_id,
35 | );
36 | }
37 | return array(
38 | 'success' => false,
39 | 'message' => $wpdb->last_error,
40 | 'query' => $wpdb->last_query,
41 | );
42 | }
43 |
44 | /**
45 | * Update records in the database.
46 | *
47 | * @param array $data Associative array of column data to update.
48 | * @param array $where Associative array of column data for WHERE clause.
49 | * @return array Array of success status and ID of inserted record.
50 | */
51 | public static function update( array $data, array $where ): array {
52 | global $wpdb;
53 | $table_name = self::get_table_name();
54 | $wpdb->update( $table_name, $data, $where );
55 | if ( empty( $wpdb->last_error ) ) {
56 | return array(
57 | 'success' => true,
58 | 'id' => $wpdb->insert_id,
59 | );
60 | }
61 | return array(
62 | 'success' => false,
63 | 'message' => $wpdb->last_error,
64 | 'query' => $wpdb->last_query,
65 | );
66 | }
67 |
68 | /**
69 | * Delete records from the database.
70 | *
71 | * @param array $where Associative array of column data for WHERE clause.
72 | * @return array Array of success status and ID of inserted record.
73 | */
74 | public static function delete( array $where ): array {
75 | global $wpdb;
76 | $table_name = self::get_table_name();
77 | $wpdb->delete( $table_name, $where );
78 | if ( empty( $wpdb->last_error ) ) {
79 | return array(
80 | 'success' => true,
81 | 'id' => $wpdb->insert_id,
82 | );
83 | }
84 | return array(
85 | 'success' => false,
86 | 'message' => $wpdb->last_error,
87 | 'query' => $wpdb->last_query,
88 | );
89 | }
90 |
91 | /**
92 | * Select records from the database.
93 | *
94 | * @param array $where Associative array of column data for WHERE clause.
95 | * @param array $columns Optional. Columns to select. Default is empty array.
96 | * @return array Database query results or null if none.
97 | */
98 | public static function select( $where = array(), $columns = array() ) {
99 | global $wpdb;
100 | $table_name = self::get_table_name();
101 |
102 | if ( empty( $columns ) ) {
103 | $columns = '*';
104 | } else {
105 | $columns = implode( ', ', $columns );
106 | }
107 |
108 | $sql = "SELECT $columns FROM $table_name WHERE 1=1";
109 | if ( empty( $where ) ) {
110 | $prepared_sql = $sql;
111 | } else {
112 | foreach ( $where as $key => $value ) {
113 | $sql .= " AND $key = %s";
114 | }
115 | $prepared_sql = $wpdb->prepare( $sql, array_values( $where ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
116 | }
117 | $wpdb->get_results( $prepared_sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
118 | if ( empty( $wpdb->last_error ) ) {
119 | return array(
120 | 'success' => true,
121 | 'data' => $wpdb->last_result,
122 | );
123 | }
124 | return array(
125 | 'success' => false,
126 | 'message' => $wpdb->last_error,
127 | 'query' => $wpdb->last_query,
128 | );
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/Traits/Singleton.php:
--------------------------------------------------------------------------------
1 |