Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Sunday, December 18, 2016

Digital Transformation

There is a saying in information technology that says "If you have a computer, don't use it" and this sound weird. Both my computers running Windows and Linux were hacked recently after I made a huge provocation on twitter. It's a freaking reality If you need to keep a confidential environment. Technically, all computers and mobile phone can be hacked moreover the telecoms company which provide your internet connection can use proxy and log your meta-data worst your social network connectivity can be analysed yet your are an idiot if you think you shouldn't use internet in most of common mortal life. 

Hackers are well organized and America has a total control over information technology so that your computer is open to tiers persons or organizations. In 1997, Microsoft operating system Windows didn't even had a key to break into the system if it was connected to a printer then there is only one solution to ensure confidentiality "No connection". Your infrastructure must be outside the internet and your cloud must be at least hybrid while anonymous internet users like you and me need to be aware of what we let on our file system.

With Big Data comes big responsibilities ! Big Data is the ability to retrieve information from large volume of data and there will be less anonymous usage of the internet once operators implemented Big Data even with authentification uncertainty because it's impossible to know who was behind the computer. Cookies and logs will allow tiers persons or organizations to know much more about you than you had expected. It's already the case for supermarket fidelity cards, not mentioning various phishing website. Avoid to give your personal information over email unless it's absolutely necessary !

Last, social networking can quickly give an overview of your personality as well as multiple information about your interests, political orientation, network of friends ... etc We can be sure that any information available on your social network will be exploited by tiers persons or organizations. It's acting like a Black box that will reveal the nature of failures or success. Keep in mind that studying the sexuality of Chinese elderly is not a problem for the department of psychiatry in the faculty of medicine of Hong Kong University !!!

Imagine the doctor Gill before the creation of Montpelier faculty of medicine in the XII century guiding people while the next Saint in the church nearby was preaching for Christian doctrine. A brand new Christian world awakened with the new power of the Church followed by recent democratic and communist revolutions between the XVIII and XX centuries. Shall we follow a computer or does privacy really matters ? The digital transformation goes far beyond organizations. Donald Trump, Hillary Clinton, new French one term presidents and Chinese leaders know it very well.

Thursday, September 8, 2016

Web development new challenge

Many mobile phone users connect to the internet with their mobile phone. It's a new reality for the web developer and a website can adapt to various screen size and terminal moreover 9 over 10 users of smartphone browse the web with their terminal. It's a significant unique visitors increase of your audience. Soon, new IoT will connect to the web like your TV, fridge, game station ... and many of them are still prototype.

The web is open since the very beginning defined by standard whatever the terminal or operating system moreover the web can adapt to the size of the terminal with a relative values which means that you use percentage when giving the size of an element instead of fixed value. Openness and relativity are the keys of web developments 

The advantage of designing for multiple platforms are numerous. The end user has the same visibility whatever the supporting technology and features are the same on each platforms with only one solution to push in production but it's more expensive with an unknown return of investment.

Above all the survival of your internet business rely on the experience of the end user knowing that an internet solution can be extremely complex and drive the end user to your competitor. It's then absolutely necessary to take into account the experience of the end user during the development or test of your solution.

You then have to choose between : 
  • traditional website for computer
  • Mobile first website
  • Responsive Design Website which adapt to the platform
  • two solutions, one for computers and one for mobiles with .htaccess router.
but the new technical solutions arriving on the market are challenging Web Development concepts.

Sunday, February 28, 2016

Matrix 6.0 Javascript Source Code

