Skip to content
wp-skills
Register
tools/elementor-plugin-generator

Elementor Plugin Generator

Generate a plugin for Elementor with this tool. It will create a plugin with a widget and a settings page. You can use it as a boilerplate for your next plugin.

Also the class name and the file name, so two addons generated here can live on one site.

One line, shown on the Plugins screen.

The plugin's own page. Linked from its name on the Plugins screen.

Conventionally the plugin's folder name, which is what WordPress.org's translation platform expects.

Yours. Bumping it is what triggers an update.

Shown on the Plugins screen.

Linked from the author's name. Needs the scheme.

Checked at load, and the plugin bails with an admin notice rather than fatalling on syntax the host cannot parse.

Checked the same way. 3.5.0 is where the registration API this generates was introduced.

my-elementor-plugin.php
<?php
/**
 * Plugin Name: My Elementor Plugin
 * Description: My Elementor Plugin Description
 * Version: 1.0
 * Author: WP Skills
 * Author URI: https://wp-skills.com
 * Text Domain: text-domain
 * Requires PHP: 7.0
 * Requires Plugins: elementor
 */

// A direct request for this file must not execute it.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class My_Elementor_Plugin_Elementor_Addon {

	const VERSION                   = '1.0';
	const MINIMUM_ELEMENTOR_VERSION = '2.0';
	const MINIMUM_PHP_VERSION       = '7.0';

	private static $instance = null;

	public static function instance(): My_Elementor_Plugin_Elementor_Addon {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	private function __construct() {
		if ( $this->check_compatibility() ) {
			add_action( 'elementor/init', array( $this, 'init' ) );
		}
	}

	/**
	 * Checks whether the site meets this addon's requirements.
	 *
	 * Each failure registers its own notice and stops, so the admin sees the
	 * first thing that is actually wrong rather than all three at once.
	 */
	public function check_compatibility(): bool {
		if ( ! did_action( 'elementor/loaded' ) ) {
			add_action( 'admin_notices', array( $this, 'notice_missing_elementor' ) );
			return false;
		}

		if ( ! version_compare( ELEMENTOR_VERSION, self::MINIMUM_ELEMENTOR_VERSION, '>=' ) ) {
			add_action( 'admin_notices', array( $this, 'notice_elementor_version' ) );
			return false;
		}

		if ( version_compare( PHP_VERSION, self::MINIMUM_PHP_VERSION, '<' ) ) {
			add_action( 'admin_notices', array( $this, 'notice_php_version' ) );
			return false;
		}

		return true;
	}

	/*
	 * Each notice names this plugin and reads its requirement from the constant
	 * above, so the message and the check can never disagree.
	 */

	public function notice_missing_elementor(): void {
		printf(
			'<div class="notice notice-warning is-dismissible"><p>%s</p></div>',
			sprintf(
				/* translators: %s: plugin name. */
				esc_html__( '%s requires Elementor to be installed and activated.', 'text-domain' ),
				'<strong>' . esc_html__( 'My Elementor Plugin', 'text-domain' ) . '</strong>'
			)
		);
	}

	public function notice_elementor_version(): void {
		printf(
			'<div class="notice notice-warning is-dismissible"><p>%s</p></div>',
			sprintf(
				/* translators: 1: plugin name, 2: minimum Elementor version. */
				esc_html__( '%1$s requires Elementor %2$s or higher.', 'text-domain' ),
				'<strong>' . esc_html__( 'My Elementor Plugin', 'text-domain' ) . '</strong>',
				esc_html( self::MINIMUM_ELEMENTOR_VERSION )
			)
		);
	}

	public function notice_php_version(): void {
		printf(
			'<div class="notice notice-warning is-dismissible"><p>%s</p></div>',
			sprintf(
				/* translators: 1: plugin name, 2: minimum PHP version. */
				esc_html__( '%1$s requires PHP %2$s or higher.', 'text-domain' ),
				'<strong>' . esc_html__( 'My Elementor Plugin', 'text-domain' ) . '</strong>',
				esc_html( self::MINIMUM_PHP_VERSION )
			)
		);
	}

	public function init(): void {
		load_plugin_textdomain( 'text-domain', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );

		// These are the registration hooks Elementor fires from 3.5 onwards.
		// Each callback receives the manager it should register with.
		add_action( 'elementor/widgets/register', array( $this, 'register_widgets' ) );
		add_action( 'elementor/controls/register', array( $this, 'register_controls' ) );
	}

	public function register_widgets( \Elementor\Widgets_Manager $widgets_manager ): void {
		// Include your widget file, then register the class it defines.
		// require_once __DIR__ . '/widgets/my-widget.php';
		// $widgets_manager->register( new \My_Elementor_Widget() );
	}

	public function register_controls( \Elementor\Controls_Manager $controls_manager ): void {
		// Include your control file, then register the class it defines.
		// require_once __DIR__ . '/controls/my-control.php';
		// $controls_manager->register( new \My_Elementor_Control() );
	}
}

function My_Elementor_Plugin_load_elementor_addon(): void {
	My_Elementor_Plugin_Elementor_Addon::instance();
}
add_action( 'plugins_loaded', 'My_Elementor_Plugin_load_elementor_addon' );