What is Prometheus?

Prometheus brings a new and simplistic approach to developing code in Drupal CMS. It works with existing Drupal CMS mechanisms and allows for a rapid MVC style of development under Drupal CMS. This brings the power of OOP and encourages better readability and simpler code, while providing faster Drupal CMS bootstrap.

Project page: http://drupal.org/project/prometheus

Prometheus Installation Guide

When you have Prometheus download, Prometheus folder should be placed under:

path - my_root_folder/sites/all/modules/contrib/

Prometheus is a development tool to enable the option so that you can do development in MVC style. You do not typically use the module itself to do anything.

The proper way to use Prometheus is to create a custom module that uses Prometheus.

How to create a custom module

In order to use Prometheus. We have to create a custom module first.

Here is a quick guide to create a custom module.

1. Create a folder for your module (eg. my_module) under custom module:

path - my_root_folder/sites/all/modules/custom/

2. Create a .info (eg. my_module.info) file inside your module folder:

path - my_root_folder/sites/all/modules/custom/my_module/

3. Edit your .info file to have the basic information. eg:

name = my module
description = "My Custom Module that uses Prometheus"
dependencies[] = prometheus
package = Custom
core = "7.x"

As you can see we have Prometheus as one of the dependencies, since since this custom module is going to use Prometheus.

4. Create a .module (eg. my_module.module) file inside your module folder:

path - my_root_folder/sites/all/modules/custom/my_module/

Now you should able to see your custom module from the Modules tab in Drupal:
path - mywebsite.com/admin/modules

Make sure your custom module is enabled.

How to setup Prometheus in your custom module

1. Create "classes" folder in your custom module folder

We will create a "classes" folder in your custom module folder:

path - my_root_folder/sites/all/modules/custom/my_module/

This "classes" folder will contain all class files you are going to code with Prometheus.

All class file should be named with the following pattern:

"myclass.class.php" - class file thumbnail with .class.php

Let's create a sample class (myclass.class.php) file now and place it inside "classes" folder

path - my_root_folder/sites/all/modules/custom/my_module/classes

We will use this myclass.class.php file later on with Prometheus.

2. Register Prometheus in your .module file.

Here is how we register Prometheus in your custom module.

Edit your .module (eg. my_module.module) file, place the following sample code in.

<?php
// module file my_module.module
define( 'CLASSES_DIR', 'classes' ); // define class folder name

require_once( CLASSES_DIR . '/myclass.class.php' ); // includes our class file

// check if Prometheus is actually exist before initialize
class_exists('Prometheus') && Prometheus::register(
  array(
    // MyClass is the class we are going to code with
    'MyClass' => array(),
  )
);
?>

Upon register the code above. When the url mywebsite.com/myclass is entered, related code inside myclass.class.php will run.

Now let's see what myclass.class.php will look like.

How to use Prometheus

Here are some sample codes:

<?php
// class file myclass.class.php
class MyClass{

    public function index(){
        print "Hello, this is my Prometheus class front page";
    }

    public function hello ( $input ){
        print "Hello: $input";
    }

    public function category ( $category1, $category2 ){
        print "Categories are $category1, $category2";
    }
    
    // url to access this page would be 
    // **replace _ with - for public access
    public function show_my_list(){
        print "my list";
    }
     
}
?>

Once new function is added, clear cache may needed for Drupal to recognize them.

As defined in the code above, here are some test case we can do to see the output.

input: mywebsite.com/myclass

output: You will see "Hello, this is my Prometheus class front page" displays on the page. As its defined in the index function.

input: mywebsite.com/myclass/hello/drupal

output: You will see "Hello: drupal" displays on the page. As "drupal" is an url argument that is load into our hello function as $input.

input: mywebsite.com/myclass/hello?input=drupal

output: You will see "Hello: Drupal" displays on the page. "drupal" is passed into hello function as a query string argument.

input: mywebsite.com/myclass/category/cruel/world

output: You will see "Categories are cruel, world" displays on the page. "cruel" and "world" are passed into category function as url arguments.

input: mywebsite.com/myclass/category?category1=cruel&category2=world

output: You will see "Categories are cruel, world" displays on the page. "cruel" and "world" are passed into category function as query string arguments.

input: mywebsite.com/myclass/show-my-list

output: "my list" will be displayed. ***Please notice that url is show-my-list instead of the function name show_my_list

Prometheus and Templates

If you don't like how your content is being displayed. Prometheus has provided the option to have your own templates.

All you have to do is to create the template folder and files with the right names.

Previously, we have named our class as "MyClass". So our template folder will be named "myclass" and placed into the following path:

path - my_root_folder/sites/all/themes/my_theme/templates/

If we want to have a template for the "hello" page, we just need to create a template file named with the following pattern:

"hello.tpl.php" - template file thumbnail with .tpl.php

**For function has "_" (eg. long_name_one):

"long-name-one.tpl.php" - "_" has to be replaced with "-" and thumbnail with .tpl.php

The template file should be placed into its class template folder which is:

path - my_root_folder/sites/all/themes/my_theme/templates/myclass/