Matrix 6.0 source code with Matrix Reloaded Core Engine. The first Matrix was written in 2000 for NetValue Online. Matrix 6.0 is a software installed on my computer without web server.

 /**  
 *   
 * matrix.js is a standalone javascript software  
 * Add entries to the page of the month and save the page with CTRL+S   
 * Use with Firefox - Mozilla Foundation  
 *  
 * @author: Fabrice Morisseau  
 * @version: 6.0  
 * @date: March 20, 2016  
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org
 **/  

 
 /**  
 *  
 * load_menu: Load the menu  
 *  
 **/  
 function load_menu() {  
 document.getElementById("menu_top").innerHTML = "";  
 }  
 /**  
 *  
 * add_div: Generate timestamp of the div  
 *  
 **/  
 function add_div() {  
 var today = new Date();  
 var y = today.getFullYear();  
 var M = today.getMonth()+1;  
 var d = today.getDate();  
 var h = today.getHours();  
 var m = today.getMinutes();  
 var s = today.getSeconds();  
 return "" + y + M + d + h + m + s;   
 }  
 /**  
 *  
 * model: Matrix Reloaded Core Engine repository  
 *  
 **/  
 function model() {  
 this.model = {};  
 this.add = function (prettyname,form) {  
 this.model[prettyname] = form;  
 }  
 this.get = function (prettyname) {  
 return this.model[prettyname];  
 }  
 }  
 /**  
 *  
 * form: Matrix Reloaded Core Engine form  
 *  
 **/  
 function form(prettyname) {  
 this.name = prettyname;  
 this.content = "";  
 this.set = function (content) {  
 this.content = content;  
 }  
 this.display = function() {  
 return this.content;  
 }  
 }  
 // Create timestamp  
 var item = add_div();  
 // Create Core Engine repository  
 var breeze = new model();  
 /**  
 *  
 * evolution: Add an entry to the main div  
 *  
 **/  
 function evolution() {  
 // Create Breeze Evolution Core Engine Forms   
 var main_evolution = new form("evolution");  
 main_evolution.set("<div id='item" + item + "' class='item" + item + "'></br></br><h2><div id='date" + item + "' class='date" + item + "'>" + document.getElementById('date').value + "</div></h2></br><div id='entry" + item + "' class='entry" + item + "'>" + document.getElementById('entry').value + "</div> <a href=javascript:update_item('"+ item +"');><img src='css/icon_edit.png' border='0'></a> <a href=javascript:delete_item('"+ item +"');><img src='css/icon_delete.png' border='0' height='18px'></a></div>");  
 // Add Breeze Evolution Core Engine Forms to Core Engine repository  
 breeze.add("evolution",main_evolution);   
 var main = document.getElementById('main').innerHTML;  
 var str = breeze.get("evolution").display();  
 while (str.search("\n") != -1)  
  str = str.replace("\n","<br>");  
 document.getElementById('main').innerHTML = str + main;  
 clear_passwd();  
 }  
 /**  
 *  
 * editor_display: Display Editor  
 *  
 **/  
 function editor_display() {  
 if (check_passwd())  
 document.getElementById("editor").innerHTML = "<br><input value='' class='date' id='date' type='text'><br><textarea value='' class='entry' id='entry' cols='60' rows='10'></textarea>&nbsp;<input name='Valid' value='Valid' onclick='javascript:evolution();return false;' type='button'>";  
 else  
 document.getElementById("editor").innerHTML = "You must set the password first";  
 }  
 /**  
 *  
 * editor_close: Close Editor  
 *  
 **/  
 function editor_close() {  
 document.getElementById("editor").innerHTML = "";  
 }  
 /**  
 *  
 * update_item: Change the entry displayer from text to update  
 *  
 * @param item: timestamp of the entry  
 *  
 **/  
 function update_item(item) {  
 if (check_passwd()) {  
 var date = document.getElementById('date' + item).innerHTML;  
 var entry = document.getElementById('entry' + item).innerHTML;  
 while (entry.search("\n") != -1)  
  entry = entry.replace("\n","");  
 while (entry.search("<br>") != -1)  
  entry = entry.replace("<br>","\n");  
 document.getElementById('date' + item).innerHTML = "<input value='" + date + "' class=update_date" + item + " id=update_date" + item + " type=text>";  
 document.getElementById('entry' + item).innerHTML = "<textarea class=update_entry" + item + " id=update_entry" + item + " cols=60 rows=10>" + entry + "</textarea>&nbsp;<input name=valid_update value=Valid onclick=javascript:valid_update('" + item + "');return false; type=button>";  
 }  
 }  
 /**  
 *  
 * valide_update: Update the entry of the main div  
 *  
 * @param item: timestamp of the entry  
 *  
 **/  
 function valid_update(item) {  
 var date = document.getElementById('update_date' + item).value;  
 var entry = document.getElementById('update_entry' + item).value;  
 while (entry.search("\n") != -1)  
  entry = entry.replace("\n","<br>");  
 document.getElementById('date' + item).innerHTML = date;  
 document.getElementById('entry' + item).innerHTML = entry;  
 clear_passwd();  
 }  
 /**  
 *  
 * delete_item: Delete an entry of the main div  
 *  
 * @param item: timestamp of the entry  
 *  
 **/  
 function delete_item(item) {  
 if (check_passwd())  
 document.getElementById('item' + item).innerHTML = "";  
 clear_passwd();  
 }  
 /**  
 *  
 * start_time: Display time every 10000ms  
 *  
 **/  
 function start_time() {  
   var today=new Date();  
   var h=today.getHours();  
   var m=today.getMinutes();  
   m = check_time(m);  
   document.getElementById('clock').innerHTML = "<center>"+h+":"+m+"</center>";  
   var t = setTimeout(function(){start_time()},10000);  
 }  
 /**  
 *  
 * check_time: Add zero in front of numbers if < 10  
 *  
 * @param i: Minutes  
 *  
 **/  
 function check_time(i) {  
   if (i<10) {i = "0" + i}; // add zero in front of numbers < 10  
   return i;  
 }  
 /**  
 *  
 * update_menu: Change the menu displayer from text to update  
 *  
 **/  
 function update_menu() {  
 var menu = document.getElementById('menu').innerHTML;  
 if (check_passwd())  
 document.getElementById('menu').innerHTML = "<textarea class=entry_menu id=entry_menu cols=50 rows=5>" + menu + "</textarea>&nbsp;<input name=valid_menu value=Valid onclick=javascript:valid_menu();return false; type=button>";  
 }  
 /**  
 *  
 * valide_menu: Update the entry of the menu  
 *  
 **/  
 function valid_menu() {  
 var menu = document.getElementById('entry_menu').value;  
 document.getElementById('menu').innerHTML = menu;  
 clear_passwd();  
 }  
 /**  
 *  
 * update_about: Change the about displayer from text to update  
 *  
 **/  
 function update_about() {  
 var about = document.getElementById('about').innerHTML;  
 if (check_passwd())  
 document.getElementById('about').innerHTML = "<textarea class=entry_about id=entry_about cols=50 rows=5>" + about + "</textarea>&nbsp;<input name=valid_about value=Valid onclick=javascript:valid_about();return false; type=button>";  
 }  
 /**  
 *  
 * valide_about: Update the entry of the about  
 *  
 **/  
 function valid_about() {  
 var about = document.getElementById('entry_about').value;  
 document.getElementById('about').innerHTML = about;  
 clear_passwd();  
 }  
 /**  
 *  
 * clear_passwd: Clear password hidden input  
 *  
 **/  
 function clear_passwd() {  
 document.getElementById('set_password_value').value = "";  
 }  
 /**  
 *  
 * check_passwd: check password hidden input  
 *  
 **/  
 function check_passwd() {  
 var str = document.getElementById('set_password_value').value;   
 if (str.hashCode() == "-1025043652")   
  return true;  
 else  
  return false;  
 }  
 /**  
 *  
 * hashCode: return hashCode of any String  
 *  
 **/  
 String.prototype.hashCode = function(){  
 var hash = 0;  
 if (this.length == 0) return hash;  
 for (i = 0; i < this.length; i++) {  
 char = this.charCodeAt(i);  
 hash = ((hash<<5)-hash)+char;  
 hash = hash & hash;   
 }  
 return hash;  
 }  



