Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Joomla platform example for Joomla Day Denmark 2012

  • Loading branch information...
commit 5c56595eefb51027ebe3c2c329869c6d1e21aedf 0 parents
@realityking authored
Showing with 48,261 additions and 0 deletions.
  1. +38 −0 Step1/application/web.php
  2. +27 −0 Step1/index.php
  3. +111 −0 Step10/application/web.php
  4. +30 −0 Step10/controller/add.php
  5. +37 −0 Step10/controller/display.php
  6. +28 −0 Step10/index.php
  7. +25 −0 Step10/model/comments.php
  8. +17 −0 Step10/templates/template/index.php
  9. +34 −0 Step10/view/comments/html.php
  10. +24 −0 Step10/view/comments/tmpl/default.php
  11. +59 −0 Step2/application/web.php
  12. +27 −0 Step2/index.php
  13. +105 −0 Step3/application/web.php
  14. +27 −0 Step3/index.php
  15. +111 −0 Step4/application/web.php
  16. +27 −0 Step4/index.php
  17. +125 −0 Step5/application/web.php
  18. +27 −0 Step5/index.php
  19. +91 −0 Step6/application/web.php
  20. +33 −0 Step6/controller/add.php
  21. +57 −0 Step6/controller/display.php
  22. +27 −0 Step6/index.php
  23. +111 −0 Step7/application/web.php
  24. +33 −0 Step7/controller/add.php
  25. +46 −0 Step7/controller/display.php
  26. +28 −0 Step7/index.php
  27. +17 −0 Step7/templates/template/index.php
  28. +111 −0 Step8/application/web.php
  29. +30 −0 Step8/controller/add.php
  30. +42 −0 Step8/controller/display.php
  31. +28 −0 Step8/index.php
  32. +24 −0 Step8/model/comments.php
  33. +17 −0 Step8/templates/template/index.php
  34. +111 −0 Step9/application/web.php
  35. +30 −0 Step9/controller/add.php
  36. +37 −0 Step9/controller/display.php
  37. +28 −0 Step9/index.php
  38. +24 −0 Step9/model/comments.php
  39. +17 −0 Step9/templates/template/index.php
  40. +29 −0 Step9/view/comments/html.php
  41. +24 −0 Step9/view/comments/tmpl/default.php
  42. +5,840 −0 bootstrap.css
  43. +841 −0 bootstrap.min.css
  44. +29 −0 libraries/compat/jsonserializable.php
  45. +36 −0 libraries/config.example.php
  46. +87 −0 libraries/import.legacy.php
  47. +54 −0 libraries/import.php
  48. +568 −0 libraries/joomla/access/access.php
  49. +176 −0 libraries/joomla/access/rule.php
  50. +219 −0 libraries/joomla/access/rules.php
  51. +151 −0 libraries/joomla/application/base.php
  52. +294 −0 libraries/joomla/application/cli.php
  53. +895 −0 libraries/joomla/application/daemon.php
  54. +107 −0 libraries/joomla/application/route.php
  55. +517 −0 libraries/joomla/application/router.php
  56. +1,187 −0 libraries/joomla/application/web.php
  57. +514 −0 libraries/joomla/application/web/client.php
  58. +153 −0 libraries/joomla/application/web/router.php
  59. +177 −0 libraries/joomla/application/web/router/base.php
  60. +142 −0 libraries/joomla/application/web/router/rest.php
  61. +195 −0 libraries/joomla/archive/archive.php
  62. +176 −0 libraries/joomla/archive/bzip2.php
  63. +42 −0 libraries/joomla/archive/extractable.php
  64. +242 −0 libraries/joomla/archive/gzip.php
  65. +217 −0 libraries/joomla/archive/tar.php
  66. +688 −0 libraries/joomla/archive/zip.php
  67. +195 −0 libraries/joomla/base/adapter.php
  68. +69 −0 libraries/joomla/base/adapterinstance.php
  69. +703 −0 libraries/joomla/cache/cache.php
  70. +235 −0 libraries/joomla/cache/controller.php
  71. +205 −0 libraries/joomla/cache/controller/callback.php
  72. +122 −0 libraries/joomla/cache/controller/output.php
  73. +196 −0 libraries/joomla/cache/controller/page.php
  74. +137 −0 libraries/joomla/cache/controller/view.php
  75. +346 −0 libraries/joomla/cache/storage.php
  76. +250 −0 libraries/joomla/cache/storage/apc.php
  77. +346 −0 libraries/joomla/cache/storage/cachelite.php
  78. +690 −0 libraries/joomla/cache/storage/file.php
  79. +71 −0 libraries/joomla/cache/storage/helper.php
  80. +477 −0 libraries/joomla/cache/storage/memcache.php
  81. +489 −0 libraries/joomla/cache/storage/memcached.php
  82. +194 −0 libraries/joomla/cache/storage/wincache.php
  83. +209 −0 libraries/joomla/cache/storage/xcache.php
  84. +1,689 −0 libraries/joomla/client/ftp.php
  85. +238 −0 libraries/joomla/client/helper.php
  86. +663 −0 libraries/joomla/client/ldap.php
  87. +137 −0 libraries/joomla/controller/base.php
  88. +51 −0 libraries/joomla/controller/controller.php
  89. +55 −0 libraries/joomla/crypt/cipher.php
  90. +40 −0 libraries/joomla/crypt/cipher/3des.php
  91. +40 −0 libraries/joomla/crypt/cipher/blowfish.php
  92. +175 −0 libraries/joomla/crypt/cipher/mcrypt.php
  93. +40 −0 libraries/joomla/crypt/cipher/rijndael256.php
  94. +283 −0 libraries/joomla/crypt/cipher/simple.php
  95. +238 −0 libraries/joomla/crypt/crypt.php
  96. +80 −0 libraries/joomla/crypt/key.php
  97. +52 −0 libraries/joomla/crypt/password.php
  98. +148 −0 libraries/joomla/crypt/password/simple.php
  99. +173 −0 libraries/joomla/database/database.php
  100. +1,684 −0 libraries/joomla/database/driver.php
  101. +413 −0 libraries/joomla/database/driver/mysql.php
  102. +722 −0 libraries/joomla/database/driver/mysqli.php
  103. +604 −0 libraries/joomla/database/driver/oracle.php
  104. +979 −0 libraries/joomla/database/driver/pdo.php
  105. +1,331 −0 libraries/joomla/database/driver/postgresql.php
  106. +29 −0 libraries/joomla/database/driver/sqlazure.php
  107. +383 −0 libraries/joomla/database/driver/sqlite.php
  108. +994 −0 libraries/joomla/database/driver/sqlsrv.php
  109. +22 −0 libraries/joomla/database/exporter.php
  110. +62 −0 libraries/joomla/database/exporter/mysql.php
  111. +298 −0 libraries/joomla/database/exporter/mysqli.php
  112. +313 −0 libraries/joomla/database/exporter/postgresql.php
  113. +191 −0 libraries/joomla/database/factory.php
  114. +22 −0 libraries/joomla/database/importer.php
  115. +61 −0 libraries/joomla/database/importer/mysql.php
  116. +654 −0 libraries/joomla/database/importer/mysqli.php
  117. +794 −0 libraries/joomla/database/importer/postgresql.php
  118. +205 −0 libraries/joomla/database/iterator.php
  119. +21 −0 libraries/joomla/database/iterator/azure.php
  120. +58 −0 libraries/joomla/database/iterator/mysql.php
  121. +57 −0 libraries/joomla/database/iterator/mysqli.php
  122. +21 −0 libraries/joomla/database/iterator/oracle.php
  123. +74 −0 libraries/joomla/database/iterator/pdo.php
  124. +21 −0 libraries/joomla/database/iterator/sqlite.php
  125. +57 −0 libraries/joomla/database/iterator/sqlsrv.php
  126. +1,568 −0 libraries/joomla/database/query.php
  127. +56 −0 libraries/joomla/database/query/limitable.php
  128. +21 −0 libraries/joomla/database/query/mysql.php
  129. +106 −0 libraries/joomla/database/query/mysqli.php
  130. +203 −0 libraries/joomla/database/query/oracle.php
  131. +21 −0 libraries/joomla/database/query/pdo.php
  132. +600 −0 libraries/joomla/database/query/postgresql.php
  133. +53 −0 libraries/joomla/database/query/preparable.php
  134. +32 −0 libraries/joomla/database/query/sqlazure.php
  135. +182 −0 libraries/joomla/database/query/sqlite.php
  136. +178 −0 libraries/joomla/database/query/sqlsrv.php
  137. +462 −0 libraries/joomla/date/date.php
  138. +964 −0 libraries/joomla/document/document.php
  139. +196 −0 libraries/joomla/document/error/error.php
  140. +497 −0 libraries/joomla/document/feed/feed.php
  141. +176 −0 libraries/joomla/document/feed/renderer/atom.php
  142. +251 −0 libraries/joomla/document/feed/renderer/rss.php
  143. +687 −0 libraries/joomla/document/html/html.php
  144. +36 −0 libraries/joomla/document/html/renderer/component.php
  145. +221 −0 libraries/joomla/document/html/renderer/head.php
  146. +125 −0 libraries/joomla/document/html/renderer/message.php
  147. +112 −0 libraries/joomla/document/html/renderer/module.php
  148. +43 −0 libraries/joomla/document/html/renderer/modules.php
  149. +74 −0 libraries/joomla/document/image/image.php
  150. +95 −0 libraries/joomla/document/json/json.php
  151. +303 −0 libraries/joomla/document/opensearch/opensearch.php
  152. +54 −0 libraries/joomla/document/raw/raw.php
  153. +75 −0 libraries/joomla/document/renderer.php
  154. +92 −0 libraries/joomla/document/xml/xml.php
  155. +663 −0 libraries/joomla/environment/browser.php
  156. +334 −0 libraries/joomla/environment/response.php
  157. +278 −0 libraries/joomla/event/dispatcher.php
  158. +78 −0 libraries/joomla/event/event.php
  159. +766 −0 libraries/joomla/factory.php
  160. +540 −0 libraries/joomla/filesystem/file.php
  161. +662 −0 libraries/joomla/filesystem/folder.php
  162. +300 −0 libraries/joomla/filesystem/helper.php
  163. +13 −0 libraries/joomla/filesystem/meta/language/en-GB/en-GB.lib_joomla_filesystem_patcher.ini
  164. +522 −0 libraries/joomla/filesystem/patcher.php
  165. +303 −0 libraries/joomla/filesystem/path.php
  166. +1,423 −0 libraries/joomla/filesystem/stream.php
  167. +298 −0 libraries/joomla/filesystem/streams/string.php
  168. +71 −0 libraries/joomla/filesystem/support/stringcontroller.php
