GeniXCMS

Control Layer

categoryAPI edit_calendar31 Mar 2026

Control Layer Reference


The Control Layer is the collection of individual controller files stored in inc/lib/Control/. These files are not called directly — they are loaded by the Control class dispatcher based on the current URL or admin page selection.

Directory Structure

inc/lib/Control/
├── Frontend/     — Public-facing page controllers (class-based, extend BaseControl)
├── Backend/      — Admin dashboard controllers (procedural)
├── Ajax/         — JSON API / AJAX endpoint controllers
├── Api/          — RESTful Resource controllers (class-based)
├── Error/        — Error page handlers
└── Install/      — Installation wizard controller

Frontend Controllers

All frontend controllers are class-based and extend BaseControl, which provides the Latte templating engine and common data. Each file instantiates its class and calls run($param) at the bottom.

How they are called:

// GxMain calls:
Control::frontend();
// Which calls:
Control::incFront('post', $param);
// Which includes:
inc/lib/Control/Frontend/post.control.php
File Class URL Pattern Description
default.control.php DefaultControl / or /paging/N/ Homepage with paginated post listing
post.control.php PostControl /slug.html Single post or page detail view
page.control.php PageControl /slug.html (type=page) Static page with optional module support
cat.control.php CatControl /category/ID/slug/ Category archive listing
tag.control.php TagControl /tag/slug/ Tag archive listing
author.control.php AuthorControl /author/username/ Author post archive
archive.control.php ArchiveControl /YYYY/MM/ Date-based monthly archive
search.control.php SearchControl /search/ Full-text search results
login.control.php LoginControl /login/ User login form and processing
register.control.php (procedural) /register/ User self-registration with email verification and account activation
forgotpass.control.php (procedural) /forgotpass/ Password reset — generates new password and emails it to user
logout.control.php (procedural) /logout/ Destroy session and redirect to home
mod.control.php ModControl /mod/MODULE_NAME.html Custom module frontend page loader (extends BaseControl)
rss.control.php (procedural) /rss/ RSS feed XML output
sitemap.control.php (procedural) /sitemap.xml XML sitemap output
thumb.control.php (procedural) /thumb/type/SIZE/ALIGN/file Dynamic image thumbnail via Image::thumbFly

Standard Frontend Controller Pattern

class PostControl extends BaseControl
{
    public function run($param)
    {
        // 1. Extract URL parameters
        $data = Router::scrap($param);

        // 2. Fetch & prepare content
        $posts = Posts::fetch(['id' => $post_id]);
        $data['posts'] = Posts::prepare($posts);

        // 3. Trigger hooks
        $data['content'] = Hooks::run('post_content_before_action', $data);
        $data['content'] .= Posts::content($post->content);

        // 4. Render through BaseControl (header + view + footer via Latte)
        $this->render('single', $data);

        // 5. Track page view
        Stats::addViews($post_id);
    }
}

// Instantiate and run at end of file:
$control = new PostControl();
$control->run($param);

Backend Controllers

Backend controllers are procedural files with no class definition. They are loaded by Control::incBack(). All operations are protected by User::access(level).

How they are called:

// Admin URL: /admin/index.php?page=posts
Control::backend();
// Which calls:
Control::incBack('posts');
// Which includes:
inc/lib/Control/Backend/posts.control.php
File ?page= Value Min Access Level Description
default.control.php (dashboard) 1 Main admin dashboard with stats
posts.control.php posts 3 Blog post CRUD (add, edit, delete, bulk actions)
pages.control.php pages 3 Static page CRUD
categories.control.php categories 1 Post category add/edit/delete
tags.control.php tags 1 Tag management
comments.control.php comments 1 Comment moderation
menus.control.php menus 1 Navigation menu builder
modules.control.php modules 1 Module listing and install/uninstall
mods.control.php mod 1 Individual module backend page loader
media.control.php media 1 Media file browser (elFinder)
themes.control.php themes 1 Theme listing and activation
users.control.php users 1 User management (CRUD, roles)
widgets.control.php widgets 1 Widget placement management
settings.control.php settings 1 General site settings
settings-cache.control.php settings-cache 1 File/Redis cache settings
settings-comments.control.php settings-comments 1 Comment system settings
settings-media.control.php settings-media 1 Image, watermark, and media settings
settings-multilang.control.php settings-multilang 1 Multi-language configuration
settings-permalink.control.php settings-permalink 1 Permalink / URL structure settings
permissions.control.php permissions 0 User role and access permission settings

User Access Levels

Level Role Notes
0 Administrator Full access — including system settings, themes, modules, and permissions
1 Supervisor Site-wide management (all backend areas except system-level settings)
2 Editor Content management and moderation
3 Author Manage their own content only
4 Contributor Post creation (review required before publish)
6 General Member Default site member — frontend access only