Monday, January 18, 2016

Linux Mint 17.3 Rosa

I just installed Linux Mint 17.3 Rosa and it works really well. Congratulation to the team behind this fantastic desktop. Most of the internet uses Linux and open source software. From freedom comes elegance says Linux Mint when you Login. Just think about the engineers working for Alsthom and the wonderful TGV. They are proud of their achievement. Isn't it ? It should be the same for the contributors of open source projects. They made the internet that billion of people use everyday.

I belong to the old school so I don't use an IDE for Web Development. Instead, I edit all my files with gedit and write native javascript, css or html. Everybody know how to use a browser nowdays. Web Development is different than Linux Mint Software Engineering. I work by progressive enhancement for development while a Software Engineer has to follow much more project management constraints.

Sunday, July 26, 2015

Amazon Web Services

You now know that you need to strike the right balance between a single page application relying on your client and a dynamic server side. The last stone of your architecture will be to deploy your software on the machines. The easiest way will be to use Amazon Web Services.

  1. Install a LAMP Server
  2. Transfer your software solution on the newly created production environment
  3. Install the RDS (Database)
  4. Create an image of your environment
  5. Configure the scalability (load balancing) of your solution
You now have a small, medium or big web application available on the internet.

Php is an easy solution to start programming on the internet without the constraints of projects development

