Skip to content

rajaishtiaq6/botble

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 

Repository files navigation

Botble Filters and Actions Documentation

Introduction

Botble provides a powerful hook system similar to WordPress, allowing developers to modify and extend functionality without changing core files. This system consists of two main components:

  1. Filters - Used to modify data before it's used or displayed
  2. Actions - Used to execute functions at specific points in code execution

This documentation explains how to use filters and actions in Botble with practical examples.

Filters

Filters allow you to modify data before it's used by the application. They are used to intercept and potentially modify values.

Basic Filter Usage

Adding a Filter

add_filter(string|array $hook, callable $callback, int $priority = 20, int $arguments = 1): void

Parameters:

  • $hook: The name of the filter hook
  • $callback: The function to run when the filter is applied
  • $priority: Priority of execution (lower numbers run first)
  • $arguments: Number of arguments the callback accepts

Applying a Filter

apply_filters(string $hook, mixed $value, mixed ...$args)

Parameters:

  • $hook: The name of the filter hook
  • $value: The value to filter
  • $args: Additional arguments to pass to the filter callback

Removing a Filter

remove_filter(string $hook): void

Filter Examples

Example 1: Modifying Table Data

// Add a filter to modify table data
add_filter(BASE_FILTER_GET_LIST_DATA, function ($data, $model, $table) {
    // Modify $data here
    return $data;
}, 10, 3);

Example 2: Modifying Page Content

// Add a filter to modify page content
add_filter(PAGE_FILTER_FRONT_PAGE_CONTENT, function ($content, $page) {
    // Add additional content or modify existing content
    $content .= '<div class="additional-content">Custom content added via filter</div>';
    return $content;
}, 20, 2);

Example 3: Adding Custom Dashboard Widgets

// Add a filter to add custom dashboard widgets
add_filter(DASHBOARD_FILTER_ADMIN_LIST, function ($widgets, $widgetSettings) {
    // Add a custom widget
    $widgets[] = [
        'id' => 'custom_widget',
        'name' => 'Custom Widget',
        'content' => view('plugins/your-plugin::widgets.custom-widget')->render(),
    ];

    return $widgets;
}, 21, 2);

Actions

Actions allow you to execute functions at specific points in the code execution. Unlike filters, actions don't modify data but perform operations.

Basic Action Usage

Adding an Action

add_action(string|array $hook, callable $callback, int $priority = 20, int $arguments = 1): void

Parameters:

  • $hook: The name of the action hook
  • $callback: The function to run when the action is triggered
  • $priority: Priority of execution (lower numbers run first)
  • $arguments: Number of arguments the callback accepts

Executing an Action

do_action(string $hook, mixed ...$args): void

Parameters:

  • $hook: The name of the action hook
  • $args: Arguments to pass to the action callback

Action Examples

Example 1: Executing Code After Content Creation

// Add an action to execute after content creation
add_action(BASE_ACTION_AFTER_CREATE_CONTENT, function ($screen, $request, $object) {
    // Perform operations after content is created
    // For example, send a notification or log the activity
    Log::info("New content created: {$object->name}");
}, 10, 3);

Example 2: Adding Custom Form Buttons

// Add an action to add custom form buttons
add_action(BASE_ACTION_FORM_ACTIONS, function ($form) {
    // Add custom buttons to the form
    echo '<button type="button" class="btn btn-info">Custom Button</button>';
}, 10, 1);

Example 3: Executing Code After User Logout

// Add an action to execute after user logout
add_action(AUTH_ACTION_AFTER_LOGOUT_SYSTEM, function ($screen, $user) {
    // Perform operations after user logout
    // For example, log the logout activity
    activity()
        ->performedOn($user)
        ->causedBy($user)
        ->log('Logged out');
}, 10, 2);

Common Hooks in Botble

Filter Hooks with Examples

BASE_FILTER_BEFORE_GET_FRONT_PAGE_ITEM

