Component Definition

From Cloudrexx Development Wiki
(Redirected from New Component)
Jump to: navigation, search

Introduction

This article describes the structure and function of a Cloudrexx component. For a tutorial on how to create your own component, do see Create Cloudrexx App.

Note: This documentation refers to version 5 or newer. For older versions of Cloudrexx, please refer to Contrexx modules. For migrating Contrexx modules to Cloudrexx components see Migrate Module to Component (v1/v2 -> v4+).

Components are self-contained parts of Cloudrexx. A component can be added or removed, without affecting other components. Components can have dependencies to other components (for Example: a lot of different components need the Html component to be present).

So when creating a component, all your code must be located within one single directory. If you change any line of code outside of your component's directory, you're probably doing something wrong...


Component types

Here's a simple graphic showing whether your code will be part of lib, core, core_modules or modules:

CoreModule.png

If you are creating/adding a library, simply create the directory /lib/{name_of_your_lib} and start developing your lib. You may skip the following steps!

Lib

Integrate third-party libraries according to Third-party libraries.

Directory structure

New components use the following directory structure:

Directory Usage Deployment
Controller Controller classes x
Data Data for the component x
Data.sql Contains base data for this component -
OldStructureWithTestData.sql Contains old structure with some data for testing -
Migration.sql Migrates OldStructureWithTestData.sql -
* All other files and folders within this folder x
Dev Development scripts -
Doc ERD, PDFs, etc. -
Model Model classes and definitions x
Entity Model entity classes x
Event Event listener classes x
Repository Model repository classes x
Yaml Model YAML definitions x
Testing Testing scripts and classes -
UnitTest UnitTests -
View View files x
Media Images, PDFs, etc. x
Script JavaScript x
Style CSS x
Templates Template files x
Frontend Template files for frontend mode x
Backend Template files for backend mode x
Command Template files for command mode x
Generic Template files used in more than one mode x
lang Language files x
en English language files x
frontend.php English frontend mode language file x
backend.php English backend mode language file x
... Other languages x
README.md Component description. (Filename is case insensitive). -
  • All of these directories are optional, README.md is mandatory.
  • The structure can be extended according to your needs, but do not add any directories to any level specified here. If you add a directory, write its name in singular CamelCase (see Naming conventions).
  • All directories with sub-directories should not directly contain files (you may break this rule in directories you create yourself, but you shouldn't).
  • All files are named in CamelCase (except README.md) and do not contain the Component's name (again see Naming conventions).

What data to store where

Where to store data depends on whether the data is per website, per component (multiple websites may use the same codebase) or per user and whether it should be publicly available or not:

Data per Public File system location Example
Component Yes <componentFolder>/View/Media/* Manual for this component as a PDF
Component No <componentFolder>/Data/* SSL certificate
Website Yes /media/public/<componentName>/* Downloads without access restrictions
Website No /media/private/<componentName>/* Downloads with access restrictions
Session Yes /tmp/public/<folderId>/* [1] Export
Session No /tmp/session_<sessionId>/<componentName>/* Uploader
  1. See \Cx\Core\Core\Controller\ComponentController::getPublicUserTempFolder()

MVC

Strictly follow the MVC pattern by putting

  • the model logic (including any business logic) into the /Model directory of a component
  • the controller logic into the /Controller directory of a component
  • and the output/GUI elements into the /View directory of a component

This also means that neither the /Model, nor the /Controller elements must contain any HTML code. Instead do use the Html component to generate HTML output.

Controller

If you create a component using the Workbench's create command it adds two controllers to your Component: A FrontendController and a BackendController. They do most of work that is needed for almost every Component for you. Both of them contain a parsePage() method with a bit of code to start with.

Backend sub navigation

The BackendController also has a method named getCommands(). You may return a one or two dimensional array of strings. There is an empty entry that will be rendered as Default. This will automatically generate a sub navigation. For example:

array(
    '',
    'lists',
    'users' => array(
        '',
        'edit',
        'import',
    ),
    'news',
    'dispatch' => array(
        '',
        'templates',
        'interface',
        'confightml',
        'activatemail',
        'confirmmail',
        'notificationmail',
        'system',
    ),
)

This would generate a navigation matching the one of the e-mail marketing module. For every level, a default is added, so the first entry can be omitted. If you only need one navigation point, you may return an empty array (default). The backend controller then searches for language variables of the following scheme: TXT_{COMPONENT_TYPE}_{COMPONENT_NAME}_ACT_{1ST_LEVEL}(_{2ND_LEVEL}). For the added default, DEFAULT is used for 1st and 2nd level.

Content

The method parsePage() gets a Sigma template as parameter. In frontend, that template consists of the content of the resolved page. In backend, a template file ({your_component_directory}/View/Template) named like the current command (see getCommands()) or Default.html is loaded.

Here you have access to your Component's name and type using $this->getName() resp. $this->getType() and to the Cx object.

Write own ComponentController

By default, the \Cx\Core\Core\Model\Entity\SystemComponentController class is used as main controller for your Component. It registers the controllers "FrontendController" and "BackendController for you. If any of the following conditions are true, you need to write your own ComponentController:

  • You want to add another Controller
  • You don't need the Frontend- or BackendController
  • You want to respond to any of the Component Hooks
  • You want to expose a method
  • Add documentation URLs for your component
  • Use command mode

In order to write your own ComponentController you can simply create a class named ComponentController which extends \Cx\Core\Core\Model\Entity\SystemComponentController in the file <yourComponentDirectory>/Controller/ComponentController.class.php.

The following table explains how to proceed for the use cases listed above:

Use case How to proceed
Add another controller
  1. Create the file <yourComponentDirectory>/Controller/<yourControllerName>Controller.class.php.
  2. Define the class <yourComponentNamespace>\Controller\<yourControllerName>Controller within the file. Let it extend \Cx\Core\Core\Model\Entity\Controller.
  3. Register the controller in your ComponentController as shown by the following example:
    /**
     * {@inheritdoc}
     */
    public function getControllerClasses()
    {
        return array('Frontend', 'Backend', '<yourControllerName>');
    }
Don't need Front- or BackendController Adjust the list in the method getControllerClasses() accordingly (see use case "Add another controller" above).
Respond to Component hooks Implement the matching method in your ComponentController according to its DocBlock.
Expose methods Select a Controller (or create a new one) to register for exposing methods. Then follow Expose a controller's method.
Add documentation URLs Set one or more of the following properties in your ComponentController:
    /**
     * URL pointing to the end-user documentation for this component
     *
     * @var string End-user documentation URL
     */
    protected $enduserDocumentationUrl = '';

    /**
     * URL pointing to the template definitions for this component
     *
     * @var string Template documentation URL
     */
    protected $templateDocumentationUrl = '';

    /**
     * URL pointing to the developer documentation for this component
     *
     * @var string Developer documentation URL
     */
    protected $developerDocumentationUrl = '';
Use command mode Overwrite the methods getCommandsForCommandMode(), getCommandDescription() and executeCommand() according to their specification.

View

The view is generated using PEAR Sigma templates (as in previous versions of Cloudrexx). As stated in section "Controller", backend templates are located in {your_component_directory}/View/Template/Backend. Frontend templates are loaded from page content. If the page content contains the placeholder [[APPLICATION_DATA]] then this placeholder is replaced by the associated application template. The application templates are located in {your_component_directory}/View/Template/Frontend. By default Default.html is loaded. If the current page has a cmd for which an application template exists then this template is used instead. Application templates can be overwritten by placing a file with the same name in {template_directory}/{your_component_type}/{your_component_name}/Template/Frontend.

JavaScript and CSS

If you create a component using the Workbench's create command it adds a Front- and Backend.js and a Front- and Backend.css. Those are automatically loaded if they exist. Drop them if you don't need them.