load_admin();
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
add_action( 'admin_footer-plugins.php', array( $this, 'render_deactivation_modal' ) );
add_action( 'wp_ajax_masscie_deactivation_feedback', array( $this, 'handle_deactivation_feedback' ) );
}
}
/**
* Load admin-only files (Widget Manager page + AJAX).
* Wrapped in a try/catch so a missing file never breaks the front end.
*
* @return void
*/
private function load_admin() {
$registry_file = MASSCIE_PATH . 'includes/class-widget-registry.php';
$manager_file = MASSCIE_PATH . 'includes/class-widget-manager.php';
$admin_file = MASSCIE_PATH . 'includes/admin/class-admin.php';
if ( file_exists( $registry_file ) ) {
require_once $registry_file;
}
if ( file_exists( $manager_file ) ) {
require_once $manager_file;
}
if ( file_exists( $admin_file ) && class_exists( 'MASSCIE\Widget_Registry' ) ) {
require_once $admin_file;
Admin\Admin::instance();
}
}
/**
* Fired on plugins_loaded.
*
* @return void
*/
public function on_plugins_loaded() {
if ( ! did_action( 'elementor/loaded' ) ) {
add_action(
'admin_notices',
function () {
printf(
'
',
esc_html__( 'MarqueeAll requires Elementor to be installed and activated.', 'marqueeall' )
);
}
);
return;
}
// Register MarqueeAll widget category.
add_action(
'elementor/elements/categories_registered',
function ( $manager ) {
$manager->add_category(
'masscie-widgets',
array(
'title' => __( 'MarqueeAll Widgets', 'marqueeall' ),
'icon' => 'fa fa-arrows-h',
)
);
}
);
// Register widgets with Elementor.
add_action( 'elementor/widgets/register', array( $this, 'register_widgets' ) );
}
/**
* Widget map — mirrors the original plugin.php manual list.
* Each entry: file path relative to MASSCIE_PATH, fully-qualified class name.
*
* @return array[]
*/
private function get_widget_map() {
return array(
'text-marquee' => array(
'file' => 'includes/widgets/class-text-marquee.php',
'class' => 'MASSCIE\Widgets\Text_Marquee',
),
'image-marquee' => array(
'file' => 'includes/widgets/class-image-marquee.php',
'class' => 'MASSCIE\Widgets\Image_Marquee',
),
'testimonial-marquee' => array(
'file' => 'includes/widgets/class-testimonial-marquee.php',
'class' => 'MASSCIE\Widgets\Testimonial_Marquee',
),
'news-ticker' => array(
'file' => 'includes/widgets/class-news-ticker.php',
'class' => 'MASSCIE\Widgets\News_Ticker',
),
'post-grid-marquee' => array(
'file' => 'includes/widgets/class-post-grid-marquee.php',
'class' => 'MASSCIE\Widgets\Post_Grid_Marquee',
),
'team-members-marquee' => array(
'file' => 'includes/widgets/class-team-members-marquee.php',
'class' => 'MASSCIE\Widgets\Team_Members_Marquee',
),
'text-scramble' => array(
'file' => 'includes/widgets/class-text-scramble.php',
'class' => 'MASSCIE\Widgets\Text_Scramble',
),
'crypto-marquee' => array(
'file' => 'includes/widgets/class-crypto-marquee.php',
'class' => 'MASSCIE\Widgets\Crypto_Marquee',
),
);
}
/**
* Register Elementor widgets.
*
* Reads the saved option directly — zero dependency on Widget_Registry
* or Widget_Manager — so widgets always load even if those files are
* missing, mis-uploaded, or cached.
*
* Logic:
* - Option missing / empty array → ALL widgets enabled (fresh install default)
* - Option present, slug = 0 → widget SKIPPED
* - Option present, slug = 1 → widget LOADED
* - Option present, slug missing → widget LOADED (new widget added later)
*
* @param \Elementor\Widgets_Manager $widgets_manager Elementor widget manager.
* @return void
*/
public function register_widgets( $widgets_manager ) {
// Read saved statuses. Returns false if option doesn't exist yet.
$status = get_option( 'marqueeall_widget_status', false );
foreach ( $this->get_widget_map() as $slug => $widget ) {
// Only skip when we have a saved option AND it explicitly sets this slug to 0.
if ( false !== $status && is_array( $status ) && isset( $status[ $slug ] ) && 0 === (int) $status[ $slug ] ) {
continue;
}
$file = MASSCIE_PATH . $widget['file'];
if ( ! file_exists( $file ) ) {
continue;
}
require_once $file;
$class = $widget['class'];
if ( ! class_exists( $class ) ) {
continue;
}
$widgets_manager->register( new $class() );
}
}
/**
* Register front-end assets (scripts/styles registered; widgets enqueue on demand).
*
* @return void
*/
public function enqueue_assets() {
wp_register_style(
'masscie-style',
MASSCIE_URL . 'assets/css/masscie.css',
array(),
MASSCIE_VERSION
);
wp_register_style(
'masscie-crypto-style',
MASSCIE_URL . 'assets/css/masscie-crypto.css',
array(),
MASSCIE_VERSION
);
wp_register_script(
'masscie-marquee',
MASSCIE_URL . 'assets/js/masscie-marquee.js',
array( 'jquery' ),
MASSCIE_VERSION,
true
);
}
/**
* Enqueue plugins.php admin assets (deactivation feedback).
*
* @param string $hook_suffix Current admin page hook.
* @return void
*/
public function enqueue_admin_assets( $hook_suffix ) {
if ( 'plugins.php' !== $hook_suffix ) {
return;
}
wp_enqueue_style(
'masscie-admin-feedback',
MASSCIE_URL . 'assets/css/masscie-admin-feedback.css',
array(),
MASSCIE_VERSION
);
wp_enqueue_script(
'masscie-admin-feedback',
MASSCIE_URL . 'assets/js/masscie-admin-feedback.js',
array( 'jquery' ),
MASSCIE_VERSION,
true
);
wp_localize_script(
'masscie-admin-feedback',
'MASSCIE_FEEDBACK',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'masscie_deactivation_feedback' ),
'plugin_slug' => 'marqueeall',
'deactivateText' => __( 'Deactivate', 'marqueeall' ),
)
);
}
/**
* Enqueue Elementor editor assets.
*
* @return void
*/
public function enqueue_elementor_editor_assets() {
wp_enqueue_style(
'marqueeall-elementor-editor',
MASSCIE_URL . 'assets/css/elementor-editor.css',
array(),
MASSCIE_VERSION
);
wp_enqueue_script(
'masscie-crypto-editor',
MASSCIE_URL . 'assets/js/crypto-editor.js',
array( 'jquery', 'select2' ),
MASSCIE_VERSION,
true
);
wp_localize_script(
'masscie-crypto-editor',
'masscieCryptoEditor',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'masscie_crypto_nonce' ),
'i18n' => array(
'fetching' => __( 'Fetching...', 'marqueeall' ),
'error' => __( 'Error fetching data. Please try again.', 'marqueeall' ),
'no_cryptos' => __( 'No cryptocurrencies found.', 'marqueeall' ),
),
)
);
if ( ! wp_script_is( 'select2', 'enqueued' ) ) {
wp_enqueue_script( 'select2' );
wp_enqueue_style( 'select2' );
}
}
/**
* Render deactivation feedback modal on plugins.php.
*
* @return void
*/
public function render_deactivation_modal() {
?>
__( 'Permission denied', 'marqueeall' ) ) );
}
$reason = isset( $_POST['reason'] ) ? sanitize_text_field( wp_unslash( $_POST['reason'] ) ) : '';
$details = isset( $_POST['details'] ) ? wp_kses_post( wp_unslash( $_POST['details'] ) ) : '';
$deactivate_url = isset( $_POST['deactivate_url'] ) ? esc_url_raw( wp_unslash( $_POST['deactivate_url'] ) ) : '';
$site_url = home_url();
wp_mail(
'amandeepsingh@webspero.com',
sprintf( 'MarqueeAll Deactivation Feedback from %s', $site_url ),
"Plugin: MarqueeAll\nSite: {$site_url}\nReason: {$reason}\n\nDetails:\n{$details}\n"
);
wp_send_json_success( array( 'deactivate_url' => $deactivate_url ) );
}
}
Plugin::instance();