Sorry, we could not display the entire diff because too many files (539) changed.
38 Step1/application/web.php
@@ -0,0 +1,38 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct();
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ $this->setBody('Hello World!');
+ }
+}
27 Step1/index.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Constant that is checked in included files to prevent direct access.
+ */
+const _JEXEC = 1;
+
+// Define the paths we need
+const JPATH_BASE = __DIR__;
+const JPATH_ROOT = __DIR__;
+define('JPATH_LIBRARIES', dirname(JPATH_ROOT) . '/libraries');
+
+// Set up the environment
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+const JDEBUG = false;
+
+// Import the Joomla Platform.
+require_once JPATH_LIBRARIES . '/import.php';
+
+// Register the prefix for our classes
+JLoader::registerPrefix('G', JPATH_BASE);
+
+// Get the application
+$app = JApplicationWeb::getInstance('GApplicationWeb');
+
+// Execute the application
+$app->execute();
111 Step10/application/web.php
@@ -0,0 +1,111 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct($input, $config, $client);
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+
+ $this->setUpDB();
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ $this->loadDocument();
+ $document = $this->getDocument();
+
+ // Register the template to the config
+ $this->set('theme', 'template');
+ $this->set('themeParams', new JRegistry);
+
+ // Inject the document object into the factory
+ JFactory::$document = $document;
+
+ switch ($document->getType())
+ {
+ case 'html' :
+ // Set metadata
+ $document->setTitle('Joomla! Guestbook');
+ break;
+ default :
+ break;
+ }
+
+ // Execute the task.
+ try
+ {
+ $controller = $this->fetchController($this->input->getCmd('task', 'display'));
+ $contents = $controller->execute();
+ }
+ catch (RuntimeException $e)
+ {
+ echo $e->getMessage();
+ $this->close($e->getCode());
+ }
+
+ $document->setBuffer($contents, 'component');
+ }
+
+ private function setUpDb()
+ {
+ $dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => '/Users/rouven/Sites/jd12dk/guestbook.sqlite'));
+ $dbo->setQuery('CREATE TABLE IF NOT EXISTS Comments (Id INTEGER PRIMARY KEY, Name TEXT, Email TEXT, Comment Text, Ip INTEGER, date TEXT)');
+ $dbo->execute();
+
+ // Inject database into JFactory
+ JFactory::$database = $dbo;
+ }
+
+ /**
+ * Method to get a controller object.
+ *
+ * @param string $task The task being executed
+ *
+ * @return JController
+ *
+ * @throws RuntimeException
+ */
+ protected function fetchController($task)
+ {
+ if (is_null($task))
+ {
+ $task = 'default';
+ }
+
+ // Set the controller class name based on the task
+ $class = 'GController' . ucfirst($task);
+
+ // If the requested controller exists let's use it.
+ if (class_exists($class))
+ {
+ return new $class;
+ }
+
+ // Nothing found. Panic.
+ throw new RuntimeException('Class ' . $class . ' not found');
+ }
+}
30 Step10/controller/add.php
@@ -0,0 +1,30 @@
+<?php
+
+defined('_JEXEC') or die;
+
+class GControllerAdd extends JControllerBase
+{
+ /**
+ * Execute the controller.
+ *
+ * @return string The rendered view.
+ */
+ public function execute()
+ {
+ $app = JFactory::getApplication();
+
+ $name = $this->input->post->getString('name');
+ $email = $this->input->post->getString('email');
+ $comment = $this->input->post->getString('comment');
+
+ if (!empty($name) && !empty($email) && !empty($comment))
+ {
+ $ip = $this->input->server->getString('REMOTE_ADDR');
+
+ $model = new GModelComments;
+ $model->add($name, $email, $comment, $ip, new JDate );
+ }
+
+ $app->redirect('index.php');
+ }
+}
37 Step10/controller/display.php
@@ -0,0 +1,37 @@
+<?php
+
+defined('_JEXEC') or die;
+
+class GControllerDisplay extends JControllerBase
+{
+ /**
+ * Execute the controller.
+ *
+ * @return string The rendered view.
+ */
+ public function execute()
+ {
+ $app = $this->getApplication();
+ $doc = $app->getDocument();
+
+ $vName = $app->input->getWord('view', 'comments');
+ $vFormat = $doc->getType();
+ $lName = $app->input->getWord('layout', 'default');
+
+ if (strcmp($vName, 'comments') == 0)
+ {
+ $app->input->set('view', 'comments');
+ }
+
+ // Register the layout paths
+ $paths = new SplPriorityQueue;
+ $paths->insert(JPATH_BASE . '/view/' . $vName . '/tmpl', 'normal');
+
+ $vClass = 'GView' . ucfirst($vName) . ucfirst($vFormat);
+ $view = new $vClass(new GModelComments, $paths);
+ $view->setLayout($lName);
+
+ // Render our view and return it to the application.
+ return $view->render();
+ }
+}
28 Step10/index.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Constant that is checked in included files to prevent direct access.
+ */
+const _JEXEC = 1;
+
+// Define the paths we need
+const JPATH_BASE = __DIR__;
+const JPATH_ROOT = __DIR__;
+define('JPATH_THEMES', JPATH_BASE . '/templates');
+define('JPATH_LIBRARIES', dirname(JPATH_ROOT) . '/libraries');
+
+// Set up the environment
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+const JDEBUG = false;
+
+// Import the Joomla Platform.
+require_once JPATH_LIBRARIES . '/import.php';
+
+// Register the prefix for our classes
+JLoader::registerPrefix('G', JPATH_BASE);
+
+// Get the application
+$app = JApplicationWeb::getInstance('GApplicationWeb');
+
+// Execute the application
+$app->execute();
25 Step10/model/comments.php
@@ -0,0 +1,25 @@
+<?php
+
+class GModelComments extends JModelDatabase
+{
+ public function getAll()
+ {
+ $db = $this->getDb();
+ $query = $db->getQuery(true);
+ $query->select('*')
+ ->from('Comments')
+ ->order('Id DESC');
+ $db->setQuery($query);
+
+ return $db->loadAssocList();
+ }
+
+ public function add($name, $email, $comment, $ip, JDate $date)
+ {
+ $db = JFactory::getDbo();
+ $query = 'INSERT INTO Comments (Name, Email, Comment, Ip, date)
+ VALUES (' . $db->quote($name) . ', ' . $db->quote($email) . ', ' . $db->quote($comment) . ', ' . $db->quote(ip2long($ip)) . ', ' . $db->quote($date->toISO8601()) . ');';
+ $db->setQuery($query);
+ return $db->execute();
+ }
+}
17 Step10/templates/template/index.php
@@ -0,0 +1,17 @@
+<?php
+defined('_JEXEC') or die;
+
+$doc = JFactory::getDocument();
+$doc->addStyleSheet('../bootstrap.css');
+?>
+
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->language; ?>" lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
+ <head>
+ <jdoc:include type="head" />
+ </head>
+ <body>
+ <h1>Guestbook</h1>
+ <jdoc:include type="component" />
+ </body>
+</html>
34 Step10/view/comments/html.php
@@ -0,0 +1,34 @@
+<?php
+
+defined('_JEXEC') or die;
+
+class GViewCommentsHtml extends JViewHtml
+{
+ public $comments = array();
+
+ public function __construct(GModelComments $model, SplPriorityQueue $paths = null)
+ {
+ parent::__construct($model, $paths);
+ }
+
+ /**
+ * Method to render the view.
+ *
+ * @return string The rendered view.
+ *
+ * @throws RuntimeException
+ */
+ public function render()
+ {
+ $comments = $this->model->getAll();
+ foreach ($comments as $key => $comment)
+ {
+ $date = new JDate($comment['date']);
+ $comments[$key]['date'] = $date->format('d.m.Y', true);
+ }
+
+ $this->comments = $comments;
+
+ return parent::render();
+ }
+}
24 Step10/view/comments/tmpl/default.php
@@ -0,0 +1,24 @@
+<?php
+defined('_JEXEC') or die;
+
+?>
+<form action="index.php" enctype="application/x-www-form-urlencoded" method="post">
+ <fieldset>
+ <input id="name" autofocus="autofocus" type="text" name="name" placeholder="Name" size="40" required="required" /><br />
+ <input id="email" type="email" name="email" placeholder="E-Mail" size="40" required="required" /><br />
+ <textarea id="comment" name="comment" placeholder="Your Comment" rows="10" cols="40" required="required"></textarea><br />
+ <input type="hidden" name="task" value="add" />
+ <input type="submit" vale="Send" />
+ </fieldset>
+</form>
+<section>
+ <h2>Comments</h2>
+ <?php
+ foreach ($this->comments as $comment)
+ {
+ echo '<article><h3><a href="mailto:' . htmlspecialchars($comment['Email']) . '">' . htmlspecialchars($comment['Name']) . '</a> wrote:</h3>
+ <p>' . htmlspecialchars($comment['Comment']) . '</p>
+ <small>' . htmlspecialchars($comment['date']) . ', ' . htmlspecialchars(long2ip($comment['Ip'])) . '</small></article>';
+ }
+ ?>
+</section>
59 Step2/application/web.php
@@ -0,0 +1,59 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct($input, $config, $client);
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ $this->setBody('
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <title>Joomla! Guestbok!</title>
+ </head>
+ <body>
+ <h1>Guestbook</h1>
+ <form action="index.php" enctype="application/x-www-form-urlencoded" method="post">
+ <fieldset>
+ <input id="name" autofocus="autofocus" type="text" name="name" placeholder="Name" size="40" required="required" /><br />
+ <input id="email" type="email" name="email" placeholder="E-Mail" size="40" required="required" /><br />
+ <textarea id="comment" name="comment" placeholder="Your Comment" rows="15" cols="40" required="required"></textarea><br />
+ <input type="submit" vale="Send" />
+ </fieldset>
+ </form>
+ <section>
+ <h2>Comments</h2>
+ </section>
+ </body>
+ </html>
+ ');
+ }
+}
27 Step2/index.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Constant that is checked in included files to prevent direct access.
+ */
+const _JEXEC = 1;
+
+// Define the paths we need
+const JPATH_BASE = __DIR__;
+const JPATH_ROOT = __DIR__;
+define('JPATH_LIBRARIES', dirname(JPATH_ROOT) . '/libraries');
+
+// Set up the environment
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+const JDEBUG = false;
+
+// Import the Joomla Platform.
+require_once JPATH_LIBRARIES . '/import.php';
+
+// Register the prefix for our classes
+JLoader::registerPrefix('G', JPATH_BASE);
+
+// Get the application
+$app = JApplicationWeb::getInstance('GApplicationWeb');
+
+// Execute the application
+$app->execute();
105 Step3/application/web.php
@@ -0,0 +1,105 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct($input, $config, $client);
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ $this->setUpDB();
+
+ $name = $this->input->post->getString('name');
+ $email = $this->input->post->getString('email');
+ $comment = $this->input->post->getString('comment');
+
+ if (!empty($name) && !empty($email) && !empty($comment))
+ {
+ $db = JFactory::getDbo();
+ $query = 'INSERT INTO Comments (Name, Email, Comment)
+ VALUES (' . $db->quote($name) . ', ' . $db->quote($email) . ', ' . $db->quote($comment) . ');';
+ $db->setQuery($query);
+
+ $db->execute();
+ }
+
+ $this->display();
+ }
+
+ private function setUpDb()
+ {
+ $dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => '/Users/rouven/Sites/jd12dk/guestbook.sqlite'));
+ $dbo->setQuery('CREATE TABLE IF NOT EXISTS Comments (Id INTEGER PRIMARY KEY, Name TEXT, Email TEXT, Comment Text, Ip INTEGER, date TEXT)');
+ $dbo->execute();
+
+ // Inject database into JFactory
+ JFactory::$database = $dbo;
+ }
+
+ private function display()
+ {
+ $db = JFactory::getDbo();
+ $query = $db->getQuery(true);
+ $query->select('*')
+ ->from('Comments');
+ $db->setQuery($query);
+ $comments = $db->loadAssocList();
+
+ $commentMarkup = '';
+ foreach ($comments as $comment)
+ {
+ $commentMarkup .= '<article><h3>' . $comment['Name'] . ' wrote:</h3>
+ <p>' . $comment['Comment'] . '</p></article>';
+ }
+
+ $this->setBody('
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <title>Joomla! Guestbok!</title>
+ </head>
+ <body>
+ <h1>Guestbook</h1>
+ <form action="index.php" enctype="application/x-www-form-urlencoded" method="post">
+ <fieldset>
+ <input id="name" autofocus="autofocus" type="text" name="name" placeholder="Name" size="40" required="required" /><br />
+ <input id="email" type="email" name="email" placeholder="E-Mail" size="40" required="required" /><br />
+ <textarea id="comment" name="comment" placeholder="Your Comment" rows="15" cols="40" required="required"></textarea><br />
+ <input type="submit" vale="Send" />
+ </fieldset>
+ </form>
+ <section>
+ <h2>Comments</h2>
+ ' . $commentMarkup . '
+ </section>
+ </body>
+ </html>
+ ');
+ }
+}
27 Step3/index.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Constant that is checked in included files to prevent direct access.
+ */
+const _JEXEC = 1;
+
+// Define the paths we need
+const JPATH_BASE = __DIR__;
+const JPATH_ROOT = __DIR__;
+define('JPATH_LIBRARIES', dirname(JPATH_ROOT) . '/libraries');
+
+// Set up the environment
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+const JDEBUG = false;
+
+// Import the Joomla Platform.
+require_once JPATH_LIBRARIES . '/import.php';
+
+// Register the prefix for our classes
+JLoader::registerPrefix('G', JPATH_BASE);
+
+// Get the application
+$app = JApplicationWeb::getInstance('GApplicationWeb');
+
+// Execute the application
+$app->execute();
111 Step4/application/web.php
@@ -0,0 +1,111 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct($input, $config, $client);
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ $this->setUpDB();
+
+ $name = $this->input->post->getString('name');
+ $email = $this->input->post->getString('email');
+ $comment = $this->input->post->getString('comment');
+
+ if (!empty($name) && !empty($email) && !empty($comment))
+ {
+ $ip = $this->input->server->getString('REMOTE_ADDR');
+ $date = new JDate;
+ $db = JFactory::getDbo();
+ $query = 'INSERT INTO Comments (Name, Email, Comment, Ip, date)
+ VALUES (' . $db->quote($name) . ', ' . $db->quote($email) . ', ' . $db->quote($comment) . ', ' . $db->quote(ip2long($ip)) . ', ' . $db->quote($date->toISO8601()) . ');';
+ $db->setQuery($query);
+
+ $db->execute();
+ }
+
+ $this->display();
+ }
+
+ private function setUpDb()
+ {
+ $dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => '/Users/rouven/Sites/jd12dk/guestbook.sqlite'));
+ $dbo->setQuery('CREATE TABLE IF NOT EXISTS Comments (Id INTEGER PRIMARY KEY, Name TEXT, Email TEXT, Comment Text, Ip INTEGER, date TEXT)');
+ $dbo->execute();
+
+ // Inject database into JFactory
+ JFactory::$database = $dbo;
+ }
+
+ private function display()
+ {
+ $db = JFactory::getDbo();
+ $query = $db->getQuery(true);
+ $query->select('*')
+ ->from('Comments');
+ $db->setQuery($query);
+ $comments = $db->loadAssocList();
+
+ $commentMarkup = '';
+ foreach ($comments as $comment)
+ {
+ $date = new JDate($comment['date']);
+ $commentMarkup .= '<article><h3><a href="mailto:' . htmlspecialchars($comment['Email']) . '">' . htmlspecialchars($comment['Name']) . '</a> wrote:</h3>
+ <p>' . htmlspecialchars($comment['Comment']) . '</p>
+ <small>' . $date->format('d.m.Y', true) . ', ' . htmlspecialchars(long2ip($comment['Ip'])) . '</small></article>';
+ }
+
+ $this->setBody('
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>Joomla! Guestbok!</title>
+ <link rel="stylesheet" href="../bootstrap.css" />
+ </head>
+ <body>
+ <h1>Guestbook</h1>
+ <form action="index.php" enctype="application/x-www-form-urlencoded" method="post">
+ <fieldset>
+ <input id="name" autofocus="autofocus" type="text" name="name" placeholder="Name" size="40" required="required" /><br />
+ <input id="email" type="email" name="email" placeholder="E-Mail" size="40" required="required" /><br />
+ <textarea id="comment" name="comment" placeholder="Your Comment" rows="10" cols="40" required="required"></textarea><br />
+ <input type="submit" vale="Send" />
+ </fieldset>
+ </form>
+ <section>
+ <h2>Comments</h2>
+ ' . $commentMarkup . '
+ </section>
+ </body>
+ </html>
+ ');
+ }
+}
27 Step4/index.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Constant that is checked in included files to prevent direct access.
+ */
+const _JEXEC = 1;
+
+// Define the paths we need
+const JPATH_BASE = __DIR__;
+const JPATH_ROOT = __DIR__;
+define('JPATH_LIBRARIES', dirname(JPATH_ROOT) . '/libraries');
+
+// Set up the environment
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+const JDEBUG = false;
+
+// Import the Joomla Platform.
+require_once JPATH_LIBRARIES . '/import.php';
+
+// Register the prefix for our classes
+JLoader::registerPrefix('G', JPATH_BASE);
+
+// Get the application
+$app = JApplicationWeb::getInstance('GApplicationWeb');
+
+// Execute the application
+$app->execute();
125 Step5/application/web.php
@@ -0,0 +1,125 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct($input, $config, $client);
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+
+ $this->setUpDB();
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ $task = $this->input->post->getCmd('task', 'display');
+
+ if ($task === 'add')
+ {
+ $this->add();
+ }
+ elseif ($task === 'display')
+ {
+ $this->display();
+ }
+ }
+
+ private function setUpDb()
+ {
+ $dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => '/Users/rouven/Sites/jd12dk/guestbook.sqlite'));
+ $dbo->setQuery('CREATE TABLE IF NOT EXISTS Comments (Id INTEGER PRIMARY KEY, Name TEXT, Email TEXT, Comment Text, Ip INTEGER, date TEXT)');
+ $dbo->execute();
+
+ // Inject database into JFactory
+ JFactory::$database = $dbo;
+ }
+
+ private function add()
+ {
+ $name = $this->input->post->getString('name');
+ $email = $this->input->post->getString('email');
+ $comment = $this->input->post->getString('comment');
+
+ if (!empty($name) && !empty($email) && !empty($comment))
+ {
+ $ip = $this->input->server->getString('REMOTE_ADDR');
+ $date = new JDate;
+ $db = JFactory::getDbo();
+ $query = 'INSERT INTO Comments (Name, Email, Comment, Ip, date)
+ VALUES (' . $db->quote($name) . ', ' . $db->quote($email) . ', ' . $db->quote($comment) . ', ' . $db->quote(ip2long($ip)) . ', ' . $db->quote($date->toISO8601()) . ');';
+ $db->setQuery($query);
+ $db->execute();
+ }
+
+ $this->redirect('index.php');
+ }
+
+ private function display()
+ {
+ $db = JFactory::getDbo();
+ $query = $db->getQuery(true);
+ $query->select('*')
+ ->from('Comments');
+ $db->setQuery($query);
+ $comments = $db->loadAssocList();
+
+ $commentMarkup = '';
+ foreach ($comments as $comment)
+ {
+ $date = new JDate($comment['date']);
+ $commentMarkup .= '<article><h3><a href="mailto:' . htmlspecialchars($comment['Email']) . '">' . htmlspecialchars($comment['Name']) . '</a> wrote:</h3>
+ <p>' . htmlspecialchars($comment['Comment']) . '</p>
+ <small>' . $date->format('d.m.Y', true) . ', ' . htmlspecialchars(long2ip($comment['Ip'])) . '</small></article>';
+ }
+
+ $this->setBody('
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>Joomla! Guestbok!</title>
+ <link rel="stylesheet" href="../bootstrap.css" />
+ </head>
+ <body>
+ <h1>Guestbook</h1>
+ <form action="index.php" enctype="application/x-www-form-urlencoded" method="post">
+ <fieldset>
+ <input id="name" autofocus="autofocus" type="text" name="name" placeholder="Name" size="40" required="required" /><br />
+ <input id="email" type="email" name="email" placeholder="E-Mail" size="40" required="required" /><br />
+ <textarea id="comment" name="comment" placeholder="Your Comment" rows="10" cols="40" required="required"></textarea><br />
+ <input type="hidden" name="task" value="add" />
+ <input type="submit" vale="Send" />
+ </fieldset>
+ </form>
+ <section>
+ <h2>Comments</h2>
+ ' . $commentMarkup . '
+ </section>
+ </body>
+ </html>
+ ');
+ }
+}
27 Step5/index.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Constant that is checked in included files to prevent direct access.
+ */
+const _JEXEC = 1;
+
+// Define the paths we need
+const JPATH_BASE = __DIR__;
+const JPATH_ROOT = __DIR__;
+define('JPATH_LIBRARIES', dirname(JPATH_ROOT) . '/libraries');
+
+// Set up the environment
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+const JDEBUG = false;
+
+// Import the Joomla Platform.
+require_once JPATH_LIBRARIES . '/import.php';
+
+// Register the prefix for our classes
+JLoader::registerPrefix('G', JPATH_BASE);
+
+// Get the application
+$app = JApplicationWeb::getInstance('GApplicationWeb');
+
+// Execute the application
+$app->execute();
91 Step6/application/web.php
@@ -0,0 +1,91 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct($input, $config, $client);
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+
+ $this->setUpDB();
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ // Execute the task.
+ try
+ {
+ $controller = $this->fetchController($this->input->getCmd('task', 'display'));
+ $contents = $controller->execute();
+ }
+ catch (RuntimeException $e)
+ {
+ echo $e->getMessage();
+ $this->close($e->getCode());
+ }
+
+ $this->setBody($contents);
+ }
+
+ private function setUpDb()
+ {
+ $dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => '/Users/rouven/Sites/jd12dk/guestbook.sqlite'));
+ $dbo->setQuery('CREATE TABLE IF NOT EXISTS Comments (Id INTEGER PRIMARY KEY, Name TEXT, Email TEXT, Comment Text, Ip INTEGER, date TEXT)');
+ $dbo->execute();
+
+ // Inject database into JFactory
+ JFactory::$database = $dbo;
+ }
+
+ /**
+ * Method to get a controller object.
+ *
+ * @param string $task The task being executed
+ *
+ * @return JController
+ *
+ * @throws RuntimeException
+ */
+ protected function fetchController($task)
+ {
+ if (is_null($task))
+ {
+ $task = 'default';
+ }
+
+ // Set the controller class name based on the task
+ $class = 'GController' . ucfirst($task);
+
+ // If the requested controller exists let's use it.
+ if (class_exists($class))
+ {
+ return new $class;
+ }
+
+ // Nothing found. Panic.
+ throw new RuntimeException('Class ' . $class . ' not found');
+ }
+}
33 Step6/controller/add.php
@@ -0,0 +1,33 @@
+<?php
+
+defined('_JEXEC') or die;
+
+class GControllerAdd extends JControllerBase
+{
+ /**
+ * Execute the controller.
+ *
+ * @return string The rendered view.
+ */
+ public function execute()
+ {
+ $app = JFactory::getApplication();
+
+ $name = $this->input->post->getString('name');
+ $email = $this->input->post->getString('email');
+ $comment = $this->input->post->getString('comment');
+
+ if (!empty($name) && !empty($email) && !empty($comment))
+ {
+ $ip = $this->input->server->getString('REMOTE_ADDR');
+ $date = new JDate;
+ $db = JFactory::getDbo();
+ $query = 'INSERT INTO Comments (Name, Email, Comment, Ip, date)
+ VALUES (' . $db->quote($name) . ', ' . $db->quote($email) . ', ' . $db->quote($comment) . ', ' . $db->quote(ip2long($ip)) . ', ' . $db->quote($date->toISO8601()) . ');';
+ $db->setQuery($query);
+ $db->execute();
+ }
+
+ $app->redirect('index.php');
+ }
+}
57 Step6/controller/display.php
@@ -0,0 +1,57 @@
+<?php
+
+defined('_JEXEC') or die;
+
+class GControllerDisplay extends JControllerBase
+{
+ /**
+ * Execute the controller.
+ *
+ * @return string The rendered view.
+ */
+ public function execute()
+ {
+ $db = JFactory::getDbo();
+ $query = $db->getQuery(true);
+ $query->select('*')
+ ->from('Comments');
+ $db->setQuery($query);
+ $comments = $db->loadAssocList();
+
+ $commentMarkup = '';
+ foreach ($comments as $comment)
+ {
+ $date = new JDate($comment['date']);
+ $commentMarkup .= '<article><h3><a href="mailto:' . htmlspecialchars($comment['Email']) . '">' . htmlspecialchars($comment['Name']) . '</a> wrote:</h3>
+ <p>' . htmlspecialchars($comment['Comment']) . '</p>
+ <small>' . $date->format('d.m.Y', true) . ', ' . htmlspecialchars(long2ip($comment['Ip'])) . '</small></article>';
+ }
+
+ return '
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>Joomla! Guestbok!</title>
+ <link rel="stylesheet" href="../bootstrap.css" />
+ </head>
+ <body>
+ <h1>Guestbook</h1>
+ <form action="index.php" enctype="application/x-www-form-urlencoded" method="post">
+ <fieldset>
+ <input id="name" autofocus="autofocus" type="text" name="name" placeholder="Name" size="40" required="required" /><br />
+ <input id="email" type="email" name="email" placeholder="E-Mail" size="40" required="required" /><br />
+ <textarea id="comment" name="comment" placeholder="Your Comment" rows="10" cols="40" required="required"></textarea><br />
+ <input type="hidden" name="task" value="add" />
+ <input type="submit" vale="Send" />
+ </fieldset>
+ </form>
+ <section>
+ <h2>Comments</h2>
+ ' . $commentMarkup . '
+ </section>
+ </body>
+ </html>
+ ';
+ }
+}
27 Step6/index.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Constant that is checked in included files to prevent direct access.
+ */
+const _JEXEC = 1;
+
+// Define the paths we need
+const JPATH_BASE = __DIR__;
+const JPATH_ROOT = __DIR__;
+define('JPATH_LIBRARIES', dirname(JPATH_ROOT) . '/libraries');
+
+// Set up the environment
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+const JDEBUG = false;
+
+// Import the Joomla Platform.
+require_once JPATH_LIBRARIES . '/import.php';
+
+// Register the prefix for our classes
+JLoader::registerPrefix('G', JPATH_BASE);
+
+// Get the application
+$app = JApplicationWeb::getInstance('GApplicationWeb');
+
+// Execute the application
+$app->execute();
111 Step7/application/web.php
@@ -0,0 +1,111 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct($input, $config, $client);
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+
+ $this->setUpDB();
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ $this->loadDocument();
+ $document = $this->getDocument();
+
+ // Register the template to the config
+ $this->set('theme', 'template');
+ $this->set('themeParams', new JRegistry);
+
+ // Inject the document object into the factory
+ JFactory::$document = $document;
+
+ switch ($document->getType())
+ {
+ case 'html' :
+ // Set metadata
+ $document->setTitle('Joomla! Guestbook');
+ break;
+ default :
+ break;
+ }
+
+ // Execute the task.
+ try
+ {
+ $controller = $this->fetchController($this->input->getCmd('task', 'display'));
+ $contents = $controller->execute();
+ }
+ catch (RuntimeException $e)
+ {
+ echo $e->getMessage();
+ $this->close($e->getCode());
+ }
+
+ $document->setBuffer($contents, 'component');
+ }
+
+ private function setUpDb()
+ {
+ $dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => '/Users/rouven/Sites/jd12dk/guestbook.sqlite'));
+ $dbo->setQuery('CREATE TABLE IF NOT EXISTS Comments (Id INTEGER PRIMARY KEY, Name TEXT, Email TEXT, Comment Text, Ip INTEGER, date TEXT)');
+ $dbo->execute();
+
+ // Inject database into JFactory
+ JFactory::$database = $dbo;
+ }
+
+ /**
+ * Method to get a controller object.
+ *
+ * @param string $task The task being executed
+ *
+ * @return JController
+ *
+ * @throws RuntimeException
+ */
+ protected function fetchController($task)
+ {
+ if (is_null($task))
+ {
+ $task = 'default';
+ }
+
+ // Set the controller class name based on the task
+ $class = 'GController' . ucfirst($task);
+
+ // If the requested controller exists let's use it.
+ if (class_exists($class))
+ {
+ return new $class;
+ }
+
+ // Nothing found. Panic.
+ throw new RuntimeException('Class ' . $class . ' not found');
+ }
+}
33 Step7/controller/add.php
@@ -0,0 +1,33 @@
+<?php
+
+defined('_JEXEC') or die;
+
+class GControllerAdd extends JControllerBase
+{
+ /**
+ * Execute the controller.
+ *
+ * @return string The rendered view.
+ */
+ public function execute()
+ {
+ $app = JFactory::getApplication();
+
+ $name = $this->input->post->getString('name');
+ $email = $this->input->post->getString('email');
+ $comment = $this->input->post->getString('comment');
+
+ if (!empty($name) && !empty($email) && !empty($comment))
+ {
+ $ip = $this->input->server->getString('REMOTE_ADDR');
+ $date = new JDate;
+ $db = JFactory::getDbo();
+ $query = 'INSERT INTO Comments (Name, Email, Comment, Ip, date)
+ VALUES (' . $db->quote($name) . ', ' . $db->quote($email) . ', ' . $db->quote($comment) . ', ' . $db->quote(ip2long($ip)) . ', ' . $db->quote($date->toISO8601()) . ');';
+ $db->setQuery($query);
+ $db->execute();
+ }
+
+ $app->redirect('index.php');
+ }
+}
46 Step7/controller/display.php
@@ -0,0 +1,46 @@
+<?php
+
+defined('_JEXEC') or die;
+
+class GControllerDisplay extends JControllerBase
+{
+ /**
+ * Execute the controller.
+ *
+ * @return string The rendered view.
+ */
+ public function execute()
+ {
+ $db = JFactory::getDbo();
+ $query = $db->getQuery(true);
+ $query->select('*')
+ ->from('Comments');
+ $db->setQuery($query);
+ $comments = $db->loadAssocList();
+
+ $commentMarkup = '';
+ foreach ($comments as $comment)
+ {
+ $date = new JDate($comment['date']);
+ $commentMarkup .= '<article><h3><a href="mailto:' . htmlspecialchars($comment['Email']) . '">' . htmlspecialchars($comment['Name']) . '</a> wrote:</h3>
+ <p>' . htmlspecialchars($comment['Comment']) . '</p>
+ <small>' . $date->format('d.m.Y', true) . ', ' . htmlspecialchars(long2ip($comment['Ip'])) . '</small></article>';
+ }
+
+ return '
+ <form action="index.php" enctype="application/x-www-form-urlencoded" method="post">
+ <fieldset>
+ <input id="name" autofocus="autofocus" type="text" name="name" placeholder="Name" size="40" required="required" /><br />
+ <input id="email" type="email" name="email" placeholder="E-Mail" size="40" required="required" /><br />
+ <textarea id="comment" name="comment" placeholder="Your Comment" rows="10" cols="40" required="required"></textarea><br />
+ <input type="hidden" name="task" value="add" />
+ <input type="submit" vale="Send" />
+ </fieldset>
+ </form>
+ <section>
+ <h2>Comments</h2>
+ ' . $commentMarkup . '
+ </section>
+ ';
+ }
+}
28 Step7/index.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Constant that is checked in included files to prevent direct access.
+ */
+const _JEXEC = 1;
+
+// Define the paths we need
+const JPATH_BASE = __DIR__;
+const JPATH_ROOT = __DIR__;
+define('JPATH_THEMES', JPATH_BASE . '/templates');
+define('JPATH_LIBRARIES', dirname(JPATH_ROOT) . '/libraries');
+
+// Set up the environment
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+const JDEBUG = false;
+
+// Import the Joomla Platform.
+require_once JPATH_LIBRARIES . '/import.php';
+
+// Register the prefix for our classes
+JLoader::registerPrefix('G', JPATH_BASE);
+
+// Get the application
+$app = JApplicationWeb::getInstance('GApplicationWeb');
+
+// Execute the application
+$app->execute();
17 Step7/templates/template/index.php
@@ -0,0 +1,17 @@
+<?php
+defined('_JEXEC') or die;
+
+$doc = JFactory::getDocument();
+$doc->addStyleSheet('../bootstrap.css');
+?>
+
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->language; ?>" lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
+ <head>
+ <jdoc:include type="head" />
+ </head>
+ <body>
+ <h1>Guestbook</h1>
+ <jdoc:include type="component" />
+ </body>
+</html>
111 Step8/application/web.php
@@ -0,0 +1,111 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct($input, $config, $client);
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+
+ $this->setUpDB();
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ $this->loadDocument();
+ $document = $this->getDocument();
+
+ // Register the template to the config
+ $this->set('theme', 'template');
+ $this->set('themeParams', new JRegistry);
+
+ // Inject the document object into the factory
+ JFactory::$document = $document;
+
+ switch ($document->getType())
+ {
+ case 'html' :
+ // Set metadata
+ $document->setTitle('Joomla! Guestbook');
+ break;
+ default :
+ break;
+ }
+
+ // Execute the task.
+ try
+ {
+ $controller = $this->fetchController($this->input->getCmd('task', 'display'));
+ $contents = $controller->execute();
+ }
+ catch (RuntimeException $e)
+ {
+ echo $e->getMessage();
+ $this->close($e->getCode());
+ }
+
+ $document->setBuffer($contents, 'component');
+ }
+
+ private function setUpDb()
+ {
+ $dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => '/Users/rouven/Sites/jd12dk/guestbook.sqlite'));
+ $dbo->setQuery('CREATE TABLE IF NOT EXISTS Comments (Id INTEGER PRIMARY KEY, Name TEXT, Email TEXT, Comment Text, Ip INTEGER, date TEXT)');
+ $dbo->execute();
+
+ // Inject database into JFactory
+ JFactory::$database = $dbo;
+ }
+
+ /**
+ * Method to get a controller object.
+ *
+ * @param string $task The task being executed
+ *
+ * @return JController
+ *
+ * @throws RuntimeException
+ */
+ protected function fetchController($task)
+ {
+ if (is_null($task))
+ {
+ $task = 'default';
+ }
+
+ // Set the controller class name based on the task
+ $class = 'GController' . ucfirst($task);
+
+ // If the requested controller exists let's use it.
+ if (class_exists($class))
+ {
+ return new $class;
+ }
+
+ // Nothing found. Panic.
+ throw new RuntimeException('Class ' . $class . ' not found');
+ }
+}
30 Step8/controller/add.php
@@ -0,0 +1,30 @@
+<?php
+
+defined('_JEXEC') or die;
+
+class GControllerAdd extends JControllerBase
+{
+ /**
+ * Execute the controller.
+ *
+ * @return string The rendered view.
+ */
+ public function execute()
+ {
+ $app = JFactory::getApplication();
+
+ $name = $this->input->post->getString('name');
+ $email = $this->input->post->getString('email');
+ $comment = $this->input->post->getString('comment');
+
+ if (!empty($name) && !empty($email) && !empty($comment))
+ {
+ $ip = $this->input->server->getString('REMOTE_ADDR');
+
+ $model = new GModelComments;
+ $model->add($name, $email, $comment, $ip, new JDate );
+ }
+
+ $app->redirect('index.php');
+ }
+}
42 Step8/controller/display.php
@@ -0,0 +1,42 @@
+<?php
+
+defined('_JEXEC') or die;
+
+class GControllerDisplay extends JControllerBase
+{
+ /**
+ * Execute the controller.
+ *
+ * @return string The rendered view.
+ */
+ public function execute()
+ {
+ $model = new GModelComments;
+ $comments = $model->getAll();
+
+ $commentMarkup = '';
+ foreach ($comments as $comment)
+ {
+ $date = new JDate($comment['date']);
+ $commentMarkup .= '<article><h3><a href="mailto:' . htmlspecialchars($comment['Email']) . '">' . htmlspecialchars($comment['Name']) . '</a> wrote:</h3>
+ <p>' . htmlspecialchars($comment['Comment']) . '</p>
+ <small>' . $date->format('d.m.Y', true) . ', ' . htmlspecialchars(long2ip($comment['Ip'])) . '</small></article>';
+ }
+
+ return '
+ <form action="index.php" enctype="application/x-www-form-urlencoded" method="post">
+ <fieldset>
+ <input id="name" autofocus="autofocus" type="text" name="name" placeholder="Name" size="40" required="required" /><br />
+ <input id="email" type="email" name="email" placeholder="E-Mail" size="40" required="required" /><br />
+ <textarea id="comment" name="comment" placeholder="Your Comment" rows="10" cols="40" required="required"></textarea><br />
+ <input type="hidden" name="task" value="add" />
+ <input type="submit" vale="Send" />
+ </fieldset>
+ </form>
+ <section>
+ <h2>Comments</h2>
+ ' . $commentMarkup . '
+ </section>
+ ';
+ }
+}
28 Step8/index.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Constant that is checked in included files to prevent direct access.
+ */
+const _JEXEC = 1;
+
+// Define the paths we need
+const JPATH_BASE = __DIR__;
+const JPATH_ROOT = __DIR__;
+define('JPATH_THEMES', JPATH_BASE . '/templates');
+define('JPATH_LIBRARIES', dirname(JPATH_ROOT) . '/libraries');
+
+// Set up the environment
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+const JDEBUG = false;
+
+// Import the Joomla Platform.
+require_once JPATH_LIBRARIES . '/import.php';
+
+// Register the prefix for our classes
+JLoader::registerPrefix('G', JPATH_BASE);
+
+// Get the application
+$app = JApplicationWeb::getInstance('GApplicationWeb');
+
+// Execute the application
+$app->execute();
24 Step8/model/comments.php
@@ -0,0 +1,24 @@
+<?php
+
+class GModelComments extends JModelDatabase
+{
+ public function getAll()
+ {
+ $db = $this->getDb();
+ $query = $db->getQuery(true);
+ $query->select('*')
+ ->from('Comments');
+ $db->setQuery($query);
+
+ return $db->loadAssocList();
+ }
+
+ public function add($name, $email, $comment, $ip, JDate $date)
+ {
+ $db = JFactory::getDbo();
+ $query = 'INSERT INTO Comments (Name, Email, Comment, Ip, date)
+ VALUES (' . $db->quote($name) . ', ' . $db->quote($email) . ', ' . $db->quote($comment) . ', ' . $db->quote(ip2long($ip)) . ', ' . $db->quote($date->toISO8601()) . ');';
+ $db->setQuery($query);
+ return $db->execute();
+ }
+}
17 Step8/templates/template/index.php
@@ -0,0 +1,17 @@
+<?php
+defined('_JEXEC') or die;
+
+$doc = JFactory::getDocument();
+$doc->addStyleSheet('../bootstrap.css');
+?>
+
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->language; ?>" lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
+ <head>
+ <jdoc:include type="head" />
+ </head>
+ <body>
+ <h1>Guestbook</h1>
+ <jdoc:include type="component" />
+ </body>
+</html>
111 Step9/application/web.php
@@ -0,0 +1,111 @@
+<?php
+defined('_JEXEC') or die;
+
+class GApplicationWeb extends JApplicationWeb
+{
+ /**
+ * Class constructor.
+ *
+ * @param mixed $input An optional argument to provide dependency injection for the application's
+ * input object. If the argument is a JInput object that object will become
+ * the application's input object, otherwise a default input object is created.
+ * @param mixed $config An optional argument to provide dependency injection for the application's
+ * config object. If the argument is a JRegistry object that object will become
+ * the application's config object, otherwise a default config object is created.
+ * @param mixed $client An optional argument to provide dependency injection for the application's
+ * client object. If the argument is a JApplicationWebClient object that object will become
+ * the application's client object, otherwise a default client object is created.
+ */
+ public function __construct(JInput $input = null, JRegistry $config = null, JApplicationWebClient $client = null)
+ {
+ parent::__construct($input, $config, $client);
+
+ $this->config->set('session', false);
+
+ // Inject the application into JFactory
+ JFactory::$application = $this;
+
+ $this->setUpDB();
+ }
+
+ /**
+ * Method to run the Web application routines.
+ *
+ * @return void
+ */
+ protected function doExecute()
+ {
+ $this->loadDocument();
+ $document = $this->getDocument();
+
+ // Register the template to the config
+ $this->set('theme', 'template');
+ $this->set('themeParams', new JRegistry);
+
+ // Inject the document object into the factory
+ JFactory::$document = $document;
+
+ switch ($document->getType())
+ {
+ case 'html' :
+ // Set metadata
+ $document->setTitle('Joomla! Guestbook');
+ break;
+ default :
+ break;
+ }
+
+ // Execute the task.
+ try
+ {
+ $controller = $this->fetchController($this->input->getCmd('task', 'display'));
+ $contents = $controller->execute();
+ }
+ catch (RuntimeException $e)
+ {
+ echo $e->getMessage();
+ $this->close($e->getCode());
+ }
+
+ $document->setBuffer($contents, 'component');
+ }
+
+ private function setUpDb()
+ {
+ $dbo = JDatabaseDriver::getInstance(array('driver' => 'sqlite', 'database' => '/Users/rouven/Sites/jd12dk/guestbook.sqlite'));
+ $dbo->setQuery('CREATE TABLE IF NOT EXISTS Comments (Id INTEGER PRIMARY KEY, Name TEXT, Email TEXT, Comment Text, Ip INTEGER, date TEXT)');
+ $dbo->execute();
+
+ // Inject database into JFactory
+ JFactory::$database = $dbo;
+ }
+
+ /**
+ * Method to get a controller object.
+ *
+ * @param string $task The task being executed
+ *
+ * @return JController
+ *
+ * @throws RuntimeException
+ */
+ protected function fetchController($task)
+ {
+ if (is_null($task))
+ {
+ $task = 'default';
+ }
+
+ // Set the controller class name based on the task
+ $class = 'GController' . ucfirst($task);
+
+ // If the requested controller exists let's use it.
+ if (class_exists($class))
+ {
+ return new $class;
+ }
+