Modifies data before retrieving front page items.

add_filter(BASE_FILTER_BEFORE_GET_FRONT_PAGE_ITEM, function ($query, $model) {
    // Example: Add a condition to only show items with a specific tag
    if ($model instanceof \Botble\Blog\Models\Post) {
        $query->whereHas('tags', function ($query) {
            $query->where('name', 'featured');
        });
    }

    return $query;
}, 10, 2);

BASE_FILTER_BEFORE_GET_SINGLE

Modifies data before retrieving a single item.

add_filter(BASE_FILTER_BEFORE_GET_SINGLE, function ($query, $model) {
    // Example: Add eager loading relationships for better performance
    if ($model instanceof \Botble\Blog\Models\Post) {
        $query->with(['categories', 'tags', 'author']);
    }

    return $query;
}, 10, 2);

BASE_FILTER_PUBLIC_SINGLE_DATA

Modifies single item data for public display.

add_filter(BASE_FILTER_PUBLIC_SINGLE_DATA, function ($data, $model) {
    // Example: Add custom data to a blog post
    if (get_class($model) === \Botble\Blog\Models\Post::class) {
        // Add related posts
        $data['related_posts'] = \Botble\Blog\Models\Post::query()
            ->wherePublished()
            ->where('id', '!=', $data['id'])
            ->whereHas('categories', function ($query) use ($model) {
                $categoryIds = $model->categories->pluck('id')->all();
                $query->whereIn('category_id', $categoryIds);
            })
            ->limit(5)
            ->get();
    }

    return $data;
}, 10, 2);

BASE_FILTER_TABLE_QUERY

Modifies table queries in the admin panel.

add_filter(BASE_FILTER_TABLE_QUERY, function ($query, $table) {
    // Example: Add a condition to a specific table
    if ($table->getModel() instanceof \Botble\Blog\Models\Post) {
        // Only show posts created by the current user for non-admin users
        if (!auth()->user()->hasPermission('posts.edit')) {
            $query->where('author_id', auth()->id());
        }
    }

    return $query;
}, 10, 2);

BASE_FILTER_GET_LIST_DATA

Modifies list data before display.

add_filter(BASE_FILTER_GET_LIST_DATA, function ($data, $model, $table) {
    // Example: Add custom data to each row in a table
    if ($model instanceof \Botble\Blog\Models\Post) {
        foreach ($data as $key => $item) {
            // Add view count from a custom analytics service
            $data[$key]['views'] = YourAnalyticsService::getViews($item->id);
        }
    }

    return $data;
}, 10, 3);

DASHBOARD_FILTER_ADMIN_LIST

Modifies dashboard widgets.

add_filter(DASHBOARD_FILTER_ADMIN_LIST, function ($widgets, $widgetSettings) {
    // Example: Add a custom dashboard widget
    $widgets[] = [
        'id' => 'custom_stats_widget',
        'name' => 'Custom Statistics',
        'content' => view('plugins/your-plugin::widgets.stats', [
            'stats' => YourStatsService::getStats(),
        ])->render(),
    ];

    // Example: Remove a widget
    $widgets = collect($widgets)->filter(function ($item) {
        return $item['id'] !== 'widget_to_remove';
    })->toArray();

    return $widgets;
}, 10, 2);

PAGE_FILTER_FRONT_PAGE_CONTENT

Modifies page content.

add_filter(PAGE_FILTER_FRONT_PAGE_CONTENT, function ($content, $page) {
    // Example: Add a call-to-action section at the end of the homepage
    if ($page->id == get_page_id_from_shortcode('[homepage]')) {
        $content .= view('theme.sections.cta', [
            'title' => 'Ready to get started?',
            'button_text' => 'Contact Us',
            'button_url' => url('contact'),
        ])->render();
    }

    return $content;
}, 10, 2);

PAGE_FILTER_PAGE_NAME_IN_ADMIN_LIST

Modifies page names in admin list.

