]> Kevux Git Server - koopa/commitdiff
Progress: continuing development, adding examples and example program: reservation
authorKevin Day <thekevinday@gmail.com>
Sat, 18 Feb 2017 22:41:18 +0000 (16:41 -0600)
committerKevin Day <thekevinday@gmail.com>
Sat, 18 Feb 2017 22:41:18 +0000 (16:41 -0600)
For the sake of functionality and time, I implemented a straight-forward HTML class.
I will come back later to work on CML that will be an attempt to separate the context from the content, even in the code.

There is a (currently) experimental program called reservation.
This is a reservation/scheduling system that is currently under design and will be used as a functional example for using this site.
It currently requires LDAP and a few other custom/experimental software that is to follow.
The sql code is postgresql-specific.

Other examples are included in the example direction.

There are some theme files that I am probably not going to use and may remove in the future.

30 files changed:
common/base/classes/base_cml.php [new file with mode: 0644]
common/base/classes/base_cookie.php
common/base/classes/base_database.php
common/base/classes/base_form.php [deleted file]
common/base/classes/base_html.php
common/base/classes/base_http.php
common/base/classes/base_markup.php
common/base/classes/base_mime.php
common/base/classes/base_return.php
common/base/classes/base_session.php
common/theme/classes/theme_form.php
common/theme/classes/theme_html.php
database/sql/reservation/base-cache.sql [new file with mode: 0644]
database/sql/reservation/base-content.sql [new file with mode: 0644]
database/sql/reservation/base-content_type.sql [new file with mode: 0644]
database/sql/reservation/base-first.sql [new file with mode: 0644]
database/sql/reservation/base-logs.sql [new file with mode: 0644]
database/sql/reservation/base-main.sql [new file with mode: 0644]
database/sql/reservation/base-paths.sql [new file with mode: 0644]
database/sql/reservation/base-statistics.sql [new file with mode: 0644]
database/sql/reservation/base-structure.sql [new file with mode: 0644]
database/sql/reservation/base-users.sql [new file with mode: 0644]
documentation/requirements.txt
examples/generate_uuid.php [new file with mode: 0644]
examples/http.php [new file with mode: 0644]
program/reservation/index.php [new file with mode: 0644]
program/reservation/reservation_database.php [new file with mode: 0644]
program/reservation/reservation_paths.php [new file with mode: 0644]
program/reservation/reservation_response.php [new file with mode: 0644]
program/reservation/reservation_session.php [new file with mode: 0644]

diff --git a/common/base/classes/base_cml.php b/common/base/classes/base_cml.php
new file mode 100644 (file)
index 0000000..81ed671
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/**
+ * @file
+ * Provides a class for managing Context Markup Language.
+ *
+ * Context markup language is an attempt to improve and remove all context from HTML5 and related languages.
+ * This requires a different approach which is currently under the brainstorimg/development stages.
+ *
+ * @todo: implement this.
+ *
+ * @see: https://www.w3.org/TR/html5/
+ */
+
+// include required files.
+require_once('common/base/classes/base_error.php');
+require_once('common/base/classes/base_return.php');
+require_once('common/base/classes/base_markup.php');
index 8cd55b79f777a61350ad20c22e009f9da5e9d8fd..f1d0e2017a450cc1413f7a4148af697873d47b0c 100644 (file)
@@ -32,7 +32,7 @@ class c_base_cookie extends c_base_return_array {
   private $domain;
   private $http_only;
   private $first_only;
-  private $value;
+  private $data;
 
 
   /**
@@ -47,7 +47,7 @@ class c_base_cookie extends c_base_return_array {
     $this->domain = NULL;
     $this->http_only = FALSE;
     $this->first_only = TRUE;
-    $this->value = array();
+    $this->data = array();
 
     $this->p_set_lifetime_default();
 
@@ -66,7 +66,7 @@ class c_base_cookie extends c_base_return_array {
     unset($this->domain);
     unset($this->http_only);
     unset($this->first_only);
-    unset($this->value);
+    unset($this->data);
 
     parent::__destruct();
   }
@@ -420,165 +420,41 @@ class c_base_cookie extends c_base_return_array {
   }
 
   /**
-   * Assign the value.
+   * Assign the data.
    *
    * Cookies values associated with this class are only stored as an array.
    * Be sure to wrap your values in an array.
    * The array key 'checksum' will be created if one does not already exist when building the cookie.
    *
-   * This overrides the parent class function of set_value().
-   * Expect return values to be of the form c_base_return_*.
-   *
-   * @param array $value
+   * @param array $data
    *   Any value so long as it is an array.
    *   NULL is not allowed.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
    */
-  public function set_value($value) {
-    if (!is_array($value)) {
+  public function set_data($data) {
+    if (!is_array($data)) {
       return c_base_return_error::s_false();
     }
 
-    $this->value = $value;
+    $this->data = $data;
     return new c_base_return_true();
   }
 
   /**
-   * Return the value.
-   *
-   * This overrides the parent class function of set_value().
-   * Expect return values to be of the form c_base_return_*.
+   * Return the data.
    *
-   * @return c_base_return_array $value
+   * @return c_base_return_array $data
    *   The value array stored within this class.
    *   NULL may be returned if there is no defined valid array.
    */
-  public function get_value() {
-    if (!is_null($this->value) && !is_array($this->value)) {
-      $this->value = array();
-    }
-
-    return c_base_return_array::s_new($this->value);
-  }
-
-  /**
-   * Return the value of the expected type.
-   *
-   * @return array $value
-   *   The value array stored within this class.
-   */
-  public function get_value_exact() {
-    // the value should not be changed into c_base_return_array because 'exact' should consistently mean 'exact'.
-    return parent::get_value_exact();
-  }
-
-  /**
-   * Return the value at a specific index in the array.
-   *
-   * This overrides the parent class function.
-   * Expect return values to be of the form c_base_return_*.
-   *
-   * @param string|null $key
-   *   A specific array key to load.
-   * @param string|null $type
-   *   (optional) Perform sanity checking of return value based on a known type.
-   *
-   *   If not provided, then a 'raw' type of c_base_return_value is returned.
-   *   - This may contain things like a normal PHP TRUE or FALSE.
-   *
-   *   Supported known types:
-   *     'bool': a boolean value, returns c_base_return_value.
-   *     'int': an integer value, returns c_base_return_int.
-   *     'float': a float value, returns c_base_return_float.
-   *     'string': a string value, return c_base_return_string.
-   *     'array': an array value, return c_base_return_array.
-   *     'object': an object value, return c_base_return_object.
-   *     'resource': a generic resource value, return c_base_return_resource.
-   *     'stream': a stream resource value, return c_base_return_stream.
-   *     'socket': a socket resource value, return c_base_return_socket.
-   *     'null': a NULL value, return c_base_return_value.
-   *
-   * @return c_base_return_status|c_base_return_value
-   *   A c_base_return_array is returned when no $key is defined.
-   *   A c_base_return_value, or more specific, is returned if $type is provided for known types.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_value_at($key, $type = NULL) {
-    if (!is_string($key) || empty($key)) {
-      return c_base_return_error::s_false();
-    }
-
-    // if type is supplied, it must be string.
-    if (!is_null($type) && (!is_string($type) || empty($type))) {
-      return c_base_return_error::s_false();
-    }
-
-    if (!is_array($this->value)) {
-      $this->value = array();
-    }
-
-    if (!array_key_exists($key, $this->value)) {
-      return c_base_return_error::s_false();
-    }
-
-    if (!is_null($type)) {
-      if ($type == 'bool') {
-        if (is_bool($this->value[$key])) {
-          return c_base_return_bool::s_new($this->value[$key]);
-        }
-      }
-      elseif ($type == 'int') {
-        if (is_int($this->value[$key])) {
-          return c_base_return_int::s_new($this->value[$key]);
-        }
-      }
-      elseif ($type == 'float') {
-        if (is_float($this->value[$key])) {
-          return c_base_return_float::s_new($this->value[$key]);
-        }
-      }
-      elseif ($type == 'string') {
-        if (is_string($this->value[$key])) {
-          return c_base_return_string::s_new($this->value[$key]);
-        }
-      }
-      elseif ($type == 'array') {
-        if (is_array($this->value[$key])) {
-          return c_base_return_array::s_new($this->value[$key]);
-        }
-      }
-      elseif ($type == 'object') {
-        if (is_object($this->value[$key])) {
-          return c_base_return_object::s_new($this->value[$key]);
-        }
-      }
-      elseif ($type == 'resource') {
-        if (is_resource($this->value[$key])) {
-          return c_base_return_resource::s_new($this->value[$key]);
-        }
-      }
-      elseif ($type == 'stream') {
-        if (is_stream($this->value[$key])) {
-          return c_base_return_stream::s_new($this->value[$key]);
-        }
-      }
-      elseif ($type == 'socket') {
-        if (is_socket($this->value[$key])) {
-          return c_base_return_socket::s_new($this->value[$key]);
-        }
-      }
-      elseif ($type == 'null') {
-        if (is_null($this->value[$key])) {
-          return c_base_return_value::s_new($this->value[$key]);
-        }
-      }
-
-      return c_base_return_error::s_false();
+  public function get_data() {
+    if (!is_null($this->data) && !is_array($this->data)) {
+      $this->data = array();
     }
 
-    return c_base_return_value::s_new($this->value[$key]);
+    return c_base_return_array::s_new($this->data);
   }
 
   /**
@@ -606,32 +482,32 @@ class c_base_cookie extends c_base_return_array {
    * @see: header()
    */
   public function do_push($checksum = TRUE) {
-    if (is_null($this->name) || is_null($this->value)) {
-      c_base_return_error::s_false();
+    if (is_null($this->name) || is_null($this->data)) {
+      return c_base_return_error::s_false();
     }
 
     if ($checksum) {
-      unset($this->value['checksum']);
-      $this->value['checksum'] = $this->p_build_checksum();
+      unset($this->data['checksum']);
+      $this->data['checksum'] = $this->p_build_checksum();
 
-      if (is_null($this->value['checksum'])) {
-        unset($this->value['checksum']);
+      if (is_null($this->data['checksum'])) {
+        unset($this->data['checksum']);
         return c_base_return_error::s_false();
       }
     }
 
     // @todo: consider adding support for assigning the json depth setting.
-    $json = json_encode($this->value);
+    $json = json_encode($this->data);
     if ($json === FALSE) {
       unset($json);
       return c_base_return_error::s_false();
     }
 
-    $value = rawurlencode(preg_replace('/(^\s+)|(\s+$)/us', '', $json));
+    $data = rawurlencode(preg_replace('/(^\s+)|(\s+$)/us', '', $json));
     unset($json);
 
-    //$result = setrawcookie($this->name, $value, $this->max_age, $this->path, $this->domain, $this->secure, $this->http_only);
-    $cookie = 'Set-Cookie: ' . rawurlencode($this->name) . '=' . $value . ';';
+    //$result = setrawcookie($this->name, $data, $this->max_age, $this->path, $this->domain, $this->secure, $this->http_only);
+    $cookie = 'Set-Cookie: ' . rawurlencode($this->name) . '=' . $data . ';';
 
     if (!is_null($this->domain)) {
       $cookie .= ' domain=' . $this->domain . ';';
@@ -669,7 +545,7 @@ class c_base_cookie extends c_base_return_array {
     header($cookie, FALSE);
 
     unset($cookie);
-    unset($value);
+    unset($data);
 
     return new c_base_return_true();
   }
@@ -706,7 +582,7 @@ class c_base_cookie extends c_base_return_array {
    * Retrieve the cookie from the HTTP headers sent by the client.
    *
    * This class object will be populated with the cookies settings.
-   * The cookie value will be cleared if the cookie exists.
+   * The cookie data will be cleared if the cookie exists.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
@@ -719,15 +595,15 @@ class c_base_cookie extends c_base_return_array {
     }
 
     $json = rawurldecode($_COOKIE[$this->name]);
-    $value = json_decode($json, TRUE);
+    $data = json_decode($json, TRUE);
     unset($json);
 
-    if ($value === FALSE) {
+    if ($data === FALSE) {
       return c_base_return_error::s_false();
     }
 
-    $this->value = $value;
-    unset($value);
+    $this->data = $data;
+    unset($data);
 
     return new c_base_return_true();
   }
@@ -750,7 +626,7 @@ class c_base_cookie extends c_base_return_array {
    *
    * This is only meaningful when called after self::do_pull() is used.
    *
-   * If a checksum key exists, will validate that the contents of the value are consistent with the checksum.
+   * If a checksum key exists, will validate that the contents of the data are consistent with the checksum.
    * This is useful to protect data from alterations, be it defect or accident.
    * This does not protect against malicious activities because the malicious user could simply regenerate the checksum after their changes.
    *
@@ -759,16 +635,16 @@ class c_base_cookie extends c_base_return_array {
    *   On error FALSE is returned with the error bit set.
    */
   public function validate() {
-    if (!is_array($this->value)) {
+    if (!is_array($this->data)) {
       return c_base_return_error::s_false();
     }
 
-    if (!array_key_exists('checksum', $this->value)) {
+    if (!array_key_exists('checksum', $this->data)) {
       return new c_base_return_false();
     }
 
     $checksum = $this->p_build_checksum();
-    if ($this->value['checksum'] == $checksum) {
+    if ($this->data['checksum'] == $checksum) {
       unset($checksum);
       return new c_base_return_true();
     }
@@ -778,7 +654,7 @@ class c_base_cookie extends c_base_return_array {
   }
 
   /**
-   * Builds a checksum of the value array.
+   * Builds a checksum of the data array.
    *
    * This does not assign the checksum to the array.
    * The checksum is only assigned by the do_push() or do_pull() functions.
@@ -799,7 +675,7 @@ class c_base_cookie extends c_base_return_array {
   }
 
   /**
-   * Generates a checksum of the value array.
+   * Generates a checksum of the data array.
    *
    * Any existing checksum key is preserved.
    *
@@ -809,21 +685,21 @@ class c_base_cookie extends c_base_return_array {
    * @see: hash()
    */
   private function p_build_checksum() {
-    if (!is_array($this->value)) {
-      $this->value = array();
+    if (!is_array($this->data)) {
+      $this->data = array();
     }
 
-    $has_checksum = array_key_exists('checksum', $this->value);
+    $has_checksum = array_key_exists('checksum', $this->data);
     $checksum = NULL;
     if ($has_checksum) {
-      $checksum = $this->value['checksum'];
-      unset($this->value['checksum']);
+      $checksum = $this->data['checksum'];
+      unset($this->data['checksum']);
     }
 
-    $json = json_encode($this->value);
+    $json = json_encode($this->data);
     if ($json === FALSE) {
       if ($has_checksum) {
-        $this->value['checksum'] = $checksum;
+        $this->data['checksum'] = $checksum;
       }
 
       unset($has_checksum);
@@ -834,7 +710,7 @@ class c_base_cookie extends c_base_return_array {
 
     $generated = hash(c_base_cookie::CHECKSUM_ALGORITHM, $json);
     if ($has_checksum) {
-      $this->value['checksum'] = $checksum;
+      $this->data['checksum'] = $checksum;
     }
 
     unset($has_checksum);
index 19360c07b657ddd7dbbe74a0f3fcf525bacbf25a..3cd2c6a9f20c0bd63d9303e44c03ab1a0ed8c46e 100644 (file)
@@ -69,7 +69,7 @@ class c_base_connection_string extends c_base_return_string {
 
     $this->error = NULL;
 
-    parent->__construct();
+    parent::__construct();
   }
 
   /**
@@ -91,7 +91,7 @@ class c_base_connection_string extends c_base_return_string {
 
     unset($this->error);
 
-    parent->__destruct();
+    parent::__destruct();
   }
 
   /**
@@ -304,7 +304,7 @@ class c_base_connection_string extends c_base_return_string {
   /**
    * Returns the password.
    *
-   * @return c_base_return_string|c_base_return_false
+   * @return c_base_return_string|c_base_return_status
    *   The password string.
    *   FALSE is returned if there is no assigned password.
    */
@@ -648,6 +648,7 @@ class c_base_database {
     }
 
     $this->connection_string = $connection_string;
+    $this->connection_string->build();
     return new c_base_return_true();
   }
 
@@ -872,7 +873,7 @@ class c_base_database {
    */
   public function is_connected() {
     if ($this->connected === TRUE && pg_connection_status($this->database) === PGSQL_CONNECTION_OK) {
-      return c_base_return_true();
+      return new c_base_return_true();
     }
 
     return new c_base_return_false();
diff --git a/common/base/classes/base_form.php b/common/base/classes/base_form.php
deleted file mode 100644 (file)
index 2f724be..0000000
+++ /dev/null
@@ -1,1494 +0,0 @@
-<?php
-/**
- * @file
- * Provides a class for managing system forms.
- *
- * This is currently a draft/brainstorm and is subject to be completely rewritten/redesigned.
- */
-
-// include required files.
-require_once('common/base/classes/base_error.php');
-require_once('common/base/classes/base_return.php');
-require_once('common/base/classes/base_mime.php');
-require_once('common/base/classes/base_http.php');
-require_once('common/base/classes/base_charset.php');
-require_once('common/base/classes/base_language.php');
-
-// use 'mutable' and have it set to FALSE for server-side only data that cannot be changed client side.
-// - drupal uses 'readonly' and 'disabled', but those are presentation specific, so they must not be used or related to 'mutable' (or in this case, unmutable).
-
-// associated form (sessions) with timestamp, ip address, and agent?
-// generate unique key and/or checksum for each form (and in http header).
-
-/**
- * A generic class for form attribute types.
- */
-class c_base_form_attributes {
-  const ATTRIBUTE_NONE                   = 0;
-  const ATTRIBUTE_ACCESS_KEY             = 1; // single letter
-  const ATTRIBUTE_ACCEPT                 = 2; // c_base_mime integer
-  const ATTRIBUTE_ACTION                 = 3; // string, URL
-  const ATTRIBUTE_ACTION                 = 4; // text
-  const ATTRIBUTE_AUTO_COMPLETE          = 5; // on or off, use TRUE/FALSE
-  const ATTRIBUTE_AUTO_FOCUS             = 6; // autofocus, use TRUE/FALSE
-  const ATTRIBUTE_CLASS                  = 7; // array of strings
-  const ATTRIBUTE_CHALLENGE              = 8; // challenge, use TRUE/FALSE
-  const ATTRIBUTE_CHARACTER_SET          = 9; // c_base_charset integer
-  const ATTRIBUTE_CHECKED                = 10; // checked, use TRUE/FALSE
-  const ATTRIBUTE_COLUMNS                = 11; // number
-  const ATTRIBUTE_CONTENT_EDITABLE       = 12; // TRUE, FALSE, INHERIT
-  const ATTRIBUTE_DIRECTION              = 13; // ltr, rtl, auto
-  const ATTRIBUTE_DIRECTION_NAME         = 14; // text, inputname.dir
-  const ATTRIBUTE_DISABLED               = 15; // disabled, use TRUE/FALSE
-  const ATTRIBUTE_ENCODING_TYPE          = 16; // c_base_mime integer
-  const ATTRIBUTE_FOR                    = 17; // text, element id
-  const ATTRIBUTE_FORM                   = 18; // text, form id
-  const ATTRIBUTE_FORM_ACTION            = 19; // text, url
-  const ATTRIBUTE_FORM_ENCODE_TYPE       = 20; // c_base_mime integer
-  const ATTRIBUTE_FORM_METHOD            = 21; // get or post, use HTTP_METHOD_GET and HTTP_METHOD_POST
-  const ATTRIBUTE_FORM_NO_VALIDATED      = 22; // formnovalidate, use TRUE/FALSE
-  const ATTRIBUTE_FORM_TARGET            = 23; // text, _blank, _self, _parent, _top, URL
-  const ATTRIBUTE_HIDDEN                 = 24; // TRUE/FALSE
-  const ATTRIBUTE_KEY_TYPE               = 25; // text, rsa, dsa, ec
-  const ATTRIBUTE_LABEL                  = 26; // text
-  const ATTRIBUTE_LANG                   = 27; // i_base_language, int
-  const ATTRIBUTE_LIST                   = 28; // text, datalist_id
-  const ATTRIBUTE_MAXIMUM                = 29; // number, date
-  const ATTRIBUTE_MAXIMUM_LENGTH         = 30; // number
-  const ATTRIBUTE_MINIMUM                = 31; // number, date
-  const ATTRIBUTE_MULTIPLE               = 32; // multiple, use TRUE/FALSE
-  const ATTRIBUTE_NAME                   = 33; // TRUE/FALSE
-  const ATTRIBUTE_NO_VALIDATE            = 34; // text
-  const ATTRIBUTE_ON_ABORT               = 35; // text
-  const ATTRIBUTE_ON_AFTER_PRINT         = 36; // text
-  const ATTRIBUTE_ON_ANIMATION_END       = 37; // text
-  const ATTRIBUTE_ON_ANIMATION_ITERATION = 38; // text
-  const ATTRIBUTE_ON_ANIMATION_start     = 39; // text
-  const ATTRIBUTE_ON_BEFORE_UNLOAD       = 40; // text
-  const ATTRIBUTE_ON_BEFORE_PRINT        = 41; // text
-  const ATTRIBUTE_ON_BLUR                = 42; // text
-  const ATTRIBUTE_ON_CLICK               = 43; // text
-  const ATTRIBUTE_ON_CONTEXT_MENU        = 44; // text
-  const ATTRIBUTE_ON_COPY                = 45; // text
-  const ATTRIBUTE_ON_CUT                 = 46; // text
-  const ATTRIBUTE_ON_CAN_PLAY            = 47; // text
-  const ATTRIBUTE_ON_CAN_PLAY_THROUGH    = 48; // text
-  const ATTRIBUTE_ON_CHANGE              = 49; // text
-  const ATTRIBUTE_ON_DOUBLE_CLICK        = 50; // text
-  const ATTRIBUTE_ON_DRAG                = 51; // text
-  const ATTRIBUTE_ON_DRAG_END            = 52; // text
-  const ATTRIBUTE_ON_DRAG_ENTER          = 53; // text
-  const ATTRIBUTE_ON_DRAG_LEAVE          = 54; // text
-  const ATTRIBUTE_ON_DRAG_OVER           = 55; // text
-  const ATTRIBUTE_ON_DRAG_START          = 56; // text
-  const ATTRIBUTE_ON_DROP                = 57; // text
-  const ATTRIBUTE_ON_DURATION_CHANGE     = 58; // text
-  const ATTRIBUTE_ON_ERROR               = 59; // text
-  const ATTRIBUTE_ON_EMPTIED             = 60; // text
-  const ATTRIBUTE_ON_ENDED               = 61; // text
-  const ATTRIBUTE_ON_ERROR               = 62; // text
-  const ATTRIBUTE_ON_FOCUS               = 63; // text
-  const ATTRIBUTE_ON_FOCUS_IN            = 64; // text
-  const ATTRIBUTE_ON_FOCUS_OUT           = 65; // text
-  const ATTRIBUTE_ON_HASH_CHANGE         = 66; // text
-  const ATTRIBUTE_ON_INPUT               = 67; // text
-  const ATTRIBUTE_ON_INVALID             = 68; // text
-  const ATTRIBUTE_ON_KEY_DOWN            = 69; // text
-  const ATTRIBUTE_ON_KEY_PRESS           = 70; // text
-  const ATTRIBUTE_ON_KEY_UP              = 71; // text
-  const ATTRIBUTE_ON_LOAD                = 72; // text
-  const ATTRIBUTE_ON_LOADED_DATA         = 73; // text
-  const ATTRIBUTE_ON_LOADED_META_DATA    = 74; // text
-  const ATTRIBUTE_ON_LOAD_START          = 75; // text
-  const ATTRIBUTE_ON_MOUSE_DOWN          = 76; // text
-  const ATTRIBUTE_ON_MOUSE_ENTER         = 77; // text
-  const ATTRIBUTE_ON_MOUSE_LEAVE         = 78; // text
-  const ATTRIBUTE_ON_MOUSE_MOVE          = 79; // text
-  const ATTRIBUTE_ON_MOUSE_OVER          = 80; // text
-  const ATTRIBUTE_ON_MOUSE_OUT           = 81; // text
-  const ATTRIBUTE_ON_MOUSE_UP            = 82; // text
-  const ATTRIBUTE_ON_MESSAGE             = 83; // text
-  const ATTRIBUTE_ON_MOUSE_WHEEL         = 84; // text
-  const ATTRIBUTE_ON_OPEN                = 85; // text
-  const ATTRIBUTE_ON_ONLINE              = 86; // text
-  const ATTRIBUTE_ON_OFFLINE             = 87; // text
-  const ATTRIBUTE_ON_PAGE_SHOW           = 88; // text
-  const ATTRIBUTE_ON_PAGE_HIDE           = 89; // text
-  const ATTRIBUTE_ON_PASTE               = 90; // text
-  const ATTRIBUTE_ON_PAUSE               = 91; // text
-  const ATTRIBUTE_ON_PLAY                = 92; // text
-  const ATTRIBUTE_ON_PLAYING             = 93; // text
-  const ATTRIBUTE_ON_PROGRESS            = 94; // text
-  const ATTRIBUTE_ON_POP_STATE           = 95; // text
-  const ATTRIBUTE_ON_RESIZE              = 96; // text
-  const ATTRIBUTE_ON_RESET               = 97; // text
-  const ATTRIBUTE_ON_RATE_CHANGE         = 98; // text
-  const ATTRIBUTE_ON_SCROLL              = 99; // text
-  const ATTRIBUTE_ON_SEARCH              = 100; // text
-  const ATTRIBUTE_ON_SELECT              = 101; // text
-  const ATTRIBUTE_ON_SUBMIT              = 102; // text
-  const ATTRIBUTE_ON_SEEKED              = 103; // text
-  const ATTRIBUTE_ON_SEEKING             = 104; // text
-  const ATTRIBUTE_ON_STALLED             = 105; // text
-  const ATTRIBUTE_ON_SUSPEND             = 106; // text
-  const ATTRIBUTE_ON_SHOW                = 107; // text
-  const ATTRIBUTE_ON_STORAGE             = 108; // text
-  const ATTRIBUTE_ON_TIME_UPDATE         = 109; // text
-  const ATTRIBUTE_ON_TRANSITION_END      = 110; // text
-  const ATTRIBUTE_ON_TOGGLE              = 111; // text
-  const ATTRIBUTE_ON_TOUCH_CANCEL        = 112; // text
-  const ATTRIBUTE_ON_TOUCH_END           = 113; // text
-  const ATTRIBUTE_ON_TOUCH_MOVE          = 114; // text
-  const ATTRIBUTE_ON_TOUCH_START         = 115; // text
-  const ATTRIBUTE_ON_UNLOAD              = 116; // text
-  const ATTRIBUTE_ON_VOLUME_CHANGE       = 117; // text
-  const ATTRIBUTE_ON_WAITING             = 118; // text
-  const ATTRIBUTE_ON_WHEEL               = 119; // text
-  const ATTRIBUTE_PATTERN                = 120; // text, regular expression
-  const ATTRIBUTE_PLACE_HOLDER           = 121; // text
-  const ATTRIBUTE_READONLY               = 122; // readonly, use TRUE/FALSE
-  const ATTRIBUTE_REQUIRED               = 123; // required, use TRUE/FALSE
-  const ATTRIBUTE_ROWS                   = 124; // number
-  const ATTRIBUTE_SELECTED               = 125; // selected, use TRUE/FALSE
-  const ATTRIBUTE_SIZE                   = 126; // number
-  const ATTRIBUTE_SOURCE                 = 127; // url
-  const ATTRIBUTE_SPELLCHECK             = 125; // TRUE/FALSE
-  const ATTRIBUTE_STEP                   = 128; // number
-  const ATTRIBUTE_STYLE                  = 129; // text
-  const ATTRIBUTE_TAB_INDEX              = 130; // number
-  const ATTRIBUTE_TARGET                 = 131; // text, _blank, _self, _parent, _top, URL
-  const ATTRIBUTE_TITLE                  = 132; // text
-  const ATTRIBUTE_TRANSLATE              = 133; // text
-  const ATTRIBUTE_TYPE                   = 134; // see TYPE_ constanst below.
-  const ATTRIBUTE_VALUE                  = 135; // text
-  const ATTRIBUTE_WRAP                   = 136; // hard, soft
-}
-
-/**
- * A generic class for storing a single item of form data.
- *
- * Each tag is expected to have a unique id.
- * The internal id is an integer, primarily intended to be used in databases for performance reasons.
- * The form id is a string that can be identical to the internal tag id.
- * The form id is intended to represent the form tag id or form tag name as used on HTML form id tags.
- *
- */
-class c_base_form_data_item {
-
-
-/**
- * A generic class for form tag types.
- *
- * @see: https://www.w3.org/TR/html5/forms.html#forms
- */
-class c_base_form_tags {
-  const TYPE_NONE    = 0;
-  const TYPE_TEXT    = 1;
-  const TYPE_BOOLEAN = 2;
-  const TYPE_INTEGER = 3;
-  const TYPE_FLOAT   = 4;
-
-  private $id_internal = NULL;
-  private $id_form = NULL;
-  private $type = self::TYPE_NONE;
-  private $data = NULL;
-
-  /**
-   * Class constructor.
-   */
-  public function __construct() {
-    $this->id_internal = NULL;
-    $this->id_form = NULL;
-    $this->type = self::TYPE_NONE;
-    $this->data = NULL;
-  }
-
-  /**
-   * Class destructor.
-   */
-  public function __destruct() {
-    unset($this->id_internal);
-    unset($this->id_form);
-    unset($this->type);
-    unset($this->data);
-  }
-
-  /**
-   * Assign the unique id which is intended to uniquely identify the form.
-   *
-   * @param int $id_internal
-   *   The internal numeric id to assign.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_id_internal($id_internal) {
-    if (!is_int($id_internal)) {
-      return c_base_return_error::s_false();
-    }
-
-    $this->id_internal = $id_internal;
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the unique id which is intended to uniquely identify the form.
-   *
-   * @return c_base_return_string|c_base_return_false
-   *   The unique internal id assigned to this object.
-   *   FALSE is returned if the unique numeric tag id is not set.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_id_internal() {
-    if (!isset($this->id_internal)) {
-      return new c_base_return_false();
-    }
-
-    return new c_base_return_string($this->id_internal);
-  }
-
-  /**
-   * Assign the unique id which is intended to represent the form id string.
-   *
-   * @param string $id_form
-   *   The form id string to assign.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_id_form($id_form) {
-    if (!is_string($id)) {
-      return c_base_return_error::s_false();
-    }
-
-    $this->id_form = $id_form;
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the unique id which is intended to represent the form id string.
-   *
-   * @return c_base_return_string|c_base_return_false
-   *   The form id string assigned to this object.
-   *   FALSE is returned if the unique numeric tag id is not set.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_id_form() {
-    if (!isset($this->id_form)) {
-      return new c_base_return_false();
-    }
-
-    return new c_base_return_string($this->id_form);
-  }
-
-  /**
-   * Assign the data.
-   *
-   * @param int|string|float|bool|null $data
-   *   The data whose type is directly dependend on $this->type.
-   *   Failure to assign the proper type will result in an error.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_data($data) {
-    if ($this->type === self::TYPE_NONE) {
-      if (!is_null($data)) {
-        return c_base_return_error::s_false();
-      }
-    }
-    elseif ($this->type === self::TYPE_TEXT) {
-      if (!is_string($data)) {
-        return c_base_return_error::s_false();
-      }
-    }
-    elseif ($this->type === self::TYPE_BOOLEAN) {
-      if (!is_bool($data)) {
-        return c_base_return_error::s_false();
-      }
-    }
-    elseif ($this->type === self::TYPE_NUMBER) {
-      if (!is_int($data)) {
-        return c_base_return_error::s_false();
-      }
-    }
-    elseif ($this->type === self::TYPE_FLOAT) {
-      if (!is_float($data)) {
-        return c_base_return_error::s_false();
-      }
-    }
-    else {
-      return c_base_return_error::s_false();
-    }
-
-    $this->data = $data;
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the assigned data.
-   *
-   * @return c_base_return_status|c_base_return_int|c_base_return_float|c_base_return_string|c_base_return_bool|c_base_return_null
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_data() {
-    if ($this->type === self::TYPE_NONE) {
-      return new c_base_return_null();
-    }
-    elseif ($this->type === self::TYPE_TEXT) {
-      return new c_base_return_string($this->data);
-    }
-    elseif ($this->type === self::TYPE_BOOLEAN) {
-      if ($this->data) {
-        return new c_base_return_true();
-      }
-
-      return new c_base_return_false();
-    }
-    elseif ($this->type === self::TYPE_NUMBER) {
-      return new c_base_return_int($this->data);
-    }
-    elseif ($this->type === self::TYPE_FLOAT) {
-      return new c_base_return_float($this->data);
-    }
-
-    return c_base_return_error::s_false();
-  }
-
-  /**
-   * Assign the type of data to be stored in this object.
-   *
-   * Assigning this will reset/clear the data.
-   *
-   * @param int $type
-   */
-  public function set_type($type) {
-    if ($type === self::TYPE_NONE) {
-      $this->type = $type;
-      $this->data = NULL;
-    }
-    elseif ($type === self::TYPE_TEXT) {
-      $this->type = $type;
-      $this->data = '';
-    }
-    elseif ($type === self::TYPE_BOOLEAN) {
-      $this->type = $type;
-      $this->data = FALSE;
-    }
-    elseif ($type === self::TYPE_NUMBER) {
-      $this->type = $type;
-      $this->data = 0;
-    }
-    elseif ($type === self::TYPE_FLOAT) {
-      $this->type = $type;
-      $this->data = 0.0;
-    }
-    else {
-      return c_base_return_error::s_false();
-    }
-
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the assigned type.
-   *
-   * @return c_base_return_status|c_base_return_int
-   */
-  public function get_type() {
-    return new c_base_return_int($this->type);
-  }
-}
-
-/**
- * A generic class for storing form data.
- *
- * Each tag is expected to have a unique id.
- * The internal id is an integer, primarily intended to be used in databases for performance reasons.
- * The form id is a string that can be identical to the internal id.
- * The form id is intended to represent the form id or form name as used on HTML form id tags.
- *
- */
-class c_base_form_data extends c_base_form_data_item {
-  private $data = array();
-
-  /**
-   * Class constructor.
-   */
-  public function __construct() {
-    super.__construct();
-
-    $this->data = array();
-  }
-
-  /**
-   * Class destructor.
-   */
-  public function __destruct() {
-    super.__destruct();
-
-    unset($this->data);
-  }
-
-}
-
-// below will be moved into output/theme areas.
-/**
- * A generic class for form tags.
- *
- * The unique tag id is an integer to be used for internal purposes but may be exposed on output.
- * If the id attribute is defined, then on output the id attribute is used for the HTML tag.
- *
- * @see: https://www.w3.org/TR/html5/forms.html#forms
- */
-class c_base_form_tag {
-  const TAG_NONE      = 0;
-  const TAG_INPUT     = 1;
-  const TAG_RADIO     = 2;
-  const TAG_SUBMIT    = 3;
-  const TAG_TEXT_AREA = 4;
-  const TAG_FIELD_SET = 5;
-  const TAG_SELECT    = 6;
-  const TAG_OPTION    = 7;
-  const TAG_DATA_LIST = 8;
-  const TAG_KEY_GEN   = 9;
-  const TAG_OUTPUT    = 10;
-
-  const TYPE_NONE           = 0;
-  const TYPE_TEXT           = 1;
-  const TYPE_BUTTON         = 2;
-  const TYPE_CHECKBOX       = 3;
-  const TYPE_COLOR          = 4;
-  const TYPE_DATE           = 5;
-  const TYPE_DATETIME       = 6;
-  const TYPE_DATETIME_LOCAL = 7;
-  const TYPE_EMAIL          = 8;
-  const TYPE_FILE           = 9;
-  const TYPE_HIDDEN         = 10;
-  const TYPE_IMAGE          = 11;
-  const TYPE_MONTH          = 12;
-  const TYPE_NUMBER         = 13;
-  const TYPE_PASSWORD       = 14;
-  const TYPE_RADIO          = 15;
-  const TYPE_RANGE          = 16;
-  const TYPE_RESET          = 17;
-  const TYPE_SEARCH         = 18;
-  const TYPE_SUBMIT         = 19;
-  const TYPE_TELEPHONE      = 20;
-  const TYPE_TEXT           = 21;
-  const TYPE_TIME           = 22;
-  const TYPE_URL            = 23;
-  const TYPE_WEEK           = 24;
-
-  private $id;
-  private $type;
-  private $attributes;
-  private $parent;
-  private $children;
-
-  /**
-   * Class constructor.
-   */
-  public function __construct() {
-    $this->id = NULL;
-    $this->type = self::TAG_NONE;
-    $this->attributes = array();
-    $this->parent = NULL;
-    $this->children = array();
-  }
-
-  /**
-   * Class destructor.
-   */
-  public function __destruct() {
-    unset($this->id);
-    unset($this->type);
-    unset($this->attributes);
-    unset($this->parent);
-    unset($this->children);
-  }
-
-  /**
-   * Assign the internal unique numeric tag id.
-   *
-   * @param int $id
-   *   The internal numeric id to assign.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_id($id) {
-    if (!is_int($id)) {
-      return c_base_return_error::s_false();
-    }
-
-    $this->id = $id;
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the unique numeric tag id assigned to this object.
-   *
-   * @return c_base_return_int|c_base_return_false
-   *   The tag type assigned to this class.
-   *   FALSE is returned if the unique numeric tag id is not set.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_id() {
-    if (!isset($this->id)) {
-      return new c_base_return_false();
-    }
-
-    return new c_base_return_int($this->id);
-  }
-
-  /**
-   * Assign the specified tag type.
-   *
-   * @param int $type
-   *   The tag type to assign.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_type($type) {
-    if (!is_int($type)) {
-      return c_base_return_error::s_false();
-    }
-
-    switch ($type) {
-      case self::TAG_NONE:
-      case self::TAG_INPUT:
-      case self::TAG_RADIO:
-      case self::TAG_SUBMIT:
-      case self::TAG_TEXT_AREA:
-      case self::TAG_FIELD_SET:
-      case self::TAG_SELECT:
-      case self::TAG_OPTION:
-      case self::TAG_DATA_LIST:
-      case self::TAG_KEY_GEN:
-      case self::TAG_OUTPUT:
-        break;
-      default:
-        return new c_base_return_false();
-    }
-
-    $this->type = $type;
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the tag type assigned to this object.
-   *
-   * @return c_base_return_int
-   *   The tag type assigned to this class.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_type() {
-    if (!isset($this->type)) {
-      $this->type = self::TAG_NONE;
-    }
-
-    return new c_base_return_int($this->type);
-  }
-
-  /**
-   * Assign the specified tag.
-   *
-   * @param int $attribute
-   *   The attribute to assign.
-   * @param $value
-   *   The value of the attribute.
-   *   The actual value type is specific to each attribute type.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_attribute($attribute, $value) {
-    if (!is_int($attribute)) {
-      return c_base_return_error::s_false();
-    }
-
-    switch ($attribute) {
-      case c_base_form_attributes::ATTRIBUTE_NONE:
-        unset($this->attribute[$attribute]);
-        return new c_base_return_true();
-
-      case c_base_form_attributes::ATTRIBUTE_ACTION:
-      case c_base_form_attributes::ATTRIBUTE_DIRECTION_NAME:
-      case c_base_form_attributes::ATTRIBUTE_FOR:
-      case c_base_form_attributes::ATTRIBUTE_FORM:
-      case c_base_form_attributes::ATTRIBUTE_FORM_ACTION:
-      case c_base_form_attributes::ATTRIBUTE_FORM_TARGET:
-      case c_base_form_attributes::ATTRIBUTE_KEY_TYPE:
-      case c_base_form_attributes::ATTRIBUTE_LABEL:
-      case c_base_form_attributes::ATTRIBUTE_LIST:
-      case c_base_form_attributes::ATTRIBUTE_NAME:
-      case c_base_form_attributes::ATTRIBUTE_ON_ABORT:
-      case c_base_form_attributes::ATTRIBUTE_ON_AFTER_PRINT:
-      case c_base_form_attributes::ATTRIBUTE_ON_ANIMATION_END:
-      case c_base_form_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
-      case c_base_form_attributes::ATTRIBUTE_ON_ANIMATION_start:
-      case c_base_form_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
-      case c_base_form_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
-      case c_base_form_attributes::ATTRIBUTE_ON_BLUR:
-      case c_base_form_attributes::ATTRIBUTE_ON_CLICK:
-      case c_base_form_attributes::ATTRIBUTE_ON_CONTEXT_MENU:
-      case c_base_form_attributes::ATTRIBUTE_ON_COPY:
-      case c_base_form_attributes::ATTRIBUTE_ON_CUT:
-      case c_base_form_attributes::ATTRIBUTE_ON_CAN_PLAY:
-      case c_base_form_attributes::ATTRIBUTE_ON_CAN_PLAY_THROUGH:
-      case c_base_form_attributes::ATTRIBUTE_ON_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_DOUBLE_CLICK:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_END:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_ENTER:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_LEAVE:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_OVER:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_START:
-      case c_base_form_attributes::ATTRIBUTE_ON_DROP:
-      case c_base_form_attributes::ATTRIBUTE_ON_DURATION_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_ERROR:
-      case c_base_form_attributes::ATTRIBUTE_ON_EMPTIED:
-      case c_base_form_attributes::ATTRIBUTE_ON_ENDED:
-      case c_base_form_attributes::ATTRIBUTE_ON_ERROR:
-      case c_base_form_attributes::ATTRIBUTE_ON_FOCUS:
-      case c_base_form_attributes::ATTRIBUTE_ON_FOCUS_IN:
-      case c_base_form_attributes::ATTRIBUTE_ON_FOCUS_OUT:
-      case c_base_form_attributes::ATTRIBUTE_ON_HASH_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_INPUT:
-      case c_base_form_attributes::ATTRIBUTE_ON_INVALID:
-      case c_base_form_attributes::ATTRIBUTE_ON_KEY_DOWN:
-      case c_base_form_attributes::ATTRIBUTE_ON_KEY_PRESS:
-      case c_base_form_attributes::ATTRIBUTE_ON_KEY_UP:
-      case c_base_form_attributes::ATTRIBUTE_ON_LOAD:
-      case c_base_form_attributes::ATTRIBUTE_ON_LOADED_DATA:
-      case c_base_form_attributes::ATTRIBUTE_ON_LOADED_META_DATA:
-      case c_base_form_attributes::ATTRIBUTE_ON_LOAD_START:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_DOWN:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_ENTER:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_LEAVE:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_MOVE:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_OVER:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_OUT:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_UP:
-      case c_base_form_attributes::ATTRIBUTE_ON_MESSAGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_WHEEL:
-      case c_base_form_attributes::ATTRIBUTE_ON_OPEN:
-      case c_base_form_attributes::ATTRIBUTE_ON_ONLINE:
-      case c_base_form_attributes::ATTRIBUTE_ON_OFFLINE:
-      case c_base_form_attributes::ATTRIBUTE_ON_PAGE_SHOW:
-      case c_base_form_attributes::ATTRIBUTE_ON_PAGE_HIDE:
-      case c_base_form_attributes::ATTRIBUTE_ON_PASTE:
-      case c_base_form_attributes::ATTRIBUTE_ON_PAUSE:
-      case c_base_form_attributes::ATTRIBUTE_ON_PLAY:
-      case c_base_form_attributes::ATTRIBUTE_ON_PLAYING:
-      case c_base_form_attributes::ATTRIBUTE_ON_PROGRESS:
-      case c_base_form_attributes::ATTRIBUTE_ON_POP_STATE:
-      case c_base_form_attributes::ATTRIBUTE_ON_RESIZE:
-      case c_base_form_attributes::ATTRIBUTE_ON_RESET:
-      case c_base_form_attributes::ATTRIBUTE_ON_RATE_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_SCROLL:
-      case c_base_form_attributes::ATTRIBUTE_ON_SEARCH:
-      case c_base_form_attributes::ATTRIBUTE_ON_SELECT:
-      case c_base_form_attributes::ATTRIBUTE_ON_SUBMIT:
-      case c_base_form_attributes::ATTRIBUTE_ON_SEEKED:
-      case c_base_form_attributes::ATTRIBUTE_ON_SEEKING:
-      case c_base_form_attributes::ATTRIBUTE_ON_STALLED:
-      case c_base_form_attributes::ATTRIBUTE_ON_SUSPEND:
-      case c_base_form_attributes::ATTRIBUTE_ON_SHOW:
-      case c_base_form_attributes::ATTRIBUTE_ON_STORAGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_TIME_UPDATE:
-      case c_base_form_attributes::ATTRIBUTE_ON_TRANSITION_END:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOGGLE:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_CANCEL:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_END:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_MOVE:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_START:
-      case c_base_form_attributes::ATTRIBUTE_ON_UNLOAD:
-      case c_base_form_attributes::ATTRIBUTE_ON_VOLUME_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_WAITING:
-      case c_base_form_attributes::ATTRIBUTE_ON_WHEEL:
-      case c_base_form_attributes::ATTRIBUTE_PATTERN:
-      case c_base_form_attributes::ATTRIBUTE_PLACE_HOLDER:
-      case c_base_form_attributes::ATTRIBUTE_READONLY:
-      case c_base_form_attributes::ATTRIBUTE_REQUIRED:
-      case c_base_form_attributes::ATTRIBUTE_ROWS:
-      case c_base_form_attributes::ATTRIBUTE_SELECTED:
-      case c_base_form_attributes::ATTRIBUTE_SIZE:
-      case c_base_form_attributes::ATTRIBUTE_SOURCE:
-      case c_base_form_attributes::ATTRIBUTE_STEP:
-      case c_base_form_attributes::ATTRIBUTE_TYPE:
-      case c_base_form_attributes::ATTRIBUTE_WRAP:
-      case c_base_form_attributes::ATTRIBUTE_VALUE:
-        if (!is_string($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      case c_base_form_attributes::ATTRIBUTE_FORM_NO_VALIDATED:
-      case c_base_form_attributes::ATTRIBUTE_AUTO_COMPLETE:
-      case c_base_form_attributes::ATTRIBUTE_AUTO_FOCUS:
-      case c_base_form_attributes::ATTRIBUTE_CHALLENGE:
-      case c_base_form_attributes::ATTRIBUTE_CHECKED:
-      case c_base_form_attributes::ATTRIBUTE_DISABLED:
-      case c_base_form_attributes::ATTRIBUTE_MULTIPLE:
-        if (!is_bool($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      case c_base_form_attributes::ATTRIBUTE_ACCEPT:
-      case c_base_form_attributes::ATTRIBUTE_FORM_ENCODE_TYPE:
-        if (!this->pr_validate_value_mime_type($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      case c_base_form_attributes::ATTRIBUTE_COLUMNS:
-      case c_base_form_attributes::ATTRIBUTE_MAXIMUM:
-      case c_base_form_attributes::ATTRIBUTE_MAXIMUM_LENGTH:
-      case c_base_form_attributes::ATTRIBUTE_MINIMUM:
-        if (!is_int($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      case c_base_form_attributes::ATTRIBUTE_FORM_METHOD:
-        if (!this->pr_validate_value_http_method($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      default:
-        return new c_base_return_false();
-    }
-
-    $this->attribute[$attribute] = $value;
-
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the attributes assigned to this object.
-   *
-   * @return c_base_return_array
-   *   The attributes assigned to this class.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_attributes() {
-    if (!isset($this->attributes) && !is_array($this->attributes)) {
-      $this->attributes = array();
-    }
-
-    return new c_base_return_array($this->attributes);
-  }
-
-  /**
-   * Get the value of a single attribute assigned to this object.
-   *
-   * @param int $attribute
-   *   The attribute to assign.
-   *
-   * @return c_base_return_int|c_base_return_string|c_base_return_bool|c_base_return_false
-   *   The value assigned to the attribte (the data type is different per attribute).
-   *   FALSE is returned if the element does not exist.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_attribute($attribute) {
-    if (!is_int($attribute)) {
-      return c_base_return_error::s_false();
-    }
-
-    if (!isset($this->attributes) && !is_array($this->attributes)) {
-      $this->attributes = array();
-    }
-
-    if (array_key_exists($attribute, $this->attributes)) {
-      switch ($attribute) {
-        case c_base_form_attributes::ATTRIBUTE_NONE:
-          // should not be possible, so consider this an error (attributes set to NONE are actually unset from the array).
-          return c_base_return_error::s_false();
-
-        case c_base_form_attributes::ATTRIBUTE_ACTION:
-        case c_base_form_attributes::ATTRIBUTE_DIRECTION_NAME:
-        case c_base_form_attributes::ATTRIBUTE_FOR:
-        case c_base_form_attributes::ATTRIBUTE_FORM:
-        case c_base_form_attributes::ATTRIBUTE_FORM_ACTION:
-        case c_base_form_attributes::ATTRIBUTE_FORM_TARGET:
-        case c_base_form_attributes::ATTRIBUTE_KEY_TYPE:
-        case c_base_form_attributes::ATTRIBUTE_LABEL:
-        case c_base_form_attributes::ATTRIBUTE_LIST:
-        case c_base_form_attributes::ATTRIBUTE_NAME:
-        case c_base_form_attributes::ATTRIBUTE_ON_ABORT:
-        case c_base_form_attributes::ATTRIBUTE_ON_AFTER_PRINT:
-        case c_base_form_attributes::ATTRIBUTE_ON_ANIMATION_END:
-        case c_base_form_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
-        case c_base_form_attributes::ATTRIBUTE_ON_ANIMATION_start:
-        case c_base_form_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
-        case c_base_form_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
-        case c_base_form_attributes::ATTRIBUTE_ON_BLUR:
-        case c_base_form_attributes::ATTRIBUTE_ON_CLICK:
-        case c_base_form_attributes::ATTRIBUTE_ON_CONTEXT_MENU:
-        case c_base_form_attributes::ATTRIBUTE_ON_COPY:
-        case c_base_form_attributes::ATTRIBUTE_ON_CUT:
-        case c_base_form_attributes::ATTRIBUTE_ON_CAN_PLAY:
-        case c_base_form_attributes::ATTRIBUTE_ON_CAN_PLAY_THROUGH:
-        case c_base_form_attributes::ATTRIBUTE_ON_CHANGE:
-        case c_base_form_attributes::ATTRIBUTE_ON_DOUBLE_CLICK:
-        case c_base_form_attributes::ATTRIBUTE_ON_DRAG:
-        case c_base_form_attributes::ATTRIBUTE_ON_DRAG_END:
-        case c_base_form_attributes::ATTRIBUTE_ON_DRAG_ENTER:
-        case c_base_form_attributes::ATTRIBUTE_ON_DRAG_LEAVE:
-        case c_base_form_attributes::ATTRIBUTE_ON_DRAG_OVER:
-        case c_base_form_attributes::ATTRIBUTE_ON_DRAG_START:
-        case c_base_form_attributes::ATTRIBUTE_ON_DROP:
-        case c_base_form_attributes::ATTRIBUTE_ON_DURATION_CHANGE:
-        case c_base_form_attributes::ATTRIBUTE_ON_ERROR:
-        case c_base_form_attributes::ATTRIBUTE_ON_EMPTIED:
-        case c_base_form_attributes::ATTRIBUTE_ON_ENDED:
-        case c_base_form_attributes::ATTRIBUTE_ON_ERROR:
-        case c_base_form_attributes::ATTRIBUTE_ON_FOCUS:
-        case c_base_form_attributes::ATTRIBUTE_ON_FOCUS_IN:
-        case c_base_form_attributes::ATTRIBUTE_ON_FOCUS_OUT:
-        case c_base_form_attributes::ATTRIBUTE_ON_HASH_CHANGE:
-        case c_base_form_attributes::ATTRIBUTE_ON_INPUT:
-        case c_base_form_attributes::ATTRIBUTE_ON_INVALID:
-        case c_base_form_attributes::ATTRIBUTE_ON_KEY_DOWN:
-        case c_base_form_attributes::ATTRIBUTE_ON_KEY_PRESS:
-        case c_base_form_attributes::ATTRIBUTE_ON_KEY_UP:
-        case c_base_form_attributes::ATTRIBUTE_ON_LOAD:
-        case c_base_form_attributes::ATTRIBUTE_ON_LOADED_DATA:
-        case c_base_form_attributes::ATTRIBUTE_ON_LOADED_META_DATA:
-        case c_base_form_attributes::ATTRIBUTE_ON_LOAD_START:
-        case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_DOWN:
-        case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_ENTER:
-        case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_LEAVE:
-        case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_MOVE:
-        case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_OVER:
-        case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_OUT:
-        case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_UP:
-        case c_base_form_attributes::ATTRIBUTE_ON_MESSAGE:
-        case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_WHEEL:
-        case c_base_form_attributes::ATTRIBUTE_ON_OPEN:
-        case c_base_form_attributes::ATTRIBUTE_ON_ONLINE:
-        case c_base_form_attributes::ATTRIBUTE_ON_OFFLINE:
-        case c_base_form_attributes::ATTRIBUTE_ON_PAGE_SHOW:
-        case c_base_form_attributes::ATTRIBUTE_ON_PAGE_HIDE:
-        case c_base_form_attributes::ATTRIBUTE_ON_PASTE:
-        case c_base_form_attributes::ATTRIBUTE_ON_PAUSE:
-        case c_base_form_attributes::ATTRIBUTE_ON_PLAY:
-        case c_base_form_attributes::ATTRIBUTE_ON_PLAYING:
-        case c_base_form_attributes::ATTRIBUTE_ON_PROGRESS:
-        case c_base_form_attributes::ATTRIBUTE_ON_POP_STATE:
-        case c_base_form_attributes::ATTRIBUTE_ON_RESIZE:
-        case c_base_form_attributes::ATTRIBUTE_ON_RESET:
-        case c_base_form_attributes::ATTRIBUTE_ON_RATE_CHANGE:
-        case c_base_form_attributes::ATTRIBUTE_ON_SCROLL:
-        case c_base_form_attributes::ATTRIBUTE_ON_SEARCH:
-        case c_base_form_attributes::ATTRIBUTE_ON_SELECT:
-        case c_base_form_attributes::ATTRIBUTE_ON_SUBMIT:
-        case c_base_form_attributes::ATTRIBUTE_ON_SEEKED:
-        case c_base_form_attributes::ATTRIBUTE_ON_SEEKING:
-        case c_base_form_attributes::ATTRIBUTE_ON_STALLED:
-        case c_base_form_attributes::ATTRIBUTE_ON_SUSPEND:
-        case c_base_form_attributes::ATTRIBUTE_ON_SHOW:
-        case c_base_form_attributes::ATTRIBUTE_ON_STORAGE:
-        case c_base_form_attributes::ATTRIBUTE_ON_TIME_UPDATE:
-        case c_base_form_attributes::ATTRIBUTE_ON_TRANSITION_END:
-        case c_base_form_attributes::ATTRIBUTE_ON_TOGGLE:
-        case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_CANCEL:
-        case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_END:
-        case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_MOVE:
-        case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_START:
-        case c_base_form_attributes::ATTRIBUTE_ON_UNLOAD:
-        case c_base_form_attributes::ATTRIBUTE_ON_VOLUME_CHANGE:
-        case c_base_form_attributes::ATTRIBUTE_ON_WAITING:
-        case c_base_form_attributes::ATTRIBUTE_ON_WHEEL:
-        case c_base_form_attributes::ATTRIBUTE_PATTERN:
-        case c_base_form_attributes::ATTRIBUTE_READONLY:
-        case c_base_form_attributes::ATTRIBUTE_REQUIRED:
-        case c_base_form_attributes::ATTRIBUTE_ROWS:
-        case c_base_form_attributes::ATTRIBUTE_SELECTED:
-        case c_base_form_attributes::ATTRIBUTE_SIZE:
-        case c_base_form_attributes::ATTRIBUTE_SOURCE:
-        case c_base_form_attributes::ATTRIBUTE_STEP:
-        case c_base_form_attributes::ATTRIBUTE_TYPE:
-        case c_base_form_attributes::ATTRIBUTE_WRAP:
-        case c_base_form_attributes::ATTRIBUTE_PLACE_HOLDER:
-        case c_base_form_attributes::ATTRIBUTE_VALUE:
-          return c_base_return_string::s_new($value);
-
-        case c_base_form_attributes::ATTRIBUTE_FORM_NO_VALIDATED:
-        case c_base_form_attributes::ATTRIBUTE_AUTO_COMPLETE:
-        case c_base_form_attributes::ATTRIBUTE_AUTO_FOCUS:
-        case c_base_form_attributes::ATTRIBUTE_CHALLENGE:
-        case c_base_form_attributes::ATTRIBUTE_CHECKED:
-        case c_base_form_attributes::ATTRIBUTE_DISABLED:
-        case c_base_form_attributes::ATTRIBUTE_MULTIPLE:
-          return c_base_return_bool::s_new($value);
-
-        case c_base_form_attributes::ATTRIBUTE_ACCEPT:
-        case c_base_form_attributes::ATTRIBUTE_FORM_ENCODE_TYPE:
-          return c_base_return_int::s_new($value);
-
-        case c_base_form_attributes::ATTRIBUTE_COLUMNS:
-        case c_base_form_attributes::ATTRIBUTE_MAXIMUM:
-        case c_base_form_attributes::ATTRIBUTE_MAXIMUM_LENGTH:
-        case c_base_form_attributes::ATTRIBUTE_MINIMUM:
-          return c_base_return_int::s_new($value);
-
-        case c_base_form_attributes::ATTRIBUTE_FORM_METHOD:
-          return c_base_return_int::s_new($value);
-
-        default:
-          return new c_base_return_false();
-      }
-    }
-
-    $this->attribute[$attribute] = $value;
-
-    return new c_base_return_false();
-  }
-
-  /**
-   * Assign the specified numeric id as the parent tag.
-   *
-   * @param int $parent_id
-   *   The numeric id to assign.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_parent($parent_id) {
-    if (!is_int($parent_id)) {
-      return c_base_return_error::s_false();
-    }
-
-    $this->parent = $parent_id;
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the parent tag numeric id associated with this.
-   *
-   * @return c_base_return_int|c_base_return_false
-   *   The tag type assigned to this class.
-   *   FALSE without error bit is set when no parent is defined.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_parent() {
-    if (!isset($this->parent)) {
-      return new c_base_return_false();
-    }
-
-    return new c_base_return_int($this->parent);
-  }
-
-  /**
-   * Add a child tag.
-   *
-   * @param c_base_form_tag $child
-   *   The numeric id to assign.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_child($child_tag) {
-    if (!($child_tag instanceof c_base_form_tag)) {
-      return c_base_return_error::s_false();
-    }
-
-    // this requires the class to have a tag id assigned.
-    if (!is_int($this->id)) {
-      return c_base_return_error::s_false();
-    }
-
-    $child_id = $child_tag->get_id();
-    if (!($child_id instanceof c_base_return_int)) {
-      unset($child_id);
-      return c_base_return_error::s_false();
-    }
-    $child_id = $child_id->get_value_exact();
-
-    $child_tag->set_parent($this->id);
-    $this->children[$child_id] = $child_tag;
-    unset($child_id);
-
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the specified child by its unique numeric tag id.
-   *
-   * @param int $child_id
-   *   The unique numeric tag id of the child.
-   *
-   * @return c_base_form_return_tag|c_base_return_false
-   *   The tag type assigned to this class.
-   *   FALSE without error bit is set when the child is not defined.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_child($child_id) {
-    if (!is_array($this->children) || !array_key_exists($child_id, $this->children)) {
-      return new c_base_return_false();
-    }
-
-    if (!($this->children[$child_id] instanceof c_base_form_tag)) {
-      return c_base_return_error::s_false();
-    }
-
-    return new c_base_form_return_tag($this->children[$child_id]);
-  }
-
-  /**
-   * Assign an array of child tags.
-   *
-   * @param array $children
-   *   An array of children to assign.
-   *   The array key must be an integer or it is ignore.
-   *   The array value must be a c_base_form_tag instance or it is ignored.
-   * @param bool $append
-   *   (optional) When TRUE, child elements are appended.
-   *   When FALSE, any existing children are removed.
-   *
-   * @return c_base_return_int|c_base_return_false
-   *   An integer representing the number of children successfully added.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_children($children, $append = FALSE) {
-    if (!is_array($children)) {
-      return c_base_return_error::s_false();
-    }
-
-    if (!is_bool($append)) {
-      return c_base_return_error::s_false();
-    }
-
-    if (!$append) {
-      $this->children = array();
-    }
-
-    $added = 0;
-    foreach ($children as $child_id => $child_tag) {
-      if (!is_numeric($child_id) || !($child_tag instanceof c_base_form_tag)) {
-        continue;
-      }
-
-      $child_tag_id = $child_tag->get_id();
-      if (!($child_tag_id instanceof c_base_return_int) || $child_id != $child_tag_id->get_value_exact()) {
-        unset($child_tag_id);
-        continue;
-      }
-      unset($child_tag_id);
-
-      $child_tag->set_parent($this->id);
-      $this->children[(int) $child_id] = $child_tag;
-      $added++;
-    }
-    unset($child_id);
-    unset($child_tag);
-
-    return new c_base_return_int($added);
-  }
-
-  /**
-   * Get all assigned child tags.
-   *
-   * @return c_base_return_array|c_base_return_false
-   *   The array of child tags.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_children() {
-    if (!is_array($this->children)) {
-      $this->children = array();
-    }
-
-    return new c_base_return_array($this->children);
-  }
-
-  /**
-   * Protected function for mime values.
-   *
-   * @param int $value
-   *   The value of the attribute populate from c_base_mime.
-   *
-   * @return bool
-   *   TRUE on success.
-   *   FALSE otherwise.
-   */
-  protected function pr_validate_value_mime_type($value) {
-    if (!is_int($value)) {
-      return FALSE;
-    }
-
-    switch ($value) {
-      case c_base_mime::CATEGORY_UNKNOWN:
-      case c_base_mime::CATEGORY_PROVIDED:
-      case c_base_mime::CATEGORY_STREAM:
-      case c_base_mime::CATEGORY_TEXT:
-      case c_base_mime::CATEGORY_IMAGE:
-      case c_base_mime::CATEGORY_AUDIO:
-      case c_base_mime::CATEGORY_VIDEO:
-      case c_base_mime::CATEGORY_DOCUMENT:
-      case c_base_mime::CATEGORY_CONTAINER:
-      case c_base_mime::CATEGORY_APPLICATION:
-      case c_base_mime::TYPE_UNKNOWN:
-      case c_base_mime::TYPE_PROVIDED:
-      case c_base_mime::TYPE_STREAM:
-      case c_base_mime::TYPE_TEXT_PLAIN:
-      case c_base_mime::TYPE_TEXT_HTML:
-      case c_base_mime::TYPE_TEXT_RSS:
-      case c_base_mime::TYPE_TEXT_ICAL:
-      case c_base_mime::TYPE_TEXT_CSV:
-      case c_base_mime::TYPE_TEXT_XML:
-      case c_base_mime::TYPE_TEXT_CSS:
-      case c_base_mime::TYPE_TEXT_JS:
-      case c_base_mime::TYPE_TEXT_JSON:
-      case c_base_mime::TYPE_TEXT_RICH:
-      case c_base_mime::TYPE_TEXT_XHTML:
-      case c_base_mime::TYPE_TEXT_PS:
-      case c_base_mime::TYPE_IMAGE_PNG:
-      case c_base_mime::TYPE_IMAGE_GIF:
-      case c_base_mime::TYPE_IMAGE_JPEG:
-      case c_base_mime::TYPE_IMAGE_BMP:
-      case c_base_mime::TYPE_IMAGE_SVG:
-      case c_base_mime::TYPE_IMAGE_TIFF:
-      case c_base_mime::TYPE_AUDIO_WAV:
-      case c_base_mime::TYPE_AUDIO_OGG:
-      case c_base_mime::TYPE_AUDIO_MP3:
-      case c_base_mime::TYPE_AUDIO_MP4:
-      case c_base_mime::TYPE_AUDIO_MIDI:
-      case c_base_mime::TYPE_VIDEO_MPEG:
-      case c_base_mime::TYPE_VIDEO_OGG:
-      case c_base_mime::TYPE_VIDEO_H264:
-      case c_base_mime::TYPE_VIDEO_QUICKTIME:
-      case c_base_mime::TYPE_VIDEO_DV:
-      case c_base_mime::TYPE_VIDEO_JPEG:
-      case c_base_mime::TYPE_VIDEO_WEBM:
-      case c_base_mime::TYPE_DOCUMENT_LIBRECHART:
-      case c_base_mime::TYPE_DOCUMENT_LIBREFORMULA:
-      case c_base_mime::TYPE_DOCUMENT_LIBREGRAPHIC:
-      case c_base_mime::TYPE_DOCUMENT_LIBREPRESENTATION:
-      case c_base_mime::TYPE_DOCUMENT_LIBRESPREADSHEET:
-      case c_base_mime::TYPE_DOCUMENT_LIBRETEXT:
-      case c_base_mime::TYPE_DOCUMENT_LIBREHTML:
-      case c_base_mime::TYPE_DOCUMENT_PDF:
-      case c_base_mime::TYPE_DOCUMENT_ABIWORD:
-      case c_base_mime::TYPE_DOCUMENT_MSWORD:
-      case c_base_mime::TYPE_DOCUMENT_MSEXCEL:
-      case c_base_mime::TYPE_DOCUMENT_MSPOWERPOINT:
-      case c_base_mime::TYPE_CONTAINER_TAR:
-      case c_base_mime::TYPE_CONTAINER_CPIO:
-      case c_base_mime::TYPE_CONTAINER_JAVA:
-        break;
-      default:
-        return FALSE;
-    }
-
-    return TRUE;
-  }
-
-  /**
-   * Protected function for http method values.
-   *
-   * Only GET and POST methods are supported.
-   *
-   * @param int $value
-   *   The value of the attribute populate from http method.
-   *
-   * @return bool
-   *   TRUE on success.
-   *   FALSE otherwise.
-   */
-  protected function pr_validate_value_http_method($value) {
-    if (!is_int($value)) {
-      return FALSE;
-    }
-
-    switch ($value) {
-      case c_base_http::HTTP_METHOD_NONE:
-      case c_base_http::HTTP_METHOD_GET:
-      case c_base_http::HTTP_METHOD_POST:
-        break;
-      default:
-        return FALSE;
-    }
-
-    return TRUE;
-  }
-}
-
-/**
- * A generic class for form fields.
- *
- * The unique tag id is an integer to be used for internal purposes but may be exposed on output.
- * If the id attribute is defined, then on output the id attribute is used for the HTML tag.
- *
- * This uses a simple approach to store different form inputs.
- * Each input has a single depth group (with NULL being the default group).
- * The input fields do not relate directly to the form input.
- *
- * @see: https://www.w3.org/TR/html5/forms.html#forms
- */
-class c_base_form {
-  private $id;
-  private $inputs;
-  private $attributes;
-
-  /**
-   * Class constructor.
-   */
-  public function __construct() {
-    $this->id = NULL;
-    $this->tags = array();
-    $this->attributes = array();
-  }
-
-  /**
-   * Class destructor.
-   */
-  public function __destruct() {
-    unset($this->id);
-    unset($this->tags);
-    unset($this->attributes);
-  }
-
-  /**
-   * Assign a unique numeric id to represent this form.
-   *
-   * @param int $id
-   *   The unique form tag id to assign.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_id($id) {
-    if (!is_int($id)) {
-      return c_base_return_error::s_false();
-    }
-
-    $this->id = $id;
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the unique id assigned to this object.
-   *
-   * @return c_base_return_int|c_base_return_false
-   *   The unique numeric id assigned to this object.
-   *   FALSE is returned if no id is assigned.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_id() {
-    if (!is_int($this->id)) {
-      return c_base_return_false();
-    }
-
-    return new c_base_return_int($this->id);
-  }
-
-  /**
-   * Assign the specified tag.
-   *
-   * @param int $attribute
-   *   The attribute to assign.
-   * @param $value
-   *   The value of the attribute.
-   *   The actual value type is specific to each attribute type.
-   *
-   * @return c_base_return_status
-   *   TRUE on success, FALSE otherwise.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function set_attribute($attribute, $value) {
-    if (!is_int($attribute)) {
-      return c_base_return_error::s_false();
-    }
-
-    switch ($attribute) {
-      case c_base_form_attributes::ATTRIBUTE_NONE:
-        unset($this->attribute[$attribute]);
-        return new c_base_return_true();
-
-      case c_base_form_attributes::ATTRIBUTE_ACTION:
-      case c_base_form_attributes::ATTRIBUTE_DIRECTION_NAME:
-      case c_base_form_attributes::ATTRIBUTE_FOR:
-      case c_base_form_attributes::ATTRIBUTE_FORM:
-      case c_base_form_attributes::ATTRIBUTE_FORM_ACTION:
-      case c_base_form_attributes::ATTRIBUTE_FORM_TARGET:
-      case c_base_form_attributes::ATTRIBUTE_KEY_TYPE:
-      case c_base_form_attributes::ATTRIBUTE_LABEL:
-      case c_base_form_attributes::ATTRIBUTE_LIST:
-      case c_base_form_attributes::ATTRIBUTE_NAME:
-      case c_base_form_attributes::ATTRIBUTE_ON_ABORT:
-      case c_base_form_attributes::ATTRIBUTE_ON_AFTER_PRINT:
-      case c_base_form_attributes::ATTRIBUTE_ON_ANIMATION_END:
-      case c_base_form_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
-      case c_base_form_attributes::ATTRIBUTE_ON_ANIMATION_start:
-      case c_base_form_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
-      case c_base_form_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
-      case c_base_form_attributes::ATTRIBUTE_ON_BLUR:
-      case c_base_form_attributes::ATTRIBUTE_ON_CLICK:
-      case c_base_form_attributes::ATTRIBUTE_ON_CONTEXT_MENU:
-      case c_base_form_attributes::ATTRIBUTE_ON_COPY:
-      case c_base_form_attributes::ATTRIBUTE_ON_CUT:
-      case c_base_form_attributes::ATTRIBUTE_ON_CAN_PLAY:
-      case c_base_form_attributes::ATTRIBUTE_ON_CAN_PLAY_THROUGH:
-      case c_base_form_attributes::ATTRIBUTE_ON_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_DOUBLE_CLICK:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_END:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_ENTER:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_LEAVE:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_OVER:
-      case c_base_form_attributes::ATTRIBUTE_ON_DRAG_START:
-      case c_base_form_attributes::ATTRIBUTE_ON_DROP:
-      case c_base_form_attributes::ATTRIBUTE_ON_DURATION_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_ERROR:
-      case c_base_form_attributes::ATTRIBUTE_ON_EMPTIED:
-      case c_base_form_attributes::ATTRIBUTE_ON_ENDED:
-      case c_base_form_attributes::ATTRIBUTE_ON_ERROR:
-      case c_base_form_attributes::ATTRIBUTE_ON_FOCUS:
-      case c_base_form_attributes::ATTRIBUTE_ON_FOCUS_IN:
-      case c_base_form_attributes::ATTRIBUTE_ON_FOCUS_OUT:
-      case c_base_form_attributes::ATTRIBUTE_ON_HASH_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_INPUT:
-      case c_base_form_attributes::ATTRIBUTE_ON_INVALID:
-      case c_base_form_attributes::ATTRIBUTE_ON_KEY_DOWN:
-      case c_base_form_attributes::ATTRIBUTE_ON_KEY_PRESS:
-      case c_base_form_attributes::ATTRIBUTE_ON_KEY_UP:
-      case c_base_form_attributes::ATTRIBUTE_ON_LOAD:
-      case c_base_form_attributes::ATTRIBUTE_ON_LOADED_DATA:
-      case c_base_form_attributes::ATTRIBUTE_ON_LOADED_META_DATA:
-      case c_base_form_attributes::ATTRIBUTE_ON_LOAD_START:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_DOWN:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_ENTER:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_LEAVE:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_MOVE:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_OVER:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_OUT:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_UP:
-      case c_base_form_attributes::ATTRIBUTE_ON_MESSAGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_MOUSE_WHEEL:
-      case c_base_form_attributes::ATTRIBUTE_ON_OPEN:
-      case c_base_form_attributes::ATTRIBUTE_ON_ONLINE:
-      case c_base_form_attributes::ATTRIBUTE_ON_OFFLINE:
-      case c_base_form_attributes::ATTRIBUTE_ON_PAGE_SHOW:
-      case c_base_form_attributes::ATTRIBUTE_ON_PAGE_HIDE:
-      case c_base_form_attributes::ATTRIBUTE_ON_PASTE:
-      case c_base_form_attributes::ATTRIBUTE_ON_PAUSE:
-      case c_base_form_attributes::ATTRIBUTE_ON_PLAY:
-      case c_base_form_attributes::ATTRIBUTE_ON_PLAYING:
-      case c_base_form_attributes::ATTRIBUTE_ON_PROGRESS:
-      case c_base_form_attributes::ATTRIBUTE_ON_POP_STATE:
-      case c_base_form_attributes::ATTRIBUTE_ON_RESIZE:
-      case c_base_form_attributes::ATTRIBUTE_ON_RESET:
-      case c_base_form_attributes::ATTRIBUTE_ON_RATE_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_SCROLL:
-      case c_base_form_attributes::ATTRIBUTE_ON_SEARCH:
-      case c_base_form_attributes::ATTRIBUTE_ON_SELECT:
-      case c_base_form_attributes::ATTRIBUTE_ON_SUBMIT:
-      case c_base_form_attributes::ATTRIBUTE_ON_SEEKED:
-      case c_base_form_attributes::ATTRIBUTE_ON_SEEKING:
-      case c_base_form_attributes::ATTRIBUTE_ON_STALLED:
-      case c_base_form_attributes::ATTRIBUTE_ON_SUSPEND:
-      case c_base_form_attributes::ATTRIBUTE_ON_SHOW:
-      case c_base_form_attributes::ATTRIBUTE_ON_STORAGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_TIME_UPDATE:
-      case c_base_form_attributes::ATTRIBUTE_ON_TRANSITION_END:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOGGLE:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_CANCEL:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_END:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_MOVE:
-      case c_base_form_attributes::ATTRIBUTE_ON_TOUCH_START:
-      case c_base_form_attributes::ATTRIBUTE_ON_UNLOAD:
-      case c_base_form_attributes::ATTRIBUTE_ON_VOLUME_CHANGE:
-      case c_base_form_attributes::ATTRIBUTE_ON_WAITING:
-      case c_base_form_attributes::ATTRIBUTE_ON_WHEEL:
-      case c_base_form_attributes::ATTRIBUTE_PATTERN:
-      case c_base_form_attributes::ATTRIBUTE_PLACE_HOLDER:
-      case c_base_form_attributes::ATTRIBUTE_READONLY:
-      case c_base_form_attributes::ATTRIBUTE_REQUIRED:
-      case c_base_form_attributes::ATTRIBUTE_ROWS:
-      case c_base_form_attributes::ATTRIBUTE_SELECTED:
-      case c_base_form_attributes::ATTRIBUTE_SIZE:
-      case c_base_form_attributes::ATTRIBUTE_SOURCE:
-      case c_base_form_attributes::ATTRIBUTE_STEP:
-      case c_base_form_attributes::ATTRIBUTE_TYPE:
-      case c_base_form_attributes::ATTRIBUTE_WRAP:
-      case c_base_form_attributes::ATTRIBUTE_VALUE:
-        if (!is_string($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      case c_base_form_attributes::ATTRIBUTE_FORM_NO_VALIDATED:
-      case c_base_form_attributes::ATTRIBUTE_AUTO_COMPLETE:
-      case c_base_form_attributes::ATTRIBUTE_AUTO_FOCUS:
-      case c_base_form_attributes::ATTRIBUTE_CHALLENGE:
-      case c_base_form_attributes::ATTRIBUTE_CHECKED:
-      case c_base_form_attributes::ATTRIBUTE_DISABLED:
-      case c_base_form_attributes::ATTRIBUTE_MULTIPLE:
-        if (!is_bool($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      case c_base_form_attributes::ATTRIBUTE_ACCEPT:
-      case c_base_form_attributes::ATTRIBUTE_FORM_ENCODE_TYPE:
-        if (!this->pr_validate_value_mime_type($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      case c_base_form_attributes::ATTRIBUTE_COLUMNS:
-      case c_base_form_attributes::ATTRIBUTE_MAXIMUM:
-      case c_base_form_attributes::ATTRIBUTE_MAXIMUM_LENGTH:
-      case c_base_form_attributes::ATTRIBUTE_MINIMUM:
-        if (!is_int($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      case c_base_form_attributes::ATTRIBUTE_FORM_METHOD:
-        if (!this->pr_validate_value_http_method($value)) {
-          return c_base_return_false();
-        }
-        break;
-
-      default:
-        return new c_base_return_false();
-    }
-
-    $this->attribute[$attribute] = $value;
-
-    return new c_base_return_true();
-  }
-
-  /**
-   * Get the attributes assigned to this object.
-   *
-   * @return c_base_return_array
-   *   The attributes assigned to this class.
-   *   FALSE with error bit set is returned on error.
-   */
-  public function get_attributes() {
-    if (!isset($this->attributes) && !is_array($this->attributes)) {
-      $this->attributes = array();
-    }
-
-    return new c_base_return_array($this->attributes);
-  }
-}
-
index a53b1659ae9dafeccf18f4d5cf32259d2fe27f9b..7d3db7519f06ffe1d6a85089e63b9fa50c3dfd9a 100644 (file)
@@ -3,7 +3,7 @@
  * @file
  * Provides a class for managing HTML5 Markup.
  *
- * This is currently a draft/brainstorm and is subject to be completely rewritten/redesigned.
+ * This provides basic HTML5 support in a relatively straight-forward and rough way.
  *
  * @see: https://www.w3.org/TR/html5/
  */
 // include required files.
 require_once('common/base/classes/base_error.php');
 require_once('common/base/classes/base_return.php');
+require_once('common/base/classes/base_markup.php');
 
 /**
- * A generic class for HTML tag attributes.
+ * A generic container for html tags.
  *
- * This is for the internal storage of the attributes and not external.
- * Externally, every attribute type is a string.
- * The internal uses PHP structures where easily possible.
- * Special case string values, such as percentage symbols, are not used internally.
+ * This uses a simple approach to store different html tags.
  *
- * @todo: should the class name include internal?
- * @todo: should external be in the html output class?
- * @todo: what about form processing/validation (which has external values)?
- * ---- Above is old comments to be reviewed. ----
- *
- * A generic class for HTML tag attributes.
- * This should accept and handle all
- *
- * @see: https://www.w3.org/TR/html5/forms.html#forms
+ * @todo: add support for non-standard tag attributes, which will just be a string or NULL.
  */
-class c_base_html_attribute_values {
-  const TYPE_NONE                  = 0;
-  const TYPE_BOOLEAN               = 1; // https://www.w3.org/TR/html5/infrastructure.html#boolean-attributes
-  const TYPE_ENUMERATED            = 2; // https://www.w3.org/TR/html5/infrastructure.html#keywords-and-enumerated-attributes
-  const TYPE_NUMBER                = 3; // https://www.w3.org/TR/html5/infrastructure.html#numbers
-  const TYPE_NUMBER_SIGNED         = 4; // https://www.w3.org/TR/html5/infrastructure.html#signed-integers
-  const TYPE_NUMBER_UNSIGNED       = 5; // https://www.w3.org/TR/html5/infrastructure.html#non-negative-integers
-  const TYPE_NUMBER_FLOAT          = 6; // https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
-  const TYPE_NUMBER_DIMENSION      = 7; // https://www.w3.org/TR/html5/infrastructure.html#percentages-and-dimensions
-  const TYPE_NUMBER_LIST           = 8; // https://www.w3.org/TR/html5/infrastructure.html#lists-of-integers
-  const TYPE_NUMBER_DIMENSION_LIST = 9; // https://www.w3.org/TR/html5/infrastructure.html#lists-of-dimensions
-  const TYPE_DATE                  = 10; // https://www.w3.org/TR/html5/infrastructure.html#dates-and-times
-  const TYPE_DATE_MONTH            = 11; // https://www.w3.org/TR/html5/infrastructure.html#months
-  const TYPE_DATE_DATES            = 12; // https://www.w3.org/TR/html5/infrastructure.html#dates
-  const TYPE_DATE_DATES_YEARLESS   = 13; // https://www.w3.org/TR/html5/infrastructure.html#yearless-dates
-  const TYPE_DATE_TIMES            = 14; // https://www.w3.org/TR/html5/infrastructure.html#times
-  const TYPE_DATE_DATES_FLOATING   = 15; // https://www.w3.org/TR/html5/infrastructure.html#floating-dates-and-times
-  const TYPE_DATE_TIMEZONE         = 16; // https://www.w3.org/TR/html5/infrastructure.html#time-zones
-  const TYPE_DATE_GLOBAL           = 17; // https://www.w3.org/TR/html5/infrastructure.html#global-dates-and-times
-  const TYPE_DATE_WEEKS            = 18; // https://www.w3.org/TR/html5/infrastructure.html#weeks
-  const TYPE_DATE_DURATION         = 19; // https://www.w3.org/TR/html5/infrastructure.html#durations
-  const TYPE_DATE_VAGUE            = 20; // https://www.w3.org/TR/html5/infrastructure.html#vaguer-moments-in-time
-  const TYPE_COLOR                 = 21; // https://www.w3.org/TR/html5/infrastructure.html#colors
-  const TYPE_TOKENS_SPACE          = 22; // https://www.w3.org/TR/html5/infrastructure.html#space-separated-tokenss
-  const TYPE_TOKENS_COMMA          = 23; // https://www.w3.org/TR/html5/infrastructure.html#comma-separated-tokens
-  const TYPE_REFERENCE             = 24; // https://www.w3.org/TR/html5/infrastructure.html#syntax-references
-  const TYPE_MEDIA                 = 25; // https://www.w3.org/TR/html5/infrastructure.html#mq
-  const TYPE_URL                   = 26; // https://www.w3.org/TR/html5/infrastructure.html#urls
-
-  const VALUE_NONE      = 0;
-  const VALUE_TRUE      = 1;
-  const VALUE_FALSE     = 2;
-  const VALUE_INHERITED = 3;
+class c_base_html {
+  private $id;
+  private $attributes;
+  private $attributes_body;
+  private $type;
+  private $method;
+  private $headers;
+  private $body;
 
   /**
    * Class constructor.
    */
   public function __construct() {
-    // do nothing.
+    $this->id = NULL;
+    $this->attributes = array();
+    $this->attributes_body = array();
+    $this->headers = array();
+    $this->body = array();
   }
 
   /**
    * Class destructor.
    */
   public function __destruct() {
-    // do nothing.
+    unset($this->id);
+    unset($this->attributes);
+    unset($this->attributes_body);
+    unset($this->headers);
+    unset($this->body);
   }
 
   /**
-   * Validate that value is a boolean.
+   * Assign a unique numeric id to represent this form.
    *
-   * @param int $value
-   *   The value to validate.
-   * @param bool $include_inherited
-   *   (optional) When TRUE, the "Inherited" state is supported.
+   * @param int $id
+   *   The unique form tag id to assign.
    *
    * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   *   TRUE on success, FALSE otherwise.
    *   FALSE with error bit set is returned on error.
-   *
-   * see: https://www.w3.org/TR/html5/infrastructure.html#boolean-attributes
    */
-  public static function is_boolean($value, $include_inherited = FALSE) {
-    if (!is_int($value)) {
-      return new c_base_return_false();
-    }
-
-    if (!is_bool($include_inherited)) {
+  public function set_id($id) {
+    if (!is_int($id)) {
       return c_base_return_error::s_false();
     }
 
-    switch ($value) {
-      self::VALUE_NONE:
-      self::VALUE_TRUE:
-      self::VALUE_FALSE:
-        return new c_base_return_true();
-      self::VALUE_INHERITED:
-        if ($include_inherited) {
-          return new c_base_return_true();
-        }
-        break;
+    $this->id = $id;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Get the unique id assigned to this object.
+   *
+   * @return c_base_return_int|c_base_return_status
+   *   The unique numeric id assigned to this object.
+   *   FALSE is returned if no id is assigned.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_id() {
+    if (!is_int($this->id)) {
+      return c_base_return_false();
     }
 
-    return new c_base_return_false();
+    return c_base_return_int::s_new($this->id);
   }
 
   /**
-   * Validate that value is an enumerated (or keyword) value.
+   * Assign the specified attribute.
    *
-   * @param string $value
-   *   The value to validate.
+   * @param int $attribute
+   *   The attribute to assign.
+   * @param $value
+   *   The value of the attribute.
+   *   The actual value type is specific to each attribute type.
    *
    * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   *   TRUE on success, FALSE otherwise.
    *   FALSE with error bit set is returned on error.
-   *
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#keywords-and-enumerated-attributes
    */
-  public static function is_enumerated($value) {
-    if (is_string($value)) {
-      // an enumerated (or keyword) value is simply a fancy name for string/text.
-      return new c_base_return_true();
+  public function set_attribute($attribute, $value) {
+    if (!is_int($attribute)) {
+      return c_base_return_error::s_false();
     }
 
-    return new c_base_return_false();
+    return $this->p_set_attribute($attribute, $value);
   }
 
   /**
-   * Validate that value is a number value.
+   * Assign the specified attribute to the body tag.
    *
-   * @param int $value
-   *   The value to validate.
-   * @param bool $as_unsigned
-   *   (optional) Wnen TRUE, number is treated as unsigned.
-   *   When FALSE, number is treated as signed.
+   * @param int $attribute
+   *   The attribute to assign.
+   * @param $value
+   *   The value of the attribute.
+   *   The actual value type is specific to each attribute type.
    *
    * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   *   TRUE on success, FALSE otherwise.
    *   FALSE with error bit set is returned on error.
-   *
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#numbers
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#non-negative-integers
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#time-zones
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#global-dates-and-times
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#durations
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#colors
    */
-  public static function is_number($value, $as_unsigned = FALSE) {
-    if (!is_bool($as_unsigned)) {
+  public function set_attribute_body($attribute, $value) {
+    if (!is_int($attribute)) {
       return c_base_return_error::s_false();
     }
 
-    if ($as_unsigned) {
-      if (is_int($value)) {
-        if ($value >= 0) {
-          return new c_base_return_true();
-        }
-      }
-    }
-    else {
-      if (is_int($value)) {
-        return new c_base_return_true();
-      }
+    return $this->p_set_attribute($attribute, $value, TRUE);
+  }
+
+  /**
+   * Get the attributes assigned to this object.
+   *
+   * @return c_base_return_array
+   *   The attributes assigned to this class.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_attributes() {
+    if (!isset($this->attributes) && !is_array($this->attributes)) {
+      $this->attributes = array();
     }
 
-    return new c_base_return_false();
+    return c_base_return_array::s_new($this->attributes);
   }
 
   /**
-   * Validate that value is a float value.
+   * Get the value of a single attribute assigned to this object.
    *
-   * @param float $value
-   *   The value to validate.
+   * @param int $attribute
+   *   The attribute to assign.
    *
-   * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   * @return c_base_return_int|c_base_return_string|c_base_return_bool|c_base_return_status
+   *   The value assigned to the attribte (the data type is different per attribute).
+   *   FALSE is returned if the element does not exist.
    *   FALSE with error bit set is returned on error.
-   *
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
    */
-  public static function is_float($value) {
-    if (is_float($value)) {
-      return new c_base_return_true();
+  public function get_attribute($attribute) {
+    if (!is_int($attribute)) {
+      return c_base_return_error::s_false();
     }
 
-    return new c_base_return_false();
+    return $this->p_get_attribute($attribute);
   }
 
   /**
-   * Validate that value is an unsigned number value.
+   * Get the value of a single attribute assigned to this object.
    *
-   * This is functionaly the same as a float or an unsigned integer.
+   * These attributes are assigned to the body tag.
    *
-   * @param float $value
-   *   The value to validate.
+   * @param int $attribute
+   *   The attribute to assign.
    *
-   * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   * @return c_base_return_int|c_base_return_string|c_base_return_bool|c_base_return_status
+   *   The value assigned to the attribte (the data type is different per attribute).
+   *   FALSE is returned if the element does not exist.
    *   FALSE with error bit set is returned on error.
-   *
-   * @see: self::is_float()
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#percentages-and-dimensions
    */
-  public static function is_dimension($value) {
-    if (is_int($value) || is_float($value)) {
-      if ($value >= 0) {
-        return new c_base_return_true();
-      }
+  public function get_attribute_body($attribute) {
+    if (!is_int($attribute)) {
+      return c_base_return_error::s_false();
     }
 
-    return new c_base_return_false();
+    return $this->p_get_attribute($attribute, TRUE);
   }
 
   /**
-   * Validate that value is a list of numbers.
+   * Assign a tag to the HTML.
    *
-   * @param array $value
-   *   The value to validate.
+   * @param c_base_markup_tag $tag
+   *   The html tag tp assign.
+   * @param int|null $delta
+   *   (optional) A position in the page to assign the tag.
+   *   If NULL, then the tag is appended.
    *
    * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   *   TRUE on success, FALSE otherwise.
    *   FALSE with error bit set is returned on error.
-   *
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#lists-of-integers
    */
-  public static function is_number_list($value) {
-    if (!is_array($value)) {
-      return new c_base_return_false();
+  public function set_tag($tag, $delta = NULL) {
+    if (!($tag instanceof c_base_markup_tag)) {
+      return c_base_return_error::s_false();
     }
 
-    foreach ($value as $part) {
-      if (!is_int($part)) {
-        unset($part);
-        return c_base_return_false();
-      }
+    if (!is_null($delta) && !is_int($delta)) {
+      return c_base_return_error::s_false();
     }
-    unset($part);
 
+    if (!is_array($this->body)) {
+      $this->body = array();
+    }
+
+    if (is_null($delta)) {
+      $this->body[] = $tag;
+    }
+    else {
+      $this->body[$delta] = $tag;
+    }
     return new c_base_return_true();
   }
 
   /**
-   * Validate that value is a list of dimensions.
+   * Get tag from the HTML.
    *
-   * @param array $value
-   *   The value to validate.
+   * @param int $delta
+   *   The position in the array of the tag to get.
    *
-   * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   * @return c_base_markup_tag_return|c_base_return_status
+   *   The tag, if found at delta.
+   *   FALSE is returned if no tag is at delta.
    *   FALSE with error bit set is returned on error.
-   *
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#lists-of-dimensions
    */
-  public static function is_dimension_list($value) {
-    if (!is_array($value)) {
-      return new c_base_return_false();
+  public function get_tag($delta) {
+    if (!is_int($delta)) {
+      return c_base_return_error::s_false();
     }
 
-    foreach ($value as $part) {
-      if (!is_int($part) && !is_float($part)) {
-        unset($part);
-        return c_base_return_false();
-      }
+    if (!array_key_exists($delta, $this->body)) {
+      return new c_base_return_false();
     }
-    unset($part);
 
-    return new c_base_return_true();
+    return c_base_markup_tag_return::s_new($this->body[$delta]);
   }
 
   /**
-   * Validate that value is a date or time value.
+   * Get all body assigned to the HTML.
    *
-   * A date or time is expected to be a unix timestamp, which is a valid integer.
+   * @return c_base_return_array
+   *   FALSE is returned if no tag is at delta.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_body() {
+    if (!is_array($this->body)) {
+      return c_base_return_array::s_new(array());
+    }
+
+    return c_base_return_array::s_new($this->body);
+  }
+
+  /**
+   * Assign a header to the HTML.
    *
-   * @param int $value
-   *   The value to validate.
-   * @param bool $as_float
-   *   (optional) When TRUE, allow the date to be a float.
-   *   When FALSE, date is treated as an integer.
+   * @param c_base_markup_tag $header
+   *   The html header tp assign.
+   * @param int|null $delta
+   *   (optional) A position in the page to assign the header.
+   *   If NULL, then the header is appended.
    *
    * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   *   TRUE on success, FALSE otherwise.
    *   FALSE with error bit set is returned on error.
-   *
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#dates-and-times
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#months
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#floating-dates-and-times
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#vaguer-moments-in-time
    */
-  public static function is_date($value, $as_float = FALSE) {
-    if (!is_bool($as_float)) {
+  public function set_header($header, $delta = NULL) {
+    if (!($header instanceof c_base_markup_tag)) {
       return c_base_return_error::s_false();
     }
 
-    if ($as_float) {
-      if (is_float($value)) {
-        return new c_base_return_true();
-      }
+    if (!is_null($delta) && !is_int($delta)) {
+      return c_base_return_error::s_false();
     }
-    else {
-      if (is_int($value)) {
-        return new c_base_return_true();
-      }
+
+    // only certain header types are allowed.
+    $type = $header->get_type()->get_value_exact();
+    switch ($type) {
+      case c_base_markup_tag::TYPE_BASE:
+      case c_base_markup_tag::TYPE_LINK:
+      case c_base_markup_tag::TYPE_META:
+      case c_base_markup_tag::TYPE_NO_SCRIPT:
+      case c_base_markup_tag::TYPE_SCRIPT:
+      case c_base_markup_tag::TYPE_STYLE:
+      case c_base_markup_tag::TYPE_TITLE:
+        break;
+      default:
+        return new c_base_retun_false();
     }
 
-    return new c_base_return_false();
+    if (!is_array($this->headers)) {
+      $this->headers = array();
+    }
+
+    if (is_null($delta)) {
+      $this->headers[] = $header;
+    }
+    else {
+      $this->headers[$delta] = $header;
+    }
+    return new c_base_return_true();
   }
 
   /**
-   * Validate that value is a list of dates or times.
+   * Get header from the HTML.
    *
-   * @param array $value
-   *   The value to validate.
-   * @param bool $as_float
-   *   (optional) When TRUE, allow the date to be a float.
-   *   When FALSE, date is treated as an integer.
+   * @param int $delta
+   *   The position in the array of the header to get.
    *
-   * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   * @return c_base_markup_tag_return|c_base_return_status
+   *   The header, if found at delta.
+   *   FALSE is returned if no header is at delta.
    *   FALSE with error bit set is returned on error.
-   *
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#dates
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#yearless-dates
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#times
    */
-  public static function is_date_list($value, $as_float = FALSE) {
-    if (!is_bool($as_float)) {
+  public function get_header($delta) {
+    if (!is_int($delta)) {
       return c_base_return_error::s_false();
     }
 
-    if (!is_array($value)) {
+    if (!array_key_exists($delta, $this->headers)) {
       return new c_base_return_false();
     }
 
-    if ($as_float) {
-      foreach ($value as $part) {
-        if (!is_float($part)) {
-          unset($part);
-          return c_base_return_false();
-        }
-      }
-      unset($part);
+    return c_base_markup_tag_return::s_new($this->headers[$delta]);
+  }
+
+  /**
+   * Get all headers assigned to the HTML.
+   *
+   * @return c_base_return_array
+   *   FALSE is returned if no header is at delta.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_headers() {
+    if (!is_array($this->headers)) {
+      return c_base_return_array::s_new(array());
     }
-    else {
-      foreach ($value as $part) {
-        if (!is_int($part)) {
-          unset($part);
-          return c_base_return_false();
-        }
-      }
-      unset($part);
+
+    return c_base_return_array::s_new($this->headers);
+  }
+
+  /**
+   * Protected function for mime values.
+   *
+   * @param int $value
+   *   The value of the attribute populate from c_base_mime.
+   *
+   * @return bool
+   *   TRUE on success.
+   *   FALSE otherwise.
+   */
+  protected function pr_validate_value_mime_type($value) {
+    if (!is_int($value)) {
+      return FALSE;
     }
 
-    return new c_base_return_true();
+    switch ($value) {
+      case c_base_mime::CATEGORY_UNKNOWN:
+      case c_base_mime::CATEGORY_PROVIDED:
+      case c_base_mime::CATEGORY_STREAM:
+      case c_base_mime::CATEGORY_TEXT:
+      case c_base_mime::CATEGORY_IMAGE:
+      case c_base_mime::CATEGORY_AUDIO:
+      case c_base_mime::CATEGORY_VIDEO:
+      case c_base_mime::CATEGORY_DOCUMENT:
+      case c_base_mime::CATEGORY_CONTAINER:
+      case c_base_mime::CATEGORY_APPLICATION:
+      case c_base_mime::TYPE_UNKNOWN:
+      case c_base_mime::TYPE_PROVIDED:
+      case c_base_mime::TYPE_STREAM:
+      case c_base_mime::TYPE_MULTIPART:
+      case c_base_mime::TYPE_TEXT_PLAIN:
+      case c_base_mime::TYPE_TEXT_HTML:
+      case c_base_mime::TYPE_TEXT_RSS:
+      case c_base_mime::TYPE_TEXT_ICAL:
+      case c_base_mime::TYPE_TEXT_CSV:
+      case c_base_mime::TYPE_TEXT_XML:
+      case c_base_mime::TYPE_TEXT_CSS:
+      case c_base_mime::TYPE_TEXT_JS:
+      case c_base_mime::TYPE_TEXT_JSON:
+      case c_base_mime::TYPE_TEXT_RICH:
+      case c_base_mime::TYPE_TEXT_XHTML:
+      case c_base_mime::TYPE_TEXT_PS:
+      case c_base_mime::TYPE_IMAGE_PNG:
+      case c_base_mime::TYPE_IMAGE_GIF:
+      case c_base_mime::TYPE_IMAGE_JPEG:
+      case c_base_mime::TYPE_IMAGE_BMP:
+      case c_base_mime::TYPE_IMAGE_SVG:
+      case c_base_mime::TYPE_IMAGE_TIFF:
+      case c_base_mime::TYPE_AUDIO_WAV:
+      case c_base_mime::TYPE_AUDIO_OGG:
+      case c_base_mime::TYPE_AUDIO_MP3:
+      case c_base_mime::TYPE_AUDIO_MP4:
+      case c_base_mime::TYPE_AUDIO_MIDI:
+      case c_base_mime::TYPE_VIDEO_MPEG:
+      case c_base_mime::TYPE_VIDEO_OGG:
+      case c_base_mime::TYPE_VIDEO_H264:
+      case c_base_mime::TYPE_VIDEO_QUICKTIME:
+      case c_base_mime::TYPE_VIDEO_DV:
+      case c_base_mime::TYPE_VIDEO_JPEG:
+      case c_base_mime::TYPE_VIDEO_WEBM:
+      case c_base_mime::TYPE_DOCUMENT_LIBRECHART:
+      case c_base_mime::TYPE_DOCUMENT_LIBREFORMULA:
+      case c_base_mime::TYPE_DOCUMENT_LIBREGRAPHIC:
+      case c_base_mime::TYPE_DOCUMENT_LIBREPRESENTATION:
+      case c_base_mime::TYPE_DOCUMENT_LIBRESPREADSHEET:
+      case c_base_mime::TYPE_DOCUMENT_LIBRETEXT:
+      case c_base_mime::TYPE_DOCUMENT_LIBREHTML:
+      case c_base_mime::TYPE_DOCUMENT_PDF:
+      case c_base_mime::TYPE_DOCUMENT_ABIWORD:
+      case c_base_mime::TYPE_DOCUMENT_MSWORD:
+      case c_base_mime::TYPE_DOCUMENT_MSEXCEL:
+      case c_base_mime::TYPE_DOCUMENT_MSPOWERPOINT:
+      case c_base_mime::TYPE_CONTAINER_TAR:
+      case c_base_mime::TYPE_CONTAINER_CPIO:
+      case c_base_mime::TYPE_CONTAINER_JAVA:
+        break;
+      default:
+        return FALSE;
+    }
+
+    return TRUE;
   }
 
   /**
-   * Validate that value is a token value.
+   * Protected function for character set values.
    *
-   * This processes a single token.
-   * There are two types:
-   * 1) Space Separated
-   * 2) Comma Separated
+   * @param int $value
+   *   The value of the attribute populate from c_base_charset.
    *
-   * Perhaps I am misreading but the standard does not seem clear about other symbols.
-   * For now, I am just allowing them (I can come back later and fix this at any time).
+   * @return bool
+   *   TRUE on success.
+   *   FALSE otherwise.
+   */
+  protected function pr_validate_value_character_set($value) {
+    if (!is_int($value)) {
+      return FALSE;
+    }
+
+    switch ($value) {
+      case c_base_charset::UNDEFINED:
+      case c_base_charset::ASCII:
+      case c_base_charset::UTF_8:
+      case c_base_charset::UTF_16:
+      case c_base_charset::UTF_32:
+      case c_base_charset::ISO_8859_1:
+      case c_base_charset::ISO_8859_2:
+      case c_base_charset::ISO_8859_3:
+      case c_base_charset::ISO_8859_4:
+      case c_base_charset::ISO_8859_5:
+      case c_base_charset::ISO_8859_6:
+      case c_base_charset::ISO_8859_7:
+      case c_base_charset::ISO_8859_8:
+      case c_base_charset::ISO_8859_9:
+      case c_base_charset::ISO_8859_10:
+      case c_base_charset::ISO_8859_11:
+      case c_base_charset::ISO_8859_12:
+      case c_base_charset::ISO_8859_13:
+      case c_base_charset::ISO_8859_14:
+      case c_base_charset::ISO_8859_15:
+      case c_base_charset::ISO_8859_16:
+        break;
+      default:
+        return FALSE;
+    }
+
+    return TRUE;
+  }
+
+
+
+  /**
+   * Get the value of a single attribute assigned to this object.
    *
-   * @param string $value
-   *   The value to validate.
-   * @param bool $comma_separated
-   *   (optional) When TRUE, token is treated as a comma separated token.
-   *   When FALSE, token is treated as space separated token.
+   * @param int $attribute
+   *   The attribute to assign.
+   * @param bool $body
+   *   (optional) When TRUE, the body attributes are returned.
+   *   When FALSE, the normal attributes are returned.
    *
-   * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   * @return c_base_return_int|c_base_return_string|c_base_return_bool|c_base_return_status
+   *   The value assigned to the attribte (the data type is different per attribute).
+   *   FALSE is returned if the element does not exist.
    *   FALSE with error bit set is returned on error.
-   *
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#space-separated-tokens
-   * @see: https://www.w3.org/TR/html5/infrastructure.html#comma-separated-tokens
    */
-  public static function is_token($value, $comma_separated = FALSE) {
-    if (!is_bool($comma_separated)) {
-      return c_base_return_error::s_false();
+  private function p_get_attribute($attribute, $body = FALSE) {
+    if ($body) {
+      if (!isset($this->attributes_body) && !is_array($this->attributes_body)) {
+        $this->attributes_body = array();
+      }
+    }
+    else {
+      if (!isset($this->attributes) && !is_array($this->attributes)) {
+        $this->attributes = array();
+      }
     }
 
-    if (is_string($value)) {
-      if ($comma_Separated) {
-        if (strpos($value, ',') !== FALSE) {
-          return new c_base_return_true();
-        }
+    if ($body) {
+      if (!array_key_exists($attribute, $this->attributes_body)) {
+        return new c_base_return_false();
       }
-      else {
-        if (preg_match('/\s/i', $value) === 0) {
-          return new c_base_return_true();
-        }
+    }
+    else {
+      if (!array_key_exists($attribute, $this->attributes)) {
+        return new c_base_return_false();
       }
     }
 
+    switch ($attribute) {
+      case c_base_markup_attributes::ATTRIBUTE_NONE:
+        // should not be possible, so consider this an error (attributes set to NONE are actually unset from the array).
+        return c_base_return_error::s_false();
+
+      case c_base_markup_attributes::ATTRIBUTE_ABBR:
+      case c_base_markup_attributes::ATTRIBUTE_ACCESS_KEY:
+      case c_base_markup_attributes::ATTRIBUTE_ACTION:
+      case c_base_markup_attributes::ATTRIBUTE_ALTERNATE:
+      case c_base_markup_attributes::ATTRIBUTE_BY:
+      case c_base_markup_attributes::ATTRIBUTE_CALCULATE_MODE:
+      case c_base_markup_attributes::ATTRIBUTE_CLIP_PATH:
+      case c_base_markup_attributes::ATTRIBUTE_CLIP_PATH_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_CITE:
+      case c_base_markup_attributes::ATTRIBUTE_COLOR:
+      case c_base_markup_attributes::ATTRIBUTE_COORDINATES:
+      case c_base_markup_attributes::ATTRIBUTE_CONTENT:
+      case c_base_markup_attributes::ATTRIBUTE_CONTENT_EDITABLE:
+      case c_base_markup_attributes::ATTRIBUTE_CROSS_ORIGIN:
+      case c_base_markup_attributes::ATTRIBUTE_D:
+      case c_base_markup_attributes::ATTRIBUTE_DATA:
+      case c_base_markup_attributes::ATTRIBUTE_DATE_TIME:
+      case c_base_markup_attributes::ATTRIBUTE_DIRECTION:
+      case c_base_markup_attributes::ATTRIBUTE_DIRECTION_NAME:
+      case c_base_markup_attributes::ATTRIBUTE_DOWNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_DURATION:
+      case c_base_markup_attributes::ATTRIBUTE_FILL:
+      case c_base_markup_attributes::ATTRIBUTE_FILL_RULE:
+      case c_base_markup_attributes::ATTRIBUTE_FILL_STROKE:
+      case c_base_markup_attributes::ATTRIBUTE_FONT_SPECIFICATION:
+      case c_base_markup_attributes::ATTRIBUTE_FOR:
+      case c_base_markup_attributes::ATTRIBUTE_FORM:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_ACTION:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_TARGET:
+      case c_base_markup_attributes::ATTRIBUTE_FORMAT:
+      case c_base_markup_attributes::ATTRIBUTE_FROM:
+      case c_base_markup_attributes::ATTRIBUTE_GLYPH_REFERENCE:
+      case c_base_markup_attributes::ATTRIBUTE_GRADIANT_TRANSFORM:
+      case c_base_markup_attributes::ATTRIBUTE_GRADIANT_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_GRAPHICS:
+      case c_base_markup_attributes::ATTRIBUTE_HEADERS:
+      case c_base_markup_attributes::ATTRIBUTE_HEIGHT:
+      case c_base_markup_attributes::ATTRIBUTE_HREF:
+      case c_base_markup_attributes::ATTRIBUTE_HREF_NO:
+      case c_base_markup_attributes::ATTRIBUTE_HTTP_EQUIV:
+      case c_base_markup_attributes::ATTRIBUTE_ICON:
+      case c_base_markup_attributes::ATTRIBUTE_ID:
+      case c_base_markup_attributes::ATTRIBUTE_IN:
+      case c_base_markup_attributes::ATTRIBUTE_IN_2:
+      case c_base_markup_attributes::ATTRIBUTE_IS_MAP:
+      case c_base_markup_attributes::ATTRIBUTE_KEY_POINTS:
+      case c_base_markup_attributes::ATTRIBUTE_KEY_TYPE:
+      case c_base_markup_attributes::ATTRIBUTE_KIND:
+      case c_base_markup_attributes::ATTRIBUTE_LABEL:
+      case c_base_markup_attributes::ATTRIBUTE_LENGTH_ADJUST:
+      case c_base_markup_attributes::ATTRIBUTE_LIST:
+      case c_base_markup_attributes::ATTRIBUTE_LOCAL:
+      case c_base_markup_attributes::ATTRIBUTE_LONG_DESCRIPTION:
+      case c_base_markup_attributes::ATTRIBUTE_MARKERS:
+      case c_base_markup_attributes::ATTRIBUTE_MARKER_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_MASK_CONTENT_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_MASK_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_MAXIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_MEDIA:
+      case c_base_markup_attributes::ATTRIBUTE_METHOD:
+      case c_base_markup_attributes::ATTRIBUTE_MODE:
+      case c_base_markup_attributes::ATTRIBUTE_MINIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_NAME:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ABORT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_AFTER_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_start:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ABORT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_AFTER_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_start:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BLUR:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CANCEL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CLICK:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CONTEXT_MENU:
+      case c_base_markup_attributes::ATTRIBUTE_ON_COPY:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY_THROUGH:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CUE_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DOUBLE_CLICK:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_ENTER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_LEAVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_OVER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_START:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DROP:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DURATION_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_EMPTIED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ENDED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ERROR:
+      case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS:
+      case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS_IN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS_OUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_HASH_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_INPUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_INSTALLED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_INVALID:
+      case c_base_markup_attributes::ATTRIBUTE_ON_KEY_DOWN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_KEY_PRESS:
+      case c_base_markup_attributes::ATTRIBUTE_ON_KEY_UP:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOADED_DATA:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOADED_META_DATA:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOAD_START:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_DOWN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_ENTER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_LEAVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_MOVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OVER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_UP:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MESSAGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_WHEEL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_OPEN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ONLINE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_OFFLINE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PAGE_SHOW:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PAGE_HIDE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PASTE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PAUSE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PLAY:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PLAYING:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PROGRESS:
+      case c_base_markup_attributes::ATTRIBUTE_ON_POP_STATE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RATED_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RESIZE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RESET:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RATE_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SCROLL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SEARCH:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SELECT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SUBMIT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SEEKED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SEEKING:
+      case c_base_markup_attributes::ATTRIBUTE_ON_STALLED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SUSPEND:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SHOW:
+      case c_base_markup_attributes::ATTRIBUTE_ON_STORAGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TIME_UPDATE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TRANSITION_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOGGLE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_CANCEL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_MOVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_START:
+      case c_base_markup_attributes::ATTRIBUTE_ON_UNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_VOLUME_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_WAITING:
+      case c_base_markup_attributes::ATTRIBUTE_ON_WHEEL:
+      case c_base_markup_attributes::ATTRIBUTE_OFFSET:
+      case c_base_markup_attributes::ATTRIBUTE_OPEN:
+      case c_base_markup_attributes::ATTRIBUTE_ORIENTATION:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN_CONTENT_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN_TRANSFORM:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_PATH:
+      case c_base_markup_attributes::ATTRIBUTE_PATH_LENGTH:
+      case c_base_markup_attributes::ATTRIBUTE_PLACE_HOLDER:
+      case c_base_markup_attributes::ATTRIBUTE_POINTS:
+      case c_base_markup_attributes::ATTRIBUTE_POSTER:
+      case c_base_markup_attributes::ATTRIBUTE_PRELOAD:
+      case c_base_markup_attributes::ATTRIBUTE_PRESERVE_ASPECT_RATIO:
+      case c_base_markup_attributes::ATTRIBUTE_RADIO_GROUP:
+      case c_base_markup_attributes::ATTRIBUTE_SANDBOX:
+      case c_base_markup_attributes::ATTRIBUTE_SCOPE:
+      case c_base_markup_attributes::ATTRIBUTE_SHAPE:
+      case c_base_markup_attributes::ATTRIBUTE_REL:
+      case c_base_markup_attributes::ATTRIBUTE_RENDERING_INTENT:
+      case c_base_markup_attributes::ATTRIBUTE_REPEAT_COUNT:
+      case c_base_markup_attributes::ATTRIBUTE_ROLE:
+      case c_base_markup_attributes::ATTRIBUTE_ROTATE:
+      case c_base_markup_attributes::ATTRIBUTE_SIZE:
+      case c_base_markup_attributes::ATTRIBUTE_SIZES:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE_DOCUMENT:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE_SET:
+      case c_base_markup_attributes::ATTRIBUTE_SPAN:
+      case c_base_markup_attributes::ATTRIBUTE_SPREAD_METHOD:
+      case c_base_markup_attributes::ATTRIBUTE_STOP_COLOR:
+      case c_base_markup_attributes::ATTRIBUTE_STOP_OPACITY:
+      case c_base_markup_attributes::ATTRIBUTE_STYLE:
+      case c_base_markup_attributes::ATTRIBUTE_TARGET:
+      case c_base_markup_attributes::ATTRIBUTE_TEXT_LENGTH:
+      case c_base_markup_attributes::ATTRIBUTE_TEXT_CONTENT_ELEMENTS:
+      case c_base_markup_attributes::ATTRIBUTE_TITLE:
+      case c_base_markup_attributes::ATTRIBUTE_TRANSFORM:
+      case c_base_markup_attributes::ATTRIBUTE_TRANSLATE:
+      case c_base_markup_attributes::ATTRIBUTE_TO:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_BUTTON:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_LABEL:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_LIST:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_SVG:
+      case c_base_markup_attributes::ATTRIBUTE_USE_MAP:
+      case c_base_markup_attributes::ATTRIBUTE_VALUE:
+      case c_base_markup_attributes::ATTRIBUTE_VIEW_BOX:
+      case c_base_markup_attributes::ATTRIBUTE_WIDTH:
+      case c_base_markup_attributes::ATTRIBUTE_WRAP:
+      case c_base_markup_attributes::ATTRIBUTE_XML:
+      case c_base_markup_attributes::ATTRIBUTE_XMLNS:
+      case c_base_markup_attributes::ATTRIBUTE_XMLNS_XLINK:
+      case c_base_markup_attributes::ATTRIBUTE_XML_SPACE:
+      case c_base_markup_attributes::ATTRIBUTE_ZOOM_AND_PAN:
+        if ($body) {
+          return c_base_return_string::s_new($this->attributes_body[$attribute]);
+        }
+        else {
+          return c_base_return_string::s_new($this->attributes[$attribute]);
+        }
+
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_ATOMIC:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_AUTOCOMPLETE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_ACTIVE_DESCENDANT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_BUSY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_CHECKED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_CONTROLS:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_DESCRIBED_BY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_DISABLED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_DROP_EFFECT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_EXPANDED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_FLOW_TO:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_GRABBED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_HAS_POPUP:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_HIDDEN:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_INVALID:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LABEL:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LABELLED_BY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LEVEL:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LIVE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_LINE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_SELECTABLE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_ORIENTATION:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_OWNS:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_POSITION_INSET:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_PRESSED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_READONLY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_RELEVANT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_REQUIRED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_SELECTED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_SET_SIZE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_SORT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MAXIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MINIMIM:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_NOW:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_TEXT:
+        if ($body) {
+          return c_base_return_string::s_new($this->attributes_body[$attribute]);
+        }
+        else {
+          return c_base_return_string::s_new($this->attributes[$attribute]);
+        }
+
+      case c_base_markup_attributes::ATTRIBUTE_ASYNCHRONOUS:
+      case c_base_markup_attributes::ATTRIBUTE_ATTRIBUTE_NAME:
+      case c_base_markup_attributes::ATTRIBUTE_AUTO_COMPLETE:
+      case c_base_markup_attributes::ATTRIBUTE_AUTO_FOCUS:
+      case c_base_markup_attributes::ATTRIBUTE_AUTO_PLAY:
+      case c_base_markup_attributes::ATTRIBUTE_CHALLENGE:
+      case c_base_markup_attributes::ATTRIBUTE_CONTROLS:
+      case c_base_markup_attributes::ATTRIBUTE_CHECKED:
+      case c_base_markup_attributes::ATTRIBUTE_DEFAULT:
+      case c_base_markup_attributes::ATTRIBUTE_DEFER:
+      case c_base_markup_attributes::ATTRIBUTE_DISABLED:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_NO_VALIDATE:
+      case c_base_markup_attributes::ATTRIBUTE_HIDDEN:
+      case c_base_markup_attributes::ATTRIBUTE_LOOP:
+      case c_base_markup_attributes::ATTRIBUTE_MULTIPLE:
+      case c_base_markup_attributes::ATTRIBUTE_MUTED:
+      case c_base_markup_attributes::ATTRIBUTE_NO_VALIDATE:
+      case c_base_markup_attributes::ATTRIBUTE_READONLY:
+      case c_base_markup_attributes::ATTRIBUTE_REQUIRED:
+      case c_base_markup_attributes::ATTRIBUTE_REVERSED:
+      case c_base_markup_attributes::ATTRIBUTE_SCOPED:
+      case c_base_markup_attributes::ATTRIBUTE_SELECTED:
+      case c_base_markup_attributes::ATTRIBUTE_SORTABLE:
+      case c_base_markup_attributes::ATTRIBUTE_SORTED:
+      case c_base_markup_attributes::ATTRIBUTE_SPELLCHECK:
+        if ($body) {
+          return c_base_return_bool::s_new($this->attributes_body[$attribute]);
+        }
+        else {
+          return c_base_return_bool::s_new($this->attributes[$attribute]);
+        }
+
+      case c_base_markup_attributes::ATTRIBUTE_ACCEPT:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_ENCODE_TYPE:
+      case c_base_markup_attributes::ATTRIBUTE_ENCODING_TYPE:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE:
+        if ($body) {
+          return c_base_return_int::s_new($this->attributes_body[$attribute]);
+        }
+        else {
+          return c_base_return_int::s_new($this->attributes[$attribute]);
+        }
+
+      case c_base_markup_attributes::ATTRIBUTE_ACCEPT_CHARACTER_SET:
+      case c_base_markup_attributes::ATTRIBUTE_CHARACTER_SET:
+        if ($body) {
+          return c_base_return_int::s_new($this->attributes_body[$attribute]);
+        }
+        else {
+          return c_base_return_int::s_new($this->attributes[$attribute]);
+        }
+
+      case c_base_markup_attributes::ATTRIBUTE_CENTER_X:
+      case c_base_markup_attributes::ATTRIBUTE_CENTER_Y:
+      case c_base_markup_attributes::ATTRIBUTE_COLUMNS:
+      case c_base_markup_attributes::ATTRIBUTE_COLUMN_SPAN:
+      case c_base_markup_attributes::ATTRIBUTE_D_X:
+      case c_base_markup_attributes::ATTRIBUTE_D_Y:
+      case c_base_markup_attributes::ATTRIBUTE_FOCUS_X:
+      case c_base_markup_attributes::ATTRIBUTE_FOCUS_Y:
+      case c_base_markup_attributes::ATTRIBUTE_HIGH:
+      case c_base_markup_attributes::ATTRIBUTE_HREF_LANGUAGE:
+      case c_base_markup_attributes::ATTRIBUTE_LANGUAGE:
+      case c_base_markup_attributes::ATTRIBUTE_LOW:
+      case c_base_markup_attributes::ATTRIBUTE_MARKER_HEIGHT:
+      case c_base_markup_attributes::ATTRIBUTE_MARKER_WIDTH:
+      case c_base_markup_attributes::ATTRIBUTE_MAXIMUM_NUMBER:
+      case c_base_markup_attributes::ATTRIBUTE_MAXIMUM_LENGTH:
+      case c_base_markup_attributes::ATTRIBUTE_MINIMUM_NUMBER:
+      case c_base_markup_attributes::ATTRIBUTE_OPTIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_RADIUS:
+      case c_base_markup_attributes::ATTRIBUTE_RADIUS_X:
+      case c_base_markup_attributes::ATTRIBUTE_RADIUS_Y:
+      case c_base_markup_attributes::ATTRIBUTE_REFERENCE_X:
+      case c_base_markup_attributes::ATTRIBUTE_REFERENCE_Y:
+      case c_base_markup_attributes::ATTRIBUTE_ROWS:
+      case c_base_markup_attributes::ATTRIBUTE_ROW_SPAN:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE_LANGUAGE:
+      case c_base_markup_attributes::ATTRIBUTE_START:
+      case c_base_markup_attributes::ATTRIBUTE_STEP:
+      case c_base_markup_attributes::ATTRIBUTE_TAB_INDEX:
+      case c_base_markup_attributes::ATTRIBUTE_VALUE_NUMBER:
+      case c_base_markup_attributes::ATTRIBUTE_X:
+      case c_base_markup_attributes::ATTRIBUTE_X_1:
+      case c_base_markup_attributes::ATTRIBUTE_X_2:
+      case c_base_markup_attributes::ATTRIBUTE_X_LINK_ACTUATE:
+      case c_base_markup_attributes::ATTRIBUTE_X_LINK_HREF:
+      case c_base_markup_attributes::ATTRIBUTE_X_LINK_SHOW:
+      case c_base_markup_attributes::ATTRIBUTE_Y:
+      case c_base_markup_attributes::ATTRIBUTE_Y_1:
+      case c_base_markup_attributes::ATTRIBUTE_Y_2:
+        if ($body) {
+          return c_base_return_int::s_new($this->attributes_body[$attribute]);
+        }
+        else {
+          return c_base_return_int::s_new($this->attributes[$attribute]);
+        }
+
+      case c_base_markup_attributes::ATTRIBUTE_FORM_METHOD:
+        if ($body) {
+          return c_base_return_int::s_new($this->attributes_body[$attribute]);
+        }
+        else {
+          return c_base_return_int::s_new($this->attributes[$attribute]);
+        }
+
+      case c_base_markup_attributes::ATTRIBUTE_CLASS:
+        if ($body) {
+          return c_base_return_array::s_new($this->attributes_body[$attribute]);
+        }
+        else {
+          return c_base_return_array::s_new($this->attributes[$attribute]);
+        }
+
+      default:
+        return new c_base_return_false();
+    }
+
     return new c_base_return_false();
   }
 
   /**
-   * Validate that value is a list of syntax references.
+   * Assign the specified tag.
    *
-   * @param array $value
-   *   The value to validate.
+   * @param int $attribute
+   *   The attribute to assign.
+   * @param $value
+   *   The value of the attribute.
+   *   The actual value type is specific to each attribute type.
+   * @param bool $body
+   *   (optional) When TRUE, the body attributes are assigned.
+   *   When FALSE, the normal attributes are assigned.
    *
    * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
+   *   TRUE on success, FALSE otherwise.
    *   FALSE with error bit set is returned on error.
-   *
-   * https://www.w3.org/TR/html5/infrastructure.html#syntax-references
    */
-  public static function is_syntax_reference($value) {
-    if (!is_string($value)) {
-      return new c_base_return_false();
+  private function p_set_attribute($attribute, $value, $body = FALSE) {
+    switch ($attribute) {
+      case c_base_markup_attributes::ATTRIBUTE_NONE:
+        unset($this->attribute[$attribute]);
+        return new c_base_return_true();
+
+      case c_base_markup_attributes::ATTRIBUTE_ABBR:
+      case c_base_markup_attributes::ATTRIBUTE_ACCESS_KEY:
+      case c_base_markup_attributes::ATTRIBUTE_ACTION:
+      case c_base_markup_attributes::ATTRIBUTE_ALTERNATE:
+      case c_base_markup_attributes::ATTRIBUTE_BY:
+      case c_base_markup_attributes::ATTRIBUTE_CALCULATE_MODE:
+      case c_base_markup_attributes::ATTRIBUTE_CLIP_PATH:
+      case c_base_markup_attributes::ATTRIBUTE_CLIP_PATH_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_CITE:
+      case c_base_markup_attributes::ATTRIBUTE_COLOR:
+      case c_base_markup_attributes::ATTRIBUTE_COORDINATES:
+      case c_base_markup_attributes::ATTRIBUTE_CONTENT:
+      case c_base_markup_attributes::ATTRIBUTE_CONTENT_EDITABLE:
+      case c_base_markup_attributes::ATTRIBUTE_CROSS_ORIGIN:
+      case c_base_markup_attributes::ATTRIBUTE_D:
+      case c_base_markup_attributes::ATTRIBUTE_DATA:
+      case c_base_markup_attributes::ATTRIBUTE_DATE_TIME:
+      case c_base_markup_attributes::ATTRIBUTE_DIRECTION:
+      case c_base_markup_attributes::ATTRIBUTE_DIRECTION_NAME:
+      case c_base_markup_attributes::ATTRIBUTE_DOWNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_DURATION:
+      case c_base_markup_attributes::ATTRIBUTE_FILL:
+      case c_base_markup_attributes::ATTRIBUTE_FILL_RULE:
+      case c_base_markup_attributes::ATTRIBUTE_FILL_STROKE:
+      case c_base_markup_attributes::ATTRIBUTE_FONT_SPECIFICATION:
+      case c_base_markup_attributes::ATTRIBUTE_FOR:
+      case c_base_markup_attributes::ATTRIBUTE_FORM:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_ACTION:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_TARGET:
+      case c_base_markup_attributes::ATTRIBUTE_FORMAT:
+      case c_base_markup_attributes::ATTRIBUTE_FROM:
+      case c_base_markup_attributes::ATTRIBUTE_GLYPH_REFERENCE:
+      case c_base_markup_attributes::ATTRIBUTE_GRADIANT_TRANSFORM:
+      case c_base_markup_attributes::ATTRIBUTE_GRADIANT_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_GRAPHICS:
+      case c_base_markup_attributes::ATTRIBUTE_HEADERS:
+      case c_base_markup_attributes::ATTRIBUTE_HEIGHT:
+      case c_base_markup_attributes::ATTRIBUTE_HREF:
+      case c_base_markup_attributes::ATTRIBUTE_HREF_NO:
+      case c_base_markup_attributes::ATTRIBUTE_HTTP_EQUIV:
+      case c_base_markup_attributes::ATTRIBUTE_ICON:
+      case c_base_markup_attributes::ATTRIBUTE_ID:
+      case c_base_markup_attributes::ATTRIBUTE_IN:
+      case c_base_markup_attributes::ATTRIBUTE_IN_2:
+      case c_base_markup_attributes::ATTRIBUTE_IS_MAP:
+      case c_base_markup_attributes::ATTRIBUTE_KEY_POINTS:
+      case c_base_markup_attributes::ATTRIBUTE_KEY_TYPE:
+      case c_base_markup_attributes::ATTRIBUTE_KIND:
+      case c_base_markup_attributes::ATTRIBUTE_LABEL:
+      case c_base_markup_attributes::ATTRIBUTE_LENGTH_ADJUST:
+      case c_base_markup_attributes::ATTRIBUTE_LIST:
+      case c_base_markup_attributes::ATTRIBUTE_LOCAL:
+      case c_base_markup_attributes::ATTRIBUTE_LONG_DESCRIPTION:
+      case c_base_markup_attributes::ATTRIBUTE_MARKERS:
+      case c_base_markup_attributes::ATTRIBUTE_MARKER_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_MASK_CONTENT_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_MASK_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_MAXIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_MEDIA:
+      case c_base_markup_attributes::ATTRIBUTE_METHOD:
+      case c_base_markup_attributes::ATTRIBUTE_MODE:
+      case c_base_markup_attributes::ATTRIBUTE_MINIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_NAME:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ABORT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_AFTER_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_start:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ABORT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_AFTER_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_start:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BLUR:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CANCEL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CLICK:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CONTEXT_MENU:
+      case c_base_markup_attributes::ATTRIBUTE_ON_COPY:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY_THROUGH:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CUE_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DOUBLE_CLICK:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_ENTER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_LEAVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_OVER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_START:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DROP:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DURATION_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_EMPTIED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ENDED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ERROR:
+      case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS:
+      case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS_IN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS_OUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_HASH_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_INPUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_INSTALLED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_INVALID:
+      case c_base_markup_attributes::ATTRIBUTE_ON_KEY_DOWN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_KEY_PRESS:
+      case c_base_markup_attributes::ATTRIBUTE_ON_KEY_UP:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOADED_DATA:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOADED_META_DATA:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOAD_START:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_DOWN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_ENTER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_LEAVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_MOVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OVER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_UP:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MESSAGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_WHEEL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_OPEN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ONLINE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_OFFLINE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PAGE_SHOW:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PAGE_HIDE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PASTE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PAUSE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PLAY:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PLAYING:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PROGRESS:
+      case c_base_markup_attributes::ATTRIBUTE_ON_POP_STATE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RATED_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RESIZE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RESET:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RATE_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SCROLL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SEARCH:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SELECT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SUBMIT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SEEKED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SEEKING:
+      case c_base_markup_attributes::ATTRIBUTE_ON_STALLED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SUSPEND:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SHOW:
+      case c_base_markup_attributes::ATTRIBUTE_ON_STORAGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TIME_UPDATE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TRANSITION_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOGGLE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_CANCEL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_MOVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_START:
+      case c_base_markup_attributes::ATTRIBUTE_ON_UNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_VOLUME_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_WAITING:
+      case c_base_markup_attributes::ATTRIBUTE_ON_WHEEL:
+      case c_base_markup_attributes::ATTRIBUTE_OFFSET:
+      case c_base_markup_attributes::ATTRIBUTE_OPEN:
+      case c_base_markup_attributes::ATTRIBUTE_ORIENTATION:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN_CONTENT_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN_TRANSFORM:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_PATH:
+      case c_base_markup_attributes::ATTRIBUTE_PATH_LENGTH:
+      case c_base_markup_attributes::ATTRIBUTE_PLACE_HOLDER:
+      case c_base_markup_attributes::ATTRIBUTE_POINTS:
+      case c_base_markup_attributes::ATTRIBUTE_POSTER:
+      case c_base_markup_attributes::ATTRIBUTE_PRELOAD:
+      case c_base_markup_attributes::ATTRIBUTE_PRESERVE_ASPECT_RATIO:
+      case c_base_markup_attributes::ATTRIBUTE_RADIO_GROUP:
+      case c_base_markup_attributes::ATTRIBUTE_SANDBOX:
+      case c_base_markup_attributes::ATTRIBUTE_SCOPE:
+      case c_base_markup_attributes::ATTRIBUTE_SHAPE:
+      case c_base_markup_attributes::ATTRIBUTE_REL:
+      case c_base_markup_attributes::ATTRIBUTE_RENDERING_INTENT:
+      case c_base_markup_attributes::ATTRIBUTE_REPEAT_COUNT:
+      case c_base_markup_attributes::ATTRIBUTE_ROLE:
+      case c_base_markup_attributes::ATTRIBUTE_ROTATE:
+      case c_base_markup_attributes::ATTRIBUTE_SIZE:
+      case c_base_markup_attributes::ATTRIBUTE_SIZES:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE_DOCUMENT:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE_SET:
+      case c_base_markup_attributes::ATTRIBUTE_SPAN:
+      case c_base_markup_attributes::ATTRIBUTE_SPREAD_METHOD:
+      case c_base_markup_attributes::ATTRIBUTE_STOP_COLOR:
+      case c_base_markup_attributes::ATTRIBUTE_STOP_OPACITY:
+      case c_base_markup_attributes::ATTRIBUTE_STYLE:
+      case c_base_markup_attributes::ATTRIBUTE_TARGET:
+      case c_base_markup_attributes::ATTRIBUTE_TEXT_LENGTH:
+      case c_base_markup_attributes::ATTRIBUTE_TEXT_CONTENT_ELEMENTS:
+      case c_base_markup_attributes::ATTRIBUTE_TITLE:
+      case c_base_markup_attributes::ATTRIBUTE_TRANSFORM:
+      case c_base_markup_attributes::ATTRIBUTE_TRANSLATE:
+      case c_base_markup_attributes::ATTRIBUTE_TO:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_BUTTON:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_LABEL:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_LIST:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_SVG:
+      case c_base_markup_attributes::ATTRIBUTE_USE_MAP:
+      case c_base_markup_attributes::ATTRIBUTE_VALUE:
+      case c_base_markup_attributes::ATTRIBUTE_VIEW_BOX:
+      case c_base_markup_attributes::ATTRIBUTE_WIDTH:
+      case c_base_markup_attributes::ATTRIBUTE_WRAP:
+      case c_base_markup_attributes::ATTRIBUTE_XML:
+      case c_base_markup_attributes::ATTRIBUTE_XMLNS:
+      case c_base_markup_attributes::ATTRIBUTE_XMLNS_XLINK:
+      case c_base_markup_attributes::ATTRIBUTE_XML_SPACE:
+      case c_base_markup_attributes::ATTRIBUTE_ZOOM_AND_PAN:
+        if (!is_string($value)) {
+          return c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_ATOMIC:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_AUTOCOMPLETE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_ACTIVE_DESCENDANT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_BUSY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_CHECKED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_CONTROLS:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_DESCRIBED_BY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_DISABLED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_DROP_EFFECT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_EXPANDED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_FLOW_TO:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_GRABBED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_HAS_POPUP:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_HIDDEN:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_INVALID:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LABEL:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LABELLED_BY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LEVEL:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LIVE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_LINE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_SELECTABLE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_ORIENTATION:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_OWNS:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_POSITION_INSET:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_PRESSED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_READONLY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_RELEVANT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_REQUIRED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_SELECTED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_SET_SIZE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_SORT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MAXIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MINIMIM:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_NOW:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_TEXT:
+        if (!is_string($value)) {
+          return c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_ASYNCHRONOUS:
+      case c_base_markup_attributes::ATTRIBUTE_ATTRIBUTE_NAME:
+      case c_base_markup_attributes::ATTRIBUTE_AUTO_COMPLETE:
+      case c_base_markup_attributes::ATTRIBUTE_AUTO_FOCUS:
+      case c_base_markup_attributes::ATTRIBUTE_AUTO_PLAY:
+      case c_base_markup_attributes::ATTRIBUTE_CHALLENGE:
+      case c_base_markup_attributes::ATTRIBUTE_CONTROLS:
+      case c_base_markup_attributes::ATTRIBUTE_CHECKED:
+      case c_base_markup_attributes::ATTRIBUTE_DEFAULT:
+      case c_base_markup_attributes::ATTRIBUTE_DEFER:
+      case c_base_markup_attributes::ATTRIBUTE_DISABLED:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_NO_VALIDATE:
+      case c_base_markup_attributes::ATTRIBUTE_HIDDEN:
+      case c_base_markup_attributes::ATTRIBUTE_LOOP:
+      case c_base_markup_attributes::ATTRIBUTE_MULTIPLE:
+      case c_base_markup_attributes::ATTRIBUTE_MUTED:
+      case c_base_markup_attributes::ATTRIBUTE_NO_VALIDATE:
+      case c_base_markup_attributes::ATTRIBUTE_READONLY:
+      case c_base_markup_attributes::ATTRIBUTE_REQUIRED:
+      case c_base_markup_attributes::ATTRIBUTE_REVERSED:
+      case c_base_markup_attributes::ATTRIBUTE_SCOPED:
+      case c_base_markup_attributes::ATTRIBUTE_SELECTED:
+      case c_base_markup_attributes::ATTRIBUTE_SORTABLE:
+      case c_base_markup_attributes::ATTRIBUTE_SORTED:
+      case c_base_markup_attributes::ATTRIBUTE_SPELLCHECK:
+        if (!is_bool($value)) {
+          return c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_ACCEPT:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_ENCODE_TYPE:
+      case c_base_markup_attributes::ATTRIBUTE_ENCODING_TYPE:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE:
+        if (!$this->pr_validate_value_mime_type($value)) {
+          return c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_ACCEPT_CHARACTER_SET:
+      case c_base_markup_attributes::ATTRIBUTE_CHARACTER_SET:
+        if (!$this->pr_validate_value_character_set($value)) {
+          return c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_CENTER_X:
+      case c_base_markup_attributes::ATTRIBUTE_CENTER_Y:
+      case c_base_markup_attributes::ATTRIBUTE_COLUMNS:
+      case c_base_markup_attributes::ATTRIBUTE_COLUMN_SPAN:
+      case c_base_markup_attributes::ATTRIBUTE_D_X:
+      case c_base_markup_attributes::ATTRIBUTE_D_Y:
+      case c_base_markup_attributes::ATTRIBUTE_FOCUS_X:
+      case c_base_markup_attributes::ATTRIBUTE_FOCUS_Y:
+      case c_base_markup_attributes::ATTRIBUTE_HIGH:
+      case c_base_markup_attributes::ATTRIBUTE_HREF_LANGUAGE:
+      case c_base_markup_attributes::ATTRIBUTE_LANGUAGE:
+      case c_base_markup_attributes::ATTRIBUTE_LOW:
+      case c_base_markup_attributes::ATTRIBUTE_MARKER_HEIGHT:
+      case c_base_markup_attributes::ATTRIBUTE_MARKER_WIDTH:
+      case c_base_markup_attributes::ATTRIBUTE_MAXIMUM_NUMBER:
+      case c_base_markup_attributes::ATTRIBUTE_MAXIMUM_LENGTH:
+      case c_base_markup_attributes::ATTRIBUTE_MINIMUM_NUMBER:
+      case c_base_markup_attributes::ATTRIBUTE_OPTIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_RADIUS:
+      case c_base_markup_attributes::ATTRIBUTE_RADIUS_X:
+      case c_base_markup_attributes::ATTRIBUTE_RADIUS_Y:
+      case c_base_markup_attributes::ATTRIBUTE_REFERENCE_X:
+      case c_base_markup_attributes::ATTRIBUTE_REFERENCE_Y:
+      case c_base_markup_attributes::ATTRIBUTE_ROWS:
+      case c_base_markup_attributes::ATTRIBUTE_ROW_SPAN:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE_LANGUAGE:
+      case c_base_markup_attributes::ATTRIBUTE_START:
+      case c_base_markup_attributes::ATTRIBUTE_STEP:
+      case c_base_markup_attributes::ATTRIBUTE_TAB_INDEX:
+      case c_base_markup_attributes::ATTRIBUTE_VALUE_NUMBER:
+      case c_base_markup_attributes::ATTRIBUTE_X:
+      case c_base_markup_attributes::ATTRIBUTE_X_1:
+      case c_base_markup_attributes::ATTRIBUTE_X_2:
+      case c_base_markup_attributes::ATTRIBUTE_X_LINK_ACTUATE:
+      case c_base_markup_attributes::ATTRIBUTE_X_LINK_HREF:
+      case c_base_markup_attributes::ATTRIBUTE_X_LINK_SHOW:
+      case c_base_markup_attributes::ATTRIBUTE_Y:
+      case c_base_markup_attributes::ATTRIBUTE_Y_1:
+      case c_base_markup_attributes::ATTRIBUTE_Y_2:
+        if (!is_int($value)) {
+          return c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_CLASS:
+        if (!is_array($value)) {
+          return c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_FORM_METHOD:
+        if (!$this->pr_validate_value_http_method($value)) {
+          return c_base_return_false();
+        }
+        break;
+
+      default:
+        return new c_base_return_false();
     }
 
-    if (preg_match('/^#(^s)+/i', $value) > 0) {
-      return new c_base_return_true();
+    if ($body) {
+      $this->attributes_body[$attribute] = $value;
+    }
+    else {
+      $this->attributes[$attribute] = $value;
     }
 
-    return new c_base_return_false();
+    return new c_base_return_true();
+  }
+}
+
+/**
+ * A return class whose value is represented as a generic c_base_markup_tag_return.
+ */
+class c_base_html_return extends c_base_return_object {
+  use t_base_return_value_exact;
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
   }
 
   /**
-   * Validate that value is a list of syntax references.
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, new c_base_html());
+  }
+
+  /**
+   * Assign the value.
    *
-   * @param array $value
-   *   The value to validate.
+   * @param c_base_html $value
+   *   Any value so long as it is an resource.
+   *   NULL is not allowed.
    *
-   * @return c_base_return_status
-   *   TRUE on valid, FALSE on invalid.
-   *   FALSE with error bit set is returned on error.
+   * @return bool
+   *   TRUE on success, FALSE otherwise.
+   */
+  public function set_value($value) {
+    if (!($value instanceof c_base_html)) {
+      return FALSE;
+    }
+
+    $this->value = $value;
+    return TRUE;
+  }
+
+  /**
+   * Return the value.
    *
-   * https://www.w3.org/TR/html5/infrastructure.html#urls
+   * @return c_base_html|null $value
+   *   The value c_base_html stored within this class.
+   *   NULL may be returned if there is no defined valid c_base_markup_tag.
    */
-  public static function is_url($value) {
-    if (!is_string($value)) {
-      return new c_base_return_false();
+  public function get_value() {
+    if (!is_null($this->value) && !($this->value instanceof c_base_html)) {
+      $this->value = NULL;
     }
 
-    // @todo.
+    return $this->value;
+  }
 
-    return new c_base_return_false();
+  /**
+   * Return the value of the expected type.
+   *
+   * @return c_base_html $value
+   *   The value c_base_html stored within this class.
+   */
+  public function get_value_exact() {
+    if (!($this->value instanceof c_base_html)) {
+      $this->value = new c_base_html();
+    }
+
+    return $this->value;
   }
 }
index bcdc0ac3ac2e24c910a6a25d4b4569a58d4c3f74..877eb31cc219d56b08e7e6bc335415c9ba789d06 100644 (file)
@@ -321,7 +321,12 @@ class c_base_http extends c_base_rfc_string {
    *   The language class string.
    */
   public function get_language_class() {
-    return c_return_status_string::s_new($this->language_class);
+    if (is_null($this->language_class)) {
+      // provide us-only as a failsafe/fallback.
+      $this->language_class = 'c_base_language_us_only';
+    }
+
+    return c_base_return_string::s_new($this->language_class);
   }
 
   /**
@@ -5634,7 +5639,7 @@ class c_base_http extends c_base_rfc_string {
       'invalid' => FALSE,
     );
 
-    $stop = self::p_length_string($match) + 1;
+    $stop = self::p_length_string($match);
     if ($stop == 0) {
       unset($stop);
 
@@ -5665,7 +5670,7 @@ class c_base_http extends c_base_rfc_string {
 
     while ($current < $stop) {
       $weak = FALSE;
-      if ($text['ordinals'][$current] == c_base_ascii::W) {
+      if ($text['ordinals'][$current] == c_base_ascii::UPPER_W) {
         $current++;
         if ($current >= $stop) {
           $result['invalid'] = TRUE;
@@ -7909,3 +7914,78 @@ class c_base_http extends c_base_rfc_string {
     }
   }
 }
+/**
+ * A return class whose value is represented as a generic c_base_markup_tag_return.
+ */
+class c_base_http_return extends c_base_return_object {
+  use t_base_return_value_exact;
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, new c_base_http());
+  }
+
+  /**
+   * Assign the value.
+   *
+   * @param c_base_http $value
+   *   Any value so long as it is an resource.
+   *   NULL is not allowed.
+   *
+   * @return bool
+   *   TRUE on success, FALSE otherwise.
+   */
+  public function set_value($value) {
+    if (!($value instanceof c_base_http)) {
+      return FALSE;
+    }
+
+    $this->value = $value;
+    return TRUE;
+  }
+
+  /**
+   * Return the value.
+   *
+   * @return c_base_http|null $value
+   *   The value c_base_http stored within this class.
+   *   NULL may be returned if there is no defined valid c_base_markup_tag.
+   */
+  public function get_value() {
+    if (!is_null($this->value) && !($this->value instanceof c_base_http)) {
+      $this->value = NULL;
+    }
+
+    return $this->value;
+  }
+
+  /**
+   * Return the value of the expected type.
+   *
+   * @return c_base_http $value
+   *   The value c_base_html stored within this class.
+   */
+  public function get_value_exact() {
+    if (!($this->value instanceof c_base_http)) {
+      $this->value = new c_base_html();
+    }
+
+    return $this->value;
+  }
+}
index 0ffa6b570dac5db058e3261ee919f1407be27e13..6b55c112e73af5420b90ceb77df6a4d8c93cdba1 100644 (file)
 <?php
 /**
  * @file
- * Provides a class for htmo markup.
- *
- * This is currently a draft/brainstorm and is subject to be completely rewritten/redesigned.
+ * Provides a class for html markup.
  */
 
 // include required files.
 require_once('common/base/classes/base_error.php');
 require_once('common/base/classes/base_return.php');
+require_once('common/base/classes/base_mime.php');
+require_once('common/base/classes/base_charset.php');
+require_once('common/base/classes/base_languages.php');
+
+/**
+ * A generic class for html attribute types.
+ *
+ * @fixme: all aria-* tags are set to text, specific types need to be eventially defined.
+ *
+ * @see: https://www.w3.org/TR/html5/dom.html#index-aria-roles
+ * @see: https://www.w3.org/TR/html5/dom.html#index-aria-global
+ */
+class c_base_markup_attributes {
+  const ATTRIBUTE_NONE                   = 0;
+  const ATTRIBUTE_ABBR                   = 1; // text
+  const ATTRIBUTE_ACCESS_KEY             = 2; // single letter
+  const ATTRIBUTE_ACCEPT                 = 3; // c_base_mime integer
+  const ATTRIBUTE_ACCEPT_CHARACTER_SET   = 4; // c_base_charset integer
+  const ATTRIBUTE_ACTION                 = 5; // text
+  const ATTRIBUTE_ALTERNATE              = 6; // text
+  const ATTRIBUTE_ASYNCHRONOUS           = 7; // async, use TRUE/FALSE
+  const ATTRIBUTE_ATTRIBUTE_NAME         = 8; // text
+  const ATTRIBUTE_AUTO_COMPLETE          = 9; // on or off, use TRUE/FALSE
+  const ATTRIBUTE_AUTO_FOCUS             = 10; // autofocus, use TRUE/FALSE
+  const ATTRIBUTE_AUTO_PLAY              = 11; // autoplay, use TRUE/FALSE
+  const ATTRIBUTE_BY                     = 12; // text
+  const ATTRIBUTE_CALCULATE_MODE         = 13; // text
+  const ATTRIBUTE_CENTER_X               = 14; // number
+  const ATTRIBUTE_CENTER_Y               = 15; // number
+  const ATTRIBUTE_CLASS                  = 16; // array of strings
+  const ATTRIBUTE_CLIP_PATH              = 17; // text
+  const ATTRIBUTE_CLIP_PATH_UNITS        = 18; // text
+  const ATTRIBUTE_CHALLENGE              = 19; // challenge, use TRUE/FALSE
+  const ATTRIBUTE_CHARACTER_SET          = 20; // c_base_charset integer
+  const ATTRIBUTE_CHECKED                = 21; // checked, use TRUE/FALSE
+  const ATTRIBUTE_CITE                   = 22; // text
+  const ATTRIBUTE_COLOR                  = 23; // text
+  const ATTRIBUTE_COLUMNS                = 23; // number
+  const ATTRIBUTE_COLUMN_SPAN            = 24; // number
+  const ATTRIBUTE_CONTENT                = 25; // text
+  const ATTRIBUTE_CONTENT_EDITABLE       = 26; // text: true, false, inherit
+  const ATTRIBUTE_CONTROLS               = 27; // controls, use TRUE/FALSE
+  const ATTRIBUTE_COORDINATES            = 28; // text
+  const ATTRIBUTE_CROSS_ORIGIN           = 29; // anonymous, use-credentials
+  const ATTRIBUTE_D                      = 30; // text
+  const ATTRIBUTE_D_X                    = 31; // number
+  const ATTRIBUTE_D_Y                    = 32; // number
+  const ATTRIBUTE_DATA                   = 33; // text
+  const ATTRIBUTE_DATE_TIME              = 34; // text
+  const ATTRIBUTE_DEFAULT                = 35; // default, use TRUE/FALSE
+  const ATTRIBUTE_DEFER                  = 36; // defer, use TRUE/FALSE
+  const ATTRIBUTE_DIRECTION              = 37; // ltr, rtl, auto
+  const ATTRIBUTE_DIRECTION_NAME         = 38; // text, inputname.dir
+  const ATTRIBUTE_DISABLED               = 39; // disabled, use TRUE/FALSE
+  const ATTRIBUTE_DOWNLOAD               = 40; // text
+  const ATTRIBUTE_DURATION               = 41; // text
+  const ATTRIBUTE_ENCODING_TYPE          = 42; // c_base_mime integer
+  const ATTRIBUTE_FILL                   = 43; // text
+  const ATTRIBUTE_FILL_RULE              = 44; // text
+  const ATTRIBUTE_FILL_STROKE            = 45; // text
+  const ATTRIBUTE_FOCUS_X                = 46; // number
+  const ATTRIBUTE_FOCUS_Y                = 47; // number
+  const ATTRIBUTE_FONT_SPECIFICATION     = 48; // text
+  const ATTRIBUTE_FOR                    = 49; // text: element id
+  const ATTRIBUTE_FORM                   = 50; // text: form id
+  const ATTRIBUTE_FORM_ACTION            = 51; // text: url
+  const ATTRIBUTE_FORM_ENCODE_TYPE       = 52; // c_base_mime integer
+  const ATTRIBUTE_FORM_METHOD            = 53; // text: get or post, use HTTP_METHOD_GET and HTTP_METHOD_POST
+  const ATTRIBUTE_FORM_NO_VALIDATE       = 54; // formnovalidate, use TRUE/FALSE
+  const ATTRIBUTE_FORM_TARGET            = 55; // text, _blank, _self, _parent, _top, URL
+  const ATTRIBUTE_FORMAT                 = 56; // text
+  const ATTRIBUTE_FROM                   = 57; // text
+  const ATTRIBUTE_GLYPH_REFERENCE        = 58; // text
+  const ATTRIBUTE_GRADIANT_TRANSFORM     = 59; // text
+  const ATTRIBUTE_GRADIANT_UNITS         = 60; // text
+  const ATTRIBUTE_GRAPHICS               = 61; // text
+  const ATTRIBUTE_HEADERS                = 62; // text
+  const ATTRIBUTE_HEIGHT                 = 63; // text
+  const ATTRIBUTE_HIDDEN                 = 64; // TRUE/FALSE
+  const ATTRIBUTE_HIGH                   = 65; // number
+  const ATTRIBUTE_HREF                   = 66; // text
+  const ATTRIBUTE_HREF_LANGUAGE          = 67; // i_base_language
+  const ATTRIBUTE_HREF_NO                = 68; // text
+  const ATTRIBUTE_HTTP_EQUIV             = 69; // text
+  const ATTRIBUTE_ICON                   = 70; // text
+  const ATTRIBUTE_ID                     = 71; // text
+  const ATTRIBUTE_IN                     = 72; // text
+  const ATTRIBUTE_IN_2                   = 73; // text
+  const ATTRIBUTE_IS_MAP                 = 74; // text
+  const ATTRIBUTE_KEY_POINTS             = 75; // text
+  const ATTRIBUTE_KEY_TYPE               = 76; // text: rsa, dsa, ec
+  const ATTRIBUTE_KIND                   = 77; // text
+  const ATTRIBUTE_LABEL                  = 78; // text
+  const ATTRIBUTE_LANGUAGE               = 79; // i_base_language, int
+  const ATTRIBUTE_LENGTH_ADJUST          = 80; // text
+  const ATTRIBUTE_LIST                   = 81; // text, datalist_id
+  const ATTRIBUTE_LOCAL                  = 82; // text
+  const ATTRIBUTE_LONG_DESCRIPTION       = 83; // text
+  const ATTRIBUTE_LOOP                   = 84; // loop, use TRUE/FALSE
+  const ATTRIBUTE_LOW                    = 85; // number
+  const ATTRIBUTE_MARKERS                = 86; // text
+  const ATTRIBUTE_MARKER_HEIGHT          = 87; // number
+  const ATTRIBUTE_MARKER_UNITS           = 88; // text
+  const ATTRIBUTE_MARKER_WIDTH           = 89; // number
+  const ATTRIBUTE_MASK_CONTENT_UNITS     = 90; // text
+  const ATTRIBUTE_MASK_UNITS             = 91; // text
+  const ATTRIBUTE_MAXIMUM                = 92; // text: number, date
+  const ATTRIBUTE_MAXIMUM_NUMBER         = 93; // number
+  const ATTRIBUTE_MAXIMUM_LENGTH         = 94; // number
+  const ATTRIBUTE_MEDIA                  = 95; // text
+  const ATTRIBUTE_METHOD                 = 96; // text
+  const ATTRIBUTE_MINIMUM                = 97; // text: number, date
+  const ATTRIBUTE_MINIMUM_NUMBER         = 98; // number
+  const ATTRIBUTE_MODE                   = 99; // text
+  const ATTRIBUTE_MULTIPLE               = 100; // multiple, use TRUE/FALSE
+  const ATTRIBUTE_MUTED                  = 101; // muted, use TRUE/FALSE
+  const ATTRIBUTE_NAME                   = 102; // text
+  const ATTRIBUTE_NO_VALIDATE            = 103; // novalidate, TRUE/FALSE
+  const ATTRIBUTE_ON_ABORT               = 104; // text
+  const ATTRIBUTE_ON_AFTER_PRINT         = 105; // text
+  const ATTRIBUTE_ON_ANIMATION_END       = 106; // text
+  const ATTRIBUTE_ON_ANIMATION_ITERATION = 107; // text
+  const ATTRIBUTE_ON_ANIMATION_start     = 108; // text
+  const ATTRIBUTE_ON_BEFORE_UNLOAD       = 109; // text
+  const ATTRIBUTE_ON_BEFORE_PRINT        = 110; // text
+  const ATTRIBUTE_ON_BLUR                = 111; // text
+  const ATTRIBUTE_ON_CANCEL              = 112; // text
+  const ATTRIBUTE_ON_CLICK               = 113; // text
+  const ATTRIBUTE_ON_CONTEXT_MENU        = 114; // text
+  const ATTRIBUTE_ON_COPY                = 115; // text
+  const ATTRIBUTE_ON_CUT                 = 116; // text
+  const ATTRIBUTE_ON_CAN_PLAY            = 117; // text
+  const ATTRIBUTE_ON_CAN_PLAY_THROUGH    = 118; // text
+  const ATTRIBUTE_ON_CHANGE              = 119; // text
+  const ATTRIBUTE_ON_CUE_CHANGE          = 120; // text
+  const ATTRIBUTE_ON_DOUBLE_CLICK        = 121; // text
+  const ATTRIBUTE_ON_DRAG                = 122; // text
+  const ATTRIBUTE_ON_DRAG_END            = 123; // text
+  const ATTRIBUTE_ON_DRAG_ENTER          = 124; // text
+  const ATTRIBUTE_ON_DRAG_LEAVE          = 125; // text
+  const ATTRIBUTE_ON_DRAG_OVER           = 126; // text
+  const ATTRIBUTE_ON_DRAG_START          = 127; // text
+  const ATTRIBUTE_ON_DROP                = 128; // text
+  const ATTRIBUTE_ON_DURATION_CHANGE     = 129; // text
+  const ATTRIBUTE_ON_EMPTIED             = 130; // text
+  const ATTRIBUTE_ON_ENDED               = 131; // text
+  const ATTRIBUTE_ON_ERROR               = 132; // text
+  const ATTRIBUTE_ON_FOCUS               = 133; // text
+  const ATTRIBUTE_ON_FOCUS_IN            = 134; // text
+  const ATTRIBUTE_ON_FOCUS_OUT           = 135; // text
+  const ATTRIBUTE_ON_HASH_CHANGE         = 136; // text
+  const ATTRIBUTE_ON_INPUT               = 137; // text
+  const ATTRIBUTE_ON_INSTALLED           = 138; // text
+  const ATTRIBUTE_ON_INVALID             = 139; // text
+  const ATTRIBUTE_ON_KEY_DOWN            = 140; // text
+  const ATTRIBUTE_ON_KEY_PRESS           = 141; // text
+  const ATTRIBUTE_ON_KEY_UP              = 142; // text
+  const ATTRIBUTE_ON_LOAD                = 143; // text
+  const ATTRIBUTE_ON_LOADED_DATA         = 144; // text
+  const ATTRIBUTE_ON_LOADED_META_DATA    = 145; // text
+  const ATTRIBUTE_ON_LOAD_START          = 146; // text
+  const ATTRIBUTE_ON_MOUSE_DOWN          = 147; // text
+  const ATTRIBUTE_ON_MOUSE_ENTER         = 148; // text
+  const ATTRIBUTE_ON_MOUSE_LEAVE         = 149; // text
+  const ATTRIBUTE_ON_MOUSE_MOVE          = 150; // text
+  const ATTRIBUTE_ON_MOUSE_OVER          = 151; // text
+  const ATTRIBUTE_ON_MOUSE_OUT           = 152; // text
+  const ATTRIBUTE_ON_MOUSE_UP            = 153; // text
+  const ATTRIBUTE_ON_MESSAGE             = 154; // text
+  const ATTRIBUTE_ON_MOUSE_WHEEL         = 155; // text
+  const ATTRIBUTE_ON_OPEN                = 156; // text
+  const ATTRIBUTE_ON_ONLINE              = 157; // text
+  const ATTRIBUTE_ON_OFFLINE             = 158; // text
+  const ATTRIBUTE_ON_PAGE_SHOW           = 159; // text
+  const ATTRIBUTE_ON_PAGE_HIDE           = 160; // text
+  const ATTRIBUTE_ON_PASTE               = 161; // text
+  const ATTRIBUTE_ON_PAUSE               = 162; // text
+  const ATTRIBUTE_ON_PLAY                = 163; // text
+  const ATTRIBUTE_ON_PLAYING             = 164; // text
+  const ATTRIBUTE_ON_PROGRESS            = 165; // text
+  const ATTRIBUTE_ON_POP_STATE           = 166; // text
+  const ATTRIBUTE_ON_RATED_CHANGE        = 167; // text
+  const ATTRIBUTE_ON_RESIZE              = 168; // text
+  const ATTRIBUTE_ON_RESET               = 169; // text
+  const ATTRIBUTE_ON_RATE_CHANGE         = 170; // text
+  const ATTRIBUTE_ON_SCROLL              = 171; // text
+  const ATTRIBUTE_ON_SEARCH              = 172; // text
+  const ATTRIBUTE_ON_SELECT              = 173; // text
+  const ATTRIBUTE_ON_SUBMIT              = 174; // text
+  const ATTRIBUTE_ON_SEEKED              = 175; // text
+  const ATTRIBUTE_ON_SEEKING             = 176; // text
+  const ATTRIBUTE_ON_STALLED             = 177; // text
+  const ATTRIBUTE_ON_SUSPEND             = 178; // text
+  const ATTRIBUTE_ON_SHOW                = 179; // text
+  const ATTRIBUTE_ON_STORAGE             = 180; // text
+  const ATTRIBUTE_ON_TIME_UPDATE         = 181; // text
+  const ATTRIBUTE_ON_TRANSITION_END      = 182; // text
+  const ATTRIBUTE_ON_TOGGLE              = 183; // text
+  const ATTRIBUTE_ON_TOUCH_CANCEL        = 184; // text
+  const ATTRIBUTE_ON_TOUCH_END           = 185; // text
+  const ATTRIBUTE_ON_TOUCH_MOVE          = 186; // text
+  const ATTRIBUTE_ON_TOUCH_START         = 187; // text
+  const ATTRIBUTE_ON_UNLOAD              = 188; // text
+  const ATTRIBUTE_ON_VOLUME_CHANGE       = 189; // text
+  const ATTRIBUTE_ON_WAITING             = 190; // text
+  const ATTRIBUTE_ON_WHEEL               = 191; // text
+  const ATTRIBUTE_OFFSET                 = 192; // text
+  const ATTRIBUTE_OPEN                   = 193; // text
+  const ATTRIBUTE_OPTIMUM                = 194; // number
+  const ATTRIBUTE_ORIENTATION            = 195; // text
+  const ATTRIBUTE_PATTERN                = 196; // text, regular expression
+  const ATTRIBUTE_PATTERN_CONTENT_UNITS  = 197; // text
+  const ATTRIBUTE_PATTERN_TRANSFORM      = 198; // text
+  const ATTRIBUTE_PATTERN_UNITS          = 199; // text
+  const ATTRIBUTE_PATH                   = 200; // text
+  const ATTRIBUTE_PATH_LENGTH            = 201; // text
+  const ATTRIBUTE_PLACE_HOLDER           = 202; // text
+  const ATTRIBUTE_POINTS                 = 203; // text
+  const ATTRIBUTE_POSTER                 = 204; // text
+  const ATTRIBUTE_PRELOAD                = 205; // text
+  const ATTRIBUTE_PRESERVE_ASPECT_RATIO  = 196; // text
+  const ATTRIBUTE_RADIO_GROUP            = 207; // text
+  const ATTRIBUTE_RADIUS                 = 208; // number
+  const ATTRIBUTE_RADIUS_X               = 209; // number
+  const ATTRIBUTE_RADIUS_Y               = 210; // number
+  const ATTRIBUTE_READONLY               = 211; // readonly, use TRUE/FALSE
+  const ATTRIBUTE_REFERENCE_X            = 212; // number
+  const ATTRIBUTE_REFERENCE_Y            = 213; // number
+  const ATTRIBUTE_REL                    = 214; // text: alternate, author, dns-prefetch, help, icon, license, next, pingback, preconnect, prefetch, preload, prerender, prev, search, stylesheet
+  const ATTRIBUTE_RENDERING_INTENT       = 215; // text
+  const ATTRIBUTE_REPEAT_COUNT           = 216; // text
+  const ATTRIBUTE_REQUIRED               = 217; // required, use TRUE/FALSE
+  const ATTRIBUTE_REVERSED               = 218; // reversed, use TRUE/FALSE
+  const ATTRIBUTE_ROLE                   = 219; // text
+  const ATTRIBUTE_ROTATE                 = 220; // text
+  const ATTRIBUTE_ROWS                   = 221; // number
+  const ATTRIBUTE_ROW_SPAN               = 222; // number
+  const ATTRIBUTE_SANDBOX                = 223; // text
+  const ATTRIBUTE_SCOPE                  = 224; // text
+  const ATTRIBUTE_SCOPED                 = 225; // scoped, use TRUE/FALSE
+  const ATTRIBUTE_SELECTED               = 226; // selected, use TRUE/FALSE
+  const ATTRIBUTE_SHAPE                  = 227; // text
+  const ATTRIBUTE_SIZE                   = 228; // number
+  const ATTRIBUTE_SIZES                  = 229; // text: HeightxWidth, any
+  const ATTRIBUTE_SORTABLE               = 230; // sortable, use TRUE/FALSE
+  const ATTRIBUTE_SORTED                 = 231; // text
+  const ATTRIBUTE_SOURCE                 = 232; // text: url
+  const ATTRIBUTE_SOURCE_DOCUMENT        = 233; // text
+  const ATTRIBUTE_SOURCE_LANGUAGE        = 234; // i_base_language
+  const ATTRIBUTE_SOURCE_SET             = 235; // text
+  const ATTRIBUTE_SPAN                   = 236; // text
+  const ATTRIBUTE_SPELLCHECK             = 237; // TRUE/FALSE
+  const ATTRIBUTE_SPREAD_METHOD          = 238; // text
+  const ATTRIBUTE_START                  = 239; // number
+  const ATTRIBUTE_STEP                   = 240; // number
+  const ATTRIBUTE_STOP_COLOR             = 241; // text
+  const ATTRIBUTE_STOP_OPACITY           = 242; // text
+  const ATTRIBUTE_STYLE                  = 243; // text
+  const ATTRIBUTE_TAB_INDEX              = 244; // number
+  const ATTRIBUTE_TARGET                 = 245; // text, _blank, _self, _parent, _top, URL
+  const ATTRIBUTE_TEXT_LENGTH            = 246; // text
+  const ATTRIBUTE_TEXT_CONTENT_ELEMENTS  = 247; // text
+  const ATTRIBUTE_TITLE                  = 248; // text
+  const ATTRIBUTE_TRANSFORM              = 249; // text
+  const ATTRIBUTE_TRANSLATE              = 250; // text
+  const ATTRIBUTE_TO                     = 251; // text
+  const ATTRIBUTE_TYPE                   = 252; // mime type
+  const ATTRIBUTE_TYPE_BUTTON            = 253; // text
+  const ATTRIBUTE_TYPE_LABEL             = 254; // text
+  const ATTRIBUTE_TYPE_LIST              = 255; // text
+  const ATTRIBUTE_TYPE_SVG               = 256; // text
+  const ATTRIBUTE_USE_MAP                = 257; // text
+  const ATTRIBUTE_VALUE                  = 258; // text
+  const ATTRIBUTE_VALUE_NUMBER           = 259; // number
+  const ATTRIBUTE_VIEW_BOX               = 260; // text
+  const ATTRIBUTE_WIDTH                  = 261; // text
+  const ATTRIBUTE_WRAP                   = 262; // hard, soft
+  const ATTRIBUTE_X                      = 263; // number
+  const ATTRIBUTE_X_1                    = 264; // number
+  const ATTRIBUTE_X_2                    = 265; // number
+  const ATTRIBUTE_X_LINK_ACTUATE         = 266; // number
+  const ATTRIBUTE_X_LINK_HREF            = 267; // number
+  const ATTRIBUTE_X_LINK_SHOW            = 268; // number
+  const ATTRIBUTE_Y                      = 269; // number
+  const ATTRIBUTE_Y_1                    = 270; // number
+  const ATTRIBUTE_Y_2                    = 271; // number
+  const ATTRIBUTE_XML                    = 272; // text
+  const ATTRIBUTE_XMLNS                  = 273; // text
+  const ATTRIBUTE_XMLNS_XLINK            = 274; // text
+  const ATTRIBUTE_XML_SPACE              = 275; // text
+  const ATTRIBUTE_ZOOM_AND_PAN           = 276; // text
+
+  // wai-air roles/attributes/etc..
+  const ATTRIBUTE_ARIA_ATOMIC            = 277; // text
+  const ATTRIBUTE_ARIA_AUTOCOMPLETE      = 278; // text
+  const ATTRIBUTE_ARIA_ACTIVE_DESCENDANT = 279; // text
+  const ATTRIBUTE_ARIA_BUSY              = 280; // text
+  const ATTRIBUTE_ARIA_CHECKED           = 281; // text
+  const ATTRIBUTE_ARIA_CONTROLS          = 282; // text
+  const ATTRIBUTE_ARIA_DESCRIBED_BY      = 283; // text
+  const ATTRIBUTE_ARIA_DISABLED          = 284; // text
+  const ATTRIBUTE_ARIA_DROP_EFFECT       = 285; // text
+  const ATTRIBUTE_ARIA_EXPANDED          = 286; // text
+  const ATTRIBUTE_ARIA_FLOW_TO           = 287; // text
+  const ATTRIBUTE_ARIA_GRABBED           = 288; // text
+  const ATTRIBUTE_ARIA_HAS_POPUP         = 289; // text
+  const ATTRIBUTE_ARIA_HIDDEN            = 290; // text
+  const ATTRIBUTE_ARIA_INVALID           = 291; // text
+  const ATTRIBUTE_ARIA_LABEL             = 292; // text
+  const ATTRIBUTE_ARIA_LABELLED_BY       = 293; // text
+  const ATTRIBUTE_ARIA_LEVEL             = 294; // text
+  const ATTRIBUTE_ARIA_LIVE              = 295; // text
+  const ATTRIBUTE_ARIA_MULTI_LINE        = 296; // text
+  const ATTRIBUTE_ARIA_MULTI_SELECTABLE  = 297; // text
+  const ATTRIBUTE_ARIA_ORIENTATION       = 298; // text
+  const ATTRIBUTE_ARIA_OWNS              = 299; // text
+  const ATTRIBUTE_ARIA_POSITION_INSET    = 300; // text
+  const ATTRIBUTE_ARIA_PRESSED           = 301; // text
+  const ATTRIBUTE_ARIA_READONLY          = 302; // text
+  const ATTRIBUTE_ARIA_RELEVANT          = 303; // text
+  const ATTRIBUTE_ARIA_REQUIRED          = 304; // text
+  const ATTRIBUTE_ARIA_SELECTED          = 305; // text
+  const ATTRIBUTE_ARIA_SET_SIZE          = 306; // text
+  const ATTRIBUTE_ARIA_SORT              = 307; // text
+  const ATTRIBUTE_ARIA_VALUE_MAXIMUM     = 308; // text
+  const ATTRIBUTE_ARIA_VALUE_MINIMIM     = 309; // text
+  const ATTRIBUTE_ARIA_VALUE_NOW         = 310; // text
+  const ATTRIBUTE_ARIA_VALUE_TEXT        = 311; // text
+}
 
 /**
  * A generic class for html tags.
@@ -17,83 +344,980 @@ require_once('common/base/classes/base_return.php');
  * This class is not intended to be used for generate the theme but is instead intended to be used as a base class for both the input and the output classes for their respective purposes.
  *
  * Each tag has an internal id that is expected to be processed.
- * This is not the same as the HTML 'id' attribute but can be the same.
+ * This is not the same as the HTML 'id' attribute in that is is only allowed to be a positive integer.
  *
- * Many of the attributes are defined from HTML forms because of the number of forms.
+ * @warning: I haven't completely figured out how I am going to manage the types.
+ * For now all tag types have been created, but this is essentially mostly informative as most of this is to be handled by the theme classes.
+ * Thus, this is highly subject to change upon review.
  *
- * @see: https://www.w3.org/TR/html5/forms.html#forms
+ * @todo: add support for non-standard tag attributes, which will just be a string or NULL.
  */
 class c_base_markup_tag {
-  private $id;
+  const TYPE_NONE                       = 0;
+  const TYPE_A                          = 1;
+  const TYPE_ABBR                       = 2;
+  const TYPE_ADDRESS                    = 3;
+  const TYPE_ALTERNATE_GLYPH            = 4;
+  const TYPE_ALTERNATE_GLYPH_DEFINITION = 5;
+  const TYPE_ALTERNATE_GLYPH_ITEM       = 6;
+  const TYPE_ANIMATE                    = 7;
+  const TYPE_ANIMATE_MOTION             = 8;
+  const TYPE_ANIMATE_TRANSFORM          = 9;
+  const TYPE_AREA                       = 10;
+  const TYPE_ARTICLE                    = 11;
+  const TYPE_ASIDE                      = 12;
+  const TYPE_AUDIO                      = 13;
+  const TYPE_BOLD                       = 14;
+  const TYPE_BASE                       = 15;
+  const TYPE_BDI                        = 16;
+  const TYPE_BDO                        = 17;
+  const TYPE_BLOCKQUOTE                 = 18;
+  const TYPE_BREAK                      = 19;
+  const TYPE_BUTTON                     = 20;
+  const TYPE_CANVAS                     = 21;
+  const TYPE_CHECKBOX                   = 22;
+  const TYPE_CIRCLE                     = 23;
+  const TYPE_CITE                       = 24;
+  const TYPE_CLIP_PATH                  = 25;
+  const TYPE_CODE                       = 26;
+  const TYPE_COL                        = 27;
+  const TYPE_COL_GROUP                  = 28;
+  const TYPE_COLOR                      = 29;
+  const TYPE_COLOR_PROFILE              = 30;
+  const TYPE_CURSOR                     = 31;
+  const TYPE_DATA                       = 32;
+  const TYPE_DATA_LIST                  = 33;
+  const TYPE_DATE                       = 34;
+  const TYPE_DATE_TIME_LOCAL            = 35;
+  const TYPE_DEFS                       = 36;
+  const TYPE_DEL                        = 37;
+  const TYPE_DESCRIPTION                = 38;
+  const TYPE_DETAILS                    = 39;
+  const TYPE_DFN                        = 40;
+  const TYPE_DIALOG                     = 41;
+  const TYPE_DIVIDER                    = 42;
+  const TYPE_DEFINITION_LIST            = 43;
+  const TYPE_ELLIPSE                    = 44;
+  const TYPE_EM                         = 45;
+  const TYPE_EMAIL                      = 46;
+  const TYPE_EMBED                      = 47;
+  const TYPE_FE_BLEND                   = 48;
+  const TYPE_FIELD_SET                  = 49;
+  const TYPE_FIGURE                     = 50;
+  const TYPE_FIGURE_CAPTION             = 51;
+  const TYPE_FILE                       = 52;
+  const TYPE_FOOTER                     = 53;
+  const TYPE_FORM                       = 54;
+  const TYPE_GROUP                      = 55;
+  const TYPE_H1                         = 56;
+  const TYPE_H2                         = 57;
+  const TYPE_H3                         = 58;
+  const TYPE_H4                         = 59;
+  const TYPE_H5                         = 60;
+  const TYPE_H6                         = 61;
+  const TYPE_HEADER                     = 62;
+  const TYPE_HIDDEN                     = 63;
+  const TYPE_HORIZONTAL_RULER           = 64;
+  const TYPE_ITALICS                    = 65;
+  const TYPE_INLINE_FRAME               = 66;
+  const TYPE_IMAGE                      = 67;
+  const TYPE_IMAGE_SVG                  = 68;
+  const TYPE_INPUT                      = 69;
+  const TYPE_INS                        = 70;
+  const TYPE_KEYBOARD                   = 71;
+  const TYPE_KEY_GEN                    = 72;
+  const TYPE_LABEL                      = 73;
+  const TYPE_LEGEND                     = 74;
+  const TYPE_LIST_ITEM                  = 75;
+  const TYPE_LINE                       = 76;
+  const TYPE_LINEAR_GRADIENT            = 77;
+  const TYPE_LINK                       = 78;
+  const TYPE_MAIN                       = 79;
+  const TYPE_MAP                        = 80;
+  const TYPE_MARK                       = 81;
+  const TYPE_MARKER                     = 82;
+  const TYPE_MASK                       = 83;
+  const TYPE_MENU                       = 84;
+  const TYPE_MENU_ITEM                  = 85;
+  const TYPE_MATH                       = 86;
+  const TYPE_META                       = 87;
+  const TYPE_METER                      = 88;
+  const TYPE_MONTH                      = 89;
+  const TYPE_NAVIGATION                 = 90;
+  const TYPE_NO_SCRIPT                  = 91;
+  const TYPE_NUMBER                     = 92;
+  const TYPE_OBJECT                     = 93;
+  const TYPE_ORDERED_LIST               = 94;
+  const TYPE_OPTIONS_GROUP              = 95;
+  const TYPE_OPTION                     = 96;
+  const TYPE_OUTPUT                     = 97;
+  const TYPE_PARAGRAPH                  = 98;
+  const TYPE_PARAM                      = 99;
+  const TYPE_PASSWORD                   = 100;
+  const TYPE_PATH                       = 101;
+  const TYPE_PATTERN                    = 102;
+  const TYPE_PICTURE                    = 103;
+  const TYPE_POLYGON                    = 104;
+  const TYPE_POLYLINE                   = 105;
+  const TYPE_PREFORMATTED               = 106;
+  const TYPE_PROGRESS                   = 107;
+  const TYPE_Q                          = 108;
+  const TYPE_RADIAL_GRADIENT            = 109;
+  const TYPE_RADIO                      = 110;
+  const TYPE_RANGE                      = 111;
+  const TYPE_RECTANGLE                  = 112;
+  const TYPE_RESET                      = 113;
+  const TYPE_RUBY                       = 114;
+  const TYPE_RUBY_PARENTHESIS           = 115;
+  const TYPE_RUBY_PRONUNCIATION         = 116;
+  const TYPE_STRIKE_THROUGH             = 117;
+  const TYPE_SAMPLE                     = 118;
+  const TYPE_SCRIPT                     = 119;
+  const TYPE_SEARCH                     = 120;
+  const TYPE_SECTION                    = 121;
+  const TYPE_SELECT                     = 122;
+  const TYPE_SMALL                      = 123;
+  const TYPE_SOURCE                     = 124;
+  const TYPE_SPAN                       = 125;
+  const TYPE_STOP                       = 126;
+  const TYPE_STRONG                     = 127;
+  const TYPE_STYLE                      = 128;
+  const TYPE_SUB_SCRIPT                 = 129;
+  const TYPE_SUBMIT                     = 130;
+  const TYPE_SUPER_SCRIPT               = 131;
+  const TYPE_SVG                        = 132;
+  const TYPE_TABLE                      = 133;
+  const TYPE_TABLE_BODY                 = 134;
+  const TYPE_TABLE_CELL                 = 135;
+  const TYPE_TABLE_FOOTER               = 136;
+  const TYPE_TABLE_HEADER               = 137;
+  const TYPE_TABLE_HEADER_CELL          = 138;
+  const TYPE_TABLE_ROW                  = 139;
+  const TYPE_TELEPHONE                  = 140;
+  const TYPE_TEMPLATE                   = 141;
+  const TYPE_TERM_DESCRIPTION           = 142;
+  const TYPE_TERM_NAME                  = 143;
+  const TYPE_TEXT                       = 144;
+  const TYPE_TEXT_AREA                  = 145;
+  const TYPE_TEXT_REFERENCE             = 146;
+  const TYPE_TEXT_SPAN                  = 147;
+  const TYPE_TEXT_SVG                   = 148;
+  const TYPE_TIME                       = 149;
+  const TYPE_TITLE                      = 150;
+  const TYPE_TRACK                      = 151;
+  const TYPE_UNDERLINE                  = 152;
+  const TYPE_UNORDERED_LIST             = 153;
+  const TYPE_URL                        = 154;
+  const TYPE_USE                        = 155;
+  const TYPE_VARIABLE                   = 156;
+  const TYPE_VIDEO                      = 157;
+  const TYPE_WEEK                       = 158;
+  const TYPE_WIDE_BREAK                 = 159;
+
   private $attributes;
   private $tags;
   private $tags_total;
-  private $parent;
-  private $children;
+  private $text;
+  private $type;
 
   /**
    * Class constructor.
    */
   public function __construct() {
-    $this->id = NULL;
     $this->attributes = array();
-    $this->tags = NULL;
+    $this->tags = array();
     $this->tags_total = 0;
-    $this->parent = NULL;
-    $this->children = array();
+    $this->text = NULL;
+    $this->type = self::TYPE_TEXT;
   }
 
   /**
    * Class destructor.
    */
   public function __destruct() {
-    unset($this->id);
     unset($this->attributes);
     unset($this->tags);
     unset($this->tags_total);
-    unset($this->parent);
-    unset($this->children);
+    unset($this->text);
+    unset($this->type);
   }
 
   /**
-   * Assign the internal unique numeric tag id.
+   * Assign the specified tag.
    *
-   * @param int $id
-   *   The internal numeric id to assign.
+   * @param int $attribute
+   *   The attribute to assign.
+   * @param $value
+   *   The value of the attribute.
+   *   The actual value type is specific to each attribute type.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
    *   FALSE with error bit set is returned on error.
    */
-  public function set_id($id) {
-    if (!is_int($id)) {
+  public function set_attribute($attribute, $value) {
+    if (!is_int($attribute)) {
       return c_base_return_error::s_false();
     }
 
-    $this->id = $id;
+    switch ($attribute) {
+      case c_base_markup_attributes::ATTRIBUTE_NONE:
+        unset($this->attribute[$attribute]);
+        return new c_base_return_true();
+
+      case c_base_markup_attributes::ATTRIBUTE_ABBR:
+      case c_base_markup_attributes::ATTRIBUTE_ACCESS_KEY:
+      case c_base_markup_attributes::ATTRIBUTE_ACTION:
+      case c_base_markup_attributes::ATTRIBUTE_ALTERNATE:
+      case c_base_markup_attributes::ATTRIBUTE_BY:
+      case c_base_markup_attributes::ATTRIBUTE_CALCULATE_MODE:
+      case c_base_markup_attributes::ATTRIBUTE_CLIP_PATH:
+      case c_base_markup_attributes::ATTRIBUTE_CLIP_PATH_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_CITE:
+      case c_base_markup_attributes::ATTRIBUTE_COLOR:
+      case c_base_markup_attributes::ATTRIBUTE_COORDINATES:
+      case c_base_markup_attributes::ATTRIBUTE_CONTENT:
+      case c_base_markup_attributes::ATTRIBUTE_CONTENT_EDITABLE:
+      case c_base_markup_attributes::ATTRIBUTE_CROSS_ORIGIN:
+      case c_base_markup_attributes::ATTRIBUTE_D:
+      case c_base_markup_attributes::ATTRIBUTE_DATA:
+      case c_base_markup_attributes::ATTRIBUTE_DATE_TIME:
+      case c_base_markup_attributes::ATTRIBUTE_DIRECTION:
+      case c_base_markup_attributes::ATTRIBUTE_DIRECTION_NAME:
+      case c_base_markup_attributes::ATTRIBUTE_DOWNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_DURATION:
+      case c_base_markup_attributes::ATTRIBUTE_FILL:
+      case c_base_markup_attributes::ATTRIBUTE_FILL_RULE:
+      case c_base_markup_attributes::ATTRIBUTE_FILL_STROKE:
+      case c_base_markup_attributes::ATTRIBUTE_FONT_SPECIFICATION:
+      case c_base_markup_attributes::ATTRIBUTE_FOR:
+      case c_base_markup_attributes::ATTRIBUTE_FORM:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_ACTION:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_TARGET:
+      case c_base_markup_attributes::ATTRIBUTE_FORMAT:
+      case c_base_markup_attributes::ATTRIBUTE_FROM:
+      case c_base_markup_attributes::ATTRIBUTE_GLYPH_REFERENCE:
+      case c_base_markup_attributes::ATTRIBUTE_GRADIANT_TRANSFORM:
+      case c_base_markup_attributes::ATTRIBUTE_GRADIANT_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_GRAPHICS:
+      case c_base_markup_attributes::ATTRIBUTE_HEADERS:
+      case c_base_markup_attributes::ATTRIBUTE_HEIGHT:
+      case c_base_markup_attributes::ATTRIBUTE_HREF:
+      case c_base_markup_attributes::ATTRIBUTE_HREF_NO:
+      case c_base_markup_attributes::ATTRIBUTE_HTTP_EQUIV:
+      case c_base_markup_attributes::ATTRIBUTE_ICON:
+      case c_base_markup_attributes::ATTRIBUTE_ID:
+      case c_base_markup_attributes::ATTRIBUTE_IN:
+      case c_base_markup_attributes::ATTRIBUTE_IN_2:
+      case c_base_markup_attributes::ATTRIBUTE_IS_MAP:
+      case c_base_markup_attributes::ATTRIBUTE_KEY_POINTS:
+      case c_base_markup_attributes::ATTRIBUTE_KEY_TYPE:
+      case c_base_markup_attributes::ATTRIBUTE_KIND:
+      case c_base_markup_attributes::ATTRIBUTE_LABEL:
+      case c_base_markup_attributes::ATTRIBUTE_LENGTH_ADJUST:
+      case c_base_markup_attributes::ATTRIBUTE_LIST:
+      case c_base_markup_attributes::ATTRIBUTE_LOCAL:
+      case c_base_markup_attributes::ATTRIBUTE_LONG_DESCRIPTION:
+      case c_base_markup_attributes::ATTRIBUTE_MARKERS:
+      case c_base_markup_attributes::ATTRIBUTE_MARKER_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_MASK_CONTENT_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_MASK_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_MAXIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_MEDIA:
+      case c_base_markup_attributes::ATTRIBUTE_METHOD:
+      case c_base_markup_attributes::ATTRIBUTE_MODE:
+      case c_base_markup_attributes::ATTRIBUTE_MINIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_NAME:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ABORT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_AFTER_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_start:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ABORT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_AFTER_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_start:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_BLUR:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CANCEL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CLICK:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CONTEXT_MENU:
+      case c_base_markup_attributes::ATTRIBUTE_ON_COPY:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY_THROUGH:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_CUE_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DOUBLE_CLICK:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_ENTER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_LEAVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_OVER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_START:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DROP:
+      case c_base_markup_attributes::ATTRIBUTE_ON_DURATION_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_EMPTIED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ENDED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ERROR:
+      case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS:
+      case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS_IN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS_OUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_HASH_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_INPUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_INSTALLED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_INVALID:
+      case c_base_markup_attributes::ATTRIBUTE_ON_KEY_DOWN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_KEY_PRESS:
+      case c_base_markup_attributes::ATTRIBUTE_ON_KEY_UP:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOADED_DATA:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOADED_META_DATA:
+      case c_base_markup_attributes::ATTRIBUTE_ON_LOAD_START:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_DOWN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_ENTER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_LEAVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_MOVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OVER:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OUT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_UP:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MESSAGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_WHEEL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_OPEN:
+      case c_base_markup_attributes::ATTRIBUTE_ON_ONLINE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_OFFLINE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PAGE_SHOW:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PAGE_HIDE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PASTE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PAUSE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PLAY:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PLAYING:
+      case c_base_markup_attributes::ATTRIBUTE_ON_PROGRESS:
+      case c_base_markup_attributes::ATTRIBUTE_ON_POP_STATE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RATED_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RESIZE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RESET:
+      case c_base_markup_attributes::ATTRIBUTE_ON_RATE_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SCROLL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SEARCH:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SELECT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SUBMIT:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SEEKED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SEEKING:
+      case c_base_markup_attributes::ATTRIBUTE_ON_STALLED:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SUSPEND:
+      case c_base_markup_attributes::ATTRIBUTE_ON_SHOW:
+      case c_base_markup_attributes::ATTRIBUTE_ON_STORAGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TIME_UPDATE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TRANSITION_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOGGLE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_CANCEL:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_END:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_MOVE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_START:
+      case c_base_markup_attributes::ATTRIBUTE_ON_UNLOAD:
+      case c_base_markup_attributes::ATTRIBUTE_ON_VOLUME_CHANGE:
+      case c_base_markup_attributes::ATTRIBUTE_ON_WAITING:
+      case c_base_markup_attributes::ATTRIBUTE_ON_WHEEL:
+      case c_base_markup_attributes::ATTRIBUTE_OFFSET:
+      case c_base_markup_attributes::ATTRIBUTE_OPEN:
+      case c_base_markup_attributes::ATTRIBUTE_ORIENTATION:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN_CONTENT_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN_TRANSFORM:
+      case c_base_markup_attributes::ATTRIBUTE_PATTERN_UNITS:
+      case c_base_markup_attributes::ATTRIBUTE_PATH:
+      case c_base_markup_attributes::ATTRIBUTE_PATH_LENGTH:
+      case c_base_markup_attributes::ATTRIBUTE_PLACE_HOLDER:
+      case c_base_markup_attributes::ATTRIBUTE_POINTS:
+      case c_base_markup_attributes::ATTRIBUTE_POSTER:
+      case c_base_markup_attributes::ATTRIBUTE_PRELOAD:
+      case c_base_markup_attributes::ATTRIBUTE_PRESERVE_ASPECT_RATIO:
+      case c_base_markup_attributes::ATTRIBUTE_RADIO_GROUP:
+      case c_base_markup_attributes::ATTRIBUTE_SANDBOX:
+      case c_base_markup_attributes::ATTRIBUTE_SCOPE:
+      case c_base_markup_attributes::ATTRIBUTE_SHAPE:
+      case c_base_markup_attributes::ATTRIBUTE_REL:
+      case c_base_markup_attributes::ATTRIBUTE_RENDERING_INTENT:
+      case c_base_markup_attributes::ATTRIBUTE_REPEAT_COUNT:
+      case c_base_markup_attributes::ATTRIBUTE_ROLE:
+      case c_base_markup_attributes::ATTRIBUTE_ROTATE:
+      case c_base_markup_attributes::ATTRIBUTE_SIZE:
+      case c_base_markup_attributes::ATTRIBUTE_SIZES:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE_DOCUMENT:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE_SET:
+      case c_base_markup_attributes::ATTRIBUTE_SPAN:
+      case c_base_markup_attributes::ATTRIBUTE_SPREAD_METHOD:
+      case c_base_markup_attributes::ATTRIBUTE_STOP_COLOR:
+      case c_base_markup_attributes::ATTRIBUTE_STOP_OPACITY:
+      case c_base_markup_attributes::ATTRIBUTE_STYLE:
+      case c_base_markup_attributes::ATTRIBUTE_TARGET:
+      case c_base_markup_attributes::ATTRIBUTE_TEXT_LENGTH:
+      case c_base_markup_attributes::ATTRIBUTE_TEXT_CONTENT_ELEMENTS:
+      case c_base_markup_attributes::ATTRIBUTE_TITLE:
+      case c_base_markup_attributes::ATTRIBUTE_TRANSFORM:
+      case c_base_markup_attributes::ATTRIBUTE_TRANSLATE:
+      case c_base_markup_attributes::ATTRIBUTE_TO:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_BUTTON:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_LABEL:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_LIST:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE_SVG:
+      case c_base_markup_attributes::ATTRIBUTE_USE_MAP:
+      case c_base_markup_attributes::ATTRIBUTE_VALUE:
+      case c_base_markup_attributes::ATTRIBUTE_VIEW_BOX:
+      case c_base_markup_attributes::ATTRIBUTE_WIDTH:
+      case c_base_markup_attributes::ATTRIBUTE_WRAP:
+      case c_base_markup_attributes::ATTRIBUTE_XML:
+      case c_base_markup_attributes::ATTRIBUTE_XMLNS:
+      case c_base_markup_attributes::ATTRIBUTE_XMLNS_XLINK:
+      case c_base_markup_attributes::ATTRIBUTE_XML_SPACE:
+      case c_base_markup_attributes::ATTRIBUTE_ZOOM_AND_PAN:
+        if (!is_string($value)) {
+          return new c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_ATOMIC:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_AUTOCOMPLETE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_ACTIVE_DESCENDANT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_BUSY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_CHECKED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_CONTROLS:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_DESCRIBED_BY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_DISABLED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_DROP_EFFECT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_EXPANDED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_FLOW_TO:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_GRABBED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_HAS_POPUP:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_HIDDEN:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_INVALID:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LABEL:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LABELLED_BY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LEVEL:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_LIVE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_LINE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_SELECTABLE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_ORIENTATION:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_OWNS:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_POSITION_INSET:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_PRESSED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_READONLY:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_RELEVANT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_REQUIRED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_SELECTED:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_SET_SIZE:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_SORT:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MAXIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MINIMIM:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_NOW:
+      case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_TEXT:
+        if (!is_string($value)) {
+          return new c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_ASYNCHRONOUS:
+      case c_base_markup_attributes::ATTRIBUTE_ATTRIBUTE_NAME:
+      case c_base_markup_attributes::ATTRIBUTE_AUTO_COMPLETE:
+      case c_base_markup_attributes::ATTRIBUTE_AUTO_FOCUS:
+      case c_base_markup_attributes::ATTRIBUTE_AUTO_PLAY:
+      case c_base_markup_attributes::ATTRIBUTE_CHALLENGE:
+      case c_base_markup_attributes::ATTRIBUTE_CONTROLS:
+      case c_base_markup_attributes::ATTRIBUTE_CHECKED:
+      case c_base_markup_attributes::ATTRIBUTE_DEFAULT:
+      case c_base_markup_attributes::ATTRIBUTE_DEFER:
+      case c_base_markup_attributes::ATTRIBUTE_DISABLED:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_NO_VALIDATE:
+      case c_base_markup_attributes::ATTRIBUTE_HIDDEN:
+      case c_base_markup_attributes::ATTRIBUTE_LOOP:
+      case c_base_markup_attributes::ATTRIBUTE_MULTIPLE:
+      case c_base_markup_attributes::ATTRIBUTE_MUTED:
+      case c_base_markup_attributes::ATTRIBUTE_NO_VALIDATE:
+      case c_base_markup_attributes::ATTRIBUTE_READONLY:
+      case c_base_markup_attributes::ATTRIBUTE_REQUIRED:
+      case c_base_markup_attributes::ATTRIBUTE_REVERSED:
+      case c_base_markup_attributes::ATTRIBUTE_SCOPED:
+      case c_base_markup_attributes::ATTRIBUTE_SELECTED:
+      case c_base_markup_attributes::ATTRIBUTE_SORTABLE:
+      case c_base_markup_attributes::ATTRIBUTE_SORTED:
+      case c_base_markup_attributes::ATTRIBUTE_SPELLCHECK:
+        if (!is_bool($value)) {
+          return new c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_ACCEPT:
+      case c_base_markup_attributes::ATTRIBUTE_FORM_ENCODE_TYPE:
+      case c_base_markup_attributes::ATTRIBUTE_ENCODING_TYPE:
+      case c_base_markup_attributes::ATTRIBUTE_TYPE:
+        if (!$this->pr_validate_value_mime_type($value)) {
+          return new c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_ACCEPT_CHARACTER_SET:
+      case c_base_markup_attributes::ATTRIBUTE_CHARACTER_SET:
+        if (!$this->pr_validate_value_character_set($value)) {
+          return new c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_CENTER_X:
+      case c_base_markup_attributes::ATTRIBUTE_CENTER_Y:
+      case c_base_markup_attributes::ATTRIBUTE_COLUMNS:
+      case c_base_markup_attributes::ATTRIBUTE_COLUMN_SPAN:
+      case c_base_markup_attributes::ATTRIBUTE_D_X:
+      case c_base_markup_attributes::ATTRIBUTE_D_Y:
+      case c_base_markup_attributes::ATTRIBUTE_FOCUS_X:
+      case c_base_markup_attributes::ATTRIBUTE_FOCUS_Y:
+      case c_base_markup_attributes::ATTRIBUTE_HIGH:
+      case c_base_markup_attributes::ATTRIBUTE_HREF_LANGUAGE:
+      case c_base_markup_attributes::ATTRIBUTE_LANGUAGE:
+      case c_base_markup_attributes::ATTRIBUTE_LOW:
+      case c_base_markup_attributes::ATTRIBUTE_MARKER_HEIGHT:
+      case c_base_markup_attributes::ATTRIBUTE_MARKER_WIDTH:
+      case c_base_markup_attributes::ATTRIBUTE_MAXIMUM_NUMBER:
+      case c_base_markup_attributes::ATTRIBUTE_MAXIMUM_LENGTH:
+      case c_base_markup_attributes::ATTRIBUTE_MINIMUM_NUMBER:
+      case c_base_markup_attributes::ATTRIBUTE_OPTIMUM:
+      case c_base_markup_attributes::ATTRIBUTE_RADIUS:
+      case c_base_markup_attributes::ATTRIBUTE_RADIUS_X:
+      case c_base_markup_attributes::ATTRIBUTE_RADIUS_Y:
+      case c_base_markup_attributes::ATTRIBUTE_REFERENCE_X:
+      case c_base_markup_attributes::ATTRIBUTE_REFERENCE_Y:
+      case c_base_markup_attributes::ATTRIBUTE_ROWS:
+      case c_base_markup_attributes::ATTRIBUTE_ROW_SPAN:
+      case c_base_markup_attributes::ATTRIBUTE_SOURCE_LANGUAGE:
+      case c_base_markup_attributes::ATTRIBUTE_START:
+      case c_base_markup_attributes::ATTRIBUTE_STEP:
+      case c_base_markup_attributes::ATTRIBUTE_TAB_INDEX:
+      case c_base_markup_attributes::ATTRIBUTE_VALUE_NUMBER:
+      case c_base_markup_attributes::ATTRIBUTE_X:
+      case c_base_markup_attributes::ATTRIBUTE_X_1:
+      case c_base_markup_attributes::ATTRIBUTE_X_2:
+      case c_base_markup_attributes::ATTRIBUTE_X_LINK_ACTUATE:
+      case c_base_markup_attributes::ATTRIBUTE_X_LINK_HREF:
+      case c_base_markup_attributes::ATTRIBUTE_X_LINK_SHOW:
+      case c_base_markup_attributes::ATTRIBUTE_Y:
+      case c_base_markup_attributes::ATTRIBUTE_Y_1:
+      case c_base_markup_attributes::ATTRIBUTE_Y_2:
+        if (!is_int($value)) {
+          return new c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_CLASS:
+        if (!is_array($value)) {
+          return new c_base_return_false();
+        }
+        break;
+
+      case c_base_markup_attributes::ATTRIBUTE_FORM_METHOD:
+        if (!$this->pr_validate_value_http_method($value)) {
+          return new c_base_return_false();
+        }
+        break;
+
+      default:
+        return new c_base_return_false();
+    }
+
+    $this->attributes[$attribute] = $value;
     return new c_base_return_true();
   }
 
   /**
-   * Get the unique numeric tag id assigned to this object.
+   * Get the attributes assigned to this object.
    *
-   * @return c_base_return_int|c_base_return_status
-   *   The tag type assigned to this class.
-   *   FALSE is returned if the unique numeric tag id is not set.
+   * @return c_base_return_array
+   *   The attributes assigned to this class.
    *   FALSE with error bit set is returned on error.
    */
-  public function get_id() {
-    if (!isset($this->id)) {
-      return new c_base_return_false();
+  public function get_attributes() {
+    if (!isset($this->attributes) && !is_array($this->attributes)) {
+      $this->attributes = array();
     }
 
-    return new c_base_return_int($this->id);
+    return c_base_return_array::s_new($this->attributes);
   }
 
   /**
-   * Add or append a given tag to the object.
+   * Get the value of a single attribute assigned to this object.
    *
-   * If the tag is not assigned a unique internal id, then one is generated.
+   * @param int $attribute
+   *   The attribute to assign.
+   *
+   * @return c_base_return_int|c_base_return_string|c_base_return_bool|c_base_return_status
+   *   The value assigned to the attribte (the data type is different per attribute).
+   *   FALSE is returned if the element does not exist.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_attribute($attribute) {
+    if (!is_int($attribute)) {
+      return c_base_return_error::s_false();
+    }
+
+    if (!isset($this->attributes) && !is_array($this->attributes)) {
+      $this->attributes = array();
+    }
+
+    if (array_key_exists($attribute, $this->attributes)) {
+      switch ($attribute) {
+        case c_base_markup_attributes::ATTRIBUTE_NONE:
+          // should not be possible, so consider this an error (attributes set to NONE are actually unset from the array).
+          return c_base_return_error::s_false();
+
+        case c_base_markup_attributes::ATTRIBUTE_ABBR:
+        case c_base_markup_attributes::ATTRIBUTE_ACCESS_KEY:
+        case c_base_markup_attributes::ATTRIBUTE_ACTION:
+        case c_base_markup_attributes::ATTRIBUTE_ALTERNATE:
+        case c_base_markup_attributes::ATTRIBUTE_BY:
+        case c_base_markup_attributes::ATTRIBUTE_CALCULATE_MODE:
+        case c_base_markup_attributes::ATTRIBUTE_CLIP_PATH:
+        case c_base_markup_attributes::ATTRIBUTE_CLIP_PATH_UNITS:
+        case c_base_markup_attributes::ATTRIBUTE_CITE:
+        case c_base_markup_attributes::ATTRIBUTE_COLOR:
+        case c_base_markup_attributes::ATTRIBUTE_COORDINATES:
+        case c_base_markup_attributes::ATTRIBUTE_CONTENT:
+        case c_base_markup_attributes::ATTRIBUTE_CONTENT_EDITABLE:
+        case c_base_markup_attributes::ATTRIBUTE_CROSS_ORIGIN:
+        case c_base_markup_attributes::ATTRIBUTE_D:
+        case c_base_markup_attributes::ATTRIBUTE_DATA:
+        case c_base_markup_attributes::ATTRIBUTE_DATE_TIME:
+        case c_base_markup_attributes::ATTRIBUTE_DIRECTION:
+        case c_base_markup_attributes::ATTRIBUTE_DIRECTION_NAME:
+        case c_base_markup_attributes::ATTRIBUTE_DOWNLOAD:
+        case c_base_markup_attributes::ATTRIBUTE_DURATION:
+        case c_base_markup_attributes::ATTRIBUTE_FILL:
+        case c_base_markup_attributes::ATTRIBUTE_FILL_RULE:
+        case c_base_markup_attributes::ATTRIBUTE_FILL_STROKE:
+        case c_base_markup_attributes::ATTRIBUTE_FONT_SPECIFICATION:
+        case c_base_markup_attributes::ATTRIBUTE_FOR:
+        case c_base_markup_attributes::ATTRIBUTE_FORM:
+        case c_base_markup_attributes::ATTRIBUTE_FORM_ACTION:
+        case c_base_markup_attributes::ATTRIBUTE_FORM_TARGET:
+        case c_base_markup_attributes::ATTRIBUTE_FORMAT:
+        case c_base_markup_attributes::ATTRIBUTE_FROM:
+        case c_base_markup_attributes::ATTRIBUTE_GLYPH_REFERENCE:
+        case c_base_markup_attributes::ATTRIBUTE_GRADIANT_TRANSFORM:
+        case c_base_markup_attributes::ATTRIBUTE_GRADIANT_UNITS:
+        case c_base_markup_attributes::ATTRIBUTE_GRAPHICS:
+        case c_base_markup_attributes::ATTRIBUTE_HEADERS:
+        case c_base_markup_attributes::ATTRIBUTE_HEIGHT:
+        case c_base_markup_attributes::ATTRIBUTE_HREF:
+        case c_base_markup_attributes::ATTRIBUTE_HREF_NO:
+        case c_base_markup_attributes::ATTRIBUTE_HTTP_EQUIV:
+        case c_base_markup_attributes::ATTRIBUTE_ICON:
+        case c_base_markup_attributes::ATTRIBUTE_ID:
+        case c_base_markup_attributes::ATTRIBUTE_IN:
+        case c_base_markup_attributes::ATTRIBUTE_IN_2:
+        case c_base_markup_attributes::ATTRIBUTE_IS_MAP:
+        case c_base_markup_attributes::ATTRIBUTE_KEY_POINTS:
+        case c_base_markup_attributes::ATTRIBUTE_KEY_TYPE:
+        case c_base_markup_attributes::ATTRIBUTE_KIND:
+        case c_base_markup_attributes::ATTRIBUTE_LABEL:
+        case c_base_markup_attributes::ATTRIBUTE_LENGTH_ADJUST:
+        case c_base_markup_attributes::ATTRIBUTE_LIST:
+        case c_base_markup_attributes::ATTRIBUTE_LOCAL:
+        case c_base_markup_attributes::ATTRIBUTE_LONG_DESCRIPTION:
+        case c_base_markup_attributes::ATTRIBUTE_MARKERS:
+        case c_base_markup_attributes::ATTRIBUTE_MARKER_UNITS:
+        case c_base_markup_attributes::ATTRIBUTE_MASK_CONTENT_UNITS:
+        case c_base_markup_attributes::ATTRIBUTE_MASK_UNITS:
+        case c_base_markup_attributes::ATTRIBUTE_MAXIMUM:
+        case c_base_markup_attributes::ATTRIBUTE_MEDIA:
+        case c_base_markup_attributes::ATTRIBUTE_METHOD:
+        case c_base_markup_attributes::ATTRIBUTE_MODE:
+        case c_base_markup_attributes::ATTRIBUTE_MINIMUM:
+        case c_base_markup_attributes::ATTRIBUTE_NAME:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ABORT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_AFTER_PRINT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_END:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_start:
+        case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
+        case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ABORT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_AFTER_PRINT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_END:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_ITERATION:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ANIMATION_start:
+        case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_UNLOAD:
+        case c_base_markup_attributes::ATTRIBUTE_ON_BEFORE_PRINT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_BLUR:
+        case c_base_markup_attributes::ATTRIBUTE_ON_CANCEL:
+        case c_base_markup_attributes::ATTRIBUTE_ON_CLICK:
+        case c_base_markup_attributes::ATTRIBUTE_ON_CONTEXT_MENU:
+        case c_base_markup_attributes::ATTRIBUTE_ON_COPY:
+        case c_base_markup_attributes::ATTRIBUTE_ON_CUT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY:
+        case c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY_THROUGH:
+        case c_base_markup_attributes::ATTRIBUTE_ON_CHANGE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_CUE_CHANGE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_DOUBLE_CLICK:
+        case c_base_markup_attributes::ATTRIBUTE_ON_DRAG:
+        case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_END:
+        case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_ENTER:
+        case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_LEAVE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_OVER:
+        case c_base_markup_attributes::ATTRIBUTE_ON_DRAG_START:
+        case c_base_markup_attributes::ATTRIBUTE_ON_DROP:
+        case c_base_markup_attributes::ATTRIBUTE_ON_DURATION_CHANGE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_EMPTIED:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ENDED:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ERROR:
+        case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS:
+        case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS_IN:
+        case c_base_markup_attributes::ATTRIBUTE_ON_FOCUS_OUT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_HASH_CHANGE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_INPUT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_INSTALLED:
+        case c_base_markup_attributes::ATTRIBUTE_ON_INVALID:
+        case c_base_markup_attributes::ATTRIBUTE_ON_KEY_DOWN:
+        case c_base_markup_attributes::ATTRIBUTE_ON_KEY_PRESS:
+        case c_base_markup_attributes::ATTRIBUTE_ON_KEY_UP:
+        case c_base_markup_attributes::ATTRIBUTE_ON_LOAD:
+        case c_base_markup_attributes::ATTRIBUTE_ON_LOADED_DATA:
+        case c_base_markup_attributes::ATTRIBUTE_ON_LOADED_META_DATA:
+        case c_base_markup_attributes::ATTRIBUTE_ON_LOAD_START:
+        case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_DOWN:
+        case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_ENTER:
+        case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_LEAVE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_MOVE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OVER:
+        case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OUT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_UP:
+        case c_base_markup_attributes::ATTRIBUTE_ON_MESSAGE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_WHEEL:
+        case c_base_markup_attributes::ATTRIBUTE_ON_OPEN:
+        case c_base_markup_attributes::ATTRIBUTE_ON_ONLINE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_OFFLINE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_PAGE_SHOW:
+        case c_base_markup_attributes::ATTRIBUTE_ON_PAGE_HIDE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_PASTE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_PAUSE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_PLAY:
+        case c_base_markup_attributes::ATTRIBUTE_ON_PLAYING:
+        case c_base_markup_attributes::ATTRIBUTE_ON_PROGRESS:
+        case c_base_markup_attributes::ATTRIBUTE_ON_POP_STATE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_RATED_CHANGE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_RESIZE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_RESET:
+        case c_base_markup_attributes::ATTRIBUTE_ON_RATE_CHANGE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_SCROLL:
+        case c_base_markup_attributes::ATTRIBUTE_ON_SEARCH:
+        case c_base_markup_attributes::ATTRIBUTE_ON_SELECT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_SUBMIT:
+        case c_base_markup_attributes::ATTRIBUTE_ON_SEEKED:
+        case c_base_markup_attributes::ATTRIBUTE_ON_SEEKING:
+        case c_base_markup_attributes::ATTRIBUTE_ON_STALLED:
+        case c_base_markup_attributes::ATTRIBUTE_ON_SUSPEND:
+        case c_base_markup_attributes::ATTRIBUTE_ON_SHOW:
+        case c_base_markup_attributes::ATTRIBUTE_ON_STORAGE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_TIME_UPDATE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_TRANSITION_END:
+        case c_base_markup_attributes::ATTRIBUTE_ON_TOGGLE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_CANCEL:
+        case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_END:
+        case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_MOVE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_TOUCH_START:
+        case c_base_markup_attributes::ATTRIBUTE_ON_UNLOAD:
+        case c_base_markup_attributes::ATTRIBUTE_ON_VOLUME_CHANGE:
+        case c_base_markup_attributes::ATTRIBUTE_ON_WAITING:
+        case c_base_markup_attributes::ATTRIBUTE_ON_WHEEL:
+        case c_base_markup_attributes::ATTRIBUTE_OFFSET:
+        case c_base_markup_attributes::ATTRIBUTE_OPEN:
+        case c_base_markup_attributes::ATTRIBUTE_ORIENTATION:
+        case c_base_markup_attributes::ATTRIBUTE_PATTERN:
+        case c_base_markup_attributes::ATTRIBUTE_PATTERN_CONTENT_UNITS:
+        case c_base_markup_attributes::ATTRIBUTE_PATTERN_TRANSFORM:
+        case c_base_markup_attributes::ATTRIBUTE_PATTERN_UNITS:
+        case c_base_markup_attributes::ATTRIBUTE_PATH:
+        case c_base_markup_attributes::ATTRIBUTE_PATH_LENGTH:
+        case c_base_markup_attributes::ATTRIBUTE_PLACE_HOLDER:
+        case c_base_markup_attributes::ATTRIBUTE_POINTS:
+        case c_base_markup_attributes::ATTRIBUTE_POSTER:
+        case c_base_markup_attributes::ATTRIBUTE_PRELOAD:
+        case c_base_markup_attributes::ATTRIBUTE_PRESERVE_ASPECT_RATIO:
+        case c_base_markup_attributes::ATTRIBUTE_RADIO_GROUP:
+        case c_base_markup_attributes::ATTRIBUTE_SANDBOX:
+        case c_base_markup_attributes::ATTRIBUTE_SCOPE:
+        case c_base_markup_attributes::ATTRIBUTE_SHAPE:
+        case c_base_markup_attributes::ATTRIBUTE_REL:
+        case c_base_markup_attributes::ATTRIBUTE_RENDERING_INTENT:
+        case c_base_markup_attributes::ATTRIBUTE_REPEAT_COUNT:
+        case c_base_markup_attributes::ATTRIBUTE_ROLE:
+        case c_base_markup_attributes::ATTRIBUTE_ROTATE:
+        case c_base_markup_attributes::ATTRIBUTE_SIZE:
+        case c_base_markup_attributes::ATTRIBUTE_SIZES:
+        case c_base_markup_attributes::ATTRIBUTE_SOURCE:
+        case c_base_markup_attributes::ATTRIBUTE_SOURCE_DOCUMENT:
+        case c_base_markup_attributes::ATTRIBUTE_SOURCE_SET:
+        case c_base_markup_attributes::ATTRIBUTE_SPAN:
+        case c_base_markup_attributes::ATTRIBUTE_SPREAD_METHOD:
+        case c_base_markup_attributes::ATTRIBUTE_STOP_COLOR:
+        case c_base_markup_attributes::ATTRIBUTE_STOP_OPACITY:
+        case c_base_markup_attributes::ATTRIBUTE_STYLE:
+        case c_base_markup_attributes::ATTRIBUTE_TARGET:
+        case c_base_markup_attributes::ATTRIBUTE_TEXT_LENGTH:
+        case c_base_markup_attributes::ATTRIBUTE_TEXT_CONTENT_ELEMENTS:
+        case c_base_markup_attributes::ATTRIBUTE_TITLE:
+        case c_base_markup_attributes::ATTRIBUTE_TRANSFORM:
+        case c_base_markup_attributes::ATTRIBUTE_TRANSLATE:
+        case c_base_markup_attributes::ATTRIBUTE_TO:
+        case c_base_markup_attributes::ATTRIBUTE_TYPE_BUTTON:
+        case c_base_markup_attributes::ATTRIBUTE_TYPE_LABEL:
+        case c_base_markup_attributes::ATTRIBUTE_TYPE_LIST:
+        case c_base_markup_attributes::ATTRIBUTE_TYPE_SVG:
+        case c_base_markup_attributes::ATTRIBUTE_USE_MAP:
+        case c_base_markup_attributes::ATTRIBUTE_VALUE:
+        case c_base_markup_attributes::ATTRIBUTE_VIEW_BOX:
+        case c_base_markup_attributes::ATTRIBUTE_WIDTH:
+        case c_base_markup_attributes::ATTRIBUTE_WRAP:
+        case c_base_markup_attributes::ATTRIBUTE_XML:
+        case c_base_markup_attributes::ATTRIBUTE_XMLNS:
+        case c_base_markup_attributes::ATTRIBUTE_XMLNS_XLINK:
+        case c_base_markup_attributes::ATTRIBUTE_XML_SPACE:
+        case c_base_markup_attributes::ATTRIBUTE_ZOOM_AND_PAN:
+          return c_base_return_string::s_new($this->attributes[$attribute]);
+
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_ATOMIC:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_AUTOCOMPLETE:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_ACTIVE_DESCENDANT:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_BUSY:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_CHECKED:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_CONTROLS:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_DESCRIBED_BY:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_DISABLED:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_DROP_EFFECT:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_EXPANDED:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_FLOW_TO:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_GRABBED:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_HAS_POPUP:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_HIDDEN:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_INVALID:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_LABEL:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_LABELLED_BY:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_LEVEL:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_LIVE:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_LINE:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_SELECTABLE:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_ORIENTATION:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_OWNS:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_POSITION_INSET:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_PRESSED:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_READONLY:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_RELEVANT:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_REQUIRED:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_SELECTED:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_SET_SIZE:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_SORT:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MAXIMUM:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MINIMIM:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_NOW:
+        case c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_TEXT:
+          return c_base_return_string::s_new($this->attributes[$attribute]);
+
+        case c_base_markup_attributes::ATTRIBUTE_ASYNCHRONOUS:
+        case c_base_markup_attributes::ATTRIBUTE_ATTRIBUTE_NAME:
+        case c_base_markup_attributes::ATTRIBUTE_AUTO_COMPLETE:
+        case c_base_markup_attributes::ATTRIBUTE_AUTO_FOCUS:
+        case c_base_markup_attributes::ATTRIBUTE_AUTO_PLAY:
+        case c_base_markup_attributes::ATTRIBUTE_CHALLENGE:
+        case c_base_markup_attributes::ATTRIBUTE_CONTROLS:
+        case c_base_markup_attributes::ATTRIBUTE_CHECKED:
+        case c_base_markup_attributes::ATTRIBUTE_DEFAULT:
+        case c_base_markup_attributes::ATTRIBUTE_DEFER:
+        case c_base_markup_attributes::ATTRIBUTE_DISABLED:
+        case c_base_markup_attributes::ATTRIBUTE_FORM_NO_VALIDATE:
+        case c_base_markup_attributes::ATTRIBUTE_HIDDEN:
+        case c_base_markup_attributes::ATTRIBUTE_LOOP:
+        case c_base_markup_attributes::ATTRIBUTE_MULTIPLE:
+        case c_base_markup_attributes::ATTRIBUTE_MUTED:
+        case c_base_markup_attributes::ATTRIBUTE_NO_VALIDATE:
+        case c_base_markup_attributes::ATTRIBUTE_READONLY:
+        case c_base_markup_attributes::ATTRIBUTE_REQUIRED:
+        case c_base_markup_attributes::ATTRIBUTE_REVERSED:
+        case c_base_markup_attributes::ATTRIBUTE_SCOPED:
+        case c_base_markup_attributes::ATTRIBUTE_SELECTED:
+        case c_base_markup_attributes::ATTRIBUTE_SORTABLE:
+        case c_base_markup_attributes::ATTRIBUTE_SORTED:
+        case c_base_markup_attributes::ATTRIBUTE_SPELLCHECK:
+          return c_base_return_bool::s_new($this->attributes[$attribute]);
+
+        case c_base_markup_attributes::ATTRIBUTE_ACCEPT:
+        case c_base_markup_attributes::ATTRIBUTE_FORM_ENCODE_TYPE:
+        case c_base_markup_attributes::ATTRIBUTE_ENCODING_TYPE:
+        case c_base_markup_attributes::ATTRIBUTE_TYPE:
+          return c_base_return_int::s_new($this->attributes[$attribute]);
+
+        case c_base_markup_attributes::ATTRIBUTE_ACCEPT_CHARACTER_SET:
+        case c_base_markup_attributes::ATTRIBUTE_CHARACTER_SET:
+          return c_base_return_int::s_new($this->attributes[$attribute]);
+
+        case c_base_markup_attributes::ATTRIBUTE_CENTER_X:
+        case c_base_markup_attributes::ATTRIBUTE_CENTER_Y:
+        case c_base_markup_attributes::ATTRIBUTE_COLUMNS:
+        case c_base_markup_attributes::ATTRIBUTE_COLUMN_SPAN:
+        case c_base_markup_attributes::ATTRIBUTE_D_X:
+        case c_base_markup_attributes::ATTRIBUTE_D_Y:
+        case c_base_markup_attributes::ATTRIBUTE_FOCUS_X:
+        case c_base_markup_attributes::ATTRIBUTE_FOCUS_Y:
+        case c_base_markup_attributes::ATTRIBUTE_HIGH:
+        case c_base_markup_attributes::ATTRIBUTE_HREF_LANGUAGE:
+        case c_base_markup_attributes::ATTRIBUTE_LANGUAGE:
+        case c_base_markup_attributes::ATTRIBUTE_LOW:
+        case c_base_markup_attributes::ATTRIBUTE_MARKER_HEIGHT:
+        case c_base_markup_attributes::ATTRIBUTE_MARKER_WIDTH:
+        case c_base_markup_attributes::ATTRIBUTE_MAXIMUM_NUMBER:
+        case c_base_markup_attributes::ATTRIBUTE_MAXIMUM_LENGTH:
+        case c_base_markup_attributes::ATTRIBUTE_MINIMUM_NUMBER:
+        case c_base_markup_attributes::ATTRIBUTE_OPTIMUM:
+        case c_base_markup_attributes::ATTRIBUTE_RADIUS:
+        case c_base_markup_attributes::ATTRIBUTE_RADIUS_X:
+        case c_base_markup_attributes::ATTRIBUTE_RADIUS_Y:
+        case c_base_markup_attributes::ATTRIBUTE_REFERENCE_X:
+        case c_base_markup_attributes::ATTRIBUTE_REFERENCE_Y:
+        case c_base_markup_attributes::ATTRIBUTE_ROWS:
+        case c_base_markup_attributes::ATTRIBUTE_ROW_SPAN:
+        case c_base_markup_attributes::ATTRIBUTE_SOURCE_LANGUAGE:
+        case c_base_markup_attributes::ATTRIBUTE_START:
+        case c_base_markup_attributes::ATTRIBUTE_STEP:
+        case c_base_markup_attributes::ATTRIBUTE_TAB_INDEX:
+        case c_base_markup_attributes::ATTRIBUTE_VALUE_NUMBER:
+        case c_base_markup_attributes::ATTRIBUTE_X:
+        case c_base_markup_attributes::ATTRIBUTE_X_1:
+        case c_base_markup_attributes::ATTRIBUTE_X_2:
+        case c_base_markup_attributes::ATTRIBUTE_X_LINK_ACTUATE:
+        case c_base_markup_attributes::ATTRIBUTE_X_LINK_HREF:
+        case c_base_markup_attributes::ATTRIBUTE_X_LINK_SHOW:
+        case c_base_markup_attributes::ATTRIBUTE_Y:
+        case c_base_markup_attributes::ATTRIBUTE_Y_1:
+        case c_base_markup_attributes::ATTRIBUTE_Y_2:
+          return c_base_return_int::s_new($this->attributes[$attribute]);
+
+        case c_base_markup_attributes::ATTRIBUTE_FORM_METHOD:
+          return c_base_return_int::s_new($this->attributes[$attribute]);
+
+        case c_base_markup_attributes::ATTRIBUTE_CLASS:
+          return c_base_return_array::s_new($this->attributes[$attribute]);
+
+        default:
+          return new c_base_return_false();
+      }
+    }
+
+    return new c_base_return_false();
+  }
+
+  /**
+   * Add or append a given tag to the object.
    *
    * @param c_base_markup_tag $tag
    *   The tag to assign.
@@ -101,9 +1325,9 @@ class c_base_markup_tag {
    *   (optional) A position within the children array to assign the tag.
    *   If NULL, then the tag is appended to the end of the children array.
    *
-   * @return c_base_return_int|$c_base_return_status
-   *   The position in which the tag was added is returned on success.
-   *   FALSE is reeturned if an tag at the specified index already exists.
+   * @return c_base_return_status
+   *   TRUE is returned on success.
+   *   FALSE is returned if an tag at the specified index already exists.
    *   FALSE with error bit set is returned on error.
    */
   public function set_tag($tag, $index = NULL) {
@@ -115,43 +1339,540 @@ class c_base_markup_tag {
       return c_base_return_error::s_false();
     }
 
-    $tag_id = $tag->get_id();
-    if (!($tag_id instanceof c_base_return_int)) {
-      // PHP fails to provide an end() equivalent to get the end key.
-      // This performs a less efficient process of generating an array of keys and then calling end() on that array.
-      // This is then used to get the last key so that the end key can be used as the tag id.
-      $keys = array_keys($this->tags);
-      $tag_id = end($keys);
-      unset($keys);
+    if (!is_array($this->tags)) {
+      $this->tags = array();
+    }
 
-      $tag->set_id($tag_id);
+    if (is_null($index)) {
+      $this->tags[] = $tag;
+    }
+    else {
+      $this->tags[$index] = $tag;
     }
 
-    if (!array_key_exists($tag_id, $this->tags)) {
-      $this->tags[$tag_id] = $tag;
+    $this->tags_total++;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Remove a tag at the given index.
+   *
+   * @param int|null $index
+   *   A position within the children array to assign the tag.
+   *   If NULL, then the tag at the end of the children array is removed.
+   *
+   * @return c_base_return_status
+   *   TRUE is returned on success.
+   *   FALSE is returned if there is no tag at the specified index.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function unset_tag($index) {
+    if (!is_null($index) && (!is_int($index) && $index < 0)) {
+      return c_base_return_error::s_false();
     }
 
-    if (is_null($index)) {
-      $this->children[] = $tag;
+    if (!is_array($this->tags)) {
+      $this->tags = array();
+    }
 
-      // PHP fails to provide an end() equivalent to get the end key.
-      // This performs a less efficient process of generating an array of keys and then calling end() on that array.
-      // This is then used to get the last key so that the end key can be used as the tag children position.
-      $keys = array_keys($this->tags);
-      $index = end($keys);
-      unset($keys);
+    if (is_null($index)) {
+      if (!empty($this->tags)) {
+        array_pop($this->tags);
+      }
+      else {
+        return new c_base_return_false();
+      }
     }
     else {
-      if (array_key_exists($index, $this->children)) {
+      if (array_key_exists($index, $this->tags)) {
+        unset($this->tags[$index]);
+      }
+      else {
         return new c_base_return_false();
       }
+    }
+
+    $this->tags_total--;
+    return new c_base_return_true();
+  }
 
-      $this->children[$index] = $tag;
-      ksort($this->children);
+  /**
+   * Get the tag at the given position.
+   *
+   * @param int $index
+   *   The position of the child tag to get.
+   *
+   * @return c_base_markup_tag|c_base_return_status
+   *   The tag at the given index.
+   *   FALSE is returned without error bit set if there is no tag at the given index.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_tag($index) {
+    if (!is_int($index) && $index < 0) {
+      return c_base_return_error::s_false();
     }
-    unset($tag_id);
 
-    $this->tags_total++;
-    return new c_base_return_int::s_new($index);
+    if (!array_key_exists($index, $this->tags)) {
+      return new c_base_return_false();
+    }
+
+    return $this->tags[$index];
+  }
+
+  /**
+   * Get all child tags associated with this object.
+   *
+   * @return c_base_return_array|c_base_return_status
+   *   An array of child tags.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_tags() {
+    if (!is_array($this->tags)) {
+      $this->tags = array();
+    }
+
+    return c_base_return_array::s_new($this->tags);
+  }
+
+  /**
+   * Assign basic text to this tag.
+   *
+   * This is considered the 'content' of the tag.
+   *
+   * @param string $text
+   *   The text to assign.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function set_text($text) {
+    if (!is_string($text)) {
+      return c_base_return_error::s_false();
+    }
+
+    $this->text = $text;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Retrieve basic text to this tag.
+   *
+   * This is considered the 'content' of the tag.
+   *
+   * @return c_base_return_string
+   *   The text string.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_text() {
+    if (!is_string($this->text)) {
+      $this->text = '';
+    }
+
+    return c_base_return_string::s_new($this->text);
+  }
+
+  /**
+   * Assign the specified tag type.
+   *
+   * @param int $type
+   *   The tag type to assign.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function set_type($type) {
+    if (!is_int($type)) {
+      return c_base_return_error::s_false();
+    }
+
+    switch ($type) {
+      case self::TYPE_NONE:
+      case self::TYPE_A:
+      case self::TYPE_ABBR:
+      case self::TYPE_ADDRESS:
+      case self::TYPE_ALTERNATE_GLYPH:
+      case self::TYPE_ALTERNATE_GLYPH_DEFINITION:
+      case self::TYPE_ALTERNATE_GLYPH_ITEM:
+      case self::TYPE_ANIMATE:
+      case self::TYPE_ANIMATE_MOTION:
+      case self::TYPE_ANIMATE_TRANSFORM:
+      case self::TYPE_AREA:
+      case self::TYPE_ARTICLE:
+      case self::TYPE_ASIDE:
+      case self::TYPE_AUDIO:
+      case self::TYPE_BOLD:
+      case self::TYPE_BASE:
+      case self::TYPE_BDI:
+      case self::TYPE_BDO:
+      case self::TYPE_BLOCKQUOTE:
+      case self::TYPE_BREAK:
+      case self::TYPE_BUTTON:
+      case self::TYPE_CANVAS:
+      case self::TYPE_CHECKBOX:
+      case self::TYPE_CIRCLE:
+      case self::TYPE_CITE:
+      case self::TYPE_CLIP_PATH:
+      case self::TYPE_CODE:
+      case self::TYPE_COL:
+      case self::TYPE_COL_GROUP:
+      case self::TYPE_COLOR:
+      case self::TYPE_COLOR_PROFILE:
+      case self::TYPE_CURSOR:
+      case self::TYPE_DATA:
+      case self::TYPE_DATA_LIST:
+      case self::TYPE_DATE:
+      case self::TYPE_DATE_TIME_LOCAL:
+      case self::TYPE_DEFS:
+      case self::TYPE_DEL:
+      case self::TYPE_DESCRIPTION:
+      case self::TYPE_DETAILS:
+      case self::TYPE_DFN:
+      case self::TYPE_DIALOG:
+      case self::TYPE_DIVIDER:
+      case self::TYPE_DEFINITION_LIST:
+      case self::TYPE_TERM_NAME:
+      case self::TYPE_ELLIPSE:
+      case self::TYPE_EM:
+      case self::TYPE_EMAIL:
+      case self::TYPE_EMBED:
+      case self::TYPE_FE_BLEND:
+      case self::TYPE_FIELD_SET:
+      case self::TYPE_FIGURE:
+      case self::TYPE_FIGURE_CAPTION:
+      case self::TYPE_FILE:
+      case self::TYPE_FOOTER:
+      case self::TYPE_FORM:
+      case self::TYPE_GROUP:
+      case self::TYPE_H1:
+      case self::TYPE_H2:
+      case self::TYPE_H3:
+      case self::TYPE_H4:
+      case self::TYPE_H5:
+      case self::TYPE_H6:
+      case self::TYPE_HEADER:
+      case self::TYPE_HIDDEN:
+      case self::TYPE_HORIZONTAL_RULER:
+      case self::TYPE_ITALICS:
+      case self::TYPE_INLINE_FRAME:
+      case self::TYPE_IMAGE:
+      case self::TYPE_IMAGE_SVG:
+      case self::TYPE_INPUT:
+      case self::TYPE_INS:
+      case self::TYPE_KEYBOARD:
+      case self::TYPE_KEY_GEN:
+      case self::TYPE_LABEL:
+      case self::TYPE_LEGEND:
+      case self::TYPE_LIST_ITEM:
+      case self::TYPE_LINE:
+      case self::TYPE_LINEAR_GRADIENT:
+      case self::TYPE_LINK:
+      case self::TYPE_MAIN:
+      case self::TYPE_MAP:
+      case self::TYPE_MARK:
+      case self::TYPE_MARKER:
+      case self::TYPE_MASK:
+      case self::TYPE_MENU:
+      case self::TYPE_MENU_ITEM:
+      case self::TYPE_MATH:
+      case self::TYPE_META:
+      case self::TYPE_METER:
+      case self::TYPE_MONTH:
+      case self::TYPE_NAVIGATION:
+      case self::TYPE_NO_SCRIPT:
+      case self::TYPE_NUMBER:
+      case self::TYPE_OBJECT:
+      case self::TYPE_ORDERED_LIST:
+      case self::TYPE_OPTIONS_GROUP:
+      case self::TYPE_OPTION:
+      case self::TYPE_OUTPUT:
+      case self::TYPE_PARAGRAPH:
+      case self::TYPE_PARAM:
+      case self::TYPE_PASSWORD:
+      case self::TYPE_PATH:
+      case self::TYPE_PATTERN:
+      case self::TYPE_PICTURE:
+      case self::TYPE_POLYGON:
+      case self::TYPE_POLYLINE:
+      case self::TYPE_PREFORMATTED:
+      case self::TYPE_PROGRESS:
+      case self::TYPE_Q:
+      case self::TYPE_RADIAL_GRADIENT:
+      case self::TYPE_RADIO:
+      case self::TYPE_RANGE:
+      case self::TYPE_RECTANGLE:
+      case self::TYPE_RESET:
+      case self::TYPE_RUBY:
+      case self::TYPE_RUBY_PARENTHESIS:
+      case self::TYPE_RUBY_PRONUNCIATION:
+      case self::TYPE_STRIKE_THROUGH:
+      case self::TYPE_SAMPLE:
+      case self::TYPE_SCRIPT:
+      case self::TYPE_SEARCH:
+      case self::TYPE_SECTION:
+      case self::TYPE_SELECT:
+      case self::TYPE_SMALL:
+      case self::TYPE_SOURCE:
+      case self::TYPE_SPAN:
+      case self::TYPE_STOP:
+      case self::TYPE_STRONG:
+      case self::TYPE_STYLE:
+      case self::TYPE_SUB_SCRIPT:
+      case self::TYPE_SUBMIT:
+      case self::TYPE_SUPER_SCRIPT:
+      case self::TYPE_SVG:
+      case self::TYPE_TABLE:
+      case self::TYPE_TABLE_BODY:
+      case self::TYPE_TABLE_CELL:
+      case self::TYPE_TABLE_FOOTER:
+      case self::TYPE_TABLE_HEADER:
+      case self::TYPE_TABLE_HEADER_CELL:
+      case self::TYPE_TABLE_ROW:
+      case self::TYPE_TELEPHONE:
+      case self::TYPE_TEMPLATE:
+      case self::TYPE_TERM_DESCRIPTION:
+      case self::TYPE_TEXT:
+      case self::TYPE_TEXT_AREA:
+      case self::TYPE_TEXT_REFERENCE:
+      case self::TYPE_TEXT_SPAN:
+      case self::TYPE_TEXT_SVG:
+      case self::TYPE_TIME:
+      case self::TYPE_TITLE:
+      case self::TYPE_TRACK:
+      case self::TYPE_UNDERLINE:
+      case self::TYPE_UNORDERED_LIST:
+      case self::TYPE_URL:
+      case self::TYPE_USE:
+      case self::TYPE_VARIABLE:
+      case self::TYPE_VIDEO:
+      case self::TYPE_WEEK:
+      case self::TYPE_WIDE_BREAK:
+        break;
+      default:
+        return new c_base_return_false();
+    }
+
+    $this->type = $type;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Get the tag type assigned to this object.
+   *
+   * @return c_base_return_int
+   *   The tag type assigned to this class.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_type() {
+    if (!isset($this->type)) {
+      $this->type = self::TYPE_NONE;
+    }
+
+    return c_base_return_int::s_new($this->type);
+  }
+
+  /**
+   * Protected function for mime values.
+   *
+   * @param int $value
+   *   The value of the attribute populate from c_base_mime.
+   *
+   * @return bool
+   *   TRUE on success.
+   *   FALSE otherwise.
+   */
+  protected function pr_validate_value_mime_type($value) {
+    if (!is_int($value)) {
+      return FALSE;
+    }
+
+    switch ($value) {
+      case c_base_mime::CATEGORY_UNKNOWN:
+      case c_base_mime::CATEGORY_PROVIDED:
+      case c_base_mime::CATEGORY_STREAM:
+      case c_base_mime::CATEGORY_TEXT:
+      case c_base_mime::CATEGORY_IMAGE:
+      case c_base_mime::CATEGORY_AUDIO:
+      case c_base_mime::CATEGORY_VIDEO:
+      case c_base_mime::CATEGORY_DOCUMENT:
+      case c_base_mime::CATEGORY_CONTAINER:
+      case c_base_mime::CATEGORY_APPLICATION:
+      case c_base_mime::TYPE_UNKNOWN:
+      case c_base_mime::TYPE_PROVIDED:
+      case c_base_mime::TYPE_STREAM:
+      case c_base_mime::TYPE_MULTIPART:
+      case c_base_mime::TYPE_TEXT_PLAIN:
+      case c_base_mime::TYPE_TEXT_HTML:
+      case c_base_mime::TYPE_TEXT_RSS:
+      case c_base_mime::TYPE_TEXT_ICAL:
+      case c_base_mime::TYPE_TEXT_CSV:
+      case c_base_mime::TYPE_TEXT_XML:
+      case c_base_mime::TYPE_TEXT_CSS:
+      case c_base_mime::TYPE_TEXT_JS:
+      case c_base_mime::TYPE_TEXT_JSON:
+      case c_base_mime::TYPE_TEXT_RICH:
+      case c_base_mime::TYPE_TEXT_XHTML:
+      case c_base_mime::TYPE_TEXT_PS:
+      case c_base_mime::TYPE_IMAGE_PNG:
+      case c_base_mime::TYPE_IMAGE_GIF:
+      case c_base_mime::TYPE_IMAGE_JPEG:
+      case c_base_mime::TYPE_IMAGE_BMP:
+      case c_base_mime::TYPE_IMAGE_SVG:
+      case c_base_mime::TYPE_IMAGE_TIFF:
+      case c_base_mime::TYPE_AUDIO_WAV:
+      case c_base_mime::TYPE_AUDIO_OGG:
+      case c_base_mime::TYPE_AUDIO_MP3:
+      case c_base_mime::TYPE_AUDIO_MP4:
+      case c_base_mime::TYPE_AUDIO_MIDI:
+      case c_base_mime::TYPE_VIDEO_MPEG:
+      case c_base_mime::TYPE_VIDEO_OGG:
+      case c_base_mime::TYPE_VIDEO_H264:
+      case c_base_mime::TYPE_VIDEO_QUICKTIME:
+      case c_base_mime::TYPE_VIDEO_DV:
+      case c_base_mime::TYPE_VIDEO_JPEG:
+      case c_base_mime::TYPE_VIDEO_WEBM:
+      case c_base_mime::TYPE_DOCUMENT_LIBRECHART:
+      case c_base_mime::TYPE_DOCUMENT_LIBREFORMULA:
+      case c_base_mime::TYPE_DOCUMENT_LIBREGRAPHIC:
+      case c_base_mime::TYPE_DOCUMENT_LIBREPRESENTATION:
+      case c_base_mime::TYPE_DOCUMENT_LIBRESPREADSHEET:
+      case c_base_mime::TYPE_DOCUMENT_LIBRETEXT:
+      case c_base_mime::TYPE_DOCUMENT_LIBREHTML:
+      case c_base_mime::TYPE_DOCUMENT_PDF:
+      case c_base_mime::TYPE_DOCUMENT_ABIWORD:
+      case c_base_mime::TYPE_DOCUMENT_MSWORD:
+      case c_base_mime::TYPE_DOCUMENT_MSEXCEL:
+      case c_base_mime::TYPE_DOCUMENT_MSPOWERPOINT:
+      case c_base_mime::TYPE_CONTAINER_TAR:
+      case c_base_mime::TYPE_CONTAINER_CPIO:
+      case c_base_mime::TYPE_CONTAINER_JAVA:
+        break;
+      default:
+        return FALSE;
+    }
+
+    return TRUE;
+  }
+
+  /**
+   * Protected function for character set values.
+   *
+   * @param int $value
+   *   The value of the attribute populate from c_base_charset.
+   *
+   * @return bool
+   *   TRUE on success.
+   *   FALSE otherwise.
+   */
+  protected function pr_validate_value_character_set($value) {
+    if (!is_int($value)) {
+      return FALSE;
+    }
+
+    switch ($value) {
+      case c_base_charset::UNDEFINED:
+      case c_base_charset::ASCII:
+      case c_base_charset::UTF_8:
+      case c_base_charset::UTF_16:
+      case c_base_charset::UTF_32:
+      case c_base_charset::ISO_8859_1:
+      case c_base_charset::ISO_8859_2:
+      case c_base_charset::ISO_8859_3:
+      case c_base_charset::ISO_8859_4:
+      case c_base_charset::ISO_8859_5:
+      case c_base_charset::ISO_8859_6:
+      case c_base_charset::ISO_8859_7:
+      case c_base_charset::ISO_8859_8:
+      case c_base_charset::ISO_8859_9:
+      case c_base_charset::ISO_8859_10:
+      case c_base_charset::ISO_8859_11:
+      case c_base_charset::ISO_8859_12:
+      case c_base_charset::ISO_8859_13:
+      case c_base_charset::ISO_8859_14:
+      case c_base_charset::ISO_8859_15:
+      case c_base_charset::ISO_8859_16:
+        break;
+      default:
+        return FALSE;
+    }
+
+    return TRUE;
+  }
+}
+
+/**
+ * A return class whose value is represented as a generic c_base_markup_tag_return.
+ */
+class c_base_markup_tag_return extends c_base_return_value {
+  use t_base_return_value_exact;
+
+  /**
+   * @see: t_base_return_value::p_s_new()
+   */
+  public static function s_new($value) {
+    return self::p_s_new($value, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value::p_s_value()
+   */
+  public static function s_value($return) {
+    return self::p_s_value($return, __CLASS__);
+  }
+
+  /**
+   * @see: t_base_return_value_exact::p_s_value_exact()
+   */
+  public static function s_value_exact($return) {
+    return self::p_s_value_exact($return, __CLASS__, new c_base_markup_tag());
+  }
+
+  /**
+   * Assign the value.
+   *
+   * @param resource $value
+   *   Any value so long as it is an resource.
+   *   NULL is not allowed.
+   *
+   * @return bool
+   *   TRUE on success, FALSE otherwise.
+   */
+  public function set_value($value) {
+    if (!($value instanceof c_base_markup_tag)) {
+      return FALSE;
+    }
+
+    $this->value = $value;
+    return TRUE;
+  }
+
+  /**
+   * Return the value.
+   *
+   * @return c_base_markup_tag|null $value
+   *   The value c_base_markup_tag stored within this class.
+   *   NULL may be returned if there is no defined valid c_base_markup_tag.
+   */
+  public function get_value() {
+    if (!is_null($this->value) && !($this->value instanceof c_base_markup_tag)) {
+      $this->value = NULL;
+    }
+
+    return $this->value;
+  }
+
+  /**
+   * Return the value of the expected type.
+   *
+   * @return c_base_markup_tag $value
+   *   The value c_base_markup_tag stored within this class.
+   */
+  public function get_value_exact() {
+    if (!($this->value instanceof c_base_markup_tag)) {
+      $this->value = new c_base_markup_tag();
+    }
+
+    return $this->value;
   }
 }
index ea63e21a7383bb8774db9a9bda51cdbf097f58b5..3a54ad447aabb6be39359d99df89067f579fa604 100644 (file)
@@ -20,9 +20,10 @@ class c_base_mime {
   const CATEGORY_APPLICATION = 7000; // only for application/* that values not covered by any other category.
 
 
-  const TYPE_UNKNOWN  = 0;
-  const TYPE_PROVIDED = 1;
-  const TYPE_STREAM   = 2;
+  const TYPE_UNKNOWN   = 0;
+  const TYPE_PROVIDED  = 1;
+  const TYPE_STREAM    = 2;
+  const TYPE_MULTIPART = 3;
 
   const TYPE_TEXT_PLAIN = 1001;
   const TYPE_TEXT_HTML  = 1002;
@@ -77,8 +78,9 @@ class c_base_mime {
 
 
   private static $s_names_provided = array(
-    self::TYPE_PROVIDED => array('*/*', 'text/*', 'image/*', 'audio/*', 'video/*', 'application/*'),
-    self::TYPE_STREAM   => array('application/octet-stream'),
+    self::TYPE_PROVIDED  => array('*/*', 'text/*', 'image/*', 'audio/*', 'video/*', 'application/*'),
+    self::TYPE_STREAM    => array('application/octet-stream'),
+    self::TYPE_MULTIPART => array('multipart/form-data'),
   );
 
   private static $s_names_text = array(
index 010ed712b1aab9cef6dd55767d64f79f92a51c1e..8a197d830fbbe11e4b0dfa08c4d862dc280161e8 100644 (file)
@@ -56,16 +56,6 @@ trait t_base_return_value {
   }
 
   /**
-   * Return the value.
-   *
-   * @return $value
-   *   This can be anything that is to be considered a return value.
-   */
-  public function get_value() {
-    return $this->value;
-  }
-
-  /**
    * Determine if this class has a value assigned to it.
    *
    * @return bool
@@ -211,16 +201,6 @@ trait t_base_return_value_exact {
 
     return $return->get_value_exact();
   }
-
-  /**
-   * Return the value of the expected type.
-   *
-   * This guarantees that a specific type is returned.
-   *
-   * @return $value
-   *   The value of a specific type is returned.
-   */
-  abstract public function get_value_exact();
 }
 
 /**
@@ -341,6 +321,26 @@ class c_base_return {
     // when there is no error flag assigned, its value should be NULL so a simple existence check should be all that is needed.
     return $this->error instanceof c_base_error;
   }
+
+  /**
+   * Return the value.
+   *
+   * @return null $value
+   *   The value within this class.
+   */
+  public function get_value() {
+    return NULL;
+  }
+
+  /**
+   * Return the value of the expected type.
+   *
+   * @return NULL $value
+   *   The value c_base_markup_tag stored within this class.
+   */
+  public function get_value_exact() {
+    return NULL;
+  }
 }
 
 /**
@@ -358,6 +358,26 @@ class c_base_return_status extends c_base_return {
  * This class will not have any values.
  */
 class c_base_return_true extends c_base_return_status {
+
+  /**
+   * Return the value.
+   *
+   * @return bool $value
+   *   The value within this class.
+   */
+  public function get_value() {
+    return TRUE;
+  }
+
+  /**
+   * Return the value of the expected type.
+   *
+   * @return bool $value
+   *   The value c_base_markup_tag stored within this class.
+   */
+  public function get_value_exact() {
+    return TRUE;
+  }
 }
 
 /**
@@ -366,6 +386,26 @@ class c_base_return_true extends c_base_return_status {
  * This class will not have any values.
  */
 class c_base_return_false extends c_base_return_status {
+
+  /**
+   * Return the value.
+   *
+   * @return bool $value
+   *   The value within this class.
+   */
+  public function get_value() {
+    return FALSE;
+  }
+
+  /**
+   * Return the value of the expected type.
+   *
+   * @return bool $value
+   *   The value c_base_markup_tag stored within this class.
+   */
+  public function get_value_exact() {
+    return FALSE;
+  }
 }
 
 /**
@@ -395,6 +435,49 @@ class c_base_return_value extends c_base_return {
   public static function s_value($return) {
     return self::p_s_value($return, __CLASS__);
   }
+
+  /**
+   * Assign the value.
+   *
+   * @param bool $value
+   *   Any value so long as it is a bool.
+   *   NULL is not allowed.
+   *
+   * @return bool
+   *   TRUE on success, FALSE otherwise.
+   */
+  public function set_value($value) {
+    $this->value = $value;
+    return TRUE;
+  }
+
+  /**
+   * Return the value.
+   *
+   * @return $value
+   *   The value bool stored within this class.
+   */
+  public function get_value() {
+    if (!isset($this->value)) {
+      $this->value = NULL;
+    }
+
+    return $this->value;
+  }
+
+  /**
+   * Return the value of the expected type.
+   *
+   * @return $value
+   *   The value bool stored within this class.
+   */
+  public function get_value_exact() {
+    if (!isset($this->value)) {
+      $this->value = NULL;
+    }
+
+    return $this->value;
+  }
 }
 
 /**
index b261a098561af5d5c3f0a5017b841e745559350b..c1ed7202244f547e154dd1fdc11cf0e3d2202227 100644 (file)
@@ -30,7 +30,7 @@ class c_base_session {
 
   private $name;
   private $id_user;
-  private $ip;
+  private $host;
   private $password;
   private $session_id;
   private $settings;
@@ -53,7 +53,7 @@ class c_base_session {
 
     $this->name = NULL;
     $this->id_user = NULL;
-    $this->ip = NULL;
+    $this->host = NULL;
     $this->password = NULL;
     $this->session_id = NULL;
     $this->settings = NULL;
@@ -82,7 +82,7 @@ class c_base_session {
 
     unset($this->name);
     unset($this->id_user);
-    unset($this->ip);
+    unset($this->host);
     unset($this->password);
     unset($this->session_id);
     unset($this->special);
@@ -186,35 +186,35 @@ class c_base_session {
   }
 
   /**
-   * Assigns the ip address associated with the session.
+   * Assigns the host ip address associated with the session.
    *
-   * @param string $ip
-   *   The ip address.
+   * @param string $host
+   *   The host ip address.
    *
    * @return c_base_return_status
    *   TRUE on success, FALSE otherwise.
    */
-  public function set_ip($ip) {
-    if (!is_string($ip) || empty($ip)) {
+  public function set_host($host) {
+    if (!is_string($host) || empty($host)) {
       return c_base_return_error::s_false();
     }
 
-    if (mb_strlen($ip) == 0 || ip2long($ip) === FALSE) {
+    if (mb_strlen($host) == 0 || ip2long($host) === FALSE) {
       return c_base_return_error::s_false();
     }
 
-    $this->ip = $ip;
+    $this->host = $host;
     return new c_base_return_true();
   }
 
   /**
-   * Returns the stored ip address.
+   * Returns the stored host ip address.
    *
    * @return c_base_return_string
-   *   The ip address string.
+   *   The host ip address string.
    */
-  public function get_ip() {
-    return c_base_return_string::s_new($this->ip);
+  public function get_host() {
+    return c_base_return_string::s_new($this->host);
   }
 
   /**
@@ -617,7 +617,7 @@ class c_base_session {
    * @see: c_base_session::p_transfer()
    */
   public function do_pull() {
-    if (is_null($this->ip) || is_null($this->session_id)) {
+    if (is_null($this->host) || is_null($this->session_id)) {
       return c_base_return_error::s_false();
     }
 
@@ -625,7 +625,7 @@ class c_base_session {
       return c_base_return_error::s_false();
     }
 
-    $response = $this->p_transfer(array('ip' => $this->ip, 'session_id' => $this->session_id));
+    $response = $this->p_transfer(array('ip' => $this->host, 'session_id' => $this->session_id));
     if (c_base_return::s_has_error($response)) {
       return $response->get_error();
     }
@@ -690,13 +690,13 @@ class c_base_session {
    *   TRUE on success, FALSE on failure.
    *
    * @see: c_base_session::set_name()
-   * @see: c_base_session::set_ip()
+   * @see: c_base_session::set_host()
    * @see: c_base_session::set_password()
    * @see: c_base_session::do_connect()
    * @see: c_base_session::p_transfer()
    */
   public function do_push($interval_expire = NULL, $interval_max = NULL) {
-    if (is_null($this->name) || is_null($this->id_user) || is_null($this->ip) || is_null($this->password)) {
+    if (is_null($this->name) || is_null($this->id_user) || is_null($this->host) || is_null($this->password)) {
       return c_base_return_error::s_false();
     }
 
@@ -717,7 +717,7 @@ class c_base_session {
       $this->settings = array();
     }
 
-    $response = $this->p_transfer(array('name' => $this->name, 'id_user' => $this->id_user, 'ip' => $this->ip, 'password' => $this->password, 'expire' => $interval_expire, 'max' => $interval_max, 'settings' => $this->settings));
+    $response = $this->p_transfer(array('name' => $this->name, 'id_user' => $this->id_user, 'ip' => $this->host, 'password' => $this->password, 'expire' => $interval_expire, 'max' => $interval_max, 'settings' => $this->settings));
     if (c_base_return::s_has_error($response)) {
       return c_base_return_error::s_false();
     }
@@ -763,7 +763,7 @@ class c_base_session {
    * @see: self::p_transfer()
    */
   public function do_terminate() {
-    if (is_null($this->ip) || is_null($this->session_id)) {
+    if (is_null($this->host) || is_null($this->session_id)) {
       return c_base_return_error::s_false();
     }
 
@@ -771,7 +771,7 @@ class c_base_session {
       return c_base_return_error::s_false();
     }
 
-    $response = $this->p_transfer(array('ip' => $this->ip, 'session_id' => $this->session_id, 'close' => TRUE));
+    $response = $this->p_transfer(array('ip' => $this->host, 'session_id' => $this->session_id, 'close' => TRUE));
     if (c_base_return::s_has_error($response)) {
       return $response->get_error();
     }
@@ -905,7 +905,7 @@ class c_base_session_return extends c_base_return_value {
    * @see: t_base_return_value_exact::p_s_value_exact()
    */
   public static function s_value_exact($return) {
-    return self::p_s_value_exact($return, __CLASS__, FALSE);
+    return self::p_s_value_exact($return, __CLASS__, new c_base_session());
   }
 
   /**
index 8b5da3e155f8af4ad65e9e05e52914f08e7e97ed..8491b19aa06df010edbe5b2df062205a01278d3e 100644 (file)
@@ -11,7 +11,6 @@
 // include required files.
 require_once('common/base/classes/base_error.php');
 require_once('common/base/classes/base_return.php');
-require_once('common/base/classes/base_form.php');
 
 // global:
 //accesskey
@@ -95,7 +94,7 @@ require_once('common/base/classes/base_form.php');
  *
  * @see: https://www.w3.org/TR/html5/forms.html#forms
  */
-class c_theme_form_tag extends c_base_form_tag {
+class c_theme_form_tag extends c_base_markup_tag {
   private $attributes;
 
   /**
@@ -265,7 +264,7 @@ class c_theme_form_tag extends c_base_form_tag {
 
       case self::ATTRIBUTE_ACCEPT:
       case self::ATTRIBUTE_FORM_ENCODE_TYPE:
-        if (!this->pr_validate_value_mime_type($value)) {
+        if (!$this->pr_validate_value_mime_type($value)) {
           return c_base_return_false();
         }
         break;
@@ -280,7 +279,7 @@ class c_theme_form_tag extends c_base_form_tag {
         break;
 
       case self::ATTRIBUTE_FORM_METHOD:
-        if (!this->pr_validate_value_http_method($value)) {
+        if (!$this->pr_validate_value_http_method($value)) {
           return c_base_return_false();
         }
         break;
@@ -315,7 +314,7 @@ class c_theme_form_tag extends c_base_form_tag {
    * @param int $attribute
    *   The attribute to assign.
    *
-   * @return c_base_return_int|c_base_return_string|c_base_return_bool|c_base_return_false
+   * @return c_base_return_int|c_base_return_string|c_base_return_bool|c_base_return_status
    *   The value assigned to the attribte (the data type is different per attribute).
    *   FALSE is returned if the element does not exist.
    *   FALSE with error bit set is returned on error.
index 41bd434f4276b7b3b7d907c5ffeb4be086788b42..932ac436cbeca4a048ee0e5b1e12f3d8dd88b0f3 100644 (file)
  * @file
  * Provides a class for managing HTML5 Markup.
  *
- * This is currently a draft/brainstorm and is subject to be completely rewritten/redesigned.
- *
  * @see: https://www.w3.org/TR/html5/
  */
 
 // include required files.
 require_once('common/base/classes/base_error.php');
 require_once('common/base/classes/base_return.php');
+require_once('common/base/classes/base_markup.php');
+require_once('common/base/classes/base_http.php');
+require_once('common/base/classes/base_html.php');
+require_once('common/base/classes/base_mime.php');
 
 /**
- * A generic class for HTML tag attributes.
+ * An HTML theme page.
+ *
+ * This is intended to render the theme for an HTML page.
  *
- * @see: https://www.w3.org/TR/html5/forms.html#forms
+ * @todo: add support for non-standard tag attributes, which will just be a string or NULL.
+ *
+ * There are amazing levels of inconsistency in HTML5, but for now this class implements HTML5 as closely as possible.
+ * Future versions of this may violate the standard in favor of consistency and sanity.
  */
-class c_theme_html_attribute_value_boolean {
+class c_theme_html {
+  const DEFAULT_MAX_RECURSION_DEPTH = 16384;
+
+  private $html;
+  private $markup;
+  private $http;
+  private $max_recursion_depth;
+
+  /**
+   * Class constructor.
+   */
+  public function __construct() {
+    $this->html = NULL;
+    $this->markup = NULL;
+    $this->http = NULL;
+    $this->max_recursion_depth = self::DEFAULT_MAX_RECURSION_DEPTH;
+  }
+
+  /**
+   * Class destructor.
+   */
+  public function __destruct() {
+    unset($this->html);
+    unset($this->markup);
+    unset($this->http);
+    unset($this->max_recursion_depth);
+  }
+
+  /**
+   * Create a tag with commonly used properties.
+   * @param int $type
+   *   A c_base_markup_tag type id.
+   * @param string|null $id
+   *   (optional) An id attribute to assign the tag.
+   *   If null, this is variable ignored.
+   * @param array|null $classes
+   *   (optional) An array of strings representing additional classes to append.
+   *
+   * @return c_base_markup_tag_return|c_base_return_status
+   *   A newly created tag is returned on success.
+   *   FALSE with the error bit set is returned on error.
+   */
+  public static function s_create_tag($type, $id = NULL, $classes = NULL) {
+    if (!is_null($id) && !is_string($id)) {
+      return c_base_return_error::s_false();
+    }
+
+    if (!is_int($type)) {
+      return c_base_return_error::s_false();
+    }
+
+    if (!is_null($classes) && !is_array($classes)) {
+      return c_base_return_error::s_false();
+    }
+
+    $tag = new c_base_markup_tag();
+
+    $result = $tag->set_type($type);
+    if ($result instanceof c_base_return_false) {
+      return c_base_return_error::s_false();
+    }
+
+    if (is_string($id)) {
+      $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_ID, $id);
+      $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_NAME, $id);
+    }
+
+    // populate default class names based on tag type.
+    $class = array();
+    self::s_p_populate_default_class_names($type, $id, $class);
+
+    if (is_array($classes)) {
+      foreach ($classes as $class_string) {
+        if (is_string($class_string)) {
+          $class[] = $class_string;
+        }
+      }
+      unset($class_string);
+    }
+
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CLASS, $class);
+    unset($class);
+
+    return c_base_markup_tag_return::s_new($tag);
+  }
+
+  /**
+   * Assign the markup html to be themed.
+   *
+   * @param c_base_html $html
+   *   The markup html to apply the theme to.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function set_html($html) {
+    if (!($html instanceof c_base_html)) {
+      return c_base_return_error::s_false();
+    }
+
+    $this->html = $html;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Get the markup html assigned to this object.
+   *
+   * @return c_base_html_return|c_base_return_status
+   *   The markup html object.
+   *   FALSE is returned if no id is assigned.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_html() {
+    if (!($this->html instanceof c_base_html)) {
+      $this->html = new c_base_html();
+    }
+
+    return c_base_html_return::s_new($this->html);
+  }
+
+  /**
+   * Get any renderred markup.
+   *
+   * @return c_base_return_string|c_base_return_status
+   *   The unique numeric id assigned to this object.
+   *   FALSE is returned if no id is assigned.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_markup() {
+    if (!is_string($this->markup)) {
+      $this->markup = '';
+    }
+
+    return c_base_return_string::s_new($this->markup);
+  }
+
+  /**
+   * Process the markup tags and create HTML markup string.
+   *
+   * @return c_base_return_status
+   *   TRUE is returned on success, FALSE otherwise.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function render_markup() {
+    if (!($this->html instanceof c_base_html)) {
+      return c_base_return_error::s_false();
+    }
+
+    $this->markup = '<html' . $this->p_render_markup_attributes_global() . $this->p_render_markup_attributes_event_handler() . '>';
+    $this->markup .= '<head>' . $this->p_render_markup_head_tags() . '</head>';
+    $this->markup .= '<body' . $this->p_render_markup_attributes_body() .'>' . $this->p_render_markup_body_tags() . '</body>';
+    $this->markup .= '</html>';
+
+    return new c_base_return_true();
+  }
+
+  /**
+   * Assign the HTTP information.
+   *
+   * @param c_base_http $http
+   *   The markup tags to apply the theme to.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function set_http($http) {
+    if (!($http instanceof c_base_http)) {
+      return c_base_return_error::s_false();
+    }
+
+    $this->http = $http;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Get the HTTP information
+   *
+   * @return c_base_html_return|c_base_return_status
+   *   The markup tags object.
+   *   FALSE is returned if no id is assigned.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_http() {
+    if (!($this->http instanceof c_base_http)) {
+      $this->http = new c_base_http();
+    }
+
+    return c_base_http_return::s_new($this->http);
+  }
+
+  /**
+   * Assign the maximum recursion depth.
+   *
+   * @param int $max_recursion_depth
+   *   How far to recurse when generating markup from body tags.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function set_max_recursion_depth($max_recursion_depth) {
+    if (!is_int($max_recursion_depth)) {
+      return c_base_return_error::s_false();
+    }
+
+    $this->max_recursion_depth = $max_recursion_depth;
+    return new c_base_return_true();
+  }
+
+  /**
+   * Get the markup html assigned to this object.
+   *
+   * @return c_base_html_return|c_base_return_status
+   *   The markup html object.
+   *   FALSE is returned if no id is assigned.
+   *   FALSE with error bit set is returned on error.
+   */
+  public function get_max_recursion_depth() {
+    if (!is_int($this->max_recursion_depth)) {
+      $this->max_recursion_depth = self::DEFAULT_MAX_RECURSION_DEPTH;
+    }
+
+    return c_base_return_int::s_new($this->max_recursion_depth);
+  }
+
+  /**
+   * Generate a common list of class names for a given tag type.
+   *
+   * @param int $type
+   *   A c_base_markup_tag type id.
+   * @param string|null $id
+   *   A unique ID field associated with the tag.
+   *   If null, then this is ignored.
+   * @param array &$classes
+   *   An array of class names.
+   */
+  private static function s_p_populate_default_class_names($type, $id, &$class) {
+    if ($type === c_base_markup_tag::TYPE_A) {
+      $class[] = 'text';
+      $class[] = 'text-link';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-link';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ABBR) {
+      $class[] = 'text';
+      $class[] = 'text-abbreviation';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-abbreviation';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ADDRESS) {
+      $class[] = 'structure';
+      $class[] = 'structure-address';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-address';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_AREA) {
+      $class[] = 'datum';
+      $class[] = 'datum-area';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-datum';
+        $class[] = $id . '-datum-area';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ARTICLE) {
+      $class[] = 'structure';
+      $class[] = 'structure-article';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-article';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ASIDE) {
+      $class[] = 'structure';
+      $class[] = 'structure-aside';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-aside';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_AUDIO) {
+      $class[] = 'media';
+      $class[] = 'media-audio';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-media';
+        $class[] = $id . '-media-audio';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BOLD) {
+      $class[] = 'format';
+      $class[] = 'format-strong';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-strong';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BDI) {
+      $class[] = 'text';
+      $class[] = 'text-bdi';
+      $class[] = 'text-direction';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-bdi';
+        $class[] = $id . '-text-direction';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BDO) {
+      $class[] = 'text';
+      $class[] = 'text-bdo';
+      $class[] = 'text-direction';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-bdo';
+        $class[] = $id . '-text-direction';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BLOCKQUOTE) {
+      $class[] = 'text';
+      $class[] = 'text-blockquote';
+      $class[] = 'text-quote';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-blockquote';
+        $class[] = $id . '-text-quote';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BREAK) {
+      $class[] = 'structure';
+      $class[] = 'structure-break';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-break';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BUTTON) {
+      $class[] = 'field';
+      $class[] = 'field-button';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-button';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CANVAS) {
+      $class[] = 'structure';
+      $class[] = 'structure-canvas';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-canvas';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CHECKBOX) {
+      $class[] = 'field';
+      $class[] = 'field-checkbox';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-checkbox';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CITE) {
+      $class[] = 'text';
+      $class[] = 'text-cite';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-cite';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CODE) {
+      $class[] = 'text';
+      $class[] = 'text-code';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-code';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_COL) {
+      $class[] = 'structure';
+      $class[] = 'structure-column';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-column';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_COLOR) {
+      $class[] = 'field';
+      $class[] = 'field-color';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-color';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_COL_GROUP) {
+      $class[] = 'structure';
+      $class[] = 'structure-column_group';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-column_group';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DATA) {
+      $class[] = 'datum';
+      $class[] = 'datum-data';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-datum';
+        $class[] = $id . '-datum-data';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DATA) {
+      $class[] = 'datum';
+      $class[] = 'datum-data_list';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-datum';
+        $class[] = $id . '-datum-data_list';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DATE) {
+      $class[] = 'field';
+      $class[] = 'field-date';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-date';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DATE_TIME_LOCAL) {
+      $class[] = 'field';
+      $class[] = 'field-date_local_time';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-date_local_time';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TERM_DESCRIPTION) {
+      $class[] = 'text';
+      $class[] = 'text-term_description';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-term_description';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DEL) {
+      $class[] = 'format';
+      $class[] = 'format-delete';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-format';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DETAILS) {
+      $class[] = 'structure';
+      $class[] = 'structure-details';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-details';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DFN) {
+      $class[] = 'text';
+      $class[] = 'text-definition';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-definition';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DIALOG) {
+      $class[] = 'structure';
+      $class[] = 'structure-dialog';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-dialog';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DIVIDER) {
+      $class[] = 'structure';
+      $class[] = 'structure-divider';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-divider';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DIVIDER) {
+      $class[] = 'structure';
+      $class[] = 'structure-divider';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-divider';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DEFINITION_LIST) {
+      $class[] = 'structure';
+      $class[] = 'structure-definition_list';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-definition_list';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TERM_NAME) {
+      $class[] = 'text';
+      $class[] = 'text-term_name';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-term_name';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_EM) {
+      $class[] = 'format';
+      $class[] = 'format-emphasis';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-emphasis';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_EMAIL) {
+      $class[] = 'field';
+      $class[] = 'field-email';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-email';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_EMBED) {
+      $class[] = 'media';
+      $class[] = 'media-embed';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-media';
+        $class[] = $id . '-media-embed';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FIELD_SET) {
+      $class[] = 'structure';
+      $class[] = 'structure-field_set';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-field_set';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FIGURE) {
+      $class[] = 'structure';
+      $class[] = 'structure-figure';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-figure';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FIGURE_CAPTION) {
+      $class[] = 'text';
+      $class[] = 'text-figure_caption';
+      $class[] = 'text-caption';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-figure_caption';
+        $class[] = $id . '-text-caption';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FILE) {
+      $class[] = 'field';
+      $class[] = 'field-file';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-file';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FOOTER) {
+      $class[] = 'structure';
+      $class[] = 'structure-footer';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-footer';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FORM) {
+      $class[] = 'structure';
+      $class[] = 'structure-form';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-form';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H1) {
+      $class[] = 'text';
+      $class[] = 'text-heading';
+      $class[] = 'text-heading_1';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-heading';
+        $class[] = $id . '-text-heading_1';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H2) {
+      $class[] = 'text';
+      $class[] = 'text-heading';
+      $class[] = 'text-heading_2';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-heading';
+        $class[] = $id . '-text-heading_2';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H3) {
+      $class[] = 'text';
+      $class[] = 'text-heading';
+      $class[] = 'text-heading_3';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-heading';
+        $class[] = $id . '-text-heading_3';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H4) {
+      $class[] = 'text';
+      $class[] = 'text-heading';
+      $class[] = 'text-heading_4';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-heading';
+        $class[] = $id . '-text-heading_4';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H5) {
+      $class[] = 'text';
+      $class[] = 'text-heading';
+      $class[] = 'text-heading_5';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-heading';
+        $class[] = $id . '-text-heading_5';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H6) {
+      $class[] = 'text';
+      $class[] = 'text-heading';
+      $class[] = 'text-heading_6';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-heading';
+        $class[] = $id . '-text-heading_6';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_HEADER) {
+      $class[] = 'structure';
+      $class[] = 'structure-header';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-header';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_HIDDEN) {
+      $class[] = 'field';
+      $class[] = 'field-hidden';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-hidden';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_HORIZONTAL_RULER) {
+      $class[] = 'structure';
+      $class[] = 'structure-horizontal_ruler';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-horizontal_ruler';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ITALICS) {
+      $class[] = 'format';
+      $class[] = 'format-emphasis';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-emphasis';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_HORIZONTAL_RULER) {
+      $class[] = 'structure';
+      $class[] = 'structure-horizontal_ruler';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-horizontal_ruler';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_INLINE_FRAME) {
+      $class[] = 'structure';
+      $class[] = 'structure-inline_frame';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-inline_frame';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_IMAGE) {
+      $class[] = 'media';
+      $class[] = 'media-image';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-media';
+        $class[] = $id . '-media-image';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_INPUT) {
+      $class[] = 'field';
+      $class[] = 'field-input';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-input';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_INS) {
+      $class[] = 'text';
+      $class[] = 'text-insert';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-insert';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_KEYBOARD) {
+      $class[] = 'text';
+      $class[] = 'text-keyboard';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-keyboard';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_KEY_GEN) {
+      $class[] = 'field';
+      $class[] = 'field-key_generator';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-key_generator';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_LABEL) {
+      $class[] = 'field';
+      $class[] = 'field-label';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-label';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_LEGEND) {
+      $class[] = 'text';
+      $class[] = 'text-legend';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-legend';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_LIST_ITEM) {
+      $class[] = 'text';
+      $class[] = 'text-list_item';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-list_item';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MAIN) {
+      $class[] = 'structure';
+      $class[] = 'structure-main';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-main';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MAP) {
+      $class[] = 'structure';
+      $class[] = 'structure-image_map';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-image_map';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MARK) {
+      $class[] = 'format';
+      $class[] = 'format-mark';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-mark';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MENU) {
+      $class[] = 'structure';
+      $class[] = 'structure-menu';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-menu';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MENU_ITEM) {
+      $class[] = 'structure';
+      $class[] = 'structure-menu_item';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-menu_item';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_METER) {
+      $class[] = 'field';
+      $class[] = 'field-meter';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-meter';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MONTH) {
+      $class[] = 'field';
+      $class[] = 'field-month';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-month';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_NAVIGATION) {
+      $class[] = 'structure';
+      $class[] = 'structure-navigation';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-navigation';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_NO_SCRIPT) {
+      $class[] = 'structure';
+      $class[] = 'structure-no_script';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-no_script';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_NUMBER) {
+      $class[] = 'field';
+      $class[] = 'field-number';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-number';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_OBJECT) {
+      $class[] = 'media';
+      $class[] = 'media-object';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-media';
+        $class[] = $id . '-media-object';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ORDERED_LIST) {
+      $class[] = 'structure';
+      $class[] = 'structure-ordered_list';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-ordered_list';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_OPTIONS_GROUP) {
+      $class[] = 'structure';
+      $class[] = 'structure-options_group';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-options_group';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_OPTION) {
+      $class[] = 'datum';
+      $class[] = 'datum-option';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-datum';
+        $class[] = $id . '-datum-option';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_OUTPUT) {
+      $class[] = 'datum';
+      $class[] = 'datum-output';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-datum';
+        $class[] = $id . '-datum-output';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PARAGRAPH) {
+      $class[] = 'text';
+      $class[] = 'text-paragraph';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-paragraph';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PARAM) {
+      $class[] = 'datum';
+      $class[] = 'datum-parameter';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-datum';
+        $class[] = $id . '-datum-parameter';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PASSWORD) {
+      $class[] = 'field';
+      $class[] = 'field-password';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-password';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PICTURE) {
+      $class[] = 'structure';
+      $class[] = 'structure-picture';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-picture';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PREFORMATTED) {
+      $class[] = 'format';
+      $class[] = 'format-preformatted';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-preformatted';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PROGRESS) {
+      // note: 'media' is the closest thing I can think of for this tag (as in, it is like an image).
+      $class[] = 'media';
+      $class[] = 'media-progress';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-media';
+        $class[] = $id . '-media-progress';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PREFORMATTED) {
+      $class[] = 'format';
+      $class[] = 'format-preformatted';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-preformatted';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_Q) {
+      $class[] = 'text';
+      $class[] = 'text-quote';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-quote';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RADIO) {
+      $class[] = 'field';
+      $class[] = 'field-radio';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-radio';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RANGE) {
+      $class[] = 'field';
+      $class[] = 'field-range';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-range';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RESET) {
+      $class[] = 'field';
+      $class[] = 'field-reset';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-reset';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RUBY_PARENTHESIS) {
+      $class[] = 'format';
+      $class[] = 'format-ruby_parenthesis';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-ruby_parenthesis';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RUBY_PRONUNCIATION) {
+      $class[] = 'format';
+      $class[] = 'format-ruby_pronunciation';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-ruby_pronunciation';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RUBY) {
+      $class[] = 'format';
+      $class[] = 'format-ruby';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-ruby';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_STRIKE_THROUGH) {
+      $class[] = 'format';
+      $class[] = 'format-strike_through';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-strike_through';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SAMPLE) {
+      $class[] = 'text';
+      $class[] = 'text-sample';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-sample';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SEARCH) {
+      $class[] = 'field';
+      $class[] = 'field-search';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-search';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SECTION) {
+      $class[] = 'structure';
+      $class[] = 'structure-section';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-section';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SELECT) {
+      $class[] = 'field';
+      $class[] = 'field-select';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-select';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SMALL) {
+      $class[] = 'format';
+      $class[] = 'format-small';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-small';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SOURCE) {
+      $class[] = 'datum';
+      $class[] = 'datum-source';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-datum';
+        $class[] = $id . '-datum-source';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SPAN) {
+      $class[] = 'structure';
+      $class[] = 'structure-span';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-span';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_STRONG) {
+      $class[] = 'format';
+      $class[] = 'format-strong';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-strong';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SUB_SCRIPT) {
+      $class[] = 'format';
+      $class[] = 'format-sub_script';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-sub_script';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SUBMIT) {
+      $class[] = 'field';
+      $class[] = 'field-submit';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-submit';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SUPER_SCRIPT) {
+      $class[] = 'format';
+      $class[] = 'format-super_script';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-super_script';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SVG) {
+      $class[] = 'media';
+      $class[] = 'media-svg';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-media';
+        $class[] = $id . '-media-svg';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE) {
+      $class[] = 'structure';
+      $class[] = 'structure-table';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-table';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_BODY) {
+      $class[] = 'structure';
+      $class[] = 'structure-table_body';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-table_body';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_CELL) {
+      $class[] = 'structure';
+      $class[] = 'structure-table_cell';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-table_cell';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_FOOTER) {
+      $class[] = 'structure';
+      $class[] = 'structure-table_footer';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-table_footer';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_HEADER) {
+      $class[] = 'structure';
+      $class[] = 'structure-table_header';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-table_header';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_HEADER_CELL) {
+      $class[] = 'structure';
+      $class[] = 'structure-table_header_cell';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-table_header_cell';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_ROW) {
+      $class[] = 'structure';
+      $class[] = 'structure-table_row';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-table_row';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TELEPHONE) {
+      $class[] = 'field';
+      $class[] = 'field-telephone';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-telephone';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TEMPLATE) {
+      $class[] = 'datum';
+      $class[] = 'datum-template';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-datum';
+        $class[] = $id . '-datum-template';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TEXT) {
+      $class[] = 'field';
+      $class[] = 'field-text';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-text';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TEXT_AREA) {
+      $class[] = 'field';
+      $class[] = 'field-text_area';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-text_area';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TIME) {
+      $class[] = 'field';
+      $class[] = 'field-time';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-time';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TRACK) {
+      $class[] = 'datum';
+      $class[] = 'datum-track';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-datum';
+        $class[] = $id . '-datum-track';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_UNDERLINE) {
+      $class[] = 'format';
+      $class[] = 'format-underline';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-format';
+        $class[] = $id . '-format-underline';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_UNORDERED_LIST) {
+      $class[] = 'structure';
+      $class[] = 'structure-unordered_list';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-unordered_list';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_URL) {
+      $class[] = 'text';
+      $class[] = 'text-url';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-url';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_VARIABLE) {
+      $class[] = 'text';
+      $class[] = 'text-variable';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-text';
+        $class[] = $id . '-text-variable';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_VIDEO) {
+      $class[] = 'media';
+      $class[] = 'media-video';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-media';
+        $class[] = $id . '-media-video';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_WEEK) {
+      $class[] = 'field';
+      $class[] = 'field-week';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-field';
+        $class[] = $id . '-field-week';
+      }
+    }
+    elseif ($type === c_base_markup_tag::TYPE_WIDE_BREAK) {
+      $class[] = 'structure';
+      $class[] = 'structure-wide_break';
+
+      if (!is_null($id)) {
+        $class[] = $id . '-structure';
+        $class[] = $id . '-structure-wide_break';
+      }
+    }
+  }
+
+  /**
+   * Generates the HTML tag global attributes.
+   *
+   * These are used on all HTML tags.
+   *
+   * @param c_base_markup_tag|null $tag
+   *   (optional) When not NULL, represents the tag to get the attributes of.
+   *   When NULL, the html attributes are used.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_global($tag = NULL) {
+    $markup = '';
+
+
+    // attribute: id
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_ID)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ID)->get_value_exact();
+    }
+
+    if (!empty($attribute)) {
+      $markup .= ' id="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: lang
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_LANGUAGE)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LANGUAGE)->get_value_exact();
+    }
+
+    if (!empty($attribute)) {
+      $language_class_string = $this->http->get_language_class()->get_value_exact();
+      $language_class = new $language_class_string();
+      $language_array = $language_class->s_get_aliases_by_id($attribute)->get_value_exact();
+      unset($language_class);
+      unset($language_class_string);
+
+      // use the first language alias available.
+      $language = array_pop($language_array);
+      if (!empty($language)) {
+        $markup .= ' lang="' . $language . '"';
+      }
+      unset($language);
+    }
+    unset($attribute);
+
+
+    // attribute: direction
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_DIRECTION)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DIRECTION)->get_value_exact();
+    }
+
+    if (!empty($attribute)) {
+      $markup .= ' dir="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: title
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_TITLE)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TITLE)->get_value_exact();
+    }
+
+    if (!empty($attribute)) {
+      $markup .= ' title="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: access key
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_ACCESS_KEY)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ACCESS_KEY)->get_value_exact();
+    }
+
+    if (!empty($attribute)) {
+      $markup .= ' accesskey="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: contenteditable
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT_EDITABLE)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT_EDITABLE)->get_value_exact();
+    }
+
+    if (!empty($attribute)) {
+      $markup .= ' contenteditable="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: hidden
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_HIDDEN)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HIDDEN)->get_value_exact();
+    }
+
+    if ($attribute) {
+      $markup .= ' hidden';
+    }
+    unset($attribute);
+
+
+    // attribute: role
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_ROLE)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ROLE)->get_value_exact();
+    }
+
+    if (!empty($attribute)) {
+      $markup .= ' role="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: spellcheck
+    if (is_null($tag)) {
+      $is_spellcheck = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_SPELLCHECK);
+    }
+    else {
+      $is_spellcheck = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SPELLCHECK);
+    }
+
+    if (!($is_spellcheck instanceof c_base_return_false)) {
+      $is_spellcheck = $is_spellcheck->get_value_exact();
+      if ($is_spellcheck) {
+        $markup .= ' spellcheck="true"';
+      }
+      else {
+        $markup .= ' spellcheck="false"';
+      }
+    }
+
+
+    // attribute: style
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_STYLE)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_STYLE)->get_value_exact();
+    }
+
+    if (!empty($attribute)) {
+      $markup .= ' style="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: tabindex
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_TAB_INDEX)->get_value();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TAB_INDEX)->get_value();
+    }
+
+    if (is_int($attribute)) {
+      $markup .= ' tabindex="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: translate
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_TRANSLATE)->get_value_exact();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TRANSLATE)->get_value_exact();
+    }
+
+    if (!empty($attribute)) {
+      $markup .= ' translate="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: class
+    if (is_null($tag)) {
+      $attribute = $this->html->get_attribute(c_base_markup_attributes::ATTRIBUTE_CLASS)->get_value();
+    }
+    else {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CLASS)->get_value();
+    }
+
+    if (is_array($attribute) && !empty($attribute)) {
+      $markup .= ' class="' . implode(' ', $attribute) . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: aria-tags
+    $attributes = array(
+      // global tags
+      c_base_markup_attributes::ATTRIBUTE_ARIA_ATOMIC => 'aria-atomic',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_BUSY => 'aria-busy',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_CONTROLS => 'aria-controls',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_DESCRIBED_BY => 'aria-describedby',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_DISABLED => 'aria-disabled',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_DROP_EFFECT => 'aria-dropeffect',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_FLOW_TO => 'aria-flowto',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_GRABBED => 'aria-grabbed',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_HAS_POPUP => 'aria-haspopup',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_HIDDEN => 'aria-hiddem',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_INVALID => 'aria-invalid',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_LABEL => 'aria-label',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_LABELLED_BY => 'aria-labelledby',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_LIVE => 'aria-live',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_OWNS => 'aria-owns',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_RELEVANT => 'aria-relevant',
+
+      // extra context-specifc tags
+      c_base_markup_attributes::ATTRIBUTE_ARIA_AUTOCOMPLETE => 'aria-autocomplete',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_ACTIVE_DESCENDANT => 'aria-activedescendant',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_CHECKED => 'aria-checked',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_EXPANDED => 'aria-expanded',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_LEVEL => 'aria-level',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_LINE => 'aria-muultiline',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_MULTI_SELECTABLE => 'aria-multiselectable',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_ORIENTATION => 'aria-orientation',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_POSITION_INSET => 'aria-positioninsert',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_PRESSED => 'aria-pressed',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_READONLY => 'aria-readonly',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_RELEVANT => 'aria-relevant',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_REQUIRED => 'aria-required',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_SELECTED => 'aria-selected',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_SET_SIZE => 'aria-setsize',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_SORT => 'aria-sort',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MAXIMUM => 'aria-valuemax',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_MINIMIM => 'aria-valuemin',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_NOW => 'aria-valuenow',
+      c_base_markup_attributes::ATTRIBUTE_ARIA_VALUE_TEXT => 'aria-valuetext',
+    );
+
+    if (is_null($tag)) {
+      foreach ($attributes as $attribute_id => $attribute_name) {
+        $attribute = $this->html->get_attribute($attribute_id)->get_value_exact();
+        if (!empty($attribute)) {
+          $markup .= ' ' . $attribute_name . '="' . $attribute . '"';
+        }
+        unset($attribute);
+      }
+    }
+    else {
+      foreach ($attributes as $attribute_id => $attribute_name) {
+        $attribute = $tag->get_attribute($attribute_id)->get_value_exact();
+        if (!empty($attribute)) {
+          $markup .= ' ' . $attribute_name . '="' . $attribute . '"';
+        }
+        unset($attribute);
+      }
+    }
+    unset($attribute_id);
+    unset($attribute_name);
+    unset($attributes);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to event handlers.
+   *
+   * These may be specified on all HTML tags.
+   *
+   * @param c_base_markup_tag|null $tag
+   *   (optional) When not NULL, represents the tag to get the attributes of.
+   *   When NULL, the html attributes are used.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_event_handler($tag = NULL) {
+    $markup = '';
+
+    $attributes = array(
+      c_base_markup_attributes::ATTRIBUTE_ON_ABORT => 'onabort',
+      c_base_markup_attributes::ATTRIBUTE_ON_BLUR => 'onblur',
+      c_base_markup_attributes::ATTRIBUTE_ON_CANCEL => 'oncancel',
+      c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY => 'oncanplay',
+      c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY_THROUGH => 'oncanplaythrough',
+      c_base_markup_attributes::ATTRIBUTE_ON_CHANGE => 'onchange',
+      c_base_markup_attributes::ATTRIBUTE_ON_CLICK => 'onclick',
+      c_base_markup_attributes::ATTRIBUTE_ON_CUE_CHANGE => 'oncuechange',
+      c_base_markup_attributes::ATTRIBUTE_ON_DOUBLE_CLICK => 'ondblclick',
+      c_base_markup_attributes::ATTRIBUTE_ON_DURATION_CHANGE => 'ondurationchange',
+      c_base_markup_attributes::ATTRIBUTE_ON_EMPTIED => 'onemptied',
+      c_base_markup_attributes::ATTRIBUTE_ON_ENDED => 'onended',
+      c_base_markup_attributes::ATTRIBUTE_ON_ERROR => 'onerror',
+      c_base_markup_attributes::ATTRIBUTE_ON_FOCUS => 'onfocus',
+      c_base_markup_attributes::ATTRIBUTE_ON_INPUT => 'oninput',
+      c_base_markup_attributes::ATTRIBUTE_ON_INVALID => 'oninvalid',
+      c_base_markup_attributes::ATTRIBUTE_ON_KEY_DOWN => 'onkeydown',
+      c_base_markup_attributes::ATTRIBUTE_ON_KEY_PRESS => 'onkeypress',
+      c_base_markup_attributes::ATTRIBUTE_ON_KEY_UP => 'onkeyup',
+      c_base_markup_attributes::ATTRIBUTE_ON_LOAD => 'onload',
+      c_base_markup_attributes::ATTRIBUTE_ON_LOADED_DATA => 'onloadeddata',
+      c_base_markup_attributes::ATTRIBUTE_ON_LOADED_META_DATA => 'onloadedmetadata',
+      c_base_markup_attributes::ATTRIBUTE_ON_LOAD_START => 'onloadstart',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_DOWN => 'onmousedown',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_ENTER => 'onmouseenter',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_LEAVE => 'onmouseleave',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_MOVE => 'onmousemove',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OUT => 'onmouseout',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OVER => 'onmouseover',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_UP => 'onmouseup',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_WHEEL => 'onmousewheel',
+      c_base_markup_attributes::ATTRIBUTE_ON_PAUSE => 'onpause',
+      c_base_markup_attributes::ATTRIBUTE_ON_PLAY => 'onplay',
+      c_base_markup_attributes::ATTRIBUTE_ON_PLAYING => 'onplaying',
+      c_base_markup_attributes::ATTRIBUTE_ON_PROGRESS => 'onprogress',
+      c_base_markup_attributes::ATTRIBUTE_ON_RATED_CHANGE => 'onratechange',
+      c_base_markup_attributes::ATTRIBUTE_ON_RESET => 'onreset',
+      c_base_markup_attributes::ATTRIBUTE_ON_RESIZE => 'onresize',
+      c_base_markup_attributes::ATTRIBUTE_ON_SCROLL => 'onscroll',
+      c_base_markup_attributes::ATTRIBUTE_ON_SEEKED => 'onseeked',
+      c_base_markup_attributes::ATTRIBUTE_ON_SEEKING => 'onseeking',
+      c_base_markup_attributes::ATTRIBUTE_ON_SELECT => 'onselect',
+      c_base_markup_attributes::ATTRIBUTE_ON_SHOW => 'onshow',
+      c_base_markup_attributes::ATTRIBUTE_ON_INSTALLED => 'onstalled',
+      c_base_markup_attributes::ATTRIBUTE_ON_SUBMIT => 'onsubmit',
+      c_base_markup_attributes::ATTRIBUTE_ON_SUSPEND => 'onsuspend',
+      c_base_markup_attributes::ATTRIBUTE_ON_TIME_UPDATE => 'ontimeupdate',
+      c_base_markup_attributes::ATTRIBUTE_ON_TOGGLE => 'ontoggle',
+      c_base_markup_attributes::ATTRIBUTE_ON_VOLUME_CHANGE => 'onvolumechange',
+      c_base_markup_attributes::ATTRIBUTE_ON_WAITING => 'onwaiting',
+    );
+
+    if (is_null($tag)) {
+      foreach ($attributes as $attribute_id => $attribute_name) {
+        $attribute = $this->html->get_attribute($attribute_id)->get_value_exact();
+        if (!empty($attribute)) {
+          $markup .= ' ' . $attribute_name . '="' . $attribute . '"';
+        }
+        unset($attribute);
+      }
+    }
+    else {
+      foreach ($attributes as $attribute_id => $attribute_name) {
+        $attribute = $tag->get_attribute($attribute_id)->get_value_exact();
+        if (!empty($attribute)) {
+          $markup .= ' ' . $attribute_name . '="' . $attribute . '"';
+        }
+        unset($attribute);
+      }
+    }
+    unset($attribute_id);
+    unset($attribute_name);
+    unset($attributes);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag body attributes.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_body() {
+    $markup = '';
+
+
+    // attribute: id
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_ID)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' id="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: lang
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_LANGUAGE)->get_value_exact();
+    if (!empty($attribute)) {
+      $language_class_string = $this->http->get_language_class()->get_value_exact();
+      $language_class = new $language_class_string();
+      $language_array = $language_class->s_get_aliases_by_id($attribute)->get_value_exact();
+      unset($language_class);
+      unset($language_class_string);
+
+      // use the first language alias available.
+      $language = array_pop($language_array);
+      if (!empty($language)) {
+        $markup .= ' lang="' . $language . '"';
+      }
+      unset($language);
+    }
+    unset($attribute);
+
+
+    // attribute: dir
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_DIRECTION)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' dir="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: title
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_TITLE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' title="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: accesskey
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_ACCESS_KEY)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' accesskey="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: contenteditable
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_CONTENT_EDITABLE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' contenteditable="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: hidden
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_HIDDEN)->get_value_exact();
+    if ($attribute) {
+      $markup .= ' hidden';
+    }
+    unset($attribute);
+
+
+    // attribute: spellcheck
+    $is_spellcheck = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_SPELLCHECK);
+    if (!($is_spellcheck instanceof c_base_return_false)) {
+      $is_spellcheck = $is_spellcheck->get_value_exact();
+      if ($is_spellcheck) {
+        $markup .= ' spellcheck="true"';
+      }
+      else {
+        $markup .= ' spellcheck="false"';
+      }
+    }
+    unset($is_spellcheck);
+
+
+    // attribute: style
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_STYLE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' style="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: tabindex
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_TAB_INDEX)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' tabindex="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: translate
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_TRANSLATE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' translate="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: class
+    $attribute = $this->html->get_attribute_body(c_base_markup_attributes::ATTRIBUTE_CLASS)->get_value();
+    if (is_array($attribute) && !empty($attribute)) {
+      $markup .= ' class="' . implode(' ', $attribute) . '"';
+    }
+    unset($attribute);
+
+    $attributes = array(
+      c_base_markup_attributes::ATTRIBUTE_ON_ABORT => 'onabort',
+      c_base_markup_attributes::ATTRIBUTE_ON_BLUR => 'onblur',
+      c_base_markup_attributes::ATTRIBUTE_ON_CANCEL => 'oncancel',
+      c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY => 'oncanplay',
+      c_base_markup_attributes::ATTRIBUTE_ON_CAN_PLAY_THROUGH => 'oncanplaythrough',
+      c_base_markup_attributes::ATTRIBUTE_ON_CHANGE => 'onchange',
+      c_base_markup_attributes::ATTRIBUTE_ON_CLICK => 'onclick',
+      c_base_markup_attributes::ATTRIBUTE_ON_CUE_CHANGE => 'oncuechange',
+      c_base_markup_attributes::ATTRIBUTE_ON_DOUBLE_CLICK => 'ondblclick',
+      c_base_markup_attributes::ATTRIBUTE_ON_DURATION_CHANGE => 'ondurationchange',
+      c_base_markup_attributes::ATTRIBUTE_ON_EMPTIED => 'onemptied',
+      c_base_markup_attributes::ATTRIBUTE_ON_ENDED => 'onended',
+      c_base_markup_attributes::ATTRIBUTE_ON_ERROR => 'onerror',
+      c_base_markup_attributes::ATTRIBUTE_ON_FOCUS => 'onfocus',
+      c_base_markup_attributes::ATTRIBUTE_ON_INPUT => 'oninput',
+      c_base_markup_attributes::ATTRIBUTE_ON_INVALID => 'oninvalid',
+      c_base_markup_attributes::ATTRIBUTE_ON_KEY_DOWN => 'onkeydown',
+      c_base_markup_attributes::ATTRIBUTE_ON_KEY_PRESS => 'onkeypress',
+      c_base_markup_attributes::ATTRIBUTE_ON_KEY_UP => 'onkeyup',
+      c_base_markup_attributes::ATTRIBUTE_ON_LOAD => 'onload',
+      c_base_markup_attributes::ATTRIBUTE_ON_LOADED_DATA => 'onloadeddata',
+      c_base_markup_attributes::ATTRIBUTE_ON_LOADED_META_DATA => 'onloadedmetadata',
+      c_base_markup_attributes::ATTRIBUTE_ON_LOAD_START => 'onloadstart',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_DOWN => 'onmousedown',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_ENTER => 'onmouseenter',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_LEAVE => 'onmouseleave',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_MOVE => 'onmousemove',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OUT => 'onmouseout',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_OVER => 'onmouseover',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_UP => 'onmouseup',
+      c_base_markup_attributes::ATTRIBUTE_ON_MOUSE_WHEEL => 'onmousewheel',
+      c_base_markup_attributes::ATTRIBUTE_ON_PAUSE => 'onpause',
+      c_base_markup_attributes::ATTRIBUTE_ON_PLAY => 'onplay',
+      c_base_markup_attributes::ATTRIBUTE_ON_PLAYING => 'onplaying',
+      c_base_markup_attributes::ATTRIBUTE_ON_PROGRESS => 'onprogress',
+      c_base_markup_attributes::ATTRIBUTE_ON_RATED_CHANGE => 'onratechange',
+      c_base_markup_attributes::ATTRIBUTE_ON_RESET => 'onreset',
+      c_base_markup_attributes::ATTRIBUTE_ON_RESIZE => 'onresize',
+      c_base_markup_attributes::ATTRIBUTE_ON_SCROLL => 'onscroll',
+      c_base_markup_attributes::ATTRIBUTE_ON_SEEKED => 'onseeked',
+      c_base_markup_attributes::ATTRIBUTE_ON_SEEKING => 'onseeking',
+      c_base_markup_attributes::ATTRIBUTE_ON_SELECT => 'onselect',
+      c_base_markup_attributes::ATTRIBUTE_ON_SHOW => 'onshow',
+      c_base_markup_attributes::ATTRIBUTE_ON_INSTALLED => 'onstalled',
+      c_base_markup_attributes::ATTRIBUTE_ON_SUBMIT => 'onsubmit',
+      c_base_markup_attributes::ATTRIBUTE_ON_SUSPEND => 'onsuspend',
+      c_base_markup_attributes::ATTRIBUTE_ON_TIME_UPDATE => 'ontimeupdate',
+      c_base_markup_attributes::ATTRIBUTE_ON_TOGGLE => 'ontoggle',
+      c_base_markup_attributes::ATTRIBUTE_ON_VOLUME_CHANGE => 'onvolumechange',
+      c_base_markup_attributes::ATTRIBUTE_ON_WAITING => 'onwaiting',
+    );
+
+    foreach ($attributes as $attribute_id => $attribute_name) {
+      $attribute = $this->html->get_attribute_body($attribute_id)->get_value_exact();
+      if (!empty($attribute)) {
+        $markup .= ' ' . $attribute_name . '="' . $attribute . '"';
+      }
+      unset($attribute);
+    }
+    unset($attribute_id);
+    unset($attribute_name);
+    unset($attributes);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML head tags.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_head_tags() {
+    $markup = '';
+
+    $header_tags = $this->html->get_headers()->get_value();
+    if (!is_array($header_tags)) {
+      return $markup;
+    }
+
+    foreach ($header_tags as $header_tag) {
+      $tag_type = $header_tag->get_type()->get_value_exact();
+
+      if ($tag_type === c_base_markup_tag::TYPE_BASE) {
+        $markup .= '<base' . $this->p_render_markup_attributes_global($header_tag) . $this->p_render_markup_attributes_base($header_tag) . '>';
+      }
+      elseif ($tag_type === c_base_markup_tag::TYPE_LINK) {
+        $markup .= '<link' . $this->p_render_markup_attributes_global($header_tag) . $this->p_render_markup_attributes_link($header_tag) . '>';
+      }
+      elseif ($tag_type === c_base_markup_tag::TYPE_META) {
+        $markup .= '<meta' . $this->p_render_markup_attributes_global($header_tag) . $this->p_render_markup_attributes_meta($header_tag) . '>';
+      }
+      elseif ($tag_type === c_base_markup_tag::TYPE_NO_SCRIPT) {
+        $markup .= '<noscript' . $this->p_render_markup_attributes_global($header_tag) . '>';
+        $markup .= $header_tag->get_text()->get_value_exact();
+        $markup .= '</noscript>';
+      }
+      elseif ($tag_type === c_base_markup_tag::TYPE_SCRIPT) {
+        $markup .= '<script' . $this->p_render_markup_attributes_global($header_tag) . $this->p_render_markup_attributes_script($header_tag) . '>';
+        $markup .= $header_tag->get_text()->get_value_exact();
+        $markup .= '</script>';
+      }
+      elseif ($tag_type === c_base_markup_tag::TYPE_STYLE) {
+        $markup .= '<style' . $this->p_render_markup_attributes_global($header_tag) . $this->p_render_markup_attributes_style($header_tag) . '>';
+        $markup .= $header_tag->get_text()->get_value_exact();
+        $markup .= '</style>';
+      }
+      elseif ($tag_type === c_base_markup_tag::TYPE_TEMPLATE) {
+        $markup .= '<template' . $this->p_render_markup_attributes_global($header_tag) . '>';
+        $markup .= $header_tag->get_text()->get_value_exact();
+        $markup .= '</template>';
+      }
+      elseif ($tag_type === c_base_markup_tag::TYPE_TITLE) {
+        $markup .= '<title' . $this->p_render_markup_attributes_global($header_tag) . '>';
+        $markup .= $header_tag->get_text()->get_value_exact();
+        $markup .= '</title>';
+      }
+    }
+    unset($header_tag);
+    unset($header_tags);
+    unset($tag_type);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML body tags.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_body_tags() {
+    $markup = '';
+
+    $body_tags = $this->html->get_body()->get_value();
+    if (!is_array($body_tags)) {
+      return $markup;
+    }
+
+    foreach ($body_tags as $body_tag) {
+      $tag_type = $body_tag->get_type()->get_value_exact();
+
+      $children = $body_tag->get_tags()->get_value();
+      $child_markup = '';
+      if (is_array($children)) {
+        $this->p_render_markup_body_tags_recurse($child_markup, $children, 1);
+      }
+      unset($children);
+
+      $markup .= $this->p_render_markup_body_tags_by_type($body_tag, $tag_type, $child_markup);
+    }
+    unset($body_tag);
+    unset($body_tags);
+    unset($tag_type);
+
+    return $markup;
+  }
+
+  /**
+   * Recursively generates the HTML body child tags.
+   *
+   * @param string &$markup
+   *   The markup string.
+   * @parm array $children
+   *   An array of c_base_markup_tags.
+   * @parm int $depth
+   *   An integer representing the recursion depth.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_body_tags_recurse(&$markup, $children, $depth) {
+    foreach ($children as $child_tag) {
+      $tag_type = $child_tag->get_type()->get_value_exact();
+
+      $child_markup = '';
+      if ($depth < $this->max_recursion_depth) {
+        $children = $child_tag->get_tags()->get_value();
+        if (is_array($children)) {
+          $this->p_render_markup_body_tags_recurse($child_markup, $children, $depth + 1);
+        }
+        unset($children);
+      }
+
+      $markup .= $this->p_render_markup_body_tags_by_type($child_tag, $tag_type, $child_markup);
+    }
+    unset($child_tag);
+    unset($tag_type);
+  }
+
+  /**
+   * Generates the HTML body tags for the given tag type.
+   *
+   * @todo: implement SVG body tag types.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to process.
+   * @param int $type
+   *   The tag type.
+   * @param string $child_markup
+   *   Renderred markup for child tags.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_body_tags_by_type($tag, $type, $child_markup) {
+    $markup = '';
+
+    if ($type === c_base_markup_tag::TYPE_A) {
+      $markup .= '<a' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_a($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</a>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ABBR) {
+      $markup .= '<abbr' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</abbr>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ADDRESS) {
+      $markup .= '<address' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</address>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ALTERNATE_GLYPH) {
+      $markup .= '<altglyph' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_alternate_glyph($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</altglyph>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ALTERNATE_GLYPH_DEFINITION) {
+      $markup .= '<altglyphdef' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</altglyphdef>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ALTERNATE_GLYPH_ITEM) {
+      $markup .= '<altglyphitem' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</altglyphitem>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ANIMATE) {
+      $markup .= '<animate' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_animate($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</animate>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ANIMATE_MOTION) {
+      $markup .= '<animatemotion' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_animate_motion($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</animatemotion>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ANIMATE_TRANSFORM) {
+      $markup .= '<animatetransform' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_animate_transform($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</animatetransform>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_AREA) {
+      $markup .= '<area' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_area($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</area>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ARTICLE) {
+      $markup .= '<article' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</article>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ASIDE) {
+      $markup .= '<aside' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</aside>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_AUDIO) {
+      $markup .= '<audio' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_audio($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</audio>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BOLD) {
+      $markup .= '<b' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</b>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BDI) {
+      $markup .= '<bdi' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</bdi>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BDO) {
+      $markup .= '<bdo' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</bdo>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BLOCKQUOTE) {
+      $markup .= '<blockquote' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_blockquote($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</blockquote>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BREAK) {
+      $markup .= '<br' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_BUTTON) {
+      $markup .= '<button' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_button($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</button>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CANVAS) {
+      $markup .= '<canvas' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_canvas($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</canvas>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CHECKBOX) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'checkbox') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CIRCLE) {
+      $markup .= '<circle' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_circle($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</circle>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CITE) {
+      $markup .= '<cite' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</a>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CLIP_PATH) {
+      $markup .= '<clippath' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_clip_path($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</clippath>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CODE) {
+      $markup .= '<code' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</code>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_COL) {
+      $markup .= '<col' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_col($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</col>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_COL_GROUP) {
+      $markup .= '<colgroup' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_colgroup($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</colgroup>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_COLOR) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'color') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_COLOR_PROFILE) {
+      $markup .= '<colorprofile' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_color_profile($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</colorprofile>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_CURSOR) {
+      $markup .= '<cursor' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_cursor($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</cursor>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DATA) {
+      $markup .= '<data' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_data($tag)  . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</data>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DATA_LIST) {
+      $markup .= '<datalist' . $this->p_render_markup_attributes_global($tag)  . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</datalist>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DATE) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'date') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DATE_TIME_LOCAL) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'datetime-local') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TERM_DESCRIPTION) {
+      $markup .= '<dd' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</dd>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DEFS) {
+      $markup .= '<defs' . $this->p_render_markup_attributes_global($tag)  . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</defs>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DEL) {
+      $markup .= '<del' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_del($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</del>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DESCRIPTION) {
+      $markup .= '<description' . $this->p_render_markup_attributes_global($tag)  . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</description>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DETAILS) {
+      $markup .= '<details' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_details($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</details>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DFN) {
+      $markup .= '<dfn' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</dfn>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DIALOG) {
+      $markup .= '<dialog' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_dialog($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</dialog>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DIVIDER) {
+      $markup .= '<div' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</div>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_DEFINITION_LIST) {
+      $markup .= '<dl' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</dl>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TERM_NAME) {
+      $markup .= '<dt' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</dt>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ELLIPSE) {
+      $markup .= '<ellipse' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_ellipse($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</ellipse>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_EM) {
+      $markup .= '<em' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</em>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_EMAIL) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'email') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_EMBED) {
+      $markup .= '<embed' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_embed($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</embed>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FE_BLEND) {
+      $markup .= '<feblend' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_fe_blend($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</feblend>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FIELD_SET) {
+      $markup .= '<fieldset' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_fieldset($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</fieldset>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FIGURE) {
+      $markup .= '<figure' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</figure>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FIGURE_CAPTION) {
+      $markup .= '<figcaption' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</figcaption>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_GROUP) {
+      $markup .= '<g' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_group($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</g>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FILE) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'file') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FOOTER) {
+      $markup .= '<footer' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</footer>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_FORM) {
+      $markup .= '<form' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_form($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</form>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H1) {
+      $markup .= '<h1' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</h1>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H2) {
+      $markup .= '<h2' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</h2>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H3) {
+      $markup .= '<h3' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</h3>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H4) {
+      $markup .= '<h4' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</h4>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H5) {
+      $markup .= '<h5' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag-get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</h5>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_H6) {
+      $markup .= '<h6' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</h6>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_HEADER) {
+      $markup .= '<header' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</header>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_HIDDEN) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'hidden') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_HORIZONTAL_RULER) {
+      $markup .= '<hr' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ITALICS) {
+      $markup .= '<i' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</i>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_INLINE_FRAME) {
+      $markup .= '<iframe' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_iframe($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</iframe>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_IMAGE) {
+      $markup .= '<img' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_image($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</img>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_IMAGE_SVG) {
+      $markup .= '<image' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_image_svg($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</image>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_INPUT) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_INS) {
+      $markup .= '<ins' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_ins($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</ins>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_KEYBOARD) {
+      $markup .= '<kbd' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</kbd>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_KEY_GEN) {
+      $markup .= '<keygen' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_key_gen($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</keygen>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_LABEL) {
+      $markup .= '<label' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_label($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</label>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_LEGEND) {
+      $markup .= '<legend' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</legend>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_LIST_ITEM) {
+      $markup .= '<li' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_li($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</li>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_LINE) {
+      $markup .= '<line' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_line($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</line>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_LINEAR_GRADIENT) {
+      $markup .= '<lineargradient' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_linear_gradient($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</lineargradient>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MAIN) {
+      $markup .= '<main' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</main>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MAP) {
+      $markup .= '<map' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_map($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</map>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MARK) {
+      $markup .= '<mark' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</mark>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MARKER) {
+      $markup .= '<marker' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_marker($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</marker>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MASK) {
+      $markup .= '<mask' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_mask($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</mask>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MENU) {
+      $markup .= '<menu' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_menu($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</menu>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MENU_ITEM) {
+      $markup .= '<menuitem' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_menuitem($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</menuitem>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_METER) {
+      $markup .= '<meter' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_meter($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</meter>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_MONTH) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'month') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_NAVIGATION) {
+      $markup .= '<nav' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</nav>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_NUMBER) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'number') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_OBJECT) {
+      $markup .= '<object' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_object($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</object>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_ORDERED_LIST) {
+      $markup .= '<ol' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_ol($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</ol>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_OPTIONS_GROUP) {
+      $markup .= '<opt_group' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_opt_group($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</opt_group>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_OPTION) {
+      $markup .= '<option' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_option($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</option>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_OUTPUT) {
+      $markup .= '<output' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_output($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</output>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PARAGRAPH) {
+      $markup .= '<p' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</p>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PARAM) {
+      $markup .= '<param' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_param($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</param>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PASSWORD) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'password') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PATH) {
+      $markup .= '<path' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_path($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</path>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PATTERN) {
+      $markup .= '<pattern' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_pattern($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</pattern>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PICTURE) {
+      $markup .= '<picture' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</picture>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_POLYGON) {
+      $markup .= '<polygon' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_polygon($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</polygon>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_POLYLINE) {
+      $markup .= '<polyline' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_polyline($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</polyline>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PREFORMATTED) {
+      $markup .= '<pre' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</pre>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_PROGRESS) {
+      $markup .= '<progress' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_progress($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</progress>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_Q) {
+      $markup .= '<q' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_q($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</q>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RADIAL_GRADIENT) {
+      $markup .= '<radialgradient' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_radial_gradient($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</radialgradient>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RADIO) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'radio') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RANGE) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'range') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RECTANGLE) {
+      $markup .= '<rect' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_rectangle($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</rect>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RESET) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'reset') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RUBY_PARENTHESIS) {
+      $markup .= '<rp' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</rp>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RUBY_PRONUNCIATION) {
+      $markup .= '<rt' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</rt>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_RUBY) {
+      $markup .= '<ruby' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</ruby>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_STRIKE_THROUGH) {
+      $markup .= '<s' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</s>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SAMPLE) {
+      $markup .= '<samp' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</samp>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SEARCH) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'search') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SECTION) {
+      $markup .= '<section' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</section>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SELECT) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'select') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SMALL) {
+      $markup .= '<small' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</small>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SOURCE) {
+      $markup .= '<source' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_source($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</source>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SPAN) {
+      $markup .= '<span' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</span>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_STOP) {
+      $markup .= '<stop' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_stop($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</stop>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_STRONG) {
+      $markup .= '<strong' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</strong>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SUB_SCRIPT) {
+      $markup .= '<sub' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</sub>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SUBMIT) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'submit') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_SVG) {
+      $markup .= '<svg' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_svg($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</svg>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE) {
+      $markup .= '<table' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_table($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</table>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_BODY) {
+      $markup .= '<tbody' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</tbody>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_CELL) {
+      $markup .= '<td' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</td>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_FOOTER) {
+      $markup .= '<tfoot' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</tfoot>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_HEADER) {
+      $markup .= '<thead' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</thead>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_HEADER_CELL) {
+      $markup .= '<th' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_table_header_cell($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</th>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TABLE_ROW) {
+      $markup .= '<tr' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</tr>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TEXT) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'text') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TEXT_AREA) {
+      $markup .= '<textarea' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_text_area($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</textarea>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TEXT_REFERENCE) {
+      $markup .= '<tref' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</tref>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TEXT_SPAN) {
+      $markup .= '<tspan' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</tspan>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TEXT_SVG) {
+      $markup .= '<text' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_text_svg($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</text>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TIME) {
+      $markup .= '<time' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_time($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</time>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_TRACK) {
+      $markup .= '<track' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_track($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</track>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_UNDERLINE) {
+      $markup .= '<u' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</u>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_UNORDERED_LIST) {
+      $markup .= '<a' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</a>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_URL) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'url') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_USE) {
+      $markup .= '<use' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_use($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</use>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_VARIABLE) {
+      $markup .= '<var' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</var>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_VIDEO) {
+      $markup .= '<video' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_video($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</video>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_WEEK) {
+      $markup .= '<input' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_input($tag, 'week') . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</input>';
+    }
+    elseif ($type === c_base_markup_tag::TYPE_WIDE_BREAK) {
+      $markup .= '<wbr' . $this->p_render_markup_attributes_global($tag) . $this->p_render_markup_attributes_event_handler($tag) . '>';
+      $markup .= $tag->get_text()->get_value_exact();
+      $markup .= $child_markup;
+      $markup .= '</wbr>';
+    }
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body a tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_a($tag) {
+    $markup = '';
+
+
+    // attribute: download
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DOWNLOAD)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' download="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: hreflang
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HREF_LANGUAGE)->get_value_exact();
+
+    if (!empty($attribute)) {
+      $language_class_string = $this->http->get_language_class()->get_value_exact();
+      $language_class = new $language_class_string();
+      $language_array = $language_class->s_get_aliases_by_id($attribute)->get_value_exact();
+      unset($language_class);
+      unset($language_class_string);
+
+      // use the first language alias available.
+      $language = array_pop($language_array);
+      if (!empty($language)) {
+        $markup .= ' hreflang="' . $language . '"';
+      }
+      unset($language);
+    }
+    unset($attribute);
+
+
+    // attribute: media
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MEDIA)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' media="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rel
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_REL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' rel="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: target
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TARGET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' target="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' type="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:show
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_SHOW)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:show="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:actuate
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_ACTUATE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:actuate="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body altglyph tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_alternate_glyph($tag) {
+    $markup = '';
+
+
+    // attribute: dx
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_D_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' dx="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: dy
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_D_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' dy="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: format
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORMAT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' format="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: glyphRef
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_GLYPH_REFERENCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' glyphref="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rotate
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ROTATE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' rotate="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body animate tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_animate($tag) {
+    $markup = '';
+
+
+    // attribute: attributename
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' attributename="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: by
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_BY)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' by="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: dur
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DURATION)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' dur="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: from
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FROM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' from="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: repeatcount
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_REPEAT_COUNT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' repeatcount="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: to
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TO)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' to="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body animate_motion tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_animate_motion($tag) {
+    $markup = '';
+
+
+    // attribute: calcmode
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CALCULATE_MODE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' calcmode="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: keypoints
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_KEY_POINTS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' keypoints="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: path
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PATH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' path="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rotate
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ROTATE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' rotate="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body animate_transform tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_animate_transform($tag) {
+    $markup = '';
+
+
+    // attribute: by
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_BY)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' by="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: from
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FROM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' from="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: to
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TO)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' to="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE_SVG)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' type="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body area tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_area($tag) {
+    $markup = '';
+
+
+    // attribute: alt
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ALTERNATE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' alt="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: coords
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_COORDINATES)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' coords="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: download
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DOWNLOAD)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' download="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: hreflang
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HREF_LANGUAGE)->get_value_exact();
+
+    if (!empty($attribute)) {
+      $language_class_string = $this->http->get_language_class()->get_value_exact();
+      $language_class = new $language_class_string();
+      $language_array = $language_class->s_get_aliases_by_id($attribute)->get_value_exact();
+      unset($language_class);
+      unset($language_class_string);
+
+      // use the first language alias available.
+      $language = array_pop($language_array);
+      if (!empty($language)) {
+        $markup .= ' hreflang="' . $language . '"';
+      }
+      unset($language);
+    }
+    unset($attribute);
+
+
+    // attribute: media
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MEDIA)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' media="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: nohref
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HREF_NO)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' nohref="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rel
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_REL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' rel="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: shape
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SHAPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' shape="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: target
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TARGET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' target="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' type="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body audio tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_audio($tag) {
+    $markup = '';
+
+
+    // attribute: autoplay
+    $is_autoplay = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_AUTO_PLAY)->get_value_exact();
+    if ($is_autoplay) {
+      $markup .= ' autoplay';
+    }
+
+
+    // attribute: controls
+    $is_controls = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CONTROLS)->get_value_exact();
+    if ($is_controls) {
+      $markup .= ' controls';
+    }
+
+
+    // attribute: loop
+    $is_loop = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LOOP)->get_value_exact();
+    if ($is_loop) {
+      $markup .= ' loop';
+    }
+
+
+    // attribute: muted
+    $is_muted = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MUTED)->get_value_exact();
+    if ($is_muted) {
+      $markup .= ' muted';
+    }
+
+
+    // attribute: preload
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PRELOAD)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' preload="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: src
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' src="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the head base tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_base($tag) {
+    $markup = '';
+
+
+    // attribute: href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: target
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TARGET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' target="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body blockquote tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_blockquote($tag) {
+    $markup = '';
+
+
+    // attribute: cite
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CITE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' cite="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body button tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_button($tag) {
+    $markup = '';
+
+
+    // attribute: autofocus
+    $is_autofocus = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_AUTO_FOCUS)->get_value_exact();
+    if ($is_autofocus) {
+      $markup .= ' autofocus';
+    }
+
+
+    // attribute: disabled
+    $is_disabled = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DISABLED)->get_value_exact();
+    if ($is_disabled) {
+      $markup .= ' disabled';
+    }
+
+
+    // attribute: form
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' form="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: formaction
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_ACTION)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' formaction="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: formenctype
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_ENCODE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' formenctype="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+
+    // attribute: formmethod
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_METHOD)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' formmethod="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: formnovalidate
+    $is_form_no_validate = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_NO_VALIDATE)->get_value_exact();
+    if ($is_form_no_validate) {
+      $markup .= ' formnovalidate';
+    }
+
+
+    // attribute: formtarget
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_TARGET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' formtarget="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE_BUTTON)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' type="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: value
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' value="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body canvas tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_canvas($tag) {
+    $markup = '';
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body circle tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_circle($tag) {
+    $markup = '';
+
+
+    // attribute: cx
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CENTER_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' cx="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: cy
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CENTER_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' cy="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: r
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_RADIUS)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' r="' . $attribute . '"';
+    }
+    unset($attribute);
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body clippath tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_clip_path($tag) {
+    $markup = '';
+
+
+    // attribute: clip-path
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CLIP_PATH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' clip-path="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: clippathunits
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CLIP_PATH_UNITS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' clippathunits="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body col tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_col($tag) {
+    $markup = '';
+
+
+    // attribute: span
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SPAN)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' span="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body colgroup tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_colgroup($tag) {
+    $markup = '';
+
+
+    // attribute: span
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SPAN)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' span="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body colorprofile tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_color_profile($tag) {
+    $markup = '';
+
+
+    // attribute: local
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LOCAL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' local="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rendering-intent
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_RENDERING_INTENT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' rendering-intent="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body cursor tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_cursor($tag) {
+    $markup = '';
+
+
+    // attribute: x
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body data tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_data($tag) {
+    $markup = '';
+
+
+    // attribute: value
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' value="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body del tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_del($tag) {
+    $markup = '';
+
+
+    // attribute: cite
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CITE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' cite="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: datetime
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DATE_TIME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' datetime="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body details tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_details($tag) {
+    $markup = '';
+
+
+    // attribute: open
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_OPEN)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' open="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body dialog tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_dialog($tag) {
+    $markup = '';
+
+
+    // attribute: open
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_OPEN)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' open="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body ellipse tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_ellipse($tag) {
+    $markup = '';
+
+
+    // attribute: cx
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CENTER_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' cx="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: cy
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CENTER_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' cy="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rx
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_RADIUS_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' rx="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: ry
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_RADIUS_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' ry="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body embed tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_embed($tag) {
+    $markup = '';
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: src
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' src="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' type="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body feblend tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_fe_blend($tag) {
+    $markup = '';
+
+
+    // attribute: mode
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MODE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' mode="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: in
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_IN)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' in="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: in2
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_IN_2)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' in2="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body fieldset tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_fieldset($tag) {
+    $markup = '';
+
+
+    // attribute: disabled
+    $is_disabled = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DISABLED)->get_value_exact();
+    if ($is_disabled) {
+      $markup .= ' disabled';
+    }
+
+
+    // attribute: form
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' form="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body form tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_form($tag) {
+    $markup = '';
+
+
+    // attribute: accept-charset
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ACCEPT_CHARACTER_SET)->get_value_exact();
+    if (!empty($attribute)) {
+      $value = c_base_charset::s_to_string($attribute)->get_value();
+      if (is_string($value)) {
+        $markup .= ' accept-charset="' . $value . '"';
+      }
+      unset($value);
+    }
+    unset($attribute);
+
+
+    // attribute: action
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ACTION)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' action="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: autocomplete
+    $is_autocomplete = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_AUTO_COMPLETE);
+    if (!($is_autocomplete instanceof c_base_return_false)) {
+      $is_autocomplete = $is_spellcheck->get_value_exact();
+      if ($is_autocomplete) {
+        $markup .= ' autocomplete="on"';
+      }
+      else {
+        $markup .= ' autocomplete="off"';
+      }
+    }
+    unset($is_autocomplete);
+
+
+    // attribute: enctype
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ENCODING_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' enctype="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+
+    // attribute: method
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_METHOD)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' method="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+
+
+    // attribute: novalidate
+    $is_novalidate = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NO_VALIDATE)->get_value_exact();
+    if ($is_novalidate) {
+      $markup .= ' novalidate';
+    }
+
+
+    // attribute: target
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TARGET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' target="' . $attribute . '"';
+    }
+    unset($attribute);
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body g tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_group($tag) {
+    $markup = '';
+
+
+    // attribute: fill
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FILL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' fill="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: opacity
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_OPACITY)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' opacity="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body iframe tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_iframe($tag) {
+    $markup = '';
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: sandbox
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SANDBOX)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' sandbox="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: src
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' src="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: srcdoc
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE_DOCUMENT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' srcdoc="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body img tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_image($tag) {
+    $markup = '';
+
+
+    // attribute: alt
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ALTERNATE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' alt="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: ismap
+    $is_map = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_IS_MAP)->get_value_exact();
+    if ($is_map) {
+      $markup .= ' ismap';
+    }
+
+
+    // attribute: longdesc
+    $is_map = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LONG_DESCRIPTION)->get_value_exact();
+    if ($is_map) {
+      $markup .= ' longdesc';
+    }
+
+
+    // attribute: sizes
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SIZES)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' sizes="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: src
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' src="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: srcset
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE_SET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' srcset="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: usemap
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_USE_MAP)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' usemap="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body image tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_image_svg($tag) {
+    $markup = '';
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body input tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   * @param string|null $type
+   *   (optional) If not null, then is a string that overrides the type.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_input($tag, $type = NULL) {
+    $markup = '';
+
+
+    // attribute: accept
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ACCEPT)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' accept="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+
+    // attribute: alt
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ALTERNATE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' alt="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: autocomplete
+    $is_autocomplete = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_AUTO_COMPLETE);
+    if (!($is_autocomplete instanceof c_base_return_false)) {
+      $is_autocomplete = $is_spellcheck->get_value_exact();
+      if ($is_autocomplete) {
+        $markup .= ' autocomplete="on"';
+      }
+      else {
+        $markup .= ' autocomplete="off"';
+      }
+    }
+    unset($is_autocomplete);
+
+
+    // attribute: autofocus
+    $is_autofocus = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_AUTO_FOCUS)->get_value_exact();
+    if ($is_autofocus) {
+      $markup .= ' autofocus';
+    }
+
+
+    // attribute: checked
+    $is_checked = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CHECKED)->get_value_exact();
+    if ($is_checked) {
+      $markup .= ' checked';
+    }
+
+
+    // attribute: disabled
+    $is_disabled = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DISABLED)->get_value_exact();
+    if ($is_disabled) {
+      $markup .= ' disabled';
+    }
+
+
+    // attribute: dirname
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DIRECTION_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' dirname="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: form
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' form="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: formaction
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_ACTION)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' formaction="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: formenctype
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_ENCODE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' formenctype="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+
+    // attribute: formmethod
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_METHOD)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' formmethod="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: formnovalidate
+    $is_form_no_validate = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_NO_VALIDATE)->get_value_exact();
+    if ($is_form_no_validate) {
+      $markup .= ' formnovalidate';
+    }
+
+
+    // attribute: formtarget
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM_TARGET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' formtarget="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: list
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LIST)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' list="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: max
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MAXIMUM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' max="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: maxlength
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MAXIMUM_LENGTH)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' maxlength="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: multiple
+    $is_multiple = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MULTIPLE)->get_value_exact();
+    if ($is_multiple) {
+      $markup .= ' multiple';
+    }
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: pattern
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PATTERN)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' pattern="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: placeholder
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PLACE_HOLDER)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' placeholder="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: readonly
+    $is_readonly = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_READONLY)->get_value_exact();
+    if ($is_readonly) {
+      $markup .= ' readonly';
+    }
+
+
+    // attribute: required
+    $is_required = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_REQUIRED)->get_value_exact();
+    if ($is_required) {
+      $markup .= ' required';
+    }
+
+
+    // attribute: size
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SIZE)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' size="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: src
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' src="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: step
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_STEP)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' step="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    if (is_null($type)) {
+      $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE_BUTTON)->get_value_exact();
+      if (!empty($attribute)) {
+        $markup .= ' type="' . $attribute . '"';
+      }
+      unset($attribute);
+    }
+    else {
+      $markup .= ' type="' . $type . '"';
+    }
+
+
+    // attribute: value
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' value="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body ins tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_ins($tag) {
+    $markup = '';
+
+
+    // attribute: cite
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CITE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' cite="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: datetime
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DATE_TIME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' datetime="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body keygen tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_key_gen($tag) {
+    $markup = '';
+
+
+    // attribute: autofocus
+    $is_autofocus = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_AUTO_FOCUS)->get_value_exact();
+    if ($is_autofocus) {
+      $markup .= ' autofocus';
+    }
+
+
+    // attribute: challenge
+    $is_challenge = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CHALLENGE)->get_value_exact();
+    if ($is_challenge) {
+      $markup .= ' challenge';
+    }
+
+
+    // attribute: disabled
+    $is_disabled = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DISABLED)->get_value_exact();
+    if ($is_disabled) {
+      $markup .= ' disabled';
+    }
+
+
+    // attribute: form
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' form="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: keytype
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_KEY_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' keytype="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body label tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_label($tag) {
+    $markup = '';
+
+
+    // attribute: for
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FOR)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' for="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: form
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' form="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body li tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_li($tag) {
+    $markup = '';
+
+
+    // attribute: value
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' value="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body line tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_line($tag) {
+    $markup = '';
+
+
+    // attribute: x1
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X_1)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x1="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x2
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X_2)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x2="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y1
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y_1)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y1="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y2
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y_2)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y2="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body lineargradient tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_linear_gradient($tag) {
+    $markup = '';
+
+
+    // attribute: gradientunits
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_GRADIANT_UNITS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' gradientunits="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: gradienttransform
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_GRADIANT_TRANSFORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' gradienttransform="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x1
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X_1)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x1="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x2
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X_2)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x2="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y1
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y_1)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y1="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y2
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y_2)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y2="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the head link tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_link($tag) {
+    $markup = '';
+
+
+    // attribute: crossorigin
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CROSS_ORIGIN)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' crossorigin="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: hreflang
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HREF_LANGUAGE)->get_value_exact();
+
+    if (!empty($attribute)) {
+      $language_class_string = $this->http->get_language_class()->get_value_exact();
+      $language_class = new $language_class_string();
+      $language_array = $language_class->s_get_aliases_by_id($attribute)->get_value_exact();
+      unset($language_class);
+      unset($language_class_string);
+
+      // use the first language alias available.
+      $language = array_pop($language_array);
+      if (!empty($language)) {
+        $markup .= ' hreflang="' . $language . '"';
+      }
+      unset($language);
+    }
+    unset($attribute);
+
+
+    // attribute: media
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MEDIA)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' media="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rel
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_REL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' rel="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: sizes
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SIZES)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' sizes="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: target
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TARGET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' target="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' type="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body map tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_map($tag) {
+    $markup = '';
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body marker tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_marker($tag) {
+    $markup = '';
+
+
+    // attribute: gradienttransform
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_GRADIANT_TRANSFORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' gradienttransform="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: markerheight
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MARKER_HEIGHT)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' markerheight="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: markerunits
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MARKER_UNITS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' markerunits="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: markerwidth
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MARKER_WIDTH)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' markerwidth="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: orient
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ORIENTATION)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' orient="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: refx
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_REFERENCE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' refx="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: refy
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_REFERENCE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' refy="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: viewbox
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VIEW_BOX)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' viewbox="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body mask tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_mask($tag) {
+    $markup = '';
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: maskunits
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MASK_UNITS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' maskunits="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body menu tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_menu($tag) {
+    $markup = '';
+
+
+    // attribute: label
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LABEL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' label="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE_LABEL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' type="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body menuitem tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_menuitem($tag) {
+    $markup = '';
+
+
+    // attribute: checked
+    $is_checked = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CHECKED)->get_value_exact();
+    if ($is_checked) {
+      $markup .= ' checked';
+    }
+
+
+    // attribute: default
+    $is_default = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DEFAULT)->get_value_exact();
+    if ($is_default) {
+      $markup .= ' default';
+    }
+
+
+    // attribute: disabled
+    $is_disabled = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DISABLED)->get_value_exact();
+    if ($is_disabled) {
+      $markup .= ' disabled';
+    }
+
+
+    // attribute: icon
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ICON)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' icon="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: label
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LABEL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' label="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: radiogroup
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_RADIO_GROUP)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' radiogroup="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE_LABEL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' type="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body meter tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_meter($tag) {
+    $markup = '';
+
+
+    // attribute: form
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' form="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: high
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HIGH)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' high="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: low
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LOW)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' low="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: max
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MAXIMUM_NUMBER)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' max="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: min
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MINIMUM_NUMBER)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' min="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: optimum
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_OPTIMUM)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' optimum="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: value
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE_NUMBER)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' value="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the head meta tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_meta($tag) {
+    $markup = '';
+
+
+    // attribute: charset
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CHARACTER_SET)->get_value_exact();
+    if (!empty($attribute)) {
+      $value = c_base_charset::s_to_string($attribute)->get_value_exact();
+      $markup .= ' charset="' . $value . '"';
+      unset($value);
+    }
+    unset($attribute);
+
+
+    // attribute: content
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' content="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: http-equiv
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HTTP_EQUIV)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' http-equiv="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body object tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_object($tag) {
+    $markup = '';
+
+
+    // attribute: data
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DATA)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' data="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: form
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' form="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' type="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+
+    // attribute: usemap
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_USE_MAP)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' usemap="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body ol tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_ol($tag) {
+    $markup = '';
+
+
+    // attribute: reversed
+    $is_reversed = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_REVERSED)->get_value_exact();
+    if ($is_reversed) {
+      $markup .= ' reversed';
+    }
+
+
+    // attribute: start
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_START)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' start="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE_LIST)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' type="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body optgroup tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_opt_group($tag) {
+    $markup = '';
+
+
+    // attribute: disabled
+    $is_disabled = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DISABLED)->get_value_exact();
+    if ($is_disabled) {
+      $markup .= ' disabled';
+    }
+
+
+    // attribute: label
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LABEL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' label="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body option tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_option($tag) {
+    $markup = '';
+
+
+    // attribute: disabled
+    $is_disabled = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DISABLED)->get_value_exact();
+    if ($is_disabled) {
+      $markup .= ' disabled';
+    }
+
+
+    // attribute: label
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LABEL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' label="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: disabled
+    $is_selected = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SELECTED)->get_value_exact();
+    if ($is_selected) {
+      $markup .= ' selected';
+    }
+
+
+    // attribute: value
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' value="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body output tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_output($tag) {
+    $markup = '';
+
+
+    // attribute: for
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FOR)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' for="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: form
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' form="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body param tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_param($tag) {
+    $markup = '';
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: value
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' value="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body path tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_path($tag) {
+    $markup = '';
+
+
+    // attribute: d
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_D)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' d="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: path_length
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PATH_LENGTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' pathlength="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: transform
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TRANSFORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' transform="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body pattern tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_pattern($tag) {
+    $markup = '';
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: patternunits
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PATTERN_UNITS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' patternunits="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: patterncontentunits
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PATTERN_CONTENT_UNITS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' patterncontentunits="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: patterntransform
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PATTERN_TRANSFORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' patterntransform="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: viewbox
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VIEW_BOX)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' viewbox="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body polygon tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_polygon($tag) {
+    $markup = '';
+
+
+    // attribute: points
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_POINTS)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' points="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: fill-rule
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FILL_RULE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' fill-rule="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body polyline tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_polyline($tag) {
+    $markup = '';
+
+
+    // attribute: points
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_POINTS)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' points="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body progress tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_progress($tag) {
+    $markup = '';
+
+
+    // attribute: max
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MAXIMUM_NUMBER)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' max="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: value
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE_NUMBER)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' value="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body q tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_q($tag) {
+    $markup = '';
+
+
+    // attribute: cite
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CITE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' cite="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body radialgradient tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_radial_gradient($tag) {
+    $markup = '';
+
+
+    // attribute: cx
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CENTER_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' cx="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: cy
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CENTER_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' cy="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: fx
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FOCUS_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' fx="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: fy
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FOCUS_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' fy="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: gradientunits
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_GRADIANT_UNITS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' gradientunits="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: r
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_RADIUS)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' r="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: spreadmethod
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SPREAD_METHOD)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' spreadmethod="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body rect tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_rectangle($tag) {
+    $markup = '';
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rx
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_RADIUS_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' rx="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: ry
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_RADIUS_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' cy="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body stop tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_stop($tag) {
+    $markup = '';
+
+
+    // attribute: offset
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_OFFSET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' offset="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: stop-color
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_STOP_COLOR)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' stop-color="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: stop-opacity
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_STOP_OPACITY)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' stop-opacity="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the head script tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_script($tag) {
+    $markup = '';
+
+
+    // attribute: async
+    $is_asynchronous = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ASYNCHRONOUS)->get_value_exact();
+    if ($is_asynchronous) {
+      $markup .= ' async';
+    }
+
+
+    // attribute: charset
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CHARACTER_SET)->get_value_exact();
+    if (!empty($attribute)) {
+      $value = c_base_charset::s_to_string($attribute)->get_value();
+      if (is_string($value)) {
+        $markup .= ' charset="' . $value . '"';
+      }
+      unset($value);
+    }
+    unset($attribute);
+
+
+    // attribute: defer
+    $is_deferred = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DEFER)->get_value_exact();
+    if ($is_deferred) {
+      $markup .= ' defer';
+    }
+
+
+    // attribute: src
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' src="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' type="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body source tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_source($tag) {
+    $markup = '';
+
+
+    // attribute: src
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' src="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: srcset
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE_SET)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' srcset="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: media
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MEDIA)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' media="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: sizes
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SIZES)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' sizes="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' type="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the head style tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_style($tag) {
+    $markup = '';
+
+
+    // attribute: media
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MEDIA)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' media="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: scoped
+    $is_scoped = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SCOPED)->get_value_exact();
+    if ($is_scoped) {
+      $markup .= ' scoped';
+    }
+
+
+    // attribute: type
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TYPE)->get_value_exact();
+    if (!empty($attribute)) {
+      $mime_types = c_base_mime::s_get_names_by_id($attribute);
+
+      if (is_array($mime_types)) {
+        // use the first mime type available.
+        $mime_type = array_pop($mime_types);
+
+        $markup .= ' type="' . $mime_type . '"';
+        unset($mime_type);
+      }
+      unset($mime_types);
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body svg tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_svg($tag) {
+    $markup = '';
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: viewbox
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_VIEW_BOX)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' viewbox="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xml
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XML)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xml="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xmlns
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XMLNS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xmlns="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xmlns:xlink
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XMLNS_XLINK)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xmlns:xlink="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xml:space
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XML_SPACE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xml:space="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body table tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_table($tag) {
+    $markup = '';
+
+
+    // attribute: sortable
+    $is_sortable = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SORTABLE)->get_value_exact();
+    if ($is_sortable) {
+      $markup .= ' sortable';
+    }
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body th tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_table_header_cell($tag) {
+    $markup = '';
+
+
+    // attribute: abbr
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ABBR)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' abbr="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: colspan
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_COLUMN_SPAN)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' colspan="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: headers
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEADERS)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' headers="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rowspan
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ROW_SPAN)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' rowspan="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: scope
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SCOPE)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' scope="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: sorted
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SORTED)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' sorted="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body textarea tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_text_area($tag) {
+    $markup = '';
+
+
+    // attribute: autofocus
+    $is_autofocus = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_AUTO_FOCUS)->get_value_exact();
+    if ($is_autofocus) {
+      $markup .= ' autofocus';
+    }
+
+
+    // attribute: cols
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_COLUMNS)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' cols="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: dirname
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DIRECTION_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' dirname="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: disabled
+    $is_disabled = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DISABLED)->get_value_exact();
+    if ($is_disabled) {
+      $markup .= ' disabled';
+    }
+
+
+    // attribute: form
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_FORM)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' form="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: maxlength
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MAXIMUM_LENGTH)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' maxlength="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: name
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_NAME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' name="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: placeholder
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PLACE_HOLDER)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' placeholder="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: readonly
+    $is_readonly = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_READONLY)->get_value_exact();
+    if ($is_readonly) {
+      $markup .= ' readonly';
+    }
+
+
+    // attribute: rows
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ROWS)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' rows="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: wrap
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WRAP)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' wrap="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body text tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_text_svg($tag) {
+    $markup = '';
+
+
+    // attribute: dx
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_D_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' dx="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: dy
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_D_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' dy="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: lengthadjust
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LENGTH_ADJUST)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' lengthadjust="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: rotate
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_ROTATE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' rotate="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: textlength
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_TEXT_LENGTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' textlength="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body time tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_time($tag) {
+    $markup = '';
+
+
+    // attribute: datetime
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DATE_TIME)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' datetime="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body track tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_track($tag) {
+    $markup = '';
+
+
+    // attribute: default
+    $is_default = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_DEFAULT)->get_value_exact();
+    if ($is_default) {
+      $markup .= ' default';
+    }
+
+
+    // attribute: kind
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_KIND)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' kind="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: label
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LABEL)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' label="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: src
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' src="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: srclang
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE_LANGUAGE)->get_value_exact();
+
+    if (!empty($attribute)) {
+      $language_class_string = $this->http->get_language_class()->get_value_exact();
+      $language_class = new $language_class_string();
+      $language_array = $language_class->s_get_aliases_by_id($attribute)->get_value_exact();
+      unset($language_class);
+      unset($language_class_string);
+
+      // use the first language alias available.
+      $language = array_pop($language_array);
+      if (!empty($language)) {
+        $markup .= ' srclang="' . $language . '"';
+      }
+      unset($language);
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body use tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_use($tag) {
+    $markup = '';
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: x
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_X)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' x="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: xlink:href
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_XLINK_HREF)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' xlink:href="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: y
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_Y)->get_value();
+    if (is_int($attribute)) {
+      $markup .= ' y="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
+
+  /**
+   * Generates the HTML tag attributes related to the body video tag.
+   *
+   * @param c_base_markup_tag $tag
+   *   The tag to get the attributes of.
+   *
+   * @return string
+   *   The renderred string.
+   */
+  private function p_render_markup_attributes_video($tag) {
+    $markup = '';
+
+
+    // attribute: autoplay
+    $is_autoplay = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_AUTO_PLAY)->get_value_exact();
+    if ($is_autoplay) {
+      $markup .= ' autoplay';
+    }
+
+
+    // attribute: controls
+    $is_controls = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_CONTROLS)->get_value_exact();
+    if ($is_controls) {
+      $markup .= ' controls';
+    }
+
+
+    // attribute: height
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_HEIGHT)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' height="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: loop
+    $is_loop = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_LOOP)->get_value_exact();
+    if ($is_loop) {
+      $markup .= ' loop';
+    }
+
+
+    // attribute: muted
+    $is_muted = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_MUTED)->get_value_exact();
+    if ($is_muted) {
+      $markup .= ' muted';
+    }
+
+
+    // attribute: poster
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_POSTER)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' poster="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: preload
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_PRELOAD)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' preload="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: src
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_SOURCE)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' src="' . $attribute . '"';
+    }
+    unset($attribute);
+
+
+    // attribute: width
+    $attribute = $tag->get_attribute(c_base_markup_attributes::ATTRIBUTE_WIDTH)->get_value_exact();
+    if (!empty($attribute)) {
+      $markup .= ' width="' . $attribute . '"';
+    }
+    unset($attribute);
+
+    return $markup;
+  }
 }
diff --git a/database/sql/reservation/base-cache.sql b/database/sql/reservation/base-cache.sql
new file mode 100644 (file)
index 0000000..6947a80
--- /dev/null
@@ -0,0 +1,14 @@
+/** Standardized SQL Structure - Cache **/
+/** This depends on: base-main.sql **/
+start transaction;
+
+
+
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;
+set datestyle to us;
+
+
+
+commit transaction;
diff --git a/database/sql/reservation/base-content.sql b/database/sql/reservation/base-content.sql
new file mode 100644 (file)
index 0000000..f45d3db
--- /dev/null
@@ -0,0 +1,14 @@
+/** Standardized SQL Structure - Content **/
+/** This depends on: base-structure.sql **/
+start transaction;
+
+
+
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;
+set datestyle to us;
+
+
+
+commit transaction;
diff --git a/database/sql/reservation/base-content_type.sql b/database/sql/reservation/base-content_type.sql
new file mode 100644 (file)
index 0000000..2a4e993
--- /dev/null
@@ -0,0 +1,14 @@
+/** Standardized SQL Structure - Content **/
+/** This depends on: base-users.sql **/
+start transaction;
+
+
+
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;
+set datestyle to us;
+
+
+
+commit transaction;
diff --git a/database/sql/reservation/base-first.sql b/database/sql/reservation/base-first.sql
new file mode 100644 (file)
index 0000000..3679f76
--- /dev/null
@@ -0,0 +1,56 @@
+/** First time or one time execution stuff **/
+/** Things here must be run first and cannot be run a second time due to their nature. **/
+/** For example, tablespaces need only be created 1x and then any database on the system can use them **/
+/** Be sure to replace reservation_ and reservation- with the prefix that is specific to your database. **/
+
+
+
+/** Create the roles (note: public_user and public_users are expected to have already been created. Users and not roles should be created with noinherit) **/
+create role reservation_users inherit nologin;
+create role reservation_users_administer inherit nologin;
+create role reservation_users_manager inherit nologin;
+create role reservation_users_publisher inherit nologin;
+create role reservation_users_insurer inherit nologin;
+create role reservation_users_financer inherit nologin;
+create role reservation_users_reviewer inherit nologin;
+create role reservation_users_drafter inherit nologin;
+
+grant reservation_users to reservation_users_administer with admin option;
+grant reservation_users to reservation_users_manager with admin option;
+grant reservation_users to reservation_users_publisher;
+grant reservation_users to reservation_users_insurer;
+grant reservation_users to reservation_users_financer;
+grant reservation_users to reservation_users_reviewer;
+grant reservation_users to reservation_users_drafter;
+
+grant reservation_users_manager to reservation_users_administer with admin option;
+
+grant reservation_users_publisher to reservation_users_administer with admin option;
+grant reservation_users_publisher to reservation_users_manager with admin option;
+
+grant reservation_users_insurer to reservation_users_administer with admin option;
+grant reservation_users_insurer to reservation_users_manager with admin option;
+
+grant reservation_users_financer to reservation_users_administer with admin option;
+grant reservation_users_financer to reservation_users_manager with admin option;
+
+grant reservation_users_reviewer to reservation_users_administer with admin option;
+grant reservation_users_reviewer to reservation_users_manager with admin option;
+
+grant reservation_users_drafter to reservation_users_administer with admin option;
+grant reservation_users_drafter to reservation_users_manager with admin option;
+
+/** This is the role the database should use to connect to to perform system activity **/
+/** All users auto-created by the ldap helper should be creating users with this role. **/
+create role reservation_user;
+
+grant reservation_users to reservation_user;
+
+
+/** This is the role and role group the database should use for anonymous traffic. I further suggest setting up pg_hba.conf to allow non-ssl connections (increase performance as public information is still public). **/
+/** If the data is meant to be private, then have the public account use the system user with ssl connections **/
+create role public_users;
+create role public_user;
+
+grant public_users to public user;
+
diff --git a/database/sql/reservation/base-logs.sql b/database/sql/reservation/base-logs.sql
new file mode 100644 (file)
index 0000000..8b682a1
--- /dev/null
@@ -0,0 +1,539 @@
+/** Standardized SQL Structure - Logs */
+/** This depends on: base-users.sql **/
+/** Logs will contain a uuid type so that different logs may be associated with each other as to being related. Each request will have a new uuid. Requests maintained by ajax will likely have new uuids on each request. PHP should generate the uuid. */
+start transaction;
+
+
+
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;
+set datestyle to us;
+
+
+
+/*** provide log type id and names ***/
+create table managers.t_log_types (
+  id bigint not null,
+  name_machine varchar(128) not null,
+  name_human varchar(256) not null,
+
+  date_created timestamp default localtimestamp not null,
+
+  constraint cp_log_types_id primary key (id),
+
+  constraint cu_log_types_user unique (name_machine),
+
+  constraint cc_log_types_id check (id > 0)
+);
+
+create sequence managers.s_log_types_id owned by managers.t_log_types.id;
+alter table managers.t_log_types alter column id set default nextval('managers.s_log_types_id'::regclass);
+
+grant select,insert,update on managers.t_log_types to reservation_users_administer;
+grant select on managers.t_log_types to reservation_users_manager;
+grant select,usage on managers.s_log_types_id to reservation_users_administer;
+
+create view public.v_log_types with (security_barrier=true) as
+  select id, name_machine, name_human from managers.t_log_types;
+
+grant select on public.v_log_types to reservation_users;
+grant select on public.v_log_types to public_users;
+
+
+/*** start the sequence count at 1000 to allow for < 1000 to be reserved for special uses ***/
+alter sequence managers.s_log_types_id start 1000;
+alter sequence managers.s_log_types_id restart;
+
+
+/** create well known types that can then be user for indexes (all new types added should be considered for custom indexing). **/
+insert into managers.t_log_types (id, name_machine, name_human) values (1, 'php', 'PHP');
+insert into managers.t_log_types (id, name_machine, name_human) values (2, 'theme', 'Theme');
+insert into managers.t_log_types (id, name_machine, name_human) values (3, 'cache', 'Cache');
+insert into managers.t_log_types (id, name_machine, name_human) values (4, 'javascript', 'Javascript');
+insert into managers.t_log_types (id, name_machine, name_human) values (5, 'ajax', 'AJAX');
+insert into managers.t_log_types (id, name_machine, name_human) values (6, 'sql', 'SQL');
+insert into managers.t_log_types (id, name_machine, name_human) values (7, 'form', 'Form');
+insert into managers.t_log_types (id, name_machine, name_human) values (8, 'form_validate', 'Form Validation');
+insert into managers.t_log_types (id, name_machine, name_human) values (9, 'form_submit', 'Form Submit');
+insert into managers.t_log_types (id, name_machine, name_human) values (10, 'load', 'Load');
+insert into managers.t_log_types (id, name_machine, name_human) values (11, 'save', 'Save');
+insert into managers.t_log_types (id, name_machine, name_human) values (12, 'render', 'Render');
+insert into managers.t_log_types (id, name_machine, name_human) values (13, 'client', 'Client');
+insert into managers.t_log_types (id, name_machine, name_human) values (14, 'update', 'Update');
+insert into managers.t_log_types (id, name_machine, name_human) values (15, 'delete', 'Delete');
+insert into managers.t_log_types (id, name_machine, name_human) values (16, 'redirect', 'Redirect');
+insert into managers.t_log_types (id, name_machine, name_human) values (17, 'login', 'Login');
+insert into managers.t_log_types (id, name_machine, name_human) values (18, 'logout', 'Logout');
+insert into managers.t_log_types (id, name_machine, name_human) values (19, 'session', 'Session');
+insert into managers.t_log_types (id, name_machine, name_human) values (20, 'database', 'Database');
+insert into managers.t_log_types (id, name_machine, name_human) values (21, 'not_found', 'Not Found');
+insert into managers.t_log_types (id, name_machine, name_human) values (22, 'access_denied', 'Access Denied');
+insert into managers.t_log_types (id, name_machine, name_human) values (23, 'removed', 'Removed');
+insert into managers.t_log_types (id, name_machine, name_human) values (24, 'locked', 'Locked');
+insert into managers.t_log_types (id, name_machine, name_human) values (25, 'timeout', 'Timeout');
+insert into managers.t_log_types (id, name_machine, name_human) values (26, 'expire', 'Expiration');
+insert into managers.t_log_types (id, name_machine, name_human) values (27, 'user', 'User');
+insert into managers.t_log_types (id, name_machine, name_human) values (28, 'error', 'Error');
+insert into managers.t_log_types (id, name_machine, name_human) values (29, 'content', 'Content');
+insert into managers.t_log_types (id, name_machine, name_human) values (30, 'workflow', 'Workflow');
+insert into managers.t_log_types (id, name_machine, name_human) values (31, 'draft', 'Draft');
+insert into managers.t_log_types (id, name_machine, name_human) values (32, 'clone', 'Clone');
+insert into managers.t_log_types (id, name_machine, name_human) values (33, 'publish', 'Publish');
+insert into managers.t_log_types (id, name_machine, name_human) values (34, 'revert', 'Revert');
+insert into managers.t_log_types (id, name_machine, name_human) values (35, 'validate', 'Validate');
+insert into managers.t_log_types (id, name_machine, name_human) values (36, 'approve', 'Approve');
+insert into managers.t_log_types (id, name_machine, name_human) values (37, 'password', 'Password');
+insert into managers.t_log_types (id, name_machine, name_human) values (38, 'revision', 'Revision');
+insert into managers.t_log_types (id, name_machine, name_human) values (39, 'search', 'Search');
+insert into managers.t_log_types (id, name_machine, name_human) values (40, 'access', 'Access');
+insert into managers.t_log_types (id, name_machine, name_human) values (41, 'unknown', 'Unknown');
+
+
+
+/*** provide HTTP status codes ***/
+create table managers.t_log_http_status_codes (
+  id smallint not null,
+  name_machine varchar(128) not null,
+  name_human varchar(256) not null,
+
+  date_created timestamp default localtimestamp not null,
+
+  constraint cp_log_http_status_codes_id primary key (id),
+
+  constraint cu_log_http_status_codes_user unique (name_machine),
+
+  constraint cc_log_http_status_codes_id check (id >= 0 and id < 600)
+);
+
+create sequence managers.s_log_http_status_codes_id owned by managers.t_log_http_status_codes.id;
+alter table managers.t_log_http_status_codes alter column id set default nextval('managers.s_log_http_status_codes_id'::regclass);
+
+grant select,insert,update on managers.t_log_http_status_codes to reservation_users_administer;
+grant select on managers.t_log_http_status_codes to reservation_users_manager;
+grant select,usage on managers.s_log_http_status_codes_id to reservation_users_administer;
+
+create view public.v_log_http_status_codes with (security_barrier=true) as
+  select id, name_machine, name_human from managers.t_log_http_status_codes;
+
+grant select on public.v_log_http_status_codes to reservation_users;
+grant select on public.v_log_http_status_codes to public_users;
+
+
+/** create well known types that can then be user for indexes (all new types added should be considered for custom indexing). **/
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (0, '0', 'Undefined');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (1, '1', 'Invalid');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (2, '2', 'Unknown');
+
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (100, '100', 'Continue');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (101, '101', 'Switching Protocols');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (102, '102', 'Processing');
+
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (200, '200', 'OK');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (201, '201', 'Created');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (202, '202', 'Accepted');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (203, '203', 'Non-Authoritative Information');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (204, '204', 'No Content');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (205, '205', 'Reset Content');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (206, '206', 'Partial Content');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (207, '207', 'Multi-Status');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (208, '208', 'Already Reported');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (226, '226', 'IM used');
+
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (300, '300', 'Multiple Choices');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (301, '301', 'Moved Permanently');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (302, '302', 'Found');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (303, '303', 'See Other');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (304, '304', 'Not Modified');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (305, '305', 'Use Proxy');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (306, '306', 'Switch Proxy');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (307, '307', 'Temporary Redirect');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (308, '308', 'Permanent Redirect');
+
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (400, '400', 'Bad Request');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (401, '401', 'Unauthorized');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (402, '402', 'Payment Required');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (403, '403', 'Forbidden');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (404, '404', 'Not Found');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (405, '405', 'Method Not Allowed');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (406, '406', 'Not Acceptable');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (407, '407', 'Proxy Authentication Required');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (408, '408', 'Request Timeout');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (409, '409', 'Conflict');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (410, '410', 'Gone');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (411, '411', 'Length Required');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (412, '412', 'Precondition Failed');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (413, '413', 'Payload Too Large');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (414, '414', 'Request-URI Too Long');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (415, '415', 'Unsupported Media Type');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (416, '416', 'Requested Range Not Satisfiable');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (417, '417', 'Expectation Failed');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (422, '422', 'Misdirected Request');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (423, '423', 'Locked');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (424, '424', 'Failed Dependency');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (426, '426', 'Upgrade Required');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (428, '428', 'Precondition Required');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (429, '429', 'Too Many Requests');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (431, '431', 'Request Header Fields Too Large');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (451, '451', 'Unavailable For Legal Reasons');
+
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (500, '500', 'Internal Server Error');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (501, '501', 'Not Implemented');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (502, '502', 'Bad Gateway');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (503, '503', 'Service Unavailable');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (504, '504', 'Gateway Timeout');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (505, '505', 'HTTP Version Not Supported');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (506, '506', 'Variant Also Negotiates');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (507, '507', 'Insufficient Storage');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (508, '508', 'Loop Detected');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (510, '510', 'Not Extended');
+insert into managers.t_log_http_status_codes (id, name_machine, name_human) values (511, '511', 'Network Authentication Required');
+
+
+
+/*** provide log severity level id and names ***/
+create table managers.t_log_severity_levels (
+  id bigint not null,
+  name_machine varchar(128) not null,
+  name_human varchar(256) not null,
+
+  date_created timestamp default localtimestamp not null,
+
+  constraint cp_log_severity_levels_id primary key (id),
+
+  constraint cu_log_severity_levels_user unique (name_machine),
+
+  constraint cc_log_severity_levels_id check (id > 0)
+);
+
+create sequence managers.s_log_severity_levels_id owned by managers.t_log_severity_levels.id;
+alter table managers.t_log_severity_levels alter column id set default nextval('managers.s_log_severity_levels_id'::regclass);
+
+grant select,insert,update on managers.t_log_severity_levels to reservation_users_administer;
+grant select on managers.t_log_severity_levels to reservation_users_manager;
+grant select,usage on managers.s_log_severity_levels_id to reservation_users_administer;
+
+create view public.v_log_severity_levels with (security_barrier=true) as
+  select id, name_machine, name_human from managers.t_log_severity_levels;
+
+grant select on public.v_log_severity_levels to reservation_users;
+grant select on public.v_log_severity_levels to public_users;
+
+
+/*** start the sequence count at 1000 to allow for < 1000 to be reserved for special uses ***/
+alter sequence managers.s_log_severity_levels_id start 1000;
+alter sequence managers.s_log_severity_levels_id restart;
+
+
+/** create well known types that can then be user for indexes (all new types added should be considered for custom indexing). **/
+insert into managers.t_log_severity_levels (id, name_machine, name_human) values (1, 'information', 'Information');
+insert into managers.t_log_severity_levels (id, name_machine, name_human) values (2, 'notice', 'Notice');
+insert into managers.t_log_severity_levels (id, name_machine, name_human) values (3, 'debug', 'Debug');
+insert into managers.t_log_severity_levels (id, name_machine, name_human) values (4, 'warning', 'Warning');
+insert into managers.t_log_severity_levels (id, name_machine, name_human) values (5, 'error', 'Error');
+insert into managers.t_log_severity_levels (id, name_machine, name_human) values (6, 'alert', 'Alert');
+insert into managers.t_log_severity_levels (id, name_machine, name_human) values (7, 'critical', 'Critical');
+insert into managers.t_log_severity_levels (id, name_machine, name_human) values (8, 'emergency', 'Emergency');
+
+
+
+/*** provide user activity logging ***/
+create table managers.t_log_users (
+  id bigint not null,
+  id_user bigint default 1 not null,
+  id_uuid uuid not null,
+  name_machine varchar(128) not null,
+  log_title varchar(512) not null,
+  log_type bigint not null,
+  log_severity bigint not null,
+  log_details json,
+  log_date timestamp default localtimestamp not null,
+  request_client public.ct_client not null,
+  response_code smallint not null default 0,
+
+  constraint cp_log_users_id primary key (id),
+
+  constraint cc_log_users_id check (id > 0),
+  constraint cc_log_users_log_severity check (log_severity > 0),
+
+  constraint cf_log_users_id_user foreign key (id_user, name_machine) references administers.t_users (id, name_machine) on delete set null on update cascade,
+  constraint cf_log_users_log_type foreign key (log_type) references managers.t_log_types (id) on delete restrict on update cascade,
+  constraint cf_log_users_log_severity foreign key (log_severity) references managers.t_log_severity_levels (id) on delete restrict on update cascade,
+  constraint cf_log_users_response_code foreign key (response_code) references managers.t_log_http_status_codes (id) on delete restrict on update cascade
+);
+
+create sequence managers.s_log_users_id owned by managers.t_log_users.id;
+alter table managers.t_log_users alter column id set default nextval('managers.s_log_users_id'::regclass);
+
+grant select on managers.t_log_users to reservation_users_administer;
+grant select on managers.t_log_users to reservation_users_manager;
+grant select,usage on managers.s_log_users_id to reservation_users_administer;
+grant usage on managers.s_log_users_id to reservation_users;
+grant usage on managers.s_log_users_id to public_users;
+
+create index ci_log_users_type_php on managers.t_log_users (id)
+  where log_type = 1;
+
+create index ci_log_users_type_theme on managers.t_log_users (id)
+  where log_type = 2;
+
+create index ci_log_users_type_cache on managers.t_log_users (id)
+  where log_type = 3;
+
+create index ci_log_users_type_javascript on managers.t_log_users (id)
+  where log_type = 4;
+
+create index ci_log_users_type_ajax on managers.t_log_users (id)
+  where log_type = 5;
+
+create index ci_log_users_type_sql on managers.t_log_users (id)
+  where log_type = 6;
+
+create index ci_log_users_type_redirect on managers.t_log_users (id)
+  where log_type = 16;
+
+create index ci_log_users_type_login on managers.t_log_users (id)
+  where log_type = 17;
+
+create index ci_log_users_type_logout on managers.t_log_users (id)
+  where log_type = 18;
+
+create index ci_log_users_type_user on managers.t_log_users (id)
+  where log_type = 27;
+
+create index ci_log_users_type_error on managers.t_log_users (id)
+  where log_type = 28;
+
+create index ci_log_users_type_content on managers.t_log_users (id)
+  where log_type = 29;
+
+create index ci_log_users_type_workflow on managers.t_log_users (id)
+  where log_type = 30;
+
+create index ci_log_users_type_search on managers.t_log_users (id)
+  where log_type = 39;
+
+create index ci_log_users_response_code_200 on managers.t_log_users (id)
+  where response_code = 200;
+
+create index ci_log_users_response_code_403 on managers.t_log_users (id)
+  where response_code = 403;
+
+create index ci_log_users_response_code_404 on managers.t_log_users (id)
+  where response_code = 404;
+
+create index ci_log_users_response_code_410 on managers.t_log_users (id)
+  where response_code = 410;
+
+create index ci_log_users_response_code_500 on managers.t_log_users (id)
+  where response_code = 500;
+
+create index ci_log_users_response_code_503 on managers.t_log_users (id)
+  where response_code = 503;
+
+create index ci_log_users_response_code_normal on managers.t_log_users (id)
+  where response_code in (200, 201, 202, 304);
+
+create index ci_log_users_response_code_redirects on managers.t_log_users (id)
+  where response_code in (301, 302, 303, 307, 308);
+
+create index ci_log_users_response_code_notable on managers.t_log_users (id)
+  where response_code in (400, 403, 404, 410, 500, 503);
+
+/** when using current_user reserved function/word the index gets ignored. To prevent this, create a manual/custom index and alter the behavior of the views to be more explicit. **/
+create unique index ci_log_users_current_user on managers.t_log_users (name_machine) with (fillfactor = 100);
+
+
+/** only allow select and insert for users when user id is current user **/
+create view users.v_log_users_self with (security_barrier=true) as
+  select id, id_user, id_uuid, log_title, log_type, log_severity, log_details, log_date, request_client from managers.t_log_users
+    where (name_machine)::text = (current_user)::text;
+
+grant select on users.v_log_users_self to reservation_users;
+
+create view users.v_log_users_self_insert with (security_barrier=true) as
+  select id_user, id_uuid, name_machine, log_title, log_type, log_severity, log_details, request_client from managers.t_log_users
+    where (name_machine)::text = (current_user)::text
+    with check option;
+
+grant insert on users.v_log_users_self_insert to reservation_users;
+
+
+/** only allow insert for the public user **/
+create view public.v_log_users_self_insert with (security_barrier=true) as
+  select id_user, id_uuid, name_machine, log_title, log_type, log_severity, log_details, request_client from managers.t_log_users
+    where id_user = 1 and name_machine = 'unknown'
+    with check option;
+
+grant insert on public.v_log_users_self_insert to public_users;
+
+
+/** only allow insert for the system user **/
+create view system.v_log_users_self_insert with (security_barrier=true) as
+  select id_user, id_uuid, name_machine, log_title, log_type, log_severity, log_details, request_client from managers.t_log_users
+    where id_user = 2 and name_machine = 'system'
+    with check option;
+
+grant insert on system.v_log_users_self_insert to reservation_user;
+
+
+
+/*** provide access activity logging ***/
+create table managers.t_log_activity (
+  id bigint not null,
+  id_user bigint default 1 not null,
+  id_uuid uuid not null,
+  name_machine varchar(128) not null,
+  request_path varchar(512) not null,
+  request_arguments varchar(512) not null,
+  request_date timestamp default localtimestamp not null,
+  request_client public.ct_client not null,
+  request_headers json,
+  response_headers json,
+  response_code smallint not null default 0,
+
+  constraint cp_log_activity_id primary key (id),
+
+  constraint cc_log_activity_id check (id > 0),
+
+  constraint cf_log_activity_id_user foreign key (id_user, name_machine) references administers.t_users (id, name_machine) on delete set null on update cascade,
+  constraint cf_log_activity_response_code foreign key (response_code) references managers.t_log_http_status_codes (id) on delete restrict on update cascade
+);
+
+create sequence managers.s_log_activity_id owned by managers.t_log_activity.id;
+alter table managers.t_log_activity alter column id set default nextval('managers.s_log_activity_id'::regclass);
+
+grant select on managers.t_log_activity to reservation_users_administer;
+grant select on managers.t_log_activity to reservation_users_manager;
+grant select,usage on managers.s_log_activity_id to reservation_users_administer;
+grant usage on managers.s_log_activity_id to reservation_users;
+grant usage on managers.s_log_activity_id to public_users;
+
+create index ci_log_activity_response_code_4xx on managers.t_log_activity (id)
+  where response_code >= 400 and response_code < 500;
+
+create index ci_log_activity_response_code_403 on managers.t_log_activity (id)
+  where response_code = 403;
+
+create index ci_log_activity_response_code_404 on managers.t_log_activity (id)
+  where response_code = 404;
+
+create index ci_log_activity_response_code_410 on managers.t_log_activity (id)
+  where response_code = 410;
+
+create index ci_log_activity_response_code_5xx on managers.t_log_activity (id)
+  where response_code >= 500 and response_code < 600;
+
+create index ci_log_activity_response_code_500 on managers.t_log_activity (id)
+  where response_code = 500;
+
+create index ci_log_activity_response_code_503 on managers.t_log_activity (id)
+  where response_code = 503;
+
+create index ci_log_activity_response_code_notable on managers.t_log_activity (id)
+  where response_code in (403, 404, 410, 500, 503);
+
+/** when using current_user reserved function/word the index gets ignored. To prevent this, create a manual/custom index and alter the behavior of the views to be more explicit. **/
+create unique index ci_log_activity_current_user on managers.t_log_activity (name_machine) with (fillfactor = 100);
+
+
+/** only allow select and insert for users when user id is current user **/
+create view users.v_log_activity_self with (security_barrier=true) as
+  select id, id_user, id_uuid, request_path, request_arguments, request_date, request_client, request_headers, response_headers, response_code from managers.t_log_activity
+    where (name_machine)::text = (current_user)::text;
+
+grant select on users.v_log_activity_self to reservation_users;
+
+create view users.v_log_activity_self_insert with (security_barrier=true) as
+  select id_user, id_uuid, name_machine, request_path, request_arguments, request_client, request_headers, response_headers, response_code from managers.t_log_activity
+    where (name_machine)::text = (current_user)::text
+    with check option;
+
+grant insert on users.v_log_activity_self_insert to reservation_users;
+
+
+/** only allow insert for the public user **/
+create view public.v_log_activity_self_insert with (security_barrier=true) as
+  select id_user, id_uuid, name_machine, request_path, request_arguments, request_client, request_headers, response_headers, response_code from managers.t_log_activity
+    where id_user = 1 and name_machine = 'unknown'
+    with check option;
+
+grant insert on public.v_log_activity_self_insert to public_users;
+
+
+/** only allow insert for the system user **/
+create view system.v_log_activity_self_insert with (security_barrier=true) as
+  select id_user, id_uuid, name_machine, request_path, request_arguments, request_client, request_headers, response_headers, response_code from managers.t_log_activity
+    where id_user = 2 and name_machine = 'system'
+    with check option;
+
+grant insert on system.v_log_activity_self_insert to reservation_user;
+
+
+
+/** Provide a log of problems, which are defined by the software. **/
+create table managers.t_log_problems (
+  id bigint not null,
+  name_machine varchar(128) not null,
+  name_human varchar(256) not null,
+
+  date_created timestamp default localtimestamp not null,
+
+  constraint cp_log_problems_id primary key (id),
+
+  constraint cc_log_problems_id check (id > 0),
+
+  constraint cu_log_problems_name_machine unique (name_machine)
+);
+
+grant select on managers.t_log_activity to reservation_users_administer;
+grant select on managers.t_log_activity to reservation_users_manager;
+
+
+
+/** Provide a log of problems, associated with a given user. **/
+create table managers.t_log_problems_users (
+  id_problem bigint not null,
+  id_user bigint not null,
+
+  name_machine varchar(128) not null,
+
+  date_created timestamp default localtimestamp not null,
+
+  information_additional json,
+
+  constraint cp_log_problems_users_id primary key (id_problem, id_user),
+
+  constraint cu_log_problems_users_name_machine unique (name_machine),
+
+  constraint cf_log_problems_users_id_problem foreign key (id_problem) references managers.t_log_problems (id) on delete restrict on update cascade,
+  constraint cf_log_problems_users_id_user foreign key (id_user, name_machine) references administers.t_users (id, name_machine) on delete restrict on update cascade
+);
+
+grant select,delete on managers.t_log_problems_users to reservation_users_administer;
+grant select,delete on managers.t_log_problems_users to reservation_users_manager;
+
+
+/** only allow select, insert, and delete for users when user id is current user **/
+create view users.v_log_problems_users_self with (security_barrier=true) as
+  select id_problem, id_user, date_created, information_additional from managers.t_log_problems_users
+    where (name_machine)::text = (current_user)::text;
+
+grant select on users.v_log_activity_self to reservation_users;
+
+create view users.v_log_problems_users_self_insert with (security_barrier=true) as
+  select id_problem, id_user, name_machine, information_additional from managers.t_log_problems_users
+    where (name_machine)::text = (current_user)::text
+    with check option;
+
+grant insert on users.v_log_problems_users_self_insert to reservation_users;
+
+create view users.v_log_problems_users_self_delete with (security_barrier=true) as
+  select id_problem, id_user from managers.t_log_problems_users
+    where (name_machine)::text = (current_user)::text
+    with check option;
+
+grant delete on users.v_log_problems_users_self_delete to reservation_users;
+
+
+commit transaction;
diff --git a/database/sql/reservation/base-main.sql b/database/sql/reservation/base-main.sql
new file mode 100644 (file)
index 0000000..906e8af
--- /dev/null
@@ -0,0 +1,94 @@
+/** Standardized SQL Structure - Main */
+/** This depends on: base-first.sql **/
+/** users will be called 'reservation_user_X' where X is the name, so that regex can be used on this script at a later time and mass rename these as necessary.
+  @todo: prepare for Row Level Security Policies as defined here: https://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.5 and here: http://www.depesz.com/2014/10/02/waiting-for-9-5-row-level-security-policies-rls/
+  All roles associated with a user can be determined with: "select pr.rolname from pg_auth_members pam inner join pg_roles pr on (pam.roleid = pr.oid) inner join pg_roles pr_u on (pam.member = pr_u.oid) where pr_u.rolname = user;"
+  For performance reasons, name_machine is not directly assigned as a foreign key, only the id_user is. This can result in out of sync issues if the name_machine is ever changed. To avoid this, prediodically run a cron job to analyze all the entries and fix conflicts. (name_human may also fall into this situation in certain circumstances.)
+  @todo: investigate and compare use of btree and gist for indexes used. This will require populating the data and comparing 'explain analyze' performance results. btree is the default and gist can be added by inserting 'using gist' for the index after the 'on name' part.
+  Example of date selection format: select to_char('now'::timestamp, 'YYYY/MM/DD HH12:MI:SS am '); (see: http://www.postgresql.org/docs/9.4/static/functions-formatting.html)
+  @todo: use http://www.postgresql.org/docs/9.4/static/functions-formatting.html and daterange for calendar dates and times (GiST is good for indexing ranges) (consider 'overlaps') (see: http://www.postgresql.org/docs/9.4/interactive/rangetypes.html#RANGETYPES-GIST).
+  @todo: use BRIN (pg 9.5) indexing for indexes used to optimize specific table views or for tables expected to get very large (content, logs, files, etc..) (see: https://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.5)
+*/
+start transaction;
+
+
+
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;
+set datestyle to us;
+
+
+
+/** Schemas **/
+create schema system authorization reservation_user;
+create schema administers authorization reservation_users_administer;
+create schema managers authorization reservation_users_manager;
+create schema publishers authorization reservation_users_publisher;
+create schema insurer authorization reservation_users_insurer;
+create schema financer authorization reservation_users_financer;
+create schema reviewers authorization reservation_users_reviewer;
+create schema drafters authorization reservation_users_drafter;
+create schema users authorization reservation_users;
+
+revoke create on schema system from reservation_user;
+revoke create on schema administers from reservation_users_administer;
+revoke create on schema managers from reservation_users_manager;
+revoke create on schema publishers from reservation_users_publisher;
+revoke create on schema insurer from reservation_users_insurer;
+revoke create on schema financer from reservation_users_financer;
+revoke create on schema reviewers from reservation_users_reviewer;
+revoke create on schema drafters from reservation_users_drafter;
+revoke create on schema users from reservation_users;
+
+grant usage on schema system to reservation_user;
+grant usage on schema administers to reservation_users_administer;
+grant usage on schema managers to reservation_users_manager;
+grant usage on schema publishers to reservation_users_publisher;
+grant usage on schema insurer to reservation_users_insurer;
+grant usage on schema financer to reservation_users_financer;
+grant usage on schema reviewers to reservation_users_reviewer;
+grant usage on schema drafters to reservation_users_drafter;
+grant usage on schema users to reservation_users;
+
+grant create,usage on schema system to postgres;
+grant create,usage on schema administers to postgres;
+grant create,usage on schema managers to postgres;
+grant create,usage on schema publishers to postgres;
+grant create,usage on schema insurer to postgres;
+grant create,usage on schema financer to postgres;
+grant create,usage on schema reviewers to postgres;
+grant create,usage on schema drafters to postgres;
+grant create,usage on schema users to postgres;
+
+
+/** Composite Types **/
+create type public.ct_name_person as (
+  prefix varchar(32),
+  first varchar(64),
+  middle varchar(64),
+  last varchar(64),
+  suffix varchar(32),
+  complete varchar(256)
+);
+
+create type public.ct_client as (
+  ip inet,
+  port int,
+  agent varchar(256)
+);
+
+create type public.ct_email as (
+  name varchar(128),
+  domain varchar(128),
+  private boolean
+);
+
+create type public.ct_text as (
+  content text,
+  context bigint
+);
+
+
+
+commit transaction;
diff --git a/database/sql/reservation/base-paths.sql b/database/sql/reservation/base-paths.sql
new file mode 100644 (file)
index 0000000..f45d3db
--- /dev/null
@@ -0,0 +1,14 @@
+/** Standardized SQL Structure - Content **/
+/** This depends on: base-structure.sql **/
+start transaction;
+
+
+
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;
+set datestyle to us;
+
+
+
+commit transaction;
diff --git a/database/sql/reservation/base-statistics.sql b/database/sql/reservation/base-statistics.sql
new file mode 100644 (file)
index 0000000..cffbea9
--- /dev/null
@@ -0,0 +1,181 @@
+/** Standardized SQL Structure - Statistics **/
+/** This depends on: base-logs.sql **/
+start transaction;
+
+
+
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;
+set datestyle to us;
+
+
+
+/** Provide status code statistics **/
+create table managers.t_statistics_http_status_codes (
+  code smallint not null,
+  count bigint not null default 0,
+
+  date_created timestamp default localtimestamp not null,
+
+  constraint cp_statistics_http_status_codes_code primary key (code),
+
+  constraint cc_statistics_http_status_codes_count check (count >= 0),
+
+  constraint cf_statistics_http_status_codes_code foreign key (code) references managers.t_log_http_status_codes (id) on delete restrict on update cascade
+);
+
+grant select,insert,update on managers.t_statistics_http_status_codes to reservation_users_administer;
+grant select,insert,update on managers.t_statistics_http_status_codes to reservation_users_manager;
+
+
+/** create an auto-update trigger. set the role to reservation_users_manager so that the function runs as that role when using "SECURITY DEFINER". The reservation_users_manager must also have the appropriate create privileges. **/
+grant create on schema managers to reservation_users_manager;
+set role reservation_users_manager;
+
+create function managers.f_statistics_http_status_codes_insert() returns trigger security definer as $$
+  begin
+    if (tg_op = 'INSERT') then
+      update managers.t_statistics_http_status_codes set count = (select count + 1 as count from managers.t_statistics_http_status_codes where code = new.response_code) where code = new.response_code;
+      if not found then
+        insert into managers.t_statistics_http_status_codes (code, count) values (new.response_code, 1);
+        if not found then return null; end if;
+      end if;
+
+      return new;
+    end if;
+
+    return null;
+  end;
+$$ language plpgsql;
+reset role;
+revoke create on schema managers from reservation_users_manager;
+
+create trigger tr_statistics_http_status_codes_insert
+  after insert on managers.t_log_activity
+    for each row execute procedure managers.f_statistics_http_status_codes_insert();
+
+
+/** create all of the known codes, initializing them to 0. **/
+insert into managers.t_statistics_http_status_codes (code) values (0);
+insert into managers.t_statistics_http_status_codes (code) values (1);
+insert into managers.t_statistics_http_status_codes (code) values (2);
+
+insert into managers.t_statistics_http_status_codes (code) values (100);
+insert into managers.t_statistics_http_status_codes (code) values (101);
+insert into managers.t_statistics_http_status_codes (code) values (102);
+
+insert into managers.t_statistics_http_status_codes (code) values (200);
+insert into managers.t_statistics_http_status_codes (code) values (201);
+insert into managers.t_statistics_http_status_codes (code) values (202);
+insert into managers.t_statistics_http_status_codes (code) values (203);
+insert into managers.t_statistics_http_status_codes (code) values (204);
+insert into managers.t_statistics_http_status_codes (code) values (205);
+insert into managers.t_statistics_http_status_codes (code) values (206);
+insert into managers.t_statistics_http_status_codes (code) values (207);
+insert into managers.t_statistics_http_status_codes (code) values (208);
+insert into managers.t_statistics_http_status_codes (code) values (226);
+
+insert into managers.t_statistics_http_status_codes (code) values (300);
+insert into managers.t_statistics_http_status_codes (code) values (301);
+insert into managers.t_statistics_http_status_codes (code) values (302);
+insert into managers.t_statistics_http_status_codes (code) values (303);
+insert into managers.t_statistics_http_status_codes (code) values (304);
+insert into managers.t_statistics_http_status_codes (code) values (305);
+insert into managers.t_statistics_http_status_codes (code) values (306);
+insert into managers.t_statistics_http_status_codes (code) values (307);
+insert into managers.t_statistics_http_status_codes (code) values (308);
+
+insert into managers.t_statistics_http_status_codes (code) values (400);
+insert into managers.t_statistics_http_status_codes (code) values (401);
+insert into managers.t_statistics_http_status_codes (code) values (402);
+insert into managers.t_statistics_http_status_codes (code) values (403);
+insert into managers.t_statistics_http_status_codes (code) values (404);
+insert into managers.t_statistics_http_status_codes (code) values (405);
+insert into managers.t_statistics_http_status_codes (code) values (406);
+insert into managers.t_statistics_http_status_codes (code) values (407);
+insert into managers.t_statistics_http_status_codes (code) values (408);
+insert into managers.t_statistics_http_status_codes (code) values (409);
+insert into managers.t_statistics_http_status_codes (code) values (410);
+insert into managers.t_statistics_http_status_codes (code) values (411);
+insert into managers.t_statistics_http_status_codes (code) values (412);
+insert into managers.t_statistics_http_status_codes (code) values (413);
+insert into managers.t_statistics_http_status_codes (code) values (414);
+insert into managers.t_statistics_http_status_codes (code) values (415);
+insert into managers.t_statistics_http_status_codes (code) values (416);
+insert into managers.t_statistics_http_status_codes (code) values (417);
+insert into managers.t_statistics_http_status_codes (code) values (422);
+insert into managers.t_statistics_http_status_codes (code) values (423);
+insert into managers.t_statistics_http_status_codes (code) values (424);
+insert into managers.t_statistics_http_status_codes (code) values (426);
+insert into managers.t_statistics_http_status_codes (code) values (428);
+insert into managers.t_statistics_http_status_codes (code) values (429);
+insert into managers.t_statistics_http_status_codes (code) values (431);
+insert into managers.t_statistics_http_status_codes (code) values (451);
+
+insert into managers.t_statistics_http_status_codes (code) values (500);
+insert into managers.t_statistics_http_status_codes (code) values (501);
+insert into managers.t_statistics_http_status_codes (code) values (502);
+insert into managers.t_statistics_http_status_codes (code) values (503);
+insert into managers.t_statistics_http_status_codes (code) values (504);
+insert into managers.t_statistics_http_status_codes (code) values (505);
+insert into managers.t_statistics_http_status_codes (code) values (506);
+insert into managers.t_statistics_http_status_codes (code) values (507);
+insert into managers.t_statistics_http_status_codes (code) values (508);
+insert into managers.t_statistics_http_status_codes (code) values (510);
+insert into managers.t_statistics_http_status_codes (code) values (511);
+
+
+
+/** Provide request path statistics **/
+create table managers.t_statistics_request_path (
+  path varchar(512) not null,
+  count bigint not null default 0,
+
+  date_created timestamp default localtimestamp not null,
+
+  constraint cp_statistics_request_path_code primary key (path),
+
+  constraint cc_statistics_request_path_count check (count >= 0)
+);
+
+grant select on managers.t_statistics_request_path to reservation_users_administer;
+grant select on managers.t_statistics_request_path to reservation_users_manager;
+
+/** permissions prevent this from working as desired, so for now open up these stats to the following users (via a view) **/
+create view users.v_statistics_request_path with (security_barrier=true) as
+  select path, count from managers.t_statistics_request_path
+    with check option;
+
+grant select,insert,update on users.v_statistics_request_path to reservation_users;
+
+create view public.v_statistics_request_path with (security_barrier=true) as
+  select path, count from managers.t_statistics_request_path
+    with check option;
+
+grant select,insert,update on public.v_statistics_request_path to public_users;
+
+/** create an auto-update trigger **/
+create function managers.f_statistics_request_path_insert() returns trigger as $$
+  begin
+    if (tg_op = 'INSERT') then
+      update v_statistics_request_path set count = (select count + 1 as count from v_statistics_request_path where path = new.request_path) where path = new.request_path;
+      if not found then
+        insert into v_statistics_request_path (path, count) values (new.request_path, 1);
+        if not found then return null; end if;
+      end if;
+
+      return new;
+    end if;
+
+    return null;
+  end;
+$$ language plpgsql;
+
+create trigger tr_statistics_request_path_insert
+  after insert on managers.t_log_activity
+    for each row execute procedure managers.f_statistics_request_path_insert();
+
+
+
+commit transaction;
diff --git a/database/sql/reservation/base-structure.sql b/database/sql/reservation/base-structure.sql
new file mode 100644 (file)
index 0000000..7bd32fd
--- /dev/null
@@ -0,0 +1,14 @@
+/** Standardized SQL Structure - Structure **/
+/** This depends on: base-content_type.sql **/
+start transaction;
+
+
+
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;
+set datestyle to us;
+
+
+
+commit transaction;
diff --git a/database/sql/reservation/base-users.sql b/database/sql/reservation/base-users.sql
new file mode 100644 (file)
index 0000000..3ecade6
--- /dev/null
@@ -0,0 +1,222 @@
+/** Standardized SQL Structure - Users */
+/** This depends on: base-main.sql **/
+start transaction;
+
+
+
+/** Custom database specific settings (do this on every connection made) **/
+set bytea_output to hex;
+set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;
+set datestyle to us;
+
+
+
+
+/** Users **/
+create table administers.t_users (
+  id bigint not null,
+  id_sort smallint not null default 0,
+  id_external bigint,
+  name_machine varchar(128) not null,
+  name_human public.ct_name_person default (null, null, null, null, null, null) not null,
+  address_email public.ct_email default (null, null, true) not null,
+  is_private boolean default true not null,
+  is_locked boolean default false not null,
+  is_deleted boolean default false not null,
+  date_created timestamp default localtimestamp not null,
+  date_changed timestamp default localtimestamp not null,
+  date_synced timestamp default localtimestamp not null,
+  date_deleted timestamp,
+  settings json,
+
+  constraint cp_users_id primary key (id),
+
+  constraint cc_users_id check (id > 0),
+  constraint cc_users_id_external check (id_external > 0),
+
+  constraint cu_users_id_external unique (id_external),
+  constraint cu_users_name_machine unique (name_machine),
+  constraint cu_users_user unique (id, name_machine),
+  constraint cu_external_id unique (id_external)
+);
+
+create sequence administers.s_users_id owned by administers.t_users.id;
+alter table administers.t_users alter column id set default nextval('administers.s_users_id'::regclass);
+
+grant select,insert,update on administers.t_users to reservation_users_administer;
+grant select,usage on administers.s_users_id to reservation_users_administer;
+grant usage on administers.s_users_id to reservation_users;
+
+create index ci_users_deleted_not on administers.t_users (id)
+  where is_deleted is not true;
+
+create index ci_users_private_not on administers.t_users (id)
+  where is_deleted is not true and is_private is not true;
+
+create index ci_users_private_email_not on administers.t_users (id)
+  where is_deleted is not true and is_private is not true and (address_email).private is not true;
+
+/** when using current_user reserved function/word the index gets ignored. To prevent this, create a manual/custom index and alter the behavior of the views to be more explicit. **/
+create unique index ci_users_current_user on administers.t_users (name_machine) with (fillfactor = 100);
+
+create index ci_users_id_sort_k on administers.t_users (id_sort) with (fillfactor = 100) where id_sort = 107;
+
+
+/*** start the sequence count at 1000 to allow for < 1000 to be reserved for special uses ***/
+alter sequence administers.s_users_id start 1000;
+alter sequence administers.s_users_id restart;
+
+
+/*** create hard-coded user ids ***/
+insert into administers.t_users (id, name_machine, name_human, is_private) values (1, 'unknown', (null, 'Unknown', null, null, null, 'Unknown'), false);
+insert into administers.t_users (id, name_machine, name_human, is_private) values (2, 'system', (null, 'System', null, null, null, 'System'), false);
+insert into administers.t_users (id, name_machine, name_human, is_private) values (3, 'console', (null, 'Console', null, null, null, 'Console'), false);
+insert into administers.t_users (id, name_machine, name_human, is_private) values (4, 'cron', (null, 'Cron', null, null, null, 'Cron'), false);
+
+
+/*** provide current user access to their own information ***/
+create view users.v_users_self with (security_barrier=true) as
+  select id, id_sort, id_external, name_machine, name_human, address_email, is_private, is_locked, date_created, date_changed, date_synced, settings from administers.t_users
+    where (name_machine)::text = (current_user)::text and is_deleted is not true;
+
+grant select on users.v_users_self to reservation_users;
+
+create view users.v_users_self_insert with (security_barrier=true) as
+  select id, id_sort, id_external, name_machine, name_human, address_email, is_private, settings from administers.t_users
+    where (name_machine)::text = (current_user)::text
+    with check option;
+
+grant insert on users.v_users_self_insert to reservation_users;
+
+create view users.v_users_self_update with (security_barrier=true) as
+  select address_email, is_private, date_changed, date_synced, settings from administers.t_users
+    where (name_machine)::text = (current_user)::text and is_deleted is not true and (date_changed is null or date_changed = localtimestamp)
+    with check option;
+
+grant update on users.v_users_self_update to reservation_users;
+
+
+/**** anonymous user has uid = 1 ****/
+create view public.v_users_self with (security_barrier=true) as
+  select id, id_sort, id_external, name_machine, name_human, address_email, is_private, is_locked, date_created, date_changed, date_synced, settings from administers.t_users
+    where id = 1 and is_deleted is not true and id_sort = 0;
+
+grant select on public.v_users_self to public_users;
+
+
+/**** system user has uid = 2 ****/
+create view system.v_users_self with (security_barrier=true) as
+  select id, id_sort, id_external, name_machine, name_human, address_email, is_private, is_locked, date_created, date_changed, date_synced, settings from administers.t_users
+    where id = 2 and is_deleted is not true and id_sort = 0;
+
+grant select on system.v_users_self to reservation_user;
+
+
+/*** provide public user information ***/
+create view public.v_users with (security_barrier=true) as
+  select id, id_sort, name_machine, name_human from administers.t_users
+    where (is_deleted is not true and is_private is not true) or ((name_machine)::text = (current_user)::text and is_deleted is not true);
+
+grant select on public.v_users to reservation_users;
+grant select on public.v_users to public_users;
+
+
+/*** provide e-mail address as public information only if it is explicitly allowed ***/
+create view public.v_users_email with (security_barrier=true) as
+  select id, id_sort, name_machine, name_human, address_email from administers.t_users
+    where (is_deleted is not true and is_private is not true and (address_email).private is not true) or ((name_machine)::text = (current_user)::text and is_deleted is not true);
+
+grant select on public.v_users_email to reservation_users;
+grant select on public.v_users_email to public_users;
+
+
+/*** provide managers with the ability to modify accounts ***/
+create view managers.v_users with (security_barrier=true) as
+  select id, id_sort, id_external, name_machine, name_human, address_email, is_private, is_locked, date_created, date_changed, date_synced from administers.t_users
+    where is_deleted is not true;
+
+grant select on managers.v_users to reservation_users_manager;
+
+create view managers.v_users_insert with (security_barrier=true) as
+  select id, id_sort, id_external, name_machine, name_human, address_email, is_private, is_locked, date_created, date_changed, date_synced from administers.t_users
+    where is_deleted is not true and date_created = localtimestamp and date_changed = localtimestamp and (date_synced is null or date_synced = localtimestamp)
+    with check option;
+
+grant insert on managers.v_users_insert to reservation_users_manager;
+
+create view managers.v_users_update with (security_barrier=true) as
+  select id, id_sort, id_external, name_machine, name_human, address_email, is_private, is_locked, date_changed, date_synced from administers.t_users
+    where is_deleted is not true and date_changed = localtimestamp and (date_synced is null or date_synced = localtimestamp)
+    with check option;
+
+grant update on managers.v_users_update to reservation_users_manager;
+
+
+/** Create Materialized views for table based on history **/
+create materialized view administers.vm_users_date_created_this_day as select * from administers.t_users where date_trunc('day', date_created) = date_trunc('day', current_timestamp);
+create materialized view administers.vm_users_date_created_previous_day as select * from administers.t_users where date_trunc('day', date_created) = date_trunc('day', current_timestamp) - interval '1 day';
+create materialized view administers.vm_users_date_created_previous_month as select * from administers.t_users where date_trunc('month', date_created) = date_trunc('month', current_timestamp) - interval '1 month';
+create materialized view administers.vm_users_date_created_previous_year as select * from administers.t_users where date_trunc('year', date_created) = date_trunc('year', current_timestamp) - interval '1 year';
+
+create materialized view administers.vm_users_date_changed_this_day as select * from administers.t_users where date_trunc('day', date_changed) = date_trunc('day', current_timestamp);
+create materialized view administers.vm_users_date_changed_previous_day as select * from administers.t_users where date_trunc('day', date_changed) = date_trunc('day', current_timestamp) - interval '1 day';
+create materialized view administers.vm_users_date_changed_previous_month as select * from administers.t_users where date_trunc('month', date_changed) = date_trunc('month', current_timestamp) - interval '1 month';
+create materialized view administers.vm_users_date_changed_previous_year as select * from administers.t_users where date_trunc('year', date_changed) = date_trunc('year', current_timestamp) - interval '1 year';
+
+grant select on administers.vm_users_date_created_this_day to reservation_users_administer;
+grant select on administers.vm_users_date_created_this_day to reservation_users_manager;
+grant select on administers.vm_users_date_created_previous_day to reservation_users_administer;
+grant select on administers.vm_users_date_created_previous_day to reservation_users_manager;
+grant select on administers.vm_users_date_created_previous_month to reservation_users_administer;
+grant select on administers.vm_users_date_created_previous_month to reservation_users_manager;
+grant select on administers.vm_users_date_created_previous_year to reservation_users_administer;
+grant select on administers.vm_users_date_created_previous_year to reservation_users_manager;
+
+grant select on administers.vm_users_date_changed_this_day to reservation_users_administer;
+grant select on administers.vm_users_date_changed_this_day to reservation_users_manager;
+grant select on administers.vm_users_date_changed_previous_day to reservation_users_administer;
+grant select on administers.vm_users_date_changed_previous_day to reservation_users_manager;
+grant select on administers.vm_users_date_changed_previous_month to reservation_users_administer;
+grant select on administers.vm_users_date_changed_previous_month to reservation_users_manager;
+grant select on administers.vm_users_date_changed_previous_year to reservation_users_administer;
+grant select on administers.vm_users_date_changed_previous_year to reservation_users_manager;
+
+
+/*** provide sequence id preservation table ***/
+create table administers.t_users_sequences (
+  id bigint not null,
+  id_user bigint not null,
+  name_machine varchar(128) not null,
+  is_locked boolean default true not null,
+  date_expire timestamp not null,
+
+  constraint cu_users_sequences_id unique (id),
+  constraint cu_users_sequences_name_machine unique (name_machine),
+
+  constraint cc_users_sequences_id check (id > 0),
+
+  constraint cf_users_sequences_user foreign key (id_user, name_machine) references administers.t_users (id, name_machine) on delete cascade on update cascade
+);
+
+grant select,insert,update,delete on administers.t_users_sequences to reservation_users_administer;
+
+/** when using current_user reserved function/word the index gets ignored. To prevent this, create a manual/custom index and alter the behavior of the views to be more explicit. **/
+create unique index ci_users_sequences_current_user on administers.t_users_sequences (name_machine) with (fillfactor = 40);
+
+create view public.v_users_sequences_locked with (security_barrier=true) as
+  select id, id_user, name_machine, is_locked, date_expire from administers.t_users_sequences
+    where (name_machine)::text = (current_user)::text and is_locked is true and date_expire >= current_timestamp
+    with check option;
+
+grant select,insert,update,delete on v_users_sequences_locked to reservation_users;
+
+create view public.v_users_sequences_unlocked with (security_barrier=true) as
+  select id, id_user, name_machine, is_locked, date_expire from administers.t_users_sequences
+    where (name_machine)::text = (current_user)::text and (is_locked is not true or date_expire < current_timestamp)
+    with check option;
+
+grant select,update,delete on v_users_sequences_unlocked to reservation_users;;
+
+
+
+commit transaction;
index 6eadf7819e0d59ea2a1f06fde3bdad3816152c1e..914f4751e18e25359f92f030edd1978860eb2712 100644 (file)
@@ -9,7 +9,6 @@ Postgresql: 9.6.0 or later.
 PHP: 7.1 and any patches.
 - see: https://www.php.net/
 - In general, PHP is very incompatible with itself and should use the specified versions.
-- This is initially being programmed in 5.6, but is expected to be moved to 7.1.
 
 PHP Modules:
 - mbstring
diff --git a/examples/generate_uuid.php b/examples/generate_uuid.php
new file mode 100644 (file)
index 0000000..63fddc7
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+  function do_build(&$whole, &$part, $size) {
+    while (strlen($part) < $size) {
+      $part .= base_convert(mt_rand(), 10, 16);
+    }
+
+    do_split($whole, $part, $size);
+  }
+
+  function do_split(&$whole, &$part, $size) {
+    if (strlen($part) > $size) {
+      $pieces = str_split($part, $size);
+      $whole .= $pieces[0];
+      $part = $pieces[1];
+      unset($pieces);
+    }
+    else {
+      $whole .= $part;
+      $part = '';
+    }
+  }
+
+  $guid = '';
+  $part = '';
+  do_build($guid, $part, 8);
+  $guid .= '-';
+
+  do_build($guid, $part, 4);
+  $guid .= '-';
+
+  do_build($guid, $part, 4);
+  $guid .= '-';
+
+  do_build($guid, $part, 4);
+  $guid .= '-';
+
+  do_build($guid, $part, 12);
+
+  print($guid);
+
+  print("\n");
diff --git a/examples/http.php b/examples/http.php
new file mode 100644 (file)
index 0000000..3b6e79a
--- /dev/null
@@ -0,0 +1,315 @@
+<?php
+  // make sure the class files can be loaded.
+  set_include_path('.');
+
+
+  $root_path = 'common/base/classes/';
+  require_once($root_path . 'base_http.php');
+
+  class_alias('c_base_return', 'c_return');
+  class_alias('c_base_return_status', 'c_status');
+  class_alias('c_base_return_false', 'c_false');
+  class_alias('c_base_return_true', 'c_true');
+  class_alias('c_base_return_array', 'c_array');
+  class_alias('c_base_return_string', 'c_string');
+  class_alias('c_base_return_int', 'c_int');
+  unset($root_path);
+
+
+  function program() {
+    $data_program['debug']['time_start'] = microtime(TRUE);
+    $data_program['debug']['memory_usage'] = array(0 => memory_get_usage());
+    $data_program['debug']['memory_peak'] = array(0 => memory_get_peak_usage());
+    $data_program['debug']['data_program'] = array();
+
+    $data_program['timestamp'] = microtime(TRUE);
+
+    // 1: local settings:
+    program_load_settings($data_program);
+
+    $data_program['debug']['memory_usage'][1] = memory_get_usage();
+    $data_program['debug']['memory_peak'][1] = memory_get_peak_usage();
+    gc_collect_cycles();
+
+
+    // 2: receive request information.
+    program_receive_request($data_program);
+
+    $data_program['debug']['memory_usage'][2] = memory_get_usage();
+    $data_program['debug']['memory_peak'][2] = memory_get_peak_usage();
+    gc_collect_cycles();
+
+
+    // 3: perform actions, process work.
+    program_process_request($data_program);
+
+    $data_program['debug']['memory_usage'][3] = memory_get_usage();
+    $data_program['debug']['memory_peak'][3] = memory_get_peak_usage();
+    gc_collect_cycles();
+
+
+    // 4: build or finalize theme.
+    program_process_theme($data_program);
+
+    $data_program['debug']['memory_usage'][4] = memory_get_usage();
+    $data_program['debug']['memory_peak'][4] = memory_get_peak_usage();
+    gc_collect_cycles();
+
+
+    // 5: send reqsponse information.
+    program_build_response($data_program);
+    program_send_response($data_program);
+
+    unset($data_program);
+    gc_collect_cycles();
+  }
+
+  function program_load_settings(&$data_program) {
+    ini_set('opcache.enable', FALSE);
+    ini_set('opcache.enable_cli', FALSE);
+
+    // only enable output buffering during the output stage, keep it disabled until then.
+    ini_set('output_buffering', FALSE);
+  }
+
+  function program_receive_request(&$data_program) {
+    $data_program['http'] = new c_base_http();
+
+    $data_program['http']->do_load_request();
+    $data_program['http']->set_response_content("");
+  }
+
+  function program_process_request(&$data_program) {
+    $timestamp = $data_program['http']->get_request_time();
+    if (!($timestamp instanceof c_base_return_false)) {
+      $data_program['http']->set_response_content("The request was made on (" . $timestamp->get_value_exact() . "): " . date("Y/m/d h:i:s a", $timestamp->get_value_exact()) . ": " . "<br>\n<br>\n");
+    }
+    unset($timestamp);
+
+    $data_program['http']->set_response_content("The Complete Request Array: " . "<br>\n");
+    $request = $data_program['http']->get_request()->get_value_exact();
+
+    foreach ($request as $request_id => $request_values) {
+      if (!$request_values['defined'] || $request_values['invalid']) {
+        continue;
+      }
+
+      $request_name = "Undefined";
+
+      switch ($request_id) {
+        case c_base_http::REQUEST_ACCEPT:
+          $request_name = "Accept";
+          break;
+        case c_base_http::REQUEST_ACCEPT_CHARSET:
+          $request_name = "Accept";
+          break;
+        case c_base_http::REQUEST_ACCEPT_ENCODING:
+          $request_name = "Accept-Encoding";
+          break;
+        case c_base_http::REQUEST_ACCEPT_LANGUAGE:
+          $request_name = "Accept-Language";
+          break;
+        case c_base_http::REQUEST_ACCEPT_DATETIME:
+          $request_name = "Accept-Datetime";
+          break;
+        case c_base_http::REQUEST_AUTHORIZATION:
+          $request_name = "Authorization";
+          break;
+        case c_base_http::REQUEST_CACHE_CONTROL:
+          $request_name = "Cache-Control";
+          break;
+        case c_base_http::REQUEST_CONNECTION:
+          $request_name = "Connection";
+          break;
+        case c_base_http::REQUEST_COOKIE:
+          $request_name = "Cookie";
+          break;
+        case c_base_http::REQUEST_CONTENT_LENGTH:
+          $request_name = "Content-Length";
+          break;
+        case c_base_http::REQUEST_CONTENT_TYPE:
+          $request_name = "Content-Type";
+          break;
+        case c_base_http::REQUEST_DATE:
+          $request_name = "Date";
+          break;
+        case c_base_http::REQUEST_EXPECT:
+          $request_name = "Expect";
+          break;
+        case c_base_http::REQUEST_FROM:
+          $request_name = "From";
+          break;
+        case c_base_http::REQUEST_HOST:
+          $request_name = "Host";
+          break;
+        case c_base_http::REQUEST_IF_MATCH:
+          $request_name = "If-Match";
+          break;
+        case c_base_http::REQUEST_IF_MODIFIED_SINCE:
+          $request_name = "If-Modified-Since";
+          break;
+        case c_base_http::REQUEST_IF_NONE_MATCH:
+          $request_name = "If-None-Match";
+          break;
+        case c_base_http::REQUEST_IF_RANGE:
+          $request_name = "If-Range";
+          break;
+        case c_base_http::REQUEST_IF_UNMODIFIED_SINCE:
+          $request_name = "If-Unmodified-Since";
+          break;
+        case c_base_http::REQUEST_MAX_FORWARDS:
+          $request_name = "Max-Forwards";
+          break;
+        case c_base_http::REQUEST_ORIGIN:
+          $request_name = "Origin";
+          break;
+        case c_base_http::REQUEST_PRAGMA:
+          $request_name = "Pragma";
+          break;
+        case c_base_http::REQUEST_PROXY_AUTHORIZATION:
+          $request_name = "Prox-Authorization";
+          break;
+        case c_base_http::REQUEST_RANGE:
+          $request_name = "Range";
+          break;
+        case c_base_http::REQUEST_REFERER:
+          $request_name = "Referer";
+          break;
+        case c_base_http::REQUEST_TE:
+          $request_name = "TE";
+          break;
+        case c_base_http::REQUEST_USER_AGENT:
+          $request_name = "User-Agent";
+          break;
+        case c_base_http::REQUEST_UPGRADE:
+          $request_name = "Upgrade";
+          break;
+        case c_base_http::REQUEST_VIA:
+          $request_name = "Via";
+          break;
+        case c_base_http::REQUEST_WARNING:
+          $request_name = "Warning";
+          break;
+      }
+
+      $data_program['http']->set_response_content("Request #$request_id: " . $request_name . ": " . "<br>\n");
+
+      $data_program['http']->set_response_content("<ul>\n");
+      foreach ($request_values['data'] as $key => $value) {
+        $data_program['http']->set_response_content("<li>");
+        $data_program['http']->set_response_content("<strong>" . $key . "</strong>" . " = " . print_r($value, TRUE));
+        $data_program['http']->set_response_content("</li>");
+      }
+      $data_program['http']->set_response_content("</ul>\n");
+    }
+
+    $data_program['http']->set_response_content("<br>\n");
+  }
+
+  function program_process_theme(&$data_program) {
+  }
+
+  function program_build_response(&$data_program) {
+    $data_program['http']->set_language_class('c_base_language_us_limited');
+
+    $data_program['http']->set_response_protocol('HTTP/1.1');
+    $data_program['http']->set_response_allow(c_base_http::HTTP_METHOD_GET);
+    $data_program['http']->set_response_allow(c_base_http::HTTP_METHOD_HEAD);
+    $data_program['http']->set_response_cache_control(c_base_http::CACHE_CONTROL_NO_CACHE);
+    #$data_program['http']->set_response_cache_control(c_base_http::CACHE_CONTROL_PUBLIC);
+    #$data_program['http']->set_response_cache_control(c_base_http::CACHE_CONTROL_MAX_AGE, '32');
+    #$data_program['http']->set_response_age(2);
+    #$data_program['http']->set_response_connection('close');
+    #$data_program['http']->set_response_content_disposition();
+    $data_program['http']->set_response_content_language();
+    $data_program['http']->set_response_content_type('text/html');
+    $data_program['http']->set_response_date($data_program['timestamp']);
+    $data_program['http']->set_response_expires(strtotime('+5 minutes', $data_program['timestamp']));
+    $data_program['http']->set_response_last_modified($data_program['timestamp']);
+    #$data_program['http']->set_response_location();
+    $data_program['http']->set_response_status(c_base_http_status::OK);
+    $data_program['http']->set_response_vary('host');
+    $data_program['http']->set_response_vary('user-agent');
+    $data_program['http']->set_response_vary('accept-encoding');
+
+    #$data_program['http']->set_response_date_actual(strtotime('+5 days')); // this only needs to be set for apache.
+  }
+
+  function program_send_response(&$data_program) {
+    $old_output_buffering = ini_get('output_buffering');
+    ini_set('output_buffering', 'off');
+
+    $data_program['http']->set_response_checksum_content();
+
+    $response = $data_program['http']->get_response();
+    $data_program['http']->set_response_content("The Complete Response Array: " . "<br>\n");
+    $data_program['http']->set_response_content(print_r($response->get_value_exact(), TRUE));
+    $data_program['http']->set_response_content("<br>\n");
+    unset($response);
+
+    #$data_program['http']->set_response_content("<br>\n");
+    #$data_program['http']->set_response_content("The Complete _SERVER array: " . "<br>\n");
+    #$data_program['http']->set_response_content(print_r($_SERVER, TRUE));
+    #$data_program['http']->set_response_content("<br>\n");
+
+    $data_program['http']->set_response_etag();
+
+    // example using a favicon.ico test file.
+    #$filename = '/var/www/sites/koopa/favicon.ico';
+    #$data_program['http']->set_response_content($filename, FALSE, TRUE);
+    #$data_program['http']->set_response_etag();
+    #$data_program['http']->set_response_content_type('image/gif');
+    #$data_program['http']->set_response_last_modified(filemtime($filename));
+
+    program_debug_information($data_program);
+
+    // finalize the content prior to sending headers to ensure header accuracy.
+    $data_program['http']->set_response_content_length();
+    $data_program['http']->encode_response_content();
+
+    // when the headers are sent, checksums are created, so at this point all error output should be stored and not sent.
+    $data_program['http']->send_response_headers();
+    flush();
+
+    // once the header are sent, send the content.
+    $data_program['http']->send_response_content();
+    flush();
+
+    ini_set('output_buffering', $old_output_buffering);
+    unset($old_output_buffering);
+  }
+
+  function program_debug_information(&$data_program) {
+    $data_program['debug']['memory_usage'][6] = memory_get_usage();
+    $data_program['debug']['memory_peak'][6] = memory_get_peak_usage();
+    $time_stop = microtime(TRUE);
+
+    $encoding = $data_program['http']->get_response_content_encoding();
+    if ($encoding instanceof c_base_return_false || $encoding == c_base_http::ENCODING_CHUNKED) {
+      $data_program['http']->set_response_content("<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used (1)</strong>: " . ($data_program['debug']['memory_usage'][1] - $data_program['debug']['memory_usage'][0]) . " bytes (". (floor(($data_program['debug']['memory_usage'][1] - $data_program['debug']['memory_usage'][0]) / 1024)) . " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used Peak (1)</strong>: " . ($data_program['debug']['memory_peak'][1] - $data_program['debug']['memory_peak'][0]) . " bytes (". (floor(($data_program['debug']['memory_peak'][1] - $data_program['debug']['memory_peak'][0]) / 1024)) . " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used (2)</strong>: " . ($data_program['debug']['memory_usage'][2] - $data_program['debug']['memory_usage'][0]) . " bytes (". (floor(($data_program['debug']['memory_usage'][2] - $data_program['debug']['memory_usage'][0]) / 1024)) . " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used Peak (2)</strong>: " . ($data_program['debug']['memory_peak'][2] - $data_program['debug']['memory_peak'][0]) . " bytes (". (floor(($data_program['debug']['memory_peak'][2] - $data_program['debug']['memory_peak'][0]) / 1024)) . " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used (3)</strong>: " . ($data_program['debug']['memory_usage'][3] - $data_program['debug']['memory_usage'][0]) . " bytes (". (floor(($data_program['debug']['memory_usage'][3] - $data_program['debug']['memory_usage'][0]) / 1024)) . " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used Peak (3)</strong>: " . ($data_program['debug']['memory_peak'][3] - $data_program['debug']['memory_peak'][0]) . " bytes (". (floor(($data_program['debug']['memory_peak'][3] - $data_program['debug']['memory_peak'][0]) / 1024)) . " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used (4)</strong>: " . ($data_program['debug']['memory_usage'][4] - $data_program['debug']['memory_usage'][0]) . " bytes (". (floor(($data_program['debug']['memory_usage'][4] - $data_program['debug']['memory_usage'][0]) / 1024)) . " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used Peak (4)</strong>: " . ($data_program['debug']['memory_peak'][4] - $data_program['debug']['memory_peak'][0]) . " bytes (". (floor(($data_program['debug']['memory_peak'][4] - $data_program['debug']['memory_peak'][0]) / 1024)). " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<br>\n");
+      #$data_program['http']->set_response_content("<strong>Memory Used (5)</strong>: " . ($data_program['debug']['memory_usage'][5] - $data_program['debug']['memory_usage'][0]) . " bytes (". (floor(($data_program['debug']['memory_usage'][5] - $data_program['debug']['memory_usage'][0]) / 1024)) . " KB)" . "<br>\n");
+      #$data_program['http']->set_response_content("<strong>Memory Used Peak (5)</strong>: " . ($data_program['debug']['memory_peak'][5] - $data_program['debug']['memory_peak'][0]) . " bytes (". (floor(($data_program['debug']['memory_peak'][5] - $data_program['debug']['memory_peak'][0]) / 1024)) . " KB)" . "<br>\n");
+      #$data_program['http']->set_response_content("<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used (Exit)</strong>: " . ($data_program['debug']['memory_usage'][6] - $data_program['debug']['memory_usage'][0]) . " bytes (". (floor(($data_program['debug']['memory_usage'][6] - $data_program['debug']['memory_usage'][0]) / 1024)) . " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<strong>Memory Used Peak (Exit)</strong>: " . ($data_program['debug']['memory_peak'][6] - $data_program['debug']['memory_peak'][0]) . " bytes (". (floor(($data_program['debug']['memory_peak'][6] - $data_program['debug']['memory_peak'][0]) / 1024)) . " KB)" . "<br>\n");
+      $data_program['http']->set_response_content("<br>\n");
+      $data_program['http']->set_response_content("<strong>Time Taken</strong>: " . ($time_stop - $data_program['debug']['time_start']) . " microseconds (". (floor(($time_stop - $data_program['debug']['time_start']) * 0.000001)) . " seconds)" . "<br>\n");
+    }
+    unset($encoding);
+    unset($time_stop);
+    unset($data_program['debug']);
+  }
+
+  program();
diff --git a/program/reservation/index.php b/program/reservation/index.php
new file mode 100644 (file)
index 0000000..8a3f3b0
--- /dev/null
@@ -0,0 +1,346 @@
+<?php
+  // assign custom include path.
+  set_include_path('/var/www/git/koopa');
+
+  $root_path = 'common/base/classes/';
+  require_once($root_path . 'base_http.php');
+  require_once($root_path . 'base_cookie.php');
+  require_once($root_path . 'base_ldap.php');
+  require_once($root_path . 'base_markup.php');
+  require_once($root_path . 'base_html.php');
+  require_once($root_path . 'base_charset.php');
+  require_once($root_path . 'base_database.php');
+
+  $root_path = 'common/theme/classes/';
+  require_once($root_path . 'theme_html.php');
+
+  $root_path = 'program/reservation/';
+  require_once($root_path . 'reservation_database.php');
+  require_once($root_path . 'reservation_session.php');
+  require_once($root_path . 'reservation_paths.php');
+
+  unset($root_path);
+
+  /**
+   * Load all custom settings.
+   *
+   * @return array
+   *   Custom settings.
+   */
+  function reservation_load_settings() {
+    ini_set('opcache.enable', FALSE);
+    ini_set('opcache.enable_cli', FALSE);
+
+    // only enable output buffering during the output stage, keep it disabled until then.
+    ini_set('output_buffering', FALSE);
+
+    $settings = array();
+
+    // database information
+    $settings['database_host'] = '127.0.0.1';
+    $settings['database_port'] = 5432;
+    $settings['database_name'] = 'reservation';
+    $settings['database_user'] = 'public_user';
+    $settings['database_password'] = NULL;
+    $settings['database_timeout'] = 4;
+    $settings['database_ssl_mode'] = 'require';
+    $settings['database_create_account_host'] = '127.0.0.1';
+    $settings['database_create_account_port'] = 5433;
+
+    // cookie/session information
+    $settings['cookie_name'] = 'reservation-session';
+    $settings['cookie_path'] = '/';
+    $settings['cookie_domain'] = '.localhost';
+    $settings['session_system'] = 'reservation';
+    $settings['session_expire'] = 600; // 10 minutes
+    $settings['session_max'] = 1800; // 30 minutes
+
+    // ldap information
+    $settings['ldap_server'] = 'ldaps://ldap.example.com:1636/';
+    $settings['ldap_base_dn'] = 'ou=users,ou=People';
+    $settings['ldap_fields'] = array('mail', 'gecos', 'givenname', 'cn', 'sn', 'employeenumber');
+
+    return $settings;
+  }
+
+  /**
+   * Process HTTP request.
+   *
+   * @return c_base_http
+   *   Processed and loaded request.
+   */
+  function reservation_receive_request() {
+    $http = new c_base_http();
+    $http->do_load_request();
+
+    return $http;
+  }
+
+  /**
+   * Send HTTP response.
+   *
+   * @param c_base_http $http
+   *   Http object.
+   * @param c_base_cookie $cookie
+   *   Cookie object.
+   */
+  function reservation_send_response($http, $cookie) {
+    $old_output_buffering = ini_get('output_buffering');
+    ini_set('output_buffering', 'off');
+
+    // finalize the content prior to sending headers to ensure header accuracy.
+    $http->set_response_content_length();
+    $http->encode_response_content();
+
+    // when the headers are sent, checksums are created, so at this point all error output should be stored and not sent.
+    $http->send_response_headers();
+    $cookie->do_push();
+    flush();
+
+    // once the header are sent, send the content.
+    $http->send_response_content();
+    flush();
+
+    ini_set('output_buffering', $old_output_buffering);
+    unset($old_output_buffering);
+  }
+
+  /**
+   * Process page request.
+   *
+   * @param c_base_http &$http
+   *   Http object.
+   * @param c_base_database &$databbase
+   *   The database object.
+   * @param array &$settings
+   *   System settings
+   * @param c_base_session &$session
+   *   Session information.
+   * @param c_base_cookie &$cookie
+   *   Session cookie.
+   */
+  function reservation_process_request(&$http, &$database, &$settings, &$session, &$cookie) {
+    $html = new c_base_html();
+
+
+    // assign class attribute
+    $class = array(
+      'reservation',
+      'no-script',
+      'is-html5',
+    );
+
+    $html->set_attribute(c_base_markup_attributes::ATTRIBUTE_CLASS, $class);
+    unset($class);
+
+
+    // assign id attribute
+    $html->set_attribute(c_base_markup_attributes::ATTRIBUTE_ID, 'reservation-system');
+
+
+    // assign language attribute
+    $html->set_attribute(c_base_markup_attributes::ATTRIBUTE_LANGUAGE, i_base_language::ENGLISH_US);
+
+
+    // assign direction attribute
+    $html->set_attribute(c_base_markup_attributes::ATTRIBUTE_DIRECTION, 'ltr');
+
+
+    // assign title header tag (setting title tag at delta 0 so that it can easily be overriden as needed).
+    $tag = new c_base_markup_tag();
+    $tag->set_type(c_base_markup_tag::TYPE_TITLE);
+    $tag->set_text('Reservation System');
+    $html->set_header($tag, 0);
+    unset($tag);
+
+
+    // assign base header tag
+    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_BASE)->get_value_exact();
+    #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HREF, 'http://localhost/');
+    #$html->set_header($tag);
+    #unset($tag);
+
+
+    // assign http-equiv header tag
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HTTP_EQUIV, 'Content-Type');
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'text/html; charset=utf-8');
+    $html->set_header($tag);
+    unset($tag);
+
+
+    // assign charset header tag
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CHARACTER_SET, c_base_charset::UTF_8);
+    $html->set_header($tag);
+    unset($tag);
+
+
+    // assign canonical header tag
+    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_REL, 'canonical');
+    #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HREF, 'http://localhost/');
+    #$html->set_header($tag);
+    #unset($tag);
+
+
+    // assign shortlink header tag
+    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_REL, 'shortlink');
+    #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HREF, '/');
+    #$html->set_header($tag);
+    #unset($tag);
+
+
+    // assign description header tag
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_NAME, 'description');
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'A reservation/scheduling system.');
+    $html->set_header($tag);
+    unset($tag);
+
+
+    // assign distribution header tag
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_NAME, 'distribution');
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'web');
+    $html->set_header($tag);
+    unset($tag);
+
+
+    // assign robots header tag
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_NAME, 'robots');
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'INDEX,FOLLOW');
+    $html->set_header($tag);
+    unset($tag);
+
+
+    // assign expires header tag
+    #$tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_HTTP_EQUIV, 'expires');
+    #$tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, date('r', strtotime('+30 minutes')));
+    #$html->set_header($tag);
+    #unset($tag);
+
+
+    // assign viewport header tag
+    $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_META)->get_value_exact();
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_NAME, 'viewport');
+    $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_CONTENT, 'width=device-width, initial-scale=1');
+    $html->set_header($tag);
+    unset($tag);
+
+
+    // define any global css/javascript here as appropriate link/script c_base_markup_tag tag types.
+
+
+    // finish building pages.
+    if (!isset($_SERVER["HTTPS"])) {
+      reservation_build_page_require_https($html);
+    }
+    elseif ($session === FALSE) {
+      // check to see if user has filled out the login form.
+      if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['form_id']) && $_POST['form_id'] == 'login_form') {
+        $problems = reservation_attempt_login($database, $settings, $session, $cookie);
+
+        if ($problems instanceof c_base_return_false) {
+          // @todo: render default page.
+          reservation_build_page_dashboard($html);
+          // @todo: process and handle different paths here and load page as requested.
+        }
+        else {
+
+          // @todo: render login failure.
+          // $logged_in should be an array of error messages.
+          reservation_build_login_page($html, $problems->get_value());
+        }
+      }
+      else {
+        reservation_build_login_page($html);
+      }
+    }
+    else {
+      reservation_build_page_dashboard($html);
+      // @todo: process and handle different paths here and load page as requested.
+    }
+
+    return c_base_html_return::s_new($html);
+  }
+
+  /**
+   * Render the theme.
+   *
+   * @param c_base_http $http
+   *   Http object.
+   * @param c_base_html $html
+   *   The HTML object.
+   */
+  function reservation_render_theme($http, $html) {
+    $theme = new c_theme_html();
+    $theme->set_html($html);
+    $theme->set_http($http);
+    $theme->render_markup();
+
+    return $theme->get_markup();
+  }
+
+  /**
+   * Main Program Function
+   */
+  function reservation_main() {
+    // 1: local settings:
+    $settings = reservation_load_settings();
+    gc_collect_cycles();
+
+
+    // 2: receive request information.
+    $http = reservation_receive_request();
+    gc_collect_cycles();
+
+
+    // 3: process session information
+    $cookie = new c_base_cookie();
+    $session = reservation_process_sessions($settings, $cookie)->get_value_exact();
+    gc_collect_cycles();
+
+
+    // 4: perform actions, process work.
+    $database = new c_base_database();
+    $html = reservation_process_request($http, $database, $settings, $session, $cookie)->get_value();
+    if (!($html instanceof c_base_html)) {
+      $html = new c_base_html();
+    }
+
+    if ($database->is_connected() instanceof c_base_return_true) {
+      $database->do_disconnect();
+    }
+    unset($database);
+    gc_collect_cycles();
+
+
+    // 5: build or finalize theme.
+    $markup = reservation_render_theme($http, $html)->get_value_exact();
+    unset($html);
+    gc_collect_cycles();
+
+
+    // 6: build response information.
+    $http->set_response_content($markup);
+    unset($markup);
+    gc_collect_cycles();
+
+
+    // 7: send HTTP response.
+    reservation_send_response($http, $cookie);
+    gc_collect_cycles();
+
+    unset($settings);
+    unset($http);
+    unset($session);
+    unset($cookie);
+    unset($database);
+    gc_collect_cycles();
+  }
+
+  reservation_main();
diff --git a/program/reservation/reservation_database.php b/program/reservation/reservation_database.php
new file mode 100644 (file)
index 0000000..401ec34
--- /dev/null
@@ -0,0 +1,292 @@
+<?php
+/**
+ * @file
+ * Provides reservation database functions.
+ */
+  #require_once('../../common/base/classes/base_error.php');
+  #require_once('../../common/base/classes/base_return.php');
+  #require_once('../../common/base/classes/base_session.php');
+  #require_once('../../common/base/classes/base_database.php');
+
+  /**
+   * Build the database connection string.
+   *
+   * @param c_base_database &$database
+   *   The database to connect to.
+   * @param array $settings
+   *   Custom settings.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set on error.
+   */
+  function reservation_database_string(&$database, $settings) {
+    if (!($database instanceof c_base_database)) {
+      return c_base_return_error::s_false();
+    }
+
+    $connection_string = new c_base_connection_string();
+    $connection_string->set_host($settings['database_host']);
+    $connection_string->set_port($settings['database_port']);
+    $connection_string->set_dbname($settings['database_name']);
+    $connection_string->set_user($settings['database_user']);
+
+    if (!is_null($settings['database_password'])) {
+      $connection_string->set_password($settings['database_password']);
+    }
+
+    $connection_string->set_ssl_mode($settings['database_ssl_mode']);
+    $connection_string->set_connect_timeout($settings['database_timeout']);
+
+    $database->set_connection_string($connection_string);
+    unset($connection_string);
+
+    return new c_base_return_true();
+  }
+
+  /**
+   * Connect the database and configure default settings.
+   *
+   * @param c_base_database &$database
+   *   The database to connect to.
+   *
+   * @return c_base_return_status
+   *   TRUE on success, FALSE otherwise.
+   *   FALSE with error bit set on error.
+   */
+  function reservation_database_connect(&$database) {
+    if (!($database instanceof c_base_database)) {
+      return c_base_return_error::s_false();
+    }
+
+    $status = $database->do_connect();
+    if (!($status instanceof c_base_return_true)) {
+      return $status;
+    }
+    unset($status);
+
+    // configure default settings.
+    $database->do_query('set bytea_output to hex;');
+    $database->do_query('set search_path to system,administers,managers,publishers,insurers,financers,reviewers,drafters,users,public;');
+    $database->do_query('set datestyle to us;');
+
+    return new c_base_return_true();
+  }
+
+  /**
+   * Load the user data.
+   *
+   * This is necessary to load and process session data.
+   *
+   * @param c_base_database &$database
+   *   The database to connect to.
+   * @param string $user_name
+   *   The name of the user to load.
+   * @param array|null $ldap_data
+   *   (optional) An array of ldap data (if available).
+   *   This is used to auto-populate user information in the database when an account is auto-created.
+   *
+   * @return c_base_return_array|c_base_return_status
+   *   An array of user data is returned on success.
+   *   FALSE with error bit set on error.
+   */
+  function reservation_database_get_user_data(&$database, $user_name, $ldap_data = NULL) {
+    if (!($database instanceof c_base_database)) {
+      return c_base_return_error::s_false();
+    }
+
+    if (!is_string($user_name)) {
+      return c_base_return_error::s_false();
+    }
+
+    if (!is_null($ldap_data) && !is_array($ldap_data)) {
+      return c_base_return_error::s_false();
+    }
+
+    $user_data = array(
+      'id_user' => NULL,
+      'id_sort' => $id_sort,
+    );
+
+    $id_sort = (int) ord($user_name[0]);
+
+    $parameters = array(
+      $id_sort,
+      $user_name,
+    );
+
+    $query_result = $database->do_query('select id, id_sort, id_external, name_human, address_email, is_private, is_locked, date_created, date_changed, settings from v_users_self where id_sort = $1 and name_machine like $2', $parameters);
+    unset($parameters);
+
+    if ($query_result instanceof c_base_database_result) {
+      if ($query_result->number_of_rows()->get_value_exact() > 0) {
+        $result = $query_result->fetch_row();
+        if (!($result instanceof c_base_return_false)) {
+          $result_array = $result->get_value();
+          if (is_array($result_array) && !empty($result_array)) {
+            $user_data['id_user'] = $result_array[0];
+            $user_data['id_sort'] = $result_array[1];
+            $user_data['id_external'] = $result_array[2];
+            $user_data['name_human'] = $result_array[3];
+            $user_data['address_email'] = $result_array[4];
+            $user_data['is_private'] = $result_array[5];
+            $user_data['is_locked'] = $result_array[6];
+            $user_data['date_created'] = $result_array[7];
+            $user_data['date_changed'] = $result_array[8];
+            $user_data['settings'] = json_decode($result_array[9], TRUE);
+          }
+        }
+      }
+    }
+    unset($query_result);
+
+    if (is_null($user_data['id_user'])) {
+      if (is_null($ldap_data)) {
+        $parameters = array(
+          $id_sort,
+        );
+
+        $query_result = $database->do_query('insert into v_users_self_insert (id_sort, name_machine) values ($1, user)', $parameters);
+        unset($query_result);
+        unset($parameters);
+      }
+      else {
+        $email = explode('@', $ldap_data['mail']);
+        $parameters = array(
+          $ldap_data['givenname'],
+          $ldap_data['sn'],
+          $ldap_data['cn'],
+          $email[0],
+          $email[1],
+          $ldap_data['employeenumber'],
+        );
+        $query_result = $database->do_query('insert into v_users_self_insert (id_sort, name_machine, name_human.first, name_human.last, name_human.complete, address_email, id_external) values (' . $id_sort . ', user, $1, $2, $3, ($4, $5, TRUE), $6)', $parameters);
+        unset($query_result);
+      }
+
+      $parameters = array(
+        $id_sort,
+        $user_name,
+      );
+
+      $query_result = $database->do_query('select id, id_sort, id_external, name_human, address_email, is_private, is_locked, date_created, date_changed, settings from v_users_self where id_sort = $1 and name_machine = $2');
+      unset($parameters);
+
+      if ($query_result instanceof c_base_database_result) {
+        if ($query_result->number_of_rows()->get_value_exact() > 0) {
+          $result = $query_result->fetch_row();
+          if (!($result instanceof c_base_return_false)) {
+            $result_array = $result->get_value();
+            if (is_array($result_array) && !empty($result_array)) {
+              $result_array = $result->get_value();
+              $user_data['id_user'] = $result_array[0];
+              $user_data['id_sort'] = $result_array[1];
+              $user_data['id_external'] = $result_array[2];
+              $user_data['name_human'] = $result_array[3];
+              $user_data['address_email'] = $result_array[4];
+              $user_data['is_private'] = $result_array[5];
+              $user_data['is_locked'] = $result_array[6];
+              $user_data['date_created'] = $result_array[7];
+              $user_data['date_changed'] = $result_array[8];
+              $user_data['settings'] = json_decode($result_array[9], TRUE);
+            }
+          }
+        }
+      }
+      unset($query_result);
+    }
+
+    return c_base_return_array::s_new($user_data);
+  }
+
+  /**
+   * Loads LDAP information for the given user (if available).
+   *
+   * @param array $settings
+   *   System settings array.
+   * @param string $user_name
+   *   The user name to load
+   *
+   * @return c_base_return_array|c_base_return_status
+   *   An array of ldap data associated with the given user.
+   *   This array may contain error information if there were connection problems to the ldap database.
+   *   The array structure is:
+   *     'title': a Title for any error that occured.
+   *     'message': The detailed ldap error message.
+   *     'status': c_base_return_true if there were no problems and c_base_return_false if there were problems.
+   *     'data': Any ldap data found for the given user name.
+   *   FALSE with the error bit set is returned on error.
+   */
+  function reservation_database_load_ldap_data($settings, $user_name) {
+    if (!is_array($settings)) {
+      return c_base_return_error::s_false();
+    }
+
+    if (!is_string($user_name)) {
+      return c_base_return_error::s_false();
+    }
+
+    $return_data = array(
+      'title' => NULL,
+      'message' => NULL,
+      'status' => new c_base_return_true(),
+      'data' => NULL,
+    );
+
+    $ldap = new c_base_ldap();
+    $ldap->set_name($settings['ldap_server']);
+    #$ldap->set_bind_name('');
+    #$ldap->set_bind_password('');
+    $connected = $ldap->do_connect();
+    if (c_base_return::s_has_error($connected)) {
+      $message = $ldap->get_error_message();
+
+      $return_data['title'] = 'Connection Failed';
+      $return_data['message'] = $message->get_value_exact();
+      $return_data['status'] = new c_base_return_false();
+      unset($message);
+
+      return c_base_return_array::s_new($return_data);
+    }
+
+    $read = $ldap->do_search($settings['ldap_base_dn'], '(uid=' . $user_name . ')', $settings['ldap_fields']);
+    if (c_base_return::s_has_error($read)) {
+      $message = $ldap->get_error_message();
+
+      $return_data['title'] = 'Search Failed';
+      $return_data['message'] = $message->get_value_exact();
+      $return_data['status'] = new c_base_return_false();
+      unset($message);
+
+      $ldap->do_disconnect();
+
+      return c_base_return_array::s_new($return_data);
+    }
+
+    $entries = $read->get_entry_all();
+    if ($entries instanceof c_base_return_array) {
+      $entries = $entries->get_value();
+    }
+    else {
+      $entries = array();
+    }
+
+    if ($entries['count'] > 0) {
+      $return_data['data'] = array(
+        'uid' => $user_name,
+      );
+
+      foreach ($settings['ldap_fields'] as $ldap_field) {
+        $return_data['data'][$ldap_field] = $entries[0][$ldap_field][0];
+      }
+      unset($ldap_field);
+    }
+    else {
+      $return_data['title'] = 'Username Not Found';
+      $return_data['message'] = 'The user \'' . $user_name . '\' was not found.';
+      $return_data['status'] = new c_base_return_false();
+    }
+    unset($entries);
+
+    return c_base_return_array::s_new($return_data);
+  }
diff --git a/program/reservation/reservation_paths.php b/program/reservation/reservation_paths.php
new file mode 100644 (file)
index 0000000..31eef59
--- /dev/null
@@ -0,0 +1,350 @@
+<?php
+/**
+ * @file
+ * Provides reservation session functions.
+ */
+  require_once('common/base/classes/base_error.php');
+  require_once('common/base/classes/base_return.php');
+  require_once('common/base/classes/base_markup.php');
+  require_once('common/base/classes/base_html.php');
+  require_once('common/base/classes/base_charset.php');
+
+  require_once('program/reservation/reservation_database.php');
+  require_once('program/reservation/reservation_session.php');
+
+/**
+ * Build the login page.
+ *
+ * @param c_base_html &$html
+ *   The html page object.
+ * @param null|array $problems
+ *   (optional) An array of problems to report when building the form.
+ *   This is specified only after a form is submitted.
+ *
+ * @return c_base_html_return
+ *   The markup tags object.
+ */
+function reservation_build_login_page(&$html, $problems = NULL) {
+  $problem_fields = array();
+  $problem_messages = array();
+
+  if (is_array($problems)) {
+    foreach ($problems as $problem) {
+      if (!empty($problem['fields']) && is_array($problem['fields'])) {
+        foreach ($problem['fields'] as $problem_field) {
+          $problem_fields[$problem_field] = $problem_field;
+        }
+        unset($problem_field);
+      }
+
+      if (!empty($problem['messages']) && is_string($problem['messages'])) {
+        $problem_messages[] = $problem['messages'];
+      }
+    }
+    unset($problem);
+  }
+
+  if (!empty($problem_messages)) {
+    $messages = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER, 'form_problems', array('form_problems'))->get_value_exact();
+    foreach ($problem_messages as $problem_delta => $problem_message) {
+      $class = array(
+        'form_problems-problem',
+        'form_problems-problem-' . $problem_delta,
+      );
+
+      $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER, 'form_problems-problem-' . $problem_delta, $class)->get_value_exact();
+      $tag->set_text($problem_message);
+      unset($class);
+
+      $messages->set_tag($tag);
+      unset($tag);
+    }
+    unset($problem_message);
+    unset($problem_delta);
+
+    $html->set_tag($messages);
+    unset($messages);
+  }
+  unset($problem_messages);
+
+  // login form
+  $form = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_FORM, 'login_form', array('login_form'))->get_value_exact();
+  $form->set_attribute(c_base_markup_attributes::ATTRIBUTE_METHOD, 'post');
+  $form->set_attribute(c_base_markup_attributes::ATTRIBUTE_ROLE, 'form');
+  $form->set_attribute(c_base_markup_attributes::ATTRIBUTE_ACCEPT_CHARACTER_SET, c_base_charset::UTF_8);
+
+
+  // H1
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1)->get_value_exact();
+  $tag->set_text('Login to System');
+  $form->set_tag($tag);
+  unset($tag);
+
+
+  // hidden form data
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_HIDDEN, 'form_id', array('login_form-id'))->get_value_exact();
+  $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE, 'login_form');
+  $form->set_tag($tag);
+  unset($tag);
+
+
+  // label: username
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_LABEL, NULL, array('login_form-label-username'))->get_value_exact();
+  $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_FOR, 'login_form-username');
+  $tag->set_text('Username');
+  $form->set_tag($tag);
+  unset($tag);
+
+
+  // field: username
+  $class = array(
+    'login_form-input-username',
+  );
+  if (array_key_exists('login_form-username', $problem_fields)) {
+    $class[] = 'field_has_problem';
+  }
+
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_TEXT, 'login_form-username', $class)->get_value_exact();
+  unset($class);
+
+  $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_REQUIRED, TRUE);
+  $form->set_tag($tag);
+  unset($tag);
+
+
+  // label: password
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_LABEL, NULL, array('login_form-label-password'))->get_value_exact();
+  $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_FOR, 'login_form-password');
+  $tag->set_text('Password');
+  $form->set_tag($tag);
+  unset($tag);
+
+
+  // field: password
+  $class = array(
+    'login_form-input-password',
+  );
+  if (array_key_exists('login_form-password', $problem_fields)) {
+    $class[] = 'field_has_problem';
+  }
+
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_PASSWORD, 'login_form-password', $class)->get_value_exact();
+  unset($class);
+
+  $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_REQUIRED, TRUE);
+  $form->set_tag($tag);
+  unset($tag);
+
+
+  // button: reset
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_RESET, 'login_form-reset', array('login_form-button-reset'))->get_value_exact();
+  $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE, 'Reset');
+  $form->set_tag($tag);
+  unset($tag);
+
+
+  // button: submit
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_SUBMIT, 'login_form-login', array('login_form-button-login'))->get_value_exact();
+  $tag->set_attribute(c_base_markup_attributes::ATTRIBUTE_VALUE, 'Login');
+  $form->set_tag($tag);
+  unset($tag);
+  unset($problem_fields);
+
+  $html->set_tag($form);
+  unset($form);
+}
+
+/**
+ * Validate the login form.
+ *
+ * @param c_base_database &$database
+ *   The database object.
+ * @param array &$settings
+ *   The system settings array.
+ * @param c_base_session &$session
+ *   The current session.
+ * @param c_base_cookie &$cookie
+ *   Session cookie.
+ *
+ * @return c_base_return_array|c_base_return_status
+ *   FALSE on success.
+ *   An array of problems on failure.
+ *   FALSE with error bit set is returned on error.
+ */
+function reservation_attempt_login(&$database, &$settings, &$session, &$cookie) {
+  $problems = array();
+  if (empty($_POST['login_form-username'])) {
+    $problems[] = array(
+      'fields' => array('login_form-username'),
+      'messages' => 'No valid username has been supplied.',
+    );
+  }
+
+  if (empty($_POST['login_form-password'])) {
+    $problems[] = array(
+      'fields' => array('login_form-password'),
+      'messages' => 'No valid password has been supplied.',
+    );
+  }
+
+  // explicitly deny access to internal user accounts
+  if ($_POST['login_form-username'] == 'public_user') {
+    $problems[] = array(
+      'fields' => array('login_form-username'),
+      'messages' => 'Unable to login, an incorrect user name or password has been specified.',
+    );
+  }
+
+  // return current list of problems before continuing to login attempt with credentials.
+  if (!empty($problems)) {
+    return c_base_return_array::s_new($problems);
+  }
+
+
+  // assign username and password to both session and database.
+  if (!($session instanceof c_base_session)) {
+    $session = new c_base_session();
+  }
+
+  if (empty($_SERVER['REMOTE_ADDR'])) {
+    $session->set_host('0.0.0.0');
+  }
+  else {
+    $session->set_host($_SERVER['REMOTE_ADDR']);
+  }
+
+  $session->set_system_name($settings['session_system']);
+  $session->set_name($_POST['login_form-username']);
+  $session->set_password($_POST['login_form-password']);
+  $settings['database_user'] = $_POST['login_form-username'];
+  $settings['database_password'] = $_POST['login_form-password'];
+
+  // the database string must be rebuilt using the new username and password.
+  reservation_database_string($database, $settings);
+
+  $connected = reservation_database_connect($database);
+  if (!($connected instanceof c_base_return_true)) {
+    // it is possible the user name might not exist, so try to auto-create the username if the username does not exist.
+    $ensure_result = reservation_ensure_user_account($settings, $_POST['login_form-username']);
+    // @todo: process the $ensure_result return codes.
+
+    if ($ensure_result instanceof c_base_return_int) {
+      $ensure_result = $ensure_result->get_value_exact();
+
+      $connected = new c_base_return_false();
+      if ($ensure_result === 0) {
+        // try again now that the system has attempted to ensure the user account exists.
+        $connected = reservation_database_connect($database);
+        if ($connected instanceof c_base_return_true) {
+          // @todo: add log entry.
+          #set_log_user($database, 'create_user');
+        }
+      }
+      else {
+        // @todo: possibly handle errors resulting from not being able to auto-create account.
+      }
+    }
+    unset($ensure_result);
+  }
+
+  if ($connected instanceof c_base_return_false) {
+    $problems[] = array(
+      'fields' => array('login_form-username'),
+      'messages' => 'Unable to login, an incorrect user or password has been specified.',
+    );
+  }
+  else {
+    // @todo: add log entry.
+    #set_log_user($database, 'login');
+
+    // @todo: load and store custom settings (loaded from the database and/or ldap).
+    #$session->set_id_user($user_id);
+    #$session->set_settings($user_data);
+
+    // the session needs to be opened and the data needs to be saved on successful login.
+    $result = $session->do_connect();
+    if (!c_base_return::s_has_error($result)) {
+      $ldap = reservation_database_load_ldap_data($settings, $_POST['login_form-username'])->get_value();
+      if ($ldap instanceof c_base_return_false || !is_array($ldap)) {
+        $ldap = array(
+          'data' => NULL,
+        );
+      }
+
+      if (isset($ldap['status']) && $ldap['status'] instanceof c_base_return_false) {
+        // @todo: handle error situation.
+      }
+
+      $user_data = reservation_database_get_user_data($database, $_POST['login_form-username'], $ldap['data'])->get_value();
+
+      if (is_array($user_data) && isset($user_data['id_user'])) {
+        $session->set_id_user($user_data['id_user']);
+      }
+
+      // @todo: get and use user id from $user_data.
+
+      $result = $session->do_push($settings['session_expire'], $settings['session_max']);
+      $session->do_disconnect();
+
+      $session_expire = $session->get_timeout_expire()->get_value_exact();
+      $cookie->set_expires($session_expire);
+      $cookie->set_max_age(NULL);
+
+      if ($result instanceof c_base_return_true) {
+        $data = array(
+          'session_id' => $session->get_session_id()->get_value_exact(),
+          'expire' => gmdate("D, d-M-Y H:i:s T", $session_expire), // unecessary, but provided for debug purposes.
+        );
+        $cookie->set_data($data);
+      }
+      unset($result);
+      unset($session_expire);
+    }
+    unset($result);
+
+  }
+  unset($connected);
+
+  if (empty($problems)) {
+    unset($problems);
+    return new c_base_return_false();
+  }
+
+  return c_base_return_array::s_new($problems);
+}
+
+/**
+ * Build the HTTPS requirement page.
+ * @param c_base_html &$html
+ *   The html page object.
+ *
+ * @return c_base_html_return
+ *   The markup tags object.
+ */
+function reservation_build_page_require_https(&$html) {
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1)->get_value_exact();
+  $tag->set_text('HTTPS Connection is Required');
+  $html->set_tag($tag);
+
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER)->get_value_exact();
+  $tag->set_text('Please use a secure connection to access this website.');
+  $html->set_tag($tag);
+}
+
+/**
+ * Build the dashboard page.
+ * @param c_base_html &$html
+ *   The html page object.
+ *
+ * @return c_base_html_return
+ *   The markup tags object.
+ */
+function reservation_build_page_dashboard(&$html) {
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_H1)->get_value_exact();
+  $tag->set_text('Dashboard');
+  $html->set_tag($tag);
+
+  $tag = c_theme_html::s_create_tag(c_base_markup_tag::TYPE_DIVIDER)->get_value_exact();
+  $tag->set_text('All links will go here.');
+  $html->set_tag($tag);
+}
diff --git a/program/reservation/reservation_response.php b/program/reservation/reservation_response.php
new file mode 100644 (file)
index 0000000..3c9e460
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+/**
+ * @file
+ * Provides reservation response functions.
+ */
+  require_once('../../common/base/classes/base_error.php');
+  require_once('../../common/base/classes/base_return.php');
+
+function reservation_build_respone($markup) {
+  $http->set_response_content($markup);
+}
diff --git a/program/reservation/reservation_session.php b/program/reservation/reservation_session.php
new file mode 100644 (file)
index 0000000..230e7f9
--- /dev/null
@@ -0,0 +1,164 @@
+<?php
+/**
+ * @file
+ * Provides reservation session functions.
+ */
+  require_once('common/base/classes/base_error.php');
+  require_once('common/base/classes/base_return.php');
+  require_once('common/base/classes/base_http.php');
+  require_once('common/base/classes/base_session.php');
+  require_once('common/base/classes/base_cookie.php');
+
+  require_once('program/reservation/reservation_database.php');
+
+
+  /**
+   * Process session information.
+   *
+   * @param array &$settings
+   *   System settings.
+   * @param c_base_cookie &$cookie
+   *   Cookie setting.
+   *
+   * @param c_base_return_status|c_base_session
+   *   Session information is returned on success.
+   *   FALSE is returned when no session is defined.
+   *   FALSE with error bit set is returned on error.
+   */
+  function reservation_process_sessions(&$settings, &$cookie) {
+    // cookie is used to determine whether or not the user is logged in.
+    $cookie->set_name($settings['cookie_name']);
+    $cookie->set_path($settings['cookie_path']);
+    $cookie->set_domain($settings['cookie_domain']);
+    $cookie->set_secure(TRUE);
+
+    $pulled = $cookie->do_pull();
+    if ($pulled instanceof c_base_return_true) {
+      $cookie_data = $cookie->get_data()->get_value_exact();
+
+      if (!($cookie->validate() instanceof c_base_return_true) || empty($cookie_data['session_id'])) {
+        // cookie failed validation or the cookie contains no session id.
+        return new c_base_return_false();
+      }
+
+      $session = new c_base_session();
+      $session->set_system_name($settings['session_system']);
+      $session->set_session_id($cookie_data['session_id']);
+
+      if (empty($_SERVER['REMOTE_ADDR'])) {
+        $session->set_host('0.0.0.0');
+      }
+      else {
+        $session->set_host($_SERVER['REMOTE_ADDR']);
+      }
+
+      $session_connection = $session->do_connect();
+      if (c_base_return::s_has_error($session_connection)) {
+        return $session_connection;
+      }
+
+      $result = $session->do_pull();
+      $session->do_disconnect();
+
+      if ($result instanceof c_base_return_true) {
+        $user_name = $session->get_name()->get_value();
+        $password = $session->get_password()->get_value();
+
+        if (is_string($user_name) && is_string($password)) {
+          $settings['database_user'] = $user_name;
+          $settings['database_password'] = $password;
+        }
+      }
+
+      // check to see if the session timeout has been extended and if so, then update the cookie.
+      $session_expire = $session->get_timeout_expire()->get_value_exact();
+      $session_seconds = $session_expire - time();
+      if ($session_seconds == 0) {
+        $session_seconds = -1;
+      }
+      if ($session_expire > $cookie_data['expire']) {
+        $cookie_data['expire'] = gmdate("D, d-M-Y H:i:s T", $session_expire);
+        $cookie->set_data($value);
+        $cookie->set_expires($session_expire);
+      }
+
+      return c_base_session_return::s_new($session);
+    }
+
+    return new c_base_return_false();
+  }
+
+  /**
+   * Attempt to auto-create a postgresql account.
+   *
+   * @param array $settings
+   *   System settings.
+   * @param string $username
+   *   The name of the postgresql account to auto-create.
+   *
+   * @return c_base_return_int|c_base_return_status
+   *   An integer is returned, whose codes represent the transaction result.
+   *   FALSE with error bit set is returned on error.
+   */
+  function reservation_ensure_user_account($settings, $user_name) {
+    $socket_family = AF_INET;
+    $socket_protocol = SOL_TCP;
+    $socket_type = SOCK_STREAM;
+
+    $packet_size_target = 63;
+    $packet_size_client = 1;
+
+    $socket = socket_create($socket_family, $socket_type, $socket_protocol);
+    if ($socket === FALSE) {
+      socket_close($socket);
+      return c_base_return_error::s_false();
+    }
+
+    $connected = socket_connect($socket, $settings['database_create_account_host'], $settings['database_create_account_port']);
+    if ($connected === FALSE) {
+      socket_close($socket);
+      return c_base_return_error::s_false();
+    }
+
+    $name_length = strlen(trim($user_name));
+    $difference = $packet_size_target - $name_length;
+
+    if ($difference > 0) {
+      // the packet expects a packet to be NULL terminated or at most $packet_size_target.
+      $packet = pack('a' . $name_length . 'x' . $difference, trim($user_name));
+    }
+    else {
+      $packet = pack('a' . $name_length, $user_name);
+    }
+
+    $written = socket_write($socket, $packet, $packet_size_target);
+    if ($written === FALSE) {
+      socket_close($socket);
+      return c_base_return_error::s_false();
+    }
+
+    $response = socket_read($socket, $packet_size_client);
+    socket_close($socket);
+    if (!is_string($response) || strlen($response) == 0) {
+      return c_base_return_error::s_false();
+    }
+
+    // an integer is expected to be returned by the socket.
+    $response_packet = unpack('C', $response);
+    $response_value = (int) $response_packet[1];
+
+    // response codes as defined in the c source file:
+    //    0 = no problems detected.
+    //    1 = invalid user name, bad characters, or name too long.
+    //    2 = failed to connect to the ldap server and could not query the ldap name.
+    //    3 = user name not found in ldap database.
+    //    4 = failed to connect to the database.
+    //    5 = error returned while executing the SQL command.
+    //    6 = error occured while reading input from the user (such as via recv()).
+    //    7 = error occured while writing input from the user (such as via send()).
+    //    8 = the received packet is invalid, such as wrong length.
+    //   10 = connection timed out when reading or writing.
+    //   11 = the connection is being forced closed.
+    //   12 = the connection is closing because the service is quitting.
+    return c_base_return_int::s_new($response_value);
+  }