This path may change if you are using 'prefix' in your initialization.

We will talk about it more later.

As for class file (myclass.class.php), here is how to pass variables into the template file.

<?php
// class file myclass.class.php
class MyClass{

    public function hello (){
        $hello = 'Hi';
        $world = 'Mars';
        
        return array('hello' => $hello, 'my_world' => $world);
    }
?>
<?php
// template file hello.tpl.php
print "$hello $my_world";    // output: Hi Mars
?>

More Prometheus initialization examples

prefix: manipulating url with prefixed term
hook_menu: get drupal hook_menu to restrict access etc.

<?php
// module file my_module.module
define( 'CLASSES_DIR', 'classes' ); // define class folder name

require_once( CLASSES_DIR . '/myclass.class.php' ); // includes our class file

// check if Prometheus is actually exist before initialize
class_exists('Prometheus') && Prometheus::register(
  array(
    // default behavior for Prometheus to load its content
    'DEFAULTS' => array(
      'template' => array(
        'load_as_region' => 'content'  // only load content to content area 
      ),
    ),
    'MyClass' => array(
      'paths' => array(
        'index' => array( // *special case
          'prefix' => ''  // if you have a index page and set prefix to nothing
                          // it will catch all url calls after mywebsite.com/
        ),
        'hello' => array(
          'prefix' => '',  // if prefix set to nothing, the class name would be blank
                           // to access 'hello' page
                           // the url would be mywebsite.com/hello 
                           // instead of mywebsite.com/myclass/hello
                           // if template are involved, 
                           // matching folder and path are needed see **
          'hook_menu' => array(
            // Restrict public access to hello page
            'access callback' => FALSE
          )
        ),
        'category' => array(
          'prefix' => 'your/prefix/path/',  // prefix replace the class name in url
                                            // to access 'category' page 
                                            // the url would be 
                        // mywebsite.com/your/prefix/path//category/
                        // instead of mywebsite.com/myclass/category/
                        // if template are involved, 
                        // matching folder and path are needed see **
          'type' => MENU_LOCAL_TASK,  // menu type see drupal menu type for detail
        ),
      )
    ),
  )
);
?>

*Special case

If you have define a function index() and set the prefix to none. For any url call after mywebsite.com/ will run the index function. If you want to keep the path as mywebsite.com/myclass/function, just do not configure prefix.

**Template for prefix page

path - my_root_folder/sites/all/themes/my_theme/templates/myclass/

As we mentioned before the above path is the path for any page within that class called "myclass", but since we have used prefix to replace the myclass. We also need to create the right path for the prefix.

eg. 'prefix' => 'your/prefix/path/'

Instead of

path - my_root_folder/sites/all/themes/my_theme/templates/myclass/

The path would be

path - my_root_folder/sites/all/themes/my_theme/templates/your/prefix/path/

If you want to keep the path as mywebsite.com/myclass/function, just do not configure prefix.

More Prometheus class file examples

Prometheus still have the abilities to use all drupal functions and globals as example shows below.

<?php
// class file myclass.class.php
class MyClass{

    public function hello (){
        // set page title
        drupal_set_title( 'This is page title for hello' );
        // set page message
        drupal_set_message( 'This is the message I want to pop' );
        $hello = 'Hi';
        $world = 'Mars';
        // go to myclass/world page
        drupal_goto("myclass/world");

        return array('hello' => $hello, 'my_world' => $world);
    }
    
    public function world(){
        global $user;
        $user_id = $user->uid;
        // call a internal function still needs the class name
        $result = MyClass::calculate($input1, $input2);

        return array('user_id' => $user_id, 'result' => $result);
    }
   
    // private function don't have public visibility, but page still exist
    // so you might have to name your function carefully to not have
    // conflicts with your any page
    private function calculate($input1, $input2){
        $result = $input1 + $input2;
        return $result;
    }
    
}
?>

More Prometheus template file examples

<?php
// class file myclass.class.php
class MyClass{

    public function house_list (){
        // set page title
        drupal_set_title( 'This is page title for hello' );
        // set page message
        drupal_set_message( 'This is the message I want to pop' );
        $hello = 'Hi';
        $world = 'Mars';
        // go to myclass/world page
        drupal_goto("myclass/world");

        return array('hello' => $hello, 'my_world' => $world);
    }
    