Thursday, May 21, 2015

Basic RESTFul/json API

Web Development is constraint by frequent evolutions so that you need to rewrite the whole or part of a software every 5 to 10 years. The Dynamic Web Application was a server side MVC but it's clear today that we are also moving to client side Single Page Application MVC with libraries like AngularJS. Google may not be welcome in China but I need to follow latest technology innovation. I made a new Kernel with a very basic web application in Ajax using a RESTFul/json API written in PHP.

The Kernel analyses the request and exec the endpoint

 <?php  
 /**  
  * rest.class.php  
  * author : Fabrice Morisseau  
  * creation date : April 9, 2015  
  **/ 

 abstract class rest  
 {  
   /**  
    * Property: method  
    */  
   protected $method = '';  
   /**  
    * Property: endpoint  
    */  
   protected $endpoint = '';  
   /**  
    * Property: action  
    */  
   protected $action = '';  
   /**  
    * Property: config  
    */  
   protected $config = Array();  
   /**  
    * Constructor: __construct  
    */  
   public function __construct($request) {  
     header("Content-Type: application/json");  
     $this->config = explode('/', rtrim($request, '/'));  
     $this->endpoint = $this->config[0];  
     $this->action = $this->config[1];  
     $this->method = $_SERVER['REQUEST_METHOD'];  
   }  
   public function exec() {  
     if ((int)method_exists($this, $this->endpoint) > 0) {  
       header("HTTP/1.1 200 OK");  
       $data = $this->{$this->endpoint}($this->config);  
     } else {  
       header("HTTP/1.1 404 Not Found");  
       $data = "The endpoint doesn't exist";  
     }  
     return json_encode($data);  
   }  
 }  
 ?>  

Obviously the endpoint are stored in the API which call the Kernel


 <?php  
 /**  
  * MyAPI.php 
  * author : Fabrice Morisseau  
  * creation date : April 9, 2015  
  **/   
 require_once '../../kernel/rest.class.php';  
 class MyAPI extends rest  
 {  
   protected $request;  
   public function __construct($request) {  
     parent::__construct($request);  
     $this->request = $request;  
   }  
   /**  
    * Endpoint Document  
    * Todo : Eval phpfile for documentation  
    */  
   protected function document() {  
    /**
     * Example of endpoint return $content of the document
     **/   
   }  
 }
       
 try {  
   $API = new MyAPI($_REQUEST['request']);  
   echo $API->exec();  
 } catch (Exception $e) {  
   echo json_encode(Array('error' => $e->getMessage()));  
 }  
 ?>  


while the .htaccess route the requests to the API

 <IfModule mod_rewrite.c>  
 RewriteEngine On  
 RewriteCond %{REQUEST_FILENAME} !-f  
 RewriteCond %{REQUEST_FILENAME} !-d  
 RewriteRule api/v1/(.*)$ api/v1/MyAPI.php?request=$1 [QSA,NC,L]  
 </IfModule>  


We are done with latest technology innovations and my prototype has been totally rewritten.

The Object Relational Bridge is no longer used because modelization is not flexible so that you can realize complex things but details and specific queries also matter. Modelization looks like Artificial Intelligence and the Alchemist dream moreover according to this study by the French national center in scientific research CNRS there are numerous security issues with a dynamic system. It seems better to access your data on-demand with strict security checks.

Single Page Application loads only one page while the server generates all the html code with a dynamic web application. Among the important things to notice as mentioned on wikipedia SPA are Search Engine Optimization in the case of this RESTFul/json API and Browser History as well as navigation. Those issues are critical when designing your application. Your application should have an important core generated on the server and optimized for search engine as well as on demand requests accessible with this RESTFul/json API.

Friday, March 27, 2015

Dynamic Web Application - Part 3

