ShahiAssist

Custom Modules Development

ShahiAssist’s modular architecture allows developers to extend functionality by creating custom modules. This guide covers the process of building, registering, and maintaining custom modules.

Module Architecture

Core Components

    1. Module Base Class: ShahiAssistModuleBase provides common functionality
    2. Module Registry: Manages module loading and initialization
    3. Autoloader: PSR-4 compliant class loading
    4. Settings Integration: Automatic settings page generation
    5. Module Structure

      `
      includes/modules/your_module/
      ├── class-your-module.php # Main module class
      ├── views/ # Template files
      │ ├── admin-settings.php
      │ ├── frontend-display.php
      │ └── …
      ├── assets/ # CSS/JS files
      │ ├── css/
      │ └── js/
      ├── languages/ # Translation files
      │ └── your-module.pot
      └── README.md # Documentation
      `

      Creating a Basic Module

      Step 1: Create Module Directory

      `bash
      mkdir -p includes/modules/your_module/views
      mkdir -p includes/modules/your_module/assets/css
      mkdir -p includes/modules/your_module/assets/js
      `

      Step 2: Main Module Class

      `php
      YourModule extends ShahiAssistModuleBase {

      /**
      * Module ID
      */
      protected $moduleid = ‘yourmodule’;

      /**
      * Module name
      */
      protected $module_name = ‘Your Module’;

      /**
      * Module version
      */
      protected $version = ‘1.0.0’;

      /**
      * Initialize the module
      */
      public function init() {
      // Hook into WordPress
      addaction(‘init’, [$this, ‘registerpost_types’]);
      addaction(‘adminmenu’, [$this, ‘addadminmenu’]);
      addaction(‘wpenqueuescripts’, [$this, ‘enqueuescripts’]);

      // Custom hooks
      addaction(‘shahiassistcustomhook’, [$this, ‘custom_function’]);
      }

      /**
      * Register custom post types
      */
      public function registerposttypes() {
      registerposttype(‘yourcustompost’, [
      ‘labels’ => [
      ‘name’ => __(‘Your Posts’, ‘shahi-assist’),
      ‘singularname’ => _(‘Your Post’, ‘shahi-assist’),
      ],
      ‘public’ => true,
      ‘supports’ => [‘title’, ‘editor’, ‘custom-fields’],
      ‘showinmenu’ => false,
      ]);
      }

      /**
      * Add admin menu
      */
      public function addadminmenu() {
      addsubmenupage(
      ‘shahi-assist’,
      __(‘Your Module’, ‘shahi-assist’),
      __(‘Your Module’, ‘shahi-assist’),
      ‘manage_options’,
      ‘shahi-assist-your-module’,
      [$this, ‘admin_page’]
      );
      }

      /**
      * Admin page callback
      */
      public function admin_page() {
      ?>

      fields(‘shahiassistyourmodule’);
      dosettingssections(‘shahiassistyour_module’);
      submit_button();
      ?>

      enqueuestyle(
      ‘shahi-assist-your-module’,
      plugindirurl(FILE) . ‘assets/css/your-module.css’,
      [],
      $this->version
      );

      wpenqueuescript(
      ‘shahi-assist-your-module’,
      plugindirurl(FILE) . ‘assets/js/your-module.js’,
      [‘jquery’],
      $this->version,
      true
      );
      }

      /**
      * Custom function
      */
      public function custom_function() {
      // Your custom logic here
      doaction(‘yourmodulecustomaction’);
      }

      /**
      * Get module settings
      */
      public function get_settings() {
      return [
      ‘enabled’ => [
      ‘type’ => ‘checkbox’,
      ‘label’ => __(‘Enable Module’, ‘shahi-assist’),
      ‘default’ => true,
      ],
      ‘api_key’ => [
      ‘type’ => ‘text’,
      ‘label’ => __(‘API Key’, ‘shahi-assist’),
      ‘default’ => ”,
      ],
      ];
      }

      /**
      * Activate module
      */
      public function activate() {
      // Run on module activation
      flushrewriterules();
      }

      /**
      * Deactivate module
      */
      public function deactivate() {
      // Run on module deactivation
      flushrewriterules();
      }

      /**
      * Uninstall module
      */
      public function uninstall() {
      // Clean up on uninstall
      deleteoption(‘shahiassistyourmodule_settings’);
      }
      }
      `

      Step 3: Register the Module

      Add to includes/core/class-module-registry.php:
      `php
      private function getavailablemodules() {
      return [
      // … existing modules
      ‘yourmodule’ => ‘ShahiAssistYour_Module’,
      ];
      }
      `

      Advanced Module Features

      Settings Integration

      `php
      public function get_settings() {
      return [
      ‘general’ => [
      ‘title’ => __(‘General Settings’, ‘shahi-assist’),
      ‘fields’ => [
      ‘enabled’ => [
      ‘type’ => ‘checkbox’,
      ‘label’ => __(‘Enable Module’, ‘shahi-assist’),
      ‘default’ => true,
      ],
      ‘debug_mode’ => [
      ‘type’ => ‘checkbox’,
      ‘label’ => __(‘Debug Mode’, ‘shahi-assist’),
      ‘default’ => false,
      ],
      ],
      ],
      ‘api’ => [
      ‘title’ => __(‘API Settings’, ‘shahi-assist’),
      ‘fields’ => [
      ‘api_url’ => [
      ‘type’ => ‘url’,
      ‘label’ => __(‘API URL’, ‘shahi-assist’),
      ‘default’ => ”,
      ],
      ‘api_key’ => [
      ‘type’ => ‘password’,
      ‘label’ => __(‘API Key’, ‘shahi-assist’),
      ‘default’ => ”,
      ],
      ],
      ],
      ];
      }
      `

      AJAX Handlers

      `php
      public function init() {
      // … other hooks
      addaction(‘wpajaxyourmoduleaction’, [$this, ‘ajaxhandler’]);
      addaction(‘wpajaxnoprivyourmoduleaction’, [$this, ‘ajax_handler’]);
      }

      public function ajax_handler() {
      checkajaxreferer(‘yourmodulenonce’, ‘nonce’);

      $action = sanitizetextfield($POST[‘subaction’]);

      switch ($action) {
      case ‘save_data’:
      $data = sanitizetextfield($_POST[‘data’]);
      updateoption(‘yourmodule_data’, $data);
      wpsendjson_success([‘message’ => ‘Data saved’]);
      break;

      case ‘get_data’:
      $data = getoption(‘yourmodule_data’, ”);
      wpsendjson_success([‘data’ => $data]);
      break;

      default:
      wpsendjson_error([‘message’ => ‘Invalid action’]);
      }
      }
      `

      Custom Post Types

      `php
      public function registerposttypes() {
      $labels = [
      ‘name’ => __(‘Your Items’, ‘shahi-assist’),
      ‘singularname’ => _(‘Your Item’, ‘shahi-assist’),
      ‘addnew’ => _(‘Add New’, ‘shahi-assist’),
      ‘addnewitem’ => __(‘Add New Item’, ‘shahi-assist’),
      ‘edititem’ => _(‘Edit Item’, ‘shahi-assist’),
      ‘newitem’ => _(‘New Item’, ‘shahi-assist’),
      ‘viewitem’ => _(‘View Item’, ‘shahi-assist’),
      ‘searchitems’ => _(‘Search Items’, ‘shahi-assist’),
      ‘notfound’ => _(‘No items found’, ‘shahi-assist’),
      ‘notfoundintrash’ => _(‘No items found in trash’, ‘shahi-assist’),
      ];

      registerposttype(‘your_item’, [
      ‘labels’ => $labels,
      ‘public’ => true,
      ‘supports’ => [‘title’, ‘editor’, ‘thumbnail’, ‘custom-fields’],
      ‘menu_icon’ => ‘dashicons-admin-tools’,
      ‘showinmenu’ => ‘shahi-assist’,
      ‘capability_type’ => ‘post’,
      ‘mapmetacap’ => true,
      ]);
      }
      `

      Custom Taxonomies

      `php
      public function register_taxonomies() {
      registertaxonomy(‘yourcategory’, ‘your_item’, [
      ‘labels’ => [
      ‘name’ => __(‘Categories’, ‘shahi-assist’),
      ‘singularname’ => _(‘Category’, ‘shahi-assist’),
      ],
      ‘hierarchical’ => true,
      ‘showadmincolumn’ => true,
      ‘rewrite’ => [‘slug’ => ‘your-category’],
      ]);
      }
      `

      REST API Endpoints

      `php
      public function registerrestroutes() {
      registerrestroute(‘shahi-assist/v1’, ‘/your-module’, [
      ‘methods’ => ‘GET’,
      ‘callback’ => [$this, ‘restgetdata’],
      ‘permissioncallback’ => [$this, ‘restpermissions_check’],
      ]);

      registerrestroute(‘shahi-assist/v1’, ‘/your-module’, [
      ‘methods’ => ‘POST’,
      ‘callback’ => [$this, ‘restcreateitem’],
      ‘permissioncallback’ => [$this, ‘restpermissions_check’],
      ]);
      }

      public function restgetdata($request) {
      $data = getoption(‘yourmodule_data’, []);
      return new WPRESTResponse($data, 200);
      }

      public function restcreateitem($request) {
      $params = $request->get_params();

      // Validate and sanitize
      $title = sanitizetextfield($params[‘title’]);
      $content = wpksespost($params[‘content’]);

      // Create post
      $postid = wpinsert_post([
      ‘post_title’ => $title,
      ‘post_content’ => $content,
      ‘posttype’ => ‘youritem’,
      ‘post_status’ => ‘publish’,
      ]);

      if (iswperror($post_id)) {
      return new WPError(‘createfailed’, ‘Failed to create item’, [‘status’ => 500]);
      }

      return new WPRESTResponse([‘id’ => $post_id], 201);
      }

      public function restpermissionscheck($request) {
      return currentusercan(‘edit_posts’);
      }
      `

      Module Dependencies

      Checking Dependencies

      `php
      public function check_dependencies() {
      $dependencies = [
      ‘wordpress’ => ‘5.0’,
      ‘php’ => ‘7.4’,
      ‘modules’ => [‘core’, ‘settings’],
      ];

      // Check WordPress version
      if (versioncompare(getbloginfo(‘version’), $dependencies[‘wordpress’], ‘<')) { return new WPError(‘dependencyerror’, ‘WordPress version too old’);
      }

      // Check PHP version
      if (versioncompare(PHPVERSION, $dependencies[‘php’], ‘<')) { return new WPError(‘dependencyerror’, ‘PHP version too old’);
      }

      // Check required modules
      foreach ($dependencies[‘modules’] as $module) {
      if (!ShahiAssist()->modules->is_active($module)) {
      return new WPError(‘dependencyerror’, “Required module ‘{$module}’ not active”);
      }
      }

      return true;
      }
      `

      Optional Dependencies

      `php
      public function init() {
      // Core functionality

      // Optional features based on available modules
      if (ShahiAssist()->modules->isactive(’emailnotifications’)) {
      addaction(‘yourevent’, [$this, ‘send_notification’]);
      }

      if (ShahiAssist()->modules->is_active(‘webhooks’)) {
      addaction(‘yourevent’, [$this, ‘send_webhook’]);
      }
      }
      `

      Testing and Debugging

      Unit Tests

      `php
      class TestYourModule extends WP_UnitTestCase {
      public function testmoduleinitialization() {
      $module = new ShahiAssistYourModule();
      $this->assertInstanceOf(‘ShahiAssistModuleBase’, $module);
      }

      public function testsettingsregistration() {
      $module = new ShahiAssistYourModule();
      $settings = $module->get_settings();
      $this->assertArrayHasKey(‘enabled’, $settings);
      }

      public function testcustompost_type() {
      $module = new ShahiAssistYourModule();
      $module->init();

      $this->assertTrue(posttypeexists(‘your_item’));
      }
      }
      `

      Integration Tests

      `php
      public function testfullworkflow() {
      // Create test data
      $post_id = $this->factory->post->create([
      ‘posttype’ => ‘youritem’,
      ‘post_title’ => ‘Test Item’,
      ]);

      // Test API endpoint
      $request = new WPRESTRequest(‘GET’, ‘/shahi-assist/v1/your-module’);
      $response = restdorequest($request);

      $this->assertEquals(200, $response->get_status());
      }
      `

      Debug Logging

      `php
      public function debug_log($message, $data = null) {
      if (defined(‘WPDEBUG’) && WPDEBUG) {
      $log_message = ‘[Your Module] ‘ . $message;
      if ($data) {
      $logmessage .= ‘: ‘ . printr($data, true);
      }
      errorlog($logmessage);
      }
      }
      `

      Performance Optimization

      Caching

      `php
      private function getcacheddata($key) {
      $cachekey = ‘yourmodule_’ . $key;
      $data = wpcacheget($cachekey, ‘shahiassist’);

      if ($data === false) {
      $data = $this->fetch_data($key);
      wpcacheset($cachekey, $data, ‘shahiassist’, HOURINSECONDS);
      }

      return $data;
      }
      `

      Lazy Loading

      `php
      public function enqueue_scripts() {
      // Only load on specific pages
      if (!$this->shouldloadscripts()) {
      return;
      }

      wpenqueuescript(//);
      }

      private function shouldloadscripts() {
      global $post;
      return issingular(‘youritem’) ||
      (isa($post, ‘WPPost’) && hasshortcode($post->postcontent, ‘your_shortcode’));
      }
      `

      Database Optimization

      `php
      public function createcustomtable() {
      global $wpdb;

      $tablename = $wpdb->prefix . ‘yourmodule_data’;

      $charsetcollate = $wpdb->getcharset_collate();

      $sql = “CREATE TABLE $table_name (
      id mediumint(9) NOT NULL AUTO_INCREMENT,
      data_key varchar(255) NOT NULL,
      data_value longtext NOT NULL,
      createdat datetime DEFAULT CURRENTTIMESTAMP,
      PRIMARY KEY (id),
      UNIQUE KEY datakey (datakey)
      ) $charset_collate;”;

      require_once(ABSPATH . ‘wp-admin/includes/upgrade.php’);
      dbDelta($sql);
      }
      `

      Security Best Practices

      Input Validation

      `php
      public function validate_input($input) {
      $sanitized = [];

      $sanitized[‘title’] = sanitizetextfield($input[‘title’]);
      $sanitized[’email’] = sanitize_email($input[’email’]);
      $sanitized[‘url’] = escurlraw($input[‘url’]);
      $sanitized[‘content’] = wpksespost($input[‘content’]);

      return $sanitized;
      }
      `

      Capability Checks

      `php
      public function admin_page() {
      if (!currentusercan(‘manage_options’)) {
      wpdie(_(‘You do not have sufficient permissions to access this page.’));
      }

      // Rest of the function
      }
      `

      Nonce Verification

      `php
      public function process_form() {
      if (!wpverifynonce($POST[‘yournonce’], ‘your_action’)) {
      wp_die(‘Security check failed’);
      }

      // Process form
      }
      `

      SQL Injection Prevention

      `php
      public function getdataby_id($id) {
      global $wpdb;

      return $wpdb->get_row(
      $wpdb->prepare(
      “SELECT * FROM {$wpdb->prefix}your_table WHERE id = %d”,
      intval($id)
      )
      );
      }
      `

      Distribution and Updates

      Version Management

      `php
      protected $version = ‘1.0.0’;

      public function get_version() {
      return $this->version;
      }

      public function updateversion($newversion) {
      $this->version = $new_version;
      updateoption(‘yourmoduleversion’, $newversion);

      // Run update routines if needed
      $this->run_updates();
      }
      `

      Update Routines

      `php
      private function run_updates() {
      $currentversion = getoption(‘yourmoduleversion’, ‘1.0.0’);

      if (versioncompare($currentversion, ‘1.1.0’, ‘<')) { // Update to 1.1.0 $this->updateto110();
      }

      if (versioncompare($currentversion, ‘1.2.0’, ‘<')) { // Update to 1.2.0 $this->updateto120();
      }
      }

      private function updateto110() {
      // Migration logic for 1.1.0
      }

      private function updateto120() {
      // Migration logic for 1.2.0
      }
      `

      Documentation and Support

      README.md

      `markdown

      Your Module

      A custom module for ShahiAssist that adds [functionality].

      Features

    6. Feature 1
    7. Feature 2
    8. Feature 3
    9. Installation

    10. Download and place in includes/modules/your_module/
    11. Register in module registry
    12. Activate in ShahiAssist settings
    13. Configuration

      Settings are available in ShahiAssist → Settings → Your Module.

      Usage

      [Usage instructions]

      API

      [API documentation]

      Changelog

      1.0.0

    14. Initial release
    15. `

      Inline Documentation

      `php
      /**
      * Process user input for your module
      *
      * @param array $input Raw input data
      * @return array Sanitized input data
      * @since 1.0.0
      */
      public function process_input($input) {
      // Implementation
      }
      `

      Resources

    16. WordPress Plugin Development
    17. PSR-4 Autoloading
    18. WordPress Coding Standards
    19. ShahiAssist Module Development Guide

Share this article

Was this article helpful?

Help us improve our documentation

Still need help?

Our support team is ready to assist you with personalized guidance for your workspace.

Submit a support ticket