Standard Backend Controller Pattern

if (User::access(1)) {
    // Sanitize inputs
    $name = Typo::cleanX($_POST['name']);
    $token = Typo::cleanX($_POST['token']);

    // Validate CSRF token
    if (!Token::validate($token)) {
        $alertDanger[] = _("Token not exist or expired.");
    }

    // Validate required fields
    if (empty($name)) {
        $alertDanger[] = _("Name cannot be empty.");
    }

    if (!isset($alertDanger)) {
        // Database operation
        Db::insert("INSERT INTO `table` VALUES (...)");
        $data['alertSuccess'][] = _("Saved successfully.");
        Token::remove($token);
    } else {
        $data['alertDanger'] = $alertDanger;
    }

    // Render admin template
    Theme::admin('header', $data);
    System::inc('view_name', $data);
    Theme::admin('footer');
} else {
    Theme::admin('header');
    Control::error('noaccess');
    Theme::admin('footer');
}

Ajax Controllers

Ajax controllers are procedural files that return JSON responses. They are loaded by Control::ajax() when the URL matches /ajax/{endpoint}/{token}.

How they are called:

// URL: /ajax/api/TOKEN
Control::ajax('api', $param);
// Which includes:
inc/lib/Control/Ajax/api-ajax.control.php
File Endpoint Token Required Description
api-ajax.control.php api Optional (per action) REST-like CMS data API (posts, categories, tags)
elfinder-ajax.control.php elfinder Yes elFinder file manager backend
saveimage-ajax.control.php saveimage Yes Saves images pasted into the WYSIWYG editor
tags-ajax.control.php tags Yes Tag autocomplete suggestions
version-ajax.control.php version Yes Checks for latest GeniXCMS version

Public API Endpoints (api-ajax)

Some actions are publicly accessible without a token:

Action (?action=) Token Parameters Returns
recent_posts Not required num, type, cat Array of post objects with image, excerpt
categories Not required type Array of category objects
tags Required term Array of matching tag objects

Example Request:

GET /ajax/api/TOKEN?action=recent_posts&num=5

Example Response:

{
    "status": "success",
    "data": [
        {
            "id": 42,
            "title": "Hello World",
            "url": "https://example.com/hello-world.html",
            "image": "https://example.com/thumb/type/square/size/300/...",
            "excerpt": "Short preview..."
        }
    ]
}

API Controllers (REST Resource)

API controllers are class-based files located in inc/lib/Control/Api/. These controllers follow a standard RESTful architecture, mapping HTTP verbs to specific class methods. They are dispatched by the Api class.

How they are called:

// URL: /api/v1/posts/123 (GET)
Control::api('posts', '123'); 
// Which triggers Api::dispatch('posts', '123') 
// and calls PostsApi->index('123')
File Class Endpoint Methods Support
PostsApi.class.php PostsApi /api/v1/posts GET, POST, PUT, DELETE
PagesApi.class.php PagesApi /api/v1/pages GET, POST, PUT, DELETE

Standard API Controller Pattern

All methods return a JSON response via Api::success() or Api::error().

class PostsApi
{
    /**
     * Maps to GET /api/v1/posts/ or GET /api/v1/posts/{id}
     */
    public function index($id = null)
    {
        if ($id) {
            $post = Posts::find($id);
            return $post ? Api::success($post) : Api::error(404, 'Post not found');
        }
        $posts = Posts::all();
        return Api::success($posts);
    }

    /**
     * Maps to POST /api/v1/posts/
     */
    public function submit()
    {
        $data = json_decode(file_get_contents('php://input'), true);
        $res = Posts::create($data);
        return $res ? Api::success(['id' => Db::$last_id]) : Api::error(500, 'Failed creation');
    }

    /**
     * Maps to PUT or PATCH /api/v1/posts/{id}
     */
    public function update($id)
    {
        $post = Posts::find($id);
        if (!$post) return Api::error(404, 'Post not found');

        $data = json_decode(file_get_contents('php://input'), true);
        return $post->save($data) ? Api::success(null, 'Updated') : Api::error(500, 'Failed');
    }

    /**
     * Maps to DELETE /api/v1/posts/{id}
     */
    public function delete($id)
    {
        $post = Posts::find($id);
        return $post && $post->destroy() ? Api::success(null, 'Deleted') : Api::error(500, 'Failed');
    }
}

Error Controllers

Error controllers are simple include files at inc/lib/Control/Error/ triggered by Control::error($code).

File Code Description
404.control.php 404 Page not found
noaccess.control.php noaccess Insufficient user permission
unknown.control.php (default) Generic unknown error