The last post of Dynamic Web Application will show the implementation of the ORB within the index page. There are two things to take into account : Actions and Forms
The actions will do the CRUD operations based on your Request via the Criteria knowing that they have been setup with your displayers.


 switch ($action) {  
  case "delete" :  
   if($security->isAdmin())  
    $message = $helper->doDelete($security);   
   $sql_row = $helper->redirectTo($helper->getWebhome());  
   break;  
  case "update" :        
   $message = $helper->doUpdate($security);  
   $sql_row = $helper->getPageFromId();  
   break;  
  case "insert" :  
   $message = $helper->doInsert($security);  
   $sql_row = $helper->redirectTo($_REQUEST['bin_document_name']);        
   break;  
  case "redirect" :  
   $sql_row = $helper->redirectTo($_REQUEST['redirect']);  
   break;  
  default :  
   $sql_row = $helper->getPageFromRequest();        
 }  
 if ($action != "edit")     
    $action = "view";  

meanwhile your displayers can switch in various mode


 switch ($action) {  
   case "edit" :  
    echo $fields['content']->displayEdit ($table, $sql_row, $inline_model_class,"bin");  
    echo "\n  <div class=\"comment\">\n" . $fields['content']->getWikiHelp() . "  </div>\n";  
    break;  
   default :  
    echo $fields['content']->displayView ($table, $sql_row, $inline_model_class,"bin");  

Saturday, March 21, 2015

Dynamic Web Application - Part 2

After a brief introduction to the nature of a dynamic software most commonly named "Backend" based on the ORB, we will unleash the power of the backend with the Criteria. When you need information, you will access the database with the Criteria in the following way

 function getPageFromRequest() {  
   $criteria = new Criteria();  
   $sql_connect = $this->inline_model_class->connect();   
   $criteria->fromRequestWithPrefix($this->inline_model_class,"bin");  
   $criteria->setAllColumns('document',$this->inline_model_class);  
   if ($criteria->isRequest()) {  
    $sql_result = mysql_query($this->table->doSearch($criteria,$this->inline_model_class),   
                    $sql_connect);  
    $sql_row = mysql_fetch_assoc($sql_result);  
    return $sql_row;  
   } else  
    return $false;  
  }  

Obviously, Request contains expected fields previously setup with your displayers which produces a cycle between your Request and the previous Request. In another word, this is how you program the synchronization of your system. The dynamic system is the opposite to a stateless RESTful API. For your information, the function fromRequest can configure the whole SQL Request.
  /**  
   *  function set Criteria with Http Request values.  
   *  
   *  @param object      dbmodel  
   *  @param string      prefix  
   **/   
  function fromRequestWithPrefix($model_class,$prefix) {  
   if ($prefix != "")  
    $prefix .= "_";  
   // GET Search Criteria  
   $tables_array = $model_class->getTables();  
   foreach ($tables_array as $table_name => $table_class) {  
    $fields_array = $table_class->getFields();  
    foreach ($fields_array as $field_name => $field_class) {  
      $field_string = $table_class->getPrettyName() . "_" . $field_class->getPrettyName();   
      $prefix_field_string = $prefix . $field_string;  
      if ($_GET[$prefix_field_string]) {  
       $this->add ($field_string,$_GET[$prefix_field_string]);  
      $this->isRequest = true;  
     }  
      if ($_POST[$prefix_field_string]) {  
       $this->add ($field_string,$_POST[$prefix_field_string]);  
      $this->isRequest = true;   
     }  
      $field_types = $field_class->getTypes ();  
      foreach ($field_types as $type) {  
       if ($_GET[$prefix_field_string . "_" . $type]) {  
        $this->add ($field_string . "_" . $type,$_GET[$prefix_field_string . "_" . $type]);  
       $this->isRequest = true;  
      }  
       if ($_POST[$prefix_field_string . "_" . $type]) {  
        $this->add ($field_string . "_" . $type,$_POST[$prefix_field_string . "_" . $type]);  
       $this->isRequest = true;  
      }  
      }  
    }  
   }  
   // GET COLUMNS FROM REQUEST   
   if (isset($_GET[$prefix . 'search_columns']))  
    $this->setColumns ($_GET[$prefix . 'search_columns']);  
   if (isset($_POST[$prefix . 'search_columns']))  
    $this->setColumns ($_POST[$prefix . 'search_columns']);  
   if (isset($_GET[$prefix . 'search_columns_multiple']) || isset($_POST[$prefix . 'search_columns_multiple'])) {  
    if (isset($_GET[$prefix . 'search_columns_multiple']))  
      $str_search_columns = $_GET[$prefix . 'search_columns_multiple'];  
    if (isset($_POST[$prefix . 'search_columns_multiple']))  
      $str_search_columns = $_POST[$prefix . 'search_columns_multiple'];  
    $search_column_array = preg_split("/;/",$str_search_columns);  
    $count = 0;  
    foreach ($search_column_array as $search_column) {  
      $search_columns_multiple[$count] = $search_column;  
      $count++;  
    }  
    $this->setColumns ($search_columns_multiple);  
   }  
   //GET SEARCH FIELD : Use for default displayer  
   if (isset($_GET[$prefix . 'search_fields']) || isset($_POST[$prefix . 'search_fields'])) {  
    if (isset($_GET[$prefix . 'search_fields']))  
      $str_search_fields = $_GET[$prefix . 'search_fields'];  
    if (isset($_POST[$prefix . 'search_fields']))  
      $str_search_fields = $_POST[$prefix . 'search_fields'];  
    $search_field_array = preg_split("/;/",$str_search_fields);  
    $count = 0;  
    foreach ($search_field_array as $search_field) {  
      $search_fields[$count] = $search_field;  
      $count++;  
    }  
    $this->setSearchFields ($search_fields);  
   }  
   // GET JOIN FIELDS CONFIGURATION : Use for default displayer  
   $count = 0;  
   foreach ($tables_array as $table_name => $table_class) {  
    $join_fields_array = $table_class->getJoinFields();  
    if ($join_fields_array) {  
      foreach ($join_fields_array as $join_field) {  
       if (isset ($_GET[$prefix . $join_field['name'] . "_join"]) || isset ($_POST[$prefix . $join_field['name'] . "_join"])) {  
        if (($_GET[$prefix . $join_field['name'] . "_join"] != 0)|| ($_POST[$prefix . $join_field['name'] . "_join"] != 0)) {  
         $join_fields[$count] = $table_name . "_" . $join_field['name'];  
         $count++;  
        }  
       }  
      }  
    }  
   }  
   $this->join_fields = $join_fields;  
   //GET START ROW  
   if (isset($_GET[$prefix . 'start_row']))  
    $this->setStartRow ($_GET[$prefix . 'start_row']);  
   if (isset($_POST[$prefix . 'start_row']))  
    $this->setStartRow ($_POST[$prefix . 'start_row']);  
   //GET NB ROWS  
   if (isset($_GET[$prefix . 'nb_rows']))  
    $this->setNbRows ($_GET[$prefix . 'nb_rows']);  
   if (isset($_POST[$prefix . 'nb_rows']))  
    $this->setNbRows ($_POST[$prefix . 'nb_rows']);  
   //Get Orders  
   if (isset($_GET[$prefix . 'order']))  
    $this->setOrder ($_GET[$prefix . 'order']);  
   if (isset($_POST[$prefix . 'order']))  
    $this->setOrder ($_POST[$prefix .'order']);  
  }  

Thursday, February 28, 2013

Dynamic Web Application

You can easily build a web application with an Object Relational Bridge (O.R.B). The O.R.B should handle the connection and transformation of data to/from the database SQL queries, the request from the web server HTTP Request querystring and display data from the O.R.B with displayers. I started a prototype in php back in 2004.

The Relational language SQL looks like

 select DOC_CONTENT from DOCUMENT_EN;  

it's better to generate the query with an O.R.B and object model such as

 // Main Database  
 $en = new DBModel("en","en");  
 $en->setConnection ($GLOBALS['config_class']->getProperty('en.server'),  
               $GLOBALS['config_class']->getProperty('en.user'),  
               $GLOBALS['config_class']->getProperty('en.password'),  
               $GLOBALS['config_class']->getProperty('en.db'));  
 // Document Table  
 $status = array (1=>"Draft",2=>"Publish",3=>"Archive");  
 $document = new DBTable("document","DOCUMENT_EN");  
 $document->addField ("id", new DBNumberKeyField ("id","DOC_ID",true));  
 $document->addField ("name", new DBTextField ("name","DOC_NAME",true));  
 $document->addField ("subject", new DBTextField ("subject","DOC_SUBJECT",true));  
 $document->addField ("content", new DBWikiField ("content","DOC_CONTENT",true));  
 $document->addField ("status", new DBStaticListField ("status","DOC_STATUS",$status,true));  
 $document->addField ("owner", new DBListField ("owner","DOC_OWNER","SELECT USR_ID as id, USR_FULLNAME as label FROM USER_EN",true));  
 $document->addField ("modifier", new DBListField ("modifier","DOC_MODIFIER","SELECT USR_ID as id, USR_FULLNAME as label FROM USER_EN",true));
 $document->addField ("creationdate",new DBDateField ("creationdate","DOC_CREATION_DATE",true));  
 $date_field = new DBDateField ("modificationdate","DOC_MODIFICATION_DATE",true);  
 $date_field->setValue (date ("Y-m-d H:i:s"));  
 $document->addField ("modificationdate",$date_field);  
 $document->setColumns(array("document_id","document_subject","document_status","document_owner"));  
 $document->addJoinField ("documentuser","id","did");  
 $document->addJoinField ("documentgroup","id","did");  
 ...  
 $en->addTable("document",$document);  


Obviously, you need an index page to access the web application. This index page will only use the O.R.B to handle the request and display the information or actions. Everything related to the website will be data of the O.R.B: css, menu, header, footer, plugins and pages content which means that once you have made the O.R.B, you never update the source code but you interact with it. An example is the recent changes plugin use by the web application. The plugin is a wiki page which contains runtime php code store in the database and call by the DbWikiField of the O.R.B when asked by another page.

The innovation is the DbWikiField

 

 require_once("db/dbtextfield.php");  
 require_once("util/wiki2xhtml.php");  
 require_once("db/dbcriteria.php");  
 include "plugins/TablePlugin.php";  

...

 /**  
  * CALLBACK FUNCTIONS  
  **/   
 /**  
  *  function eval php code within a wiki page  
  *  
  *  @param string      Php Code  
  **/    
 function eval_buffer($string) {  
   ob_start();  
   eval("$string[2];");  
   $ret = ob_get_contents();  
   ob_end_clean();  
   return $ret;  
 }   

...

class DBWikiField extends DBTextField 
  
  ...  
  

  function displayView ($table,$sql_row,$model,$prefix) {  
   $in = $this->get($table,$sql_row);  
   if ($this->simplified == false) {  
    $in = preg_replace_callback("/(<\?source)(.*?)source\?>/si","eval_phptag",$in);  
    $in = preg_replace_callback("/(<\?\s)(.*?)\s\?>/si","eval_buffer",$in);   
    $in = preg_replace_callback("/(<\?macro\s)(.*?)\smacro\?>/si","eval_buffer",$in);  
    $in = preg_replace_callback("/(<\?table)(.*?)table\?>/si","eval_table",$in);  
    if (preg_match('/(.*)(<no_wiki_parsing>)(.*)/',$in)) {  
     $in = preg_replace_callback("/(<no_wiki_parsing>)/si","eval_removetag",$in);   
     $this->setWikiParsing(false);  
    }  
   }  
   if ($this->wiki_parsing == true) {   
    $in = $this->wiki->transform($in);  
   }  
   if ($this->simplified == false) {  
    $in = preg_replace_callback("/(<plugin_)(.*?)>/si","eval_phpplugin",$in); # Parse plugin  
    $in = preg_replace_callback("/(<source_)(.*?)>/si","eval_phpsource",$in); # ADD BY <?source  
    $in = preg_replace_callback("/(<filesource_)(.*?)>/si","eval_phpfilesource",$in); # Parse Highlight from file  
    $in = preg_replace_callback("/(<plugindoc_)(.*?)>/si","eval_phpplugindoc",$in); # Parse Highlight from file  
   }  
   return $in;   
  }  


The DbWikiField constraints are in what we call a SandBox (See wikipedia Sandbox) because you can put programmable content in the field. A sandbox limits the programming right of a user. For example, Javascript client which runs on your computer when you surf the internet with your browser is a Sandbox. It's a limited language so that nothing really bad happens to the end user against his own will. I didn't implement a sandbox for this prototype. The Sandbox limits Global scopes in your programs for obvious safety and security reasons meanwhile the O.R.B ensures the addressing of the diversity of your production database.

For the database, you need to consider a Star Schema Database because your ORB can automatically link tables to build the queries without loops (There is only one way from one table to another in a star schema database). You can read this white paper from Craig Utley which put forward another advantage of Star Schema Database for large volume of data in read only mode and aggregated data.

Related Link
- Apache Torque