    // template for this page should be my-contact-list.tpl.php
    public function my_contact_list(){
        // get phone_list from db
        $phone_list = db_select('phone_list', 'phone_id')
	    ->fields('phone_id')
	    ->condition('type', 'work_phone','=')
	    ->execute()
	    ->fetchAll();
        
        $address_list = db_select('address_list', 'address_id')
	    ->fields('address_id')
	    ->condition('zipcode', '12345','=')
	    ->execute()
	    ->fetchAll();
        
        // can pass array no problem at all
        return array('phone_list' => $phone_list, 'address_list' => $address_list);
    }
}
?>
<?php 
// template file my-contact-list.tpl.php 
// which ever way you prefer to go through your array
?>

<table id="phone_table">
<?php
    foreach($phone_list as $phone){
        print '<tr class="phone_row">';
        print '<td>';
        print $phone['zone_code'];
        print ' - ';
        print $phone['number'];
        print '</td>';
        print '</tr>';
    }
?>
</table>
<ul>
<?php
    // which ever way you prefer to go through your array
    foreach($address_list as $address){
?>
        <li><?php print $address['text'];?></li>
<?php
    }
?>
</ul>

Prometheus custom block example

<?php
// in your  my_module.module file
/**
 * initialized the custom block
 */
function my_module_block_info(){
  
  $blocks['my_custom_block'] =  array(
    'info' => t('My New Block'),
    'weight' => -1,
    'status' => TRUE,
    // Region to be placed at
    'region' => 'content',
    // Show only on listed pages. 
    // 'pages' lists the paths where the block should be shown.
    'visibilty' => BLOCK_VISIBILITY_LISTED,
    // Page to be shown, <front> means home/landing page
    'pages' => '<front>'
  );
    
  return $blocks;
}
/**
 * assigning a view for your custom block
 */
function my_module_block_view($delta){
  $block = NULL;

  switch($delta){
  // catch the name of block you just initialized
  case 'my_custom_block':
    $block = array(
      'subject' => t(''),
      // The return content of block
      // We are doing a function call here, we will create that class later
      'content' => MyCustomBlock::front_block()
    );
  break;
  }

  return $block;
}

?>

Let's create a .class file for the custom block we just created (mycustomblock.class.php) and place it inside "classes" folder. Remember to include it inside your .module file.

<?php
// This is the class for our custom block
class MyCustomBlock {
    
    // This function will generate and return the content for our block.
    static function front_block() {
         // YOUR CODE HERE
         $vars['my_data'] = array('fruit'=>'banana', 'meat'=>'beaf');
        // Calling Prometheus, load variables into a block template then return to the screen
        // We will create this template "block-my_custom_block" later for our block data
        return Prometheus::load_template('block-my_custom_block', $vars);
    }
?>

Now we can create a template file in our Theme folder. As we defined the name above.
The template file name would be 'block-my_custom_block.tpl.php'.

<?php
print $my_data['fruit'];    // output: banana
print $my_data['meat'];    // output: beaf
?>

Prometheus Ajax example

<?php
// module file my_module.module
define( 'CLASSES_DIR', 'classes' ); // define class folder name

require_once( CLASSES_DIR . '/myclass.class.php' ); // includes our class file

// check if Prometheus is actually exist before initialize
class_exists('Prometheus') && Prometheus::register(
  array(
    // default behavior for Prometheus to load its content
    'DEFAULTS' => array(
      'template' => array(
        'load_as_region' => 'content'  // only load content to content area 
      ),
    ),
    'MyClass' => array(
      'paths' => array(
        'index' => array( // *special case
          'prefix' => ''  // if you have a index page and set prefix to nothing
                          // it will catch all url calls after mywebsite.com/
        ),
        /* ajax calls */
        'ajax_my_list' => array( // use ajax_ is not a prefix, we name this way to identify the difference.
          'view' => array(
           'json' => array()  // use json to pass values via ajax calls
          ),
        ),
      ),
    ),
  )
);
?>

Inside the .class.php file

<?php
// class file myclass.class.php
class MyClass{
    // there is actually no big difference in between ajax and normal function
    public function ajax_my_list ($input1, $input2){

        $text = 'hello, world';
        $result = $input1 + $input2;


        return array('text' => $text, 'result' => $result);
    }
    
}
?>

Inside the .tpl.php file

<?php 
// this is a template file with ajax example
?>
<script type="text/javascript">
(function($){
  $(function() {
        $("#show-data").bind('click',function(e) {
           var field1 = $('input[name=field1]').val();
           var field2 = $('input[name=field2]').val();
           // note here it's post to "ajax-my-list" instead of "ajax_my_list",
           // because we are posting to url not the function
          $.post('ajax-get-updated-cupcakes',{input1:field1, input2:field2}, function(data) {
            $('#result').html(data.result);
            $('#text').html(data.text);
          });
          e.stopPropagation();
          return false;
        });
  });
})(jQuery);
</script>
<div id="show-data">Click Me</div>
<form action="" method="post">
<input type="text" name="field1">
<input type="text" name="field2">
</form>
<div id="result"></div> <!-- will return result base on field1 and field2 input -->
<div id="text"></div> <!-- will return "hello, world -->

More example coming soon...

Comments

HipSiGa’s picture

Sorry! Anybody help me? I can't map to my hello template...

this is photo about that:
http://www.mediafire.com/view/77c3ca20ngstnd1/error.jpg

HipSiGa’s picture

anyone help me, please! :(

bleeuwen’s picture

Hi

are more examples to come?

SagarK’s picture

This module worked very well for me.
but I have a problem to integrate a drupal form in the prometheus based template.
If somebody has done this then please help?

wasimisone’s picture

I am having problem in the layout after following properly your instruction. In the content part whole page is coming where in the content part it should show only "Hello, this is my Prometheus class front page". Does anyone know about this.