add_filter(PAGE_FILTER_PAGE_NAME_IN_ADMIN_LIST, function ($name, $page) {
    // Example: Add an indicator for pages that are used in the menu
    $usedInMenu = Menu::query()
        ->whereHas('menuNodes', function ($query) use ($page) {
            $query->where('reference_id', $page->id)
                ->where('reference_type', Page::class);
        })
        ->exists();

    if ($usedInMenu) {
        $name .= ' <span class="badge badge-info">In Menu</span>';
    }

    return $name;
}, 10, 2);

Action Hooks with Examples

BASE_ACTION_INIT

Executes when the application is initialized.

add_action(BASE_ACTION_INIT, function () {
    // Example: Register a custom post type or extend functionality
    if (is_plugin_active('your-plugin')) {
        // Initialize your plugin's components
        YourPlugin::initialize();
    }

    // Example: Add custom routes
    Route::group(['prefix' => 'custom', 'middleware' => ['web', 'core']], function () {
        Route::get('page', 'YourController@index');
    });
}, 10);

BASE_ACTION_META_BOXES

Registers meta boxes for admin forms.

add_action(BASE_ACTION_META_BOXES, function ($context, $object) {
    if ($context == 'advanced' && $object instanceof \Botble\Blog\Models\Post) {
        MetaBox::addMetaBox(
            'custom_seo_box',
            'Custom SEO Options',
            function () use ($object) {
                return view('plugins/your-plugin::meta-box.seo', compact('object'))->render();
            },
            get_class($object),
            $context
        );
    }
}, 10, 2);

BASE_ACTION_FORM_ACTIONS

Adds custom form actions.

add_action(BASE_ACTION_FORM_ACTIONS, function ($form) {
    // Example: Add a custom button to forms
    echo '<a href="#" class="btn btn-warning preview-button" target="_blank">
            <i class="fa fa-eye"></i> Preview
          </a>';

    // Example: Add a custom dropdown to forms
    echo '<div class="btn-group">
            <button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown">
                More Actions <span class="caret"></span>
            </button>
            <ul class="dropdown-menu">
                <li><a href="#">Export as PDF</a></li>
                <li><a href="#">Send to Email</a></li>
            </ul>
          </div>';
}, 10, 1);

BASE_ACTION_AFTER_CREATE_CONTENT

Executes after content creation.

add_action(BASE_ACTION_AFTER_CREATE_CONTENT, function ($screen, $request, $object) {
    // Example: Send notification when a new post is created
    if ($screen == POST_MODULE_SCREEN_NAME && $object) {
        // Send email to admin
        Mail::to(setting('admin_email'))
            ->send(new \App\Mail\NewPostCreated($object));

        // Create an activity log
        activity()
            ->performedOn($object)
            ->causedBy(auth()->user())
            ->log('Created new post: ' . $object->name);

        // Ping search engines
        if ($object->status == \Botble\Base\Enums\BaseStatusEnum::PUBLISHED) {
            ping_search_engines(route('public.single', $object->slug));
        }
    }
}, 10, 3);

BASE_ACTION_AFTER_UPDATE_CONTENT

Executes after content update.

add_action(BASE_ACTION_AFTER_UPDATE_CONTENT, function ($screen, $request, $object) {
    // Example: Clear cache when a page is updated
    if ($screen == PAGE_MODULE_SCREEN_NAME) {
        Cache::forget('page_' . $object->id);

        // Regenerate sitemap
        if ($object->status == \Botble\Base\Enums\BaseStatusEnum::PUBLISHED) {
            \Botble\Sitemap\Sitemap::generate();
        }
    }
}, 10, 3);

BASE_ACTION_AFTER_DELETE_CONTENT

Executes after content deletion.

add_action(BASE_ACTION_AFTER_DELETE_CONTENT, function ($screen, $request, $object) {
    // Example: Clean up related data when a post is deleted
    if ($screen == POST_MODULE_SCREEN_NAME) {
        // Delete post metadata
        MetaBox::deleteMetaData($object, 'custom_fields');

        // Delete associated media
        \Botble\Media\Models\MediaFile::query()
            ->where('reference_id', $object->id)
            ->where('reference_type', get_class($object))
            ->delete();

        // Log the deletion
        info('Post deleted: ' . $object->name);
    }
}, 10, 3);

BASE_ACTION_BEFORE_EDIT_CONTENT

Executes before content editing.

add_action(BASE_ACTION_BEFORE_EDIT_CONTENT, function ($request, $object) {
    // Example: Check permissions or prepare data before editing
    if ($object instanceof \Botble\Blog\Models\Post) {
        // Check if user can edit this post
        if ($object->author_id != auth()->id() && !auth()->user()->hasPermission('posts.edit')) {
            abort(403, 'You do not have permission to edit this post.');
        }

        // Prepare additional data
        $object->loadMissing(['categories', 'tags']);
    }
}, 10, 2);

USER_ACTION_AFTER_UPDATE_PROFILE

Executes after user profile update.

add_action(USER_ACTION_AFTER_UPDATE_PROFILE, function ($screen, $request, $user) {
    // Example: Sync user data with a CRM or external service
    if ($user) {
        // Sync with CRM
        YourCrmService::updateContact([
            'email' => $user->email,
            'name' => $user->name,
            'phone' => $request->input('phone'),
        ]);

        // Update user preferences
        UserPreference::updateOrCreate(
            ['user_id' => $user->id],
            ['preferences' => json_encode($request->input('preferences', []))]
        );
    }
}, 10, 3);

USER_ACTION_AFTER_UPDATE_PASSWORD

Executes after user password update.

add_action(USER_ACTION_AFTER_UPDATE_PASSWORD, function ($screen, $request, $user) {
    // Example: Send notification email when password is changed
    if ($user) {
        Mail::to($user->email)
            ->send(new \App\Mail\PasswordChanged([
                'user' => $user,
                'time' => now()->format('Y-m-d H:i:s'),
                'ip' => $request->ip(),
            ]));

        // Log the password change
        activity()
            ->performedOn($user)
            ->causedBy($user)
            ->log('Changed password');
    }
}, 10, 3);

AUTH_ACTION_AFTER_LOGOUT_SYSTEM

Executes after user logout.

add_action(AUTH_ACTION_AFTER_LOGOUT_SYSTEM, function ($screen, $user) {
    // Example: Clear user-specific cache and log the logout
    if ($user) {
        // Clear user cache
        Cache::forget('user_permissions_' . $user->id);

        // Log the logout
        activity()
            ->performedOn($user)
            ->causedBy($user)
            ->log('Logged out');

        // Track with analytics
        YourAnalyticsService::trackEvent('user_logout', [
            'user_id' => $user->id,
            'time' => now()->timestamp,
        ]);
    }
}, 10, 2);

Best Practices

  1. Use Appropriate Priority: Lower numbers run first. Use this to control execution order.
  2. Document Your Hooks: When creating custom hooks, document them for other developers.
  3. Check Existing Hooks: Before creating new hooks, check if existing ones can be used.
  4. Be Mindful of Performance: Hooks can impact performance if overused or poorly implemented.
  5. Use Namespaced Hook Names: For plugins, prefix hook names to avoid conflicts.

Creating Custom Hooks

You can create your own hooks in your plugins or themes:

// Define a custom filter hook
$filteredValue = apply_filters('your_plugin_custom_filter', $originalValue, $additionalArg);

// Define a custom action hook
do_action('your_plugin_custom_action', $arg1, $arg2);

Conclusion

Filters and actions provide a powerful way to extend and customize Botble without modifying core files. By understanding and using these hooks effectively, you can create flexible and maintainable code that integrates seamlessly with the Botble ecosystem.

About

Botble Filters and Actions Documentation

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published