Skip to content
Browse files

Integrated a new method callTool() to Factory and State, which allows…

… you to call system specific functions such as filesystem cleaner or to get an index of files. More tools will be added in the future. The additional JavaScript and PHP loading now targets /scripts/ folder and not /libraries/ folder. Added the option to load external JS and CSS based on sitemap URL. File handler can also use overrides now, if a file is in resources folder. Moved '/resources/autoload.php' to '/resources/scripts/script.php'.
1 parent 2d3b066 commit a1c6713299821676f198f2275f991f334073452f @kristovaher committed
View
2 .version
@@ -1,2 +1,2 @@
-www:3.4.1
+www:3.4.2
system:1.0.0
View
6 config.ini
@@ -26,7 +26,7 @@
; @license GNU Lesser General Public License Version 3
; @tutorial /doc/pages/configuration.htm
; @since 1.0.0
-; @version 3.4.1
+; @version 3.4.2
; HTTP AUTHENTICATION
@@ -87,6 +87,8 @@
; database-name=""
; database-username=""
; database-password=""
+ ; database-persistent=0
+ ; database-errors=1
; These are database credentials for the Test Suite that is run by the test script and tests stored
; at /tools/ subfolder. It is recommended that the test database is identical in structure to
@@ -96,6 +98,8 @@
; test-database-name=""
; test-database-username=""
; test-database-password=""
+ ; test-database-persistent=0
+ ; test-database-errors=1
; SERVER
View
174 controllers/controller.example.php
@@ -31,15 +31,171 @@ class WWW_controller_example extends WWW_Factory {
* @output [key] This is an output value that might exist in the output array
* @response [500] Data returned
*/
- public function get($input){
- // New objects can be created through Factory easily
- $example=$this->getModel('example');
- // This 'loads' model with ID of 1. Note that the function call here can be anything you need, this is just used as an example
- $example->load(1);
- // Getting the data from the model
- $data=$example->get();
- // Returning the result of controller call
- return $this->resultTrue('Data returned',$data);
+ public function get($configuration){
+
+ // This is only set for demonstration purposes, remove it when using this class as template
+ $configuration['id']=1;
+
+ // ID needs to be set
+ if(isset($configuration['id'])){
+ // Loading the model and data to the model
+ $data=$this->getModel('example');
+ if($data->load($configuration['id'])){
+ // Returning an array representation of the model data
+ return $this->resultTrue('Entry found',$data->get());
+ } else {
+ // Action failed because entry was not found
+ return $this->resultFalse('Entry not found');
+ }
+ } else {
+ // Action failed because incorrect request was made to the controller
+ return $this->resultError('ID not defined');
+ }
+
+ }
+
+ /**
+ * Simple example call to get multiple database rows
+ *
+ * @param array $input input data sent to controller
+ * @input [key] This key is one of the accepted input values
+ * @return array
+ * @output [key] This is an output value that might exist in the output array
+ * @response [500] Data returned
+ */
+ public function all($configuration){
+
+ // Loading the model and sending input data to the request
+ $data=$this->getModel('example');
+ $data=$data->all($configuration);
+
+ // This returns empty array if none were found
+ if($data){
+ return $this->resultTrue('Request complete',$data);
+ } else {
+ return $this->resultFalse('Search failed');
+ }
+
+ }
+
+ /**
+ * Simple example call to add rows to database
+ *
+ * @param array $input input data sent to controller
+ * @input [key] This key is one of the accepted input values
+ * @return array
+ * @output [key] This is an output value that might exist in the output array
+ * @response [500] Data returned
+ */
+ public function add($input){
+
+ // This flag checks if error has been encountered during form validation
+ $errorsEncountered=array();
+ $errorFields=array();
+
+ // Validating input
+ if(isset($input['name']) && trim($input['name'])!=''){
+ $input['name']=trim($input['name']);
+ } else {
+ $errorFields['name']=true;
+ $errorsEncountered[]='name-incorrect';
+ }
+
+ // Data is only added if no errors were encountered
+ if(empty($errorsEncountered)){
+ // Getting model and setting the parameters
+ $data=$this->getModel('example');
+ $data->name=$input['name'];
+ // Attempting to save
+ if($data->save()){
+ return $this->resultTrue('Entry added');
+ } else {
+ return $this->resultError('Failed to add entry');
+ }
+ } else {
+ return $this->resultFalse('Input data incorrect');
+ }
+
+ }
+
+ /**
+ * Simple example call to edit rows to database
+ *
+ * @param array $input input data sent to controller
+ * @input [key] This key is one of the accepted input values
+ * @return array
+ * @output [key] This is an output value that might exist in the output array
+ * @response [500] Data returned
+ */
+ public function edit($input){
+
+ // ID has to be set when editing
+ if(isset($input['id'])){
+
+ // This flag checks if error has been encountered during form validation
+ $errorsEncountered=array();
+ $errorFields=array();
+
+ // Validating input
+ if(isset($input['name']) && trim($input['name'])!=''){
+ $input['name']=trim($input['name']);
+ } else {
+ $errorFields['name']=true;
+ $errorsEncountered[]='name-incorrect';
+ }
+
+ // Data is only edited if no errors were encountered
+ if(empty($errorsEncountered)){
+ // Getting model
+ $data=$this->getModel('example');
+ // Data loading has to work based on the provided ID
+ if($data->load($input['id'])){
+ // Setting the changed input parameters
+ $data->name=$input['name'];
+ // Attempting to save
+ if($data->save()){
+ return $this->resultTrue('Entry edited');
+ } else {
+ return $this->resultError('Failed to edit entry');
+ }
+ } else {
+ return $this->resultFalse('Entry ID not found');
+ }
+ } else {
+ return $this->resultFalse('Input data incorrect');
+ }
+
+ } else {
+ return $this->resultFalse('Entry ID is missing');
+ }
+
+ }
+
+ /**
+ * Simple example call to delete a row from database
+ *
+ * @param array $input input data sent to controller
+ * @input [key] This key is one of the accepted input values
+ * @return array
+ * @output [key] This is an output value that might exist in the output array
+ * @response [500] Data returned
+ */
+ public function delete($input){
+
+ // ID has to be set when deleting
+ if(isset($input['id'])){
+ // Getting model
+ $data=$this->getModel('example');
+ // Attempting to delete
+ if($data->delete($input['id'])){
+ return $this->resultTrue('Entry deleted');
+ } else {
+ return $this->resultError('Failed to delete entry');
+ }
+ } else {
+ return $this->resultFalse('Entry ID is missing');
+ }
+
}
}
View
35 controllers/controller.view.php
@@ -15,7 +15,7 @@
* @license GNU Lesser General Public License Version 3
* @tutorial /doc/pages/guide_view.htm
* @since 1.0.0
- * @version 3.4.1
+ * @version 3.4.2
*/
class WWW_controller_view extends WWW_Factory {
@@ -34,7 +34,7 @@ public function load($input){
unset($input['www-command'],$input['www-return-type'],$input['www-cache-timeout'],$input['www-request'],$input['www-session'],$input['www-cache-tags']);
// Getting view information
- $view=$this->getState('view');
+ $view=$this->viewData();
$systemRoot=$this->getState('system-root');
// If PHP libraries are set to be loaded, then loading them through Factory
@@ -42,8 +42,13 @@ public function load($input){
// Libraries are in a comma-separated list
$libraries=explode(',',$view['additional-php']);
foreach($libraries as $l){
- // This will throw an error, if the library is not found
- $this->loadLibrary($l);
+ if(file_exists($systemRoot.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.$l.'.php')){
+ // Requiring override file
+ require($systemRoot.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.$l.'.php');
+ } else {
+ // Requiring original file
+ require($systemRoot.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.$l.'.php');
+ }
}
}
@@ -95,6 +100,11 @@ public function load($input){
$coreStyleSheet[]='reset.css';
$coreStyleSheet[]='style.css';
+ // If Sitemap file has defined additional external CSS stylesheets
+ if(isset($view['external-css']) && $view['external-css']!=''){
+ $externalStylesheet=explode(',',$view['external-css']);
+ }
+
// If Sitemap file has defined additional CSS files
if(isset($view['additional-css']) && $view['additional-css']!=''){
$additionalStylesheet=explode(',',$view['additional-css']);
@@ -117,6 +127,11 @@ public function load($input){
$coreJavaScript[]='class.www-wrapper.js';
$coreJavaScript[]='class.www-factory.js';
+ // If Sitemap file has defined additional external JavaScript libraries
+ if(isset($view['external-js']) && $view['external-js']!=''){
+ $externalJavaScript=explode(',',$view['external-js']);
+ }
+
// If Sitemap file has defined additional JavaScript libraries
if(isset($view['additional-js']) && $view['additional-js']!=''){
$additionalJavaScript=explode(',',$view['additional-js']);
@@ -161,6 +176,11 @@ public function load($input){
<?php } ?>
<!-- Stylesheets -->
<link type="text/css" href="resources/styles/<?=implode('&',$coreStyleSheet)?>" rel="stylesheet" media="all"/>
+ <?php if(isset($externalStylesheet)){ ?>
+ <?php foreach($externalStylesheet as $style){ ?>
+ <link type="text/css" href="<?=implode('&',$style)?>" rel="stylesheet" media="all"/>
+ <?php } ?>
+ <?php } ?>
<?php if(isset($additionalStylesheet)){ ?>
<link type="text/css" href="resources/styles/<?=implode('&',$additionalStylesheet)?>" rel="stylesheet" media="all"/>
<?php } ?>
@@ -172,8 +192,13 @@ public function load($input){
<link rel="icon" href="favicon.ico" type="image/vnd.microsoft.icon"/>
<!-- JavaScript -->
<script type="text/javascript" src="resources/scripts/<?=implode('&',$coreJavaScript)?>"></script>
+ <?php if(isset($externalJavaScript)){ ?>
+ <?php foreach($externalJavaScript as $script){ ?>
+ <script type="text/javascript" src="<?=$script?>"></script>
+ <?php } ?>
+ <?php } ?>
<?php if(isset($additionalJavaScript)){ ?>
- <script type="text/javascript" src="resources/libraries/<?=implode('&',$additionalJavaScript)?>"></script>
+ <script type="text/javascript" src="resources/scripts/<?=implode('&',$additionalJavaScript)?>"></script>
<?php } ?>
<?php if(isset($moduleJavaScript)){ ?>
<script type="text/javascript" src="resources/scripts/<?=$moduleJavaScript?>"></script>
View
5 doc/index.htm
@@ -48,7 +48,8 @@
<p>This section covers feature guides and is meant to be a supplement to Tutorials. This covers all the features of Wave Framework and gives detailed overview of functionality when building Wave Framework MVC classes and functionality, especially when creating websites.</p>
<ul>
- <li><a href="pages/guide_website.htm">Website Workflow</a> - Brief overview about how Wave Framework handles URL requests</li>
+ <li><a href="pages/guide_project.htm">Project Setup</a> - Brief overview about how to set up a project</li>
+ <li><a href="pages/guide_website.htm">Website Workflow</a> - How URL requests are handled by default controllers</li>
<li><a href="pages/guide_url.htm">URL Controller and Sitemap</a> - URL routing through URL controller and sitemap</li>
<li><a href="pages/guide_view.htm">View Controller and Translations</a> - Details about default view controller, translations and view-loading</li>
<li><a href="pages/guide_mvc.htm">MVC Pattern</a> - Good practices when building models, views and controllers with Wave Framework</li>
@@ -61,7 +62,7 @@
<li><a href="pages/guide_messenger.htm">State Messenger</a> - Using state messenger</li>
<li><a href="pages/guide_logger.htm">Internal Logger</a> - Using internal logger</li>
<li><a href="pages/guide_cache.htm">Cache</a> - Cache and buffer functionality</li>
- <li><a href="pages/guide_autoload.htm">Autoload</a> - Autoload script</li>
+ <li><a href="pages/guide_autoload.htm">Autoload</a> - Automatically loaded scripts</li>
<li><a href="pages/guide_security.htm">Security</a> - Cross-site requests and general web security</li>
<li><a href="pages/guide_crypto.htm">Cryptography</a> - Encryption and decryption options</li>
<li><a href="pages/guide_performance.htm">Performance</a> - Performance testing options</li>
View
4 doc/pages/api_io.htm
@@ -113,6 +113,10 @@
<p>This allows for a lot of flexibility as it is an on-demand cache-control that can be used to speed up requests or the same Controller in some parts of the system based on their importance.</p>
+ <h3>www-cache-load-timestamp</h3>
+
+ <p>This tells the API to accept cache with different timestamp based age than the 'www-cache-timeout' value. This means that you can make a request that only allows 'www-cache-load-timestamp' aged cache, but writes a different cache age to headers and for other methods.</p>
+
<h3>www-profile</h3>
<p>This is the API profile name that should also be defined in '/resources/api.profiles.ini' file. This tells API what API profile (and thus what profile settings) the API will use when validating the API request.</p>
View
4 doc/pages/configuration.htm
@@ -56,7 +56,9 @@
database-host<br/>
database-name<br/>
database-username<br/>
- database-password</p>
+ database-password<br/>
+ database-errors<br/>
+ database-persistent</b></p>
<p>Wave Framework can connect to multiple <a href="guide_database.htm">Database</a> types, database-type values can be 'mysql', 'postgresql', 'sqlite', 'mssql' and 'oracle'. If database values are not set, then system won't attempt to connect to database. Persistent connections are allowed by using database-persistent flag, in which case same connection handle will be shared across requests from different user agents, but note that this flag is not recommended and can cause additional performance issues. If you need to add port information for host, add it after host name, like 'www.example.com:3306'.</p>
View
14 doc/pages/factory.htm
@@ -84,6 +84,18 @@
<p>This method is used to apply static Minifier class method to a text string. $data should be the data string to be modified and $type should be the format type (either xml, html, js or css). This method returns modified string that is minified by Minifier class.</p>
+ <h3>final protected viewData($variable=false)</h3>
+
+ <p>This is just a wrapper function for getting state data for view. This method returns $variable from the current view settings or the entire view data array, if this is not set.</p>
+
+ <h3>final protected getStorage($key=false)</h3>
+
+ <p>This is just a wrapper function for getting state from global state storage. This method returns $variable from the storage or the whole storage at once if this is not set.</p>
+
+ <h3>final protected setStorage($key,$value)</h3>
+
+ <p>This is just a wrapper function for getting state from global state storage. This method returns $variable from the storage or the whole storage at once if this is not set.</p>
+
<h3>final protected function resultError($message='Error',$customData=false,$responseCode=300)</h3>
<p>Wave Framework <a href="guide_mvc.htm">MVC</a> object method calls can return their data in whatever format developer finds necessary, but it is recommended to return data in a standardized form. This method returns an array in the format of an error. $message should be the verbose message returned, $customData should be an array of data returned as part of the result and $responseCode should be an response code in 3XX namespace, which is used for errors in Wave Framework.</p>
@@ -140,6 +152,8 @@
<p>This method stores data $value under key of $key. It also turns off caching of the current <a href="guide_api.htm">API</a> call as a result, since <a href="guide_messenger.htm">State Messenger</a> is outside the scope of caching. Additionally using this function also turns off caching of the page which uses it.</p>
+ <h3>final protected function callTool($type,$arg1=false,$arg2=false)</h3>
+
<h3>final protected function unsetMessengerData($key=false)</h3>
<h3>final protected function getMessengerData($key=false,$remove=true)</h3>
View
2 doc/pages/faq.htm
@@ -115,7 +115,7 @@
<p>Wave Framework uses PHP's own session handling to manipulate with user sessions and detect if sessions are used and what data is stored in $_SESSION. But sometimes it is important to use your own session handling, especially if sessions are stored on another server or through another system.</p>
- <p>While there is no way to specify how Wave Framework handles sessions directly, it is possible in PHP to rewrite session handling functions that PHP natively uses (the same ones that Wave Framework implements). PHP function that defines all the functions used for session handling is the session_set_save_handler(). You can get more information about this function from PHP's own documentation. You should define the sessions you need in in the <a href="guide_autoload.htm">Autoload</a> script in '/resources/autoload.php' file. Read more about <a href="guide_autoload.htm">Autoload</a> script in its own documentation.</p>
+ <p>While there is no way to specify how Wave Framework handles sessions directly, it is possible in PHP to rewrite session handling functions that PHP natively uses (the same ones that Wave Framework implements). PHP function that defines all the functions used for session handling is the session_set_save_handler(). You can get more information about this function from PHP's own documentation. You should define the sessions you need in in the <a href="guide_autoload.htm">Autoload</a> script in '/resources/scripts/script.php' file. Read more about <a href="guide_autoload.htm">Autoload</a> scripts in its own documentation.</p>
<h3>My Requests Fail and Decompression Error is Returned By the Browser?</h3>
View
19 doc/pages/filesystem.htm
@@ -81,6 +81,10 @@
<p><a href="guide_state.htm">State</a> is always required by Wave Framework. It is used by API and some handlers. <a href="guide_state.htm">State</a> is used to keep track of system state, configuration and its changes, such as relevant PHP settings. It allows changing these settings, and thus affecting API or PHP configuration. <a href="guide_state.htm">State</a> also includes functionality for <a href="guide_messenger.htm">State Messenger</a> , sessions, cookies, translations and sitemap data. <a href="guide_state.htm">State</a> is assigned in API and is accessible in <a href="guide_mvc.htm">MVC</a> objects through Factory wrapper methods. Multiple different states can be used by the same request, but usually just one is used per request. <a href="guide_state.htm">State</a> is only kept for the duration of the request processing and is not stored beyond its use in the request.</p>
+ <p><b>/engine/class.www-tools.php</b></p>
+
+ <p><a href="tools.htm">Tools Class</a> is used by Wave Framework Factory to allow for system-maintenance related functionality for MVC classes of the system. This allows to use filesystem cleaner, geenrate a file index of files or calculate file size of a folder.</p>
+
<p><b>/engine/class.www-wrapper.php</b></p>
<p>This class should be used when you wish to communicate with Wave Framework that is set up in another server. This class is independent from Wave Framework itself and can be used by other servers alone. This class allows sending and receiving encrypted data as well as sending files and creating session tokens in a system set up with Wave Framework. This class uses cURL (if available) to make advanced requests with file uploads and cookie containers.</p>
@@ -173,6 +177,10 @@
/resources/classes/class.{name}.js<br/>
/resources/classes/class.{name}.php<br/></b></p>
+ <p><b>/resources/files/</b></p>
+
+ <p>This folder is for all the various files that are not necessarily images or resources. This folder is used for things like static downloads.</p>
+
<p>This folder includes all the classes that can be dynamically loaded through Factory method getObject() from either JavaScript or PHP. Filename should be formatted as class.[name].php and class name as [name]. Dynamically loaded JavaScript files should also be stored in these folders and they work the same way. Two example files are provided as a starting point.</p>
<p><b>/resources/images/<br/>/resources/images/logo.png</b></p>
@@ -186,12 +194,13 @@
<p>This folder stores various PHP scripts or JavaScript files that can be dynamically loaded within MVC objects through Factory classes. These files can also be automatically loaded by URL controller, if they are set. Two example scripts are provided as a starting point.</p>
<p><b>/resources/scripts/<br/>
+ /resources/scripts/script.php<br/>
/resources/scripts/script.js<br/>
/resources/scripts/jquery.js<br/>
/resources/scripts/{view}.script.js<br/>
/resources/scripts/{view}.script.php<br/></b></p>
- <p>This folder includes all the JavaScript files. All of these files are optional, but the View Controller loads the script.js and jquery.js (jQuery framework) file by default. You can also define view-specific scripts here for both JavaScript and PHP, which are loaded by URL and View controllers if detected.</p>
+ <p>This folder includes all the JavaScript files. All of these files are optional, but the View Controller loads the script.js and jquery.js (jQuery framework) file by default and script.php file is loaded automatically by Data and API Handlers for each request as well. You can also define view-specific scripts here for both JavaScript and PHP, which are loaded by URL and View controllers if detected.</p>
<p><b>/resources/static/</b></p>
@@ -212,10 +221,6 @@
<p>This file defines observers for API. Sections in this file should be API commands, such as 'example-get' under which it is possible to set multiple observer-specific settings. If the set API command is called, then an observer is executed based on settings from this file. Note that the Input observers get the same input data that the API call itself gets, except command related data. Output observers get the data that is returned after API command execution.</p>
- <p><b>/resources/autoload.php</b></p>
-
- <p>By default, this file is empty as no libraries are used or loaded by Wave Framework. But if you wish to add system-wide functions, then this file can be used for that purpose as it is loaded by <a href="gateway.htm">Index Gateway</a> for all requests. Generally it is useful to not have a general library in a system, as it can make testing more difficult, but it can be useful at times. It is also possible to add other functionality to this file that is not necessarily a function definition. This will make sure that the <a href="gateway.htm">Index Gateway</a> and Handlers themselves are not touched during project development for the same purpose. This file is loaded only by <a href="handler_api.htm">API</a> and <a href="handler_data.htm">Data Handlers</a> and only after configuration and state has been loaded.</p>
-
<p><b>/resources/{language-code}.sitemap.ini</b></p>
<p>Sitemaps are used by WWW_controller_url to solve what view should be loaded based on user agents request. WWW_controller_url detects both languages and URL and unsolved URL nodes from the request and matches them against this file, based on language code that it detects in the request. If it finds a match here then it returns that view. Note that it can also include dynamic URL's for partial matching.</p>
@@ -293,10 +298,6 @@
<p>This is an update script template, if file with this name is added to root archive of update zip files that is given to /tools/updater.php, then this script is also executed (and then removed). This script is useful to store in other update-related commands, such as file permissions, database changes and so on.</p>
- <p><b>/tools/www-cleaner.php</b></p>
-
- <p>This is a maintenance script template. It works similarly to Cleaner tool, but is intended to be called by the server in order to automatically clean the filesystem folders. The only difference is that the log is shown only if the server itself makes the request and the 'cutoff' value cannot be sent with the request by default. Developer should change this script accordingly to make it suitable for use in whatever system it is implemented on.</p>
-
<p><b>/views/</b></p>
<p>Includes all views used by the system. Views are built with the following standard, where view name is written in filename as view.{name}.php, class itself is defined as WWW_view_{name} and when this view is created through WWW_Factory (when within one of the <a href="guide_mvc.htm">MVC</a> objects), the command is $this-&gt;getView({name},{function},{data}), where function is a method of that class and {data} is input data to that method. If function and data are not defined, then object itself is returned instead of the function result.</p>
View
17 doc/pages/guide_autoload.htm
@@ -14,17 +14,22 @@
<h2>Files</h2>
- <h3>/resources/autoload.php</h3>
+ <h3>/resources/scripts/script.php</h3>
+ <h3>/resources/scripts/script.js</h3>
<h2>Introduction</h2>
- <p>Autoload script is not necessary on most web projects as long as functionality is built with classes and objects created from those classes that are used by Controllers, Models and Views within Wave Framework. But sometimes it is necessary to load a specific library or libraries or change some PHP configuration setting globally. Autoload script can be used as an option for this.</p>
+ <p>The script.js and script.php files in '/resources/scripts/' folder are automatically loaded scripts. This means that both of these scripts, if they exist, are loaded by the system.</p>
+
+ <p>Autoloaded scripts is not necessary on most web projects as long as functionality is built with classes and objects created from those classes that are used by Controllers, Models and Views within Wave Framework and in other JavaScript files. But sometimes it is necessary to load a specific library or libraries or change some PHP configuration setting globally. Autoload script can be used as an option for this.</p>
- <h2>Using Autoload Script</h2>
+ <h2>Using Autoload Script for JavaScript</h2>
+
+ <p>JavaScript autoloaded 'script.js' file is generally considered the master JavaScript file. Most of the simple applications only store scripts in that file alone. This works similarly to any other script file loaded in the system, you just have to keep in mind that this script is loaded after all the external JavaScript libraries are already loaded (this behavior can be changed by editing View Controller).
- <p>It is not recommended to edit <a href="gateway.htm">Index Gateway</a> file at '/index.php' or handler files in '/engine/' subfolder when you wish to include libraries or run additional global methods before Wave Framework API is loaded. Editing Index Gateway and Handler files should be the last resort. Data and API Handlers however load a script that is situated in '/resources/autoload.php' file. As a result, everything that is defined in that Autoload script will be included with every HTTP request that is made to Wave Framework.</p>
+ <h2>Using Autoload Script with PHP</h2>
- <p>For example, if you wish to include a method in your system that is accessible everywhere for checking whether your server environment is 64bit or 32bit, then you can add this to your autoload script:</p>
+ <p>For example, if you wish to include a method in your system that is accessible everywhere for checking whether your server environment is 64bit or 32bit, then you can add this to your 'script.php' file:</p>
<pre>
<code>
@@ -44,7 +49,7 @@
<p>By default the Autoload script is entirely empty and nothing is loaded from it by Wave Framework.</p>
- <h2>Usable Variables and Objects</h2>
+ <h3>Usable Variables and Objects</h3>
<p>Autoload is loaded procedurally by Data and API Handlers of Wave Framework. This means that you have access to some of the core aspects of Wave Framework even before API itself is loaded. This also means that you can use the data that is stored by these variables in your Autoload functions, classes or more.</p>
View
196 doc/pages/guide_project.htm
@@ -0,0 +1,196 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title>Project Setup - Wave Framework</title>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width"/>
+ <link type="text/css" href="../style.css" rel="stylesheet" media="all"/>
+ <link rel="icon" href="../../favicon.ico" type="image/x-icon"/>
+ <link rel="icon" href="../../favicon.ico" type="image/vnd.microsoft.icon"/>
+ </head>
+ <body>
+
+ <h1>Project Setup</h1>
+
+ <h2>Files and Folders</h2>
+
+ <h3>/config.ini</h3>
+ <h3>/models/</h3>
+ <h3>/views/</h3>
+ <h3>/controllers/</h3>
+ <h3>/resources/</h3>
+ <h3>/overrides/</h3>
+ <h3>/filesystem/</h3>
+
+ <h2>Introduction</h2>
+
+ <p>Wave Framework is a small framework, but it still includes a lot of files that can make it confusing how to set up a project on Wave. The tutorials that are part of this documentation are already very helpful, but this documentation page here gives a detailed overview of what actually consists of a project when it is being set up on Wave Framework.</p>
+
+ <p>This documentation is also useful for a developer who is not familiar with Wave, but who has to tweak something about a project that is built on Wave. So make sure you read this documentation through when you're either planning a new project or have to work on a project that already exists.</p>
+
+ <h2>Configuration</h2>
+
+ <p>Configuration is stored in '/config.ini' file.</p>
+
+ <p>There is a <a href="configuration.htm">Configuration</a> documentation page that gives a detailed overview about each configuration setting that is set by default in Wave Framework. This configuration file has information about what languages are set up for the system, what database connections, what URL rules, caching settings, robots settings and meta content rules. It is recommended that you take a look at that documentation page or configuration file (which should be documented internally with comments as well, unless it is changed on an existing project) to get a thorough overview of what each setting does.</p>
+
+ <p>Developers can also write additional configuration options into this Configuration file however. All of these configuration settings are considered as internal state environmental variables and will be loaded to State object (which is accessible with getState() method calls from MVC classes). This means that if you set up custom configuration settings in this file, then you have to make sure you do not accidentally override a setting that otherwise would be automatically set by State itself during project call. There is a complete list of these State variables in the <a href="state.htm">State Class</a> documentation page.</p>
+
+ <p>It is recommended that if you wish to add your own configuration settings, then you add them either to the top or the bottom of Wave Framework's own configuration settings, so that it is easier for other developers to tell apart which settings are yours and which are not.</p>
+
+ <h2>Controllers</h2>
+
+ <p>Controllers are stored in '/controllers/' subfolder. Controller files should be in the format of 'controller.[name].php' in that folder and an example Controller is provided in that folder, but you can design the Controller however you want.</p>
+
+ <p>Controllers that are extended from WWW_Factory class have the functionality and access methods or the entire Wave Framework system, from classes to State and the API. But this is not required unless your system requires that additional functionality.</p>
+
+ <p>Controller is the core part of Wave Framework, in that all calls are sent to Controllers by Wave Framework API. All API requests, over HTTP or internally, are directed at these Controllers and their methods. Public methods of Controllers are accessible over API and private methods are considered internal-only.</p>
+
+ <p>It is recommended to only include one input parameter for Controller methods, since all the data is sent to Controller methods as a single associative array. You can define other parameters for methods as well, but those would only be accessible internally in that case and should never be required.</p>
+
+ <p>Controllers are generally loaded through API Handler by Index Gateway, but can also be loaded through Factory with 'getController()' method call. They are also accessible through API with 'api()' method call.</p>
+
+ <h3>URL Controller</h3>
+
+ <p>URL Controller is stored as '/controllers/controller.url.php' file. This is usually the default URL Controller that comes with Wave Framework, but it could be changed or modified if it is a project you're inheriting from someone else.</p>
+
+ <p>The default URL Controller is much like any other Controller that you yourself can build. It's main purpose is that Index Gateway - that gets all the URL requests - uses URL Controller in Data Handler (this handler is used whenever a regular URL and not a file is requested from the server) to find out what view the user agent is requesting. It relies on language settings from Configuration, Sitemap file from '/resources/' subfolders, and the URL that the user requested and then returns this data to Data Handler. Data Handler then loads View Controller with the data that it found.</p>
+
+ <p>In the bottom of URL Controller is also the place where you can validate the request against User permissions and see if they are allowed to access the URL or not. Default archive includes this validation as an example, but it is commented out by default. You can use that commented out section as an example of how to do this in your project.</p>
+
+ <h3>View Controller</h3>
+
+ <p>View Controller is stored as '/controllers/controller.view.php' file. If you inherited this project from someone else, then it is very likely that this file has been changed in some way by the developer. The default View Controller is provided in the downloaded archive however, so you can easily see what the file does.</p>
+
+ <p>Basically the View Controller is loaded by Data Handler after the URL has been solved and the system knows what View it should load. View Controller loads any additional resources that the Sitemap tells it to load, the basic HTML frame for the project as well as calls for the actual view itself in the body part of the view.</p>
+
+ <p>Note that it can be possible that another View Controller is used instead and that the View Controller can be named differently. This is because it is possible in Sitemap files to define another Controller to act as a View Controller. But in most projects you can expect the default View Controller to be the good starting point.</p>
+
+ <p>It is generally recommended to add only the HTML that is existing across all URL's that use this Controller in this file.</p>
+
+ <h2>Models</h2>
+
+ <p>Models are stored in '/models/' subfolder. Model files should be in the format of 'model.[name].php' in that folder and an example Model is provided in that folder, but you can design the Model however you want.</p>
+
+ <p>Models that are extended from WWW_Factory class have the functionality and access methods or the entire Wave Framework system, from classes to State and the API. But this is not required unless your system requires that additional functionality.</p>
+
+ <p>The basic idea of models is to provide a code-representation for data that is stored in database or the filesystem. Models generally should have methods for getting data from database, storing it in database, removing it from database and so on.</p>
+
+ <p>Models are generally loaded through Factory with 'getModel()' method call.</p>
+
+ <h2>Views</h2>
+
+ <p>Views are stored in '/views/' subfolder. View files should be in the format of 'view.{name}.php' in that folder and an example View is provided in that folder, but you can design the View however you want.</p>
+
+ <p>Views that are extended from WWW_Factory class have the functionality and access methods or the entire Wave Framework system, from classes to State and the API. But this is not required unless your system requires that additional functionality.</p>
+
+ <p>Views are generally loaded through View Controller by default, or through Factory with 'getView()' method call, which allows you to use nested Views.</p>
+
+ <h2>Resources</h2>
+
+ <p>Resources folder should include all the resources - such as JavaScript, CSS stylesheets, translation files and class definitions - that are used by the project. This folder includes multiple sub-folders as well as the files themselves. Here's the list of files:</p>
+
+ <ul>
+ <li><b>api.observers.ini</b> - This includes all the defined API observers and the API commands they observe.</li>
+ <li><b>api.profiles.ini</b> - This is a configuration file for API profiles, namely all the profiles that require authentication and list of API calls they can make.</li>
+ <li><b>{language}.sitemap.ini</b> - This holds the rules for all URL's and what Views they load in the system, when a regular URL request is made. There can be multiple Sitemap files, one per language defined in Configuration.</li>
+ <li><b>{language}.translations.ini</b> - This should hold all system-specific translations. There can be multiple Sitemap files, one per language defined in Configuration. Note that language-specific content should not be stored in this file and should be loaded either from database or from other files.</li>
+ <li><b>offline.htm</b> - This is only used when AppCache is used in the system, this file can be ignored in most projects.</li>
+ <li><b>placeholder.jpg</b> - This is a file that is returned with a 404 header whenever an image file is requested that is not found on the server. All the dynamic image rules still apply for this picture. This placeholder behavior can be turned off in Configuration.</li>
+ </ul>
+
+ <p>Note that it is actually possible to unify CSS and JavaScript files that are requested from '/resources/' subfolder. This means that a single HTTP request can load multiple files at once. You can look at View Controller to see how such a request is built.</p>
+
+ <h3>Files</h3>
+
+ <p>Resources folder includes '/files/' folder which is considered a general-purpose folder for storing various files that are part of the project from software perspective. Things like manuals or videos can be stored here.</p>
+
+ <h3>Images</h3>
+
+ <p>This '/resources/images/' folder is for storing all the design-related picture files.</p>
+
+ <h3>Classes</h3>
+
+ <p>It is possible to dynamically load objects with both native PHP Factory and JavaScript Factory through Wave Framework. Classes which are loaded should be stored in this folder and follow the naming standard of 'class.{name}.php' (or 'class.{name}.js' for JavaScript) and have a defined class name the same as the {name} part of the file name. After this, you can dynamically load these classes with 'getObject()' call when passing the name as the parameter.</p>
+
+ <p>These classes are stored in '/resources/classes/' subfolder.</p>
+
+ <h3>Libraries</h3>
+
+ <p>Libraries are similar to classes, except they do not return an object when dynamically loaded. File name of a library should be '{name}.php' (or '{name}.js' for JavaScript) and it can be loaded through 'loadLibrary()' method call by either JavaScript or PHP Factories.</p>
+
+ <p>These libraries are stored in '/resources/libraries/' subfolder.</p>
+
+ <h3>Scripts</h3>
+
+ <p>Scripts folder is for general as well as View-specific PHP and JavaScript files. Files that are stored in this folder can be used in multiple ways.</p>
+
+ <p>The two main files are 'script.js' and 'script.php' files. If these files are set and exist, then they are loaded for every request. PHP file is loaded by Data and API Handlers and the JavaScript file is loaded by the View Controller.</p>
+
+ <p>You can also define View-specific PHP and JavaScript files here, if you add files with naming standard '{view}.script.php' or '{view}.script.js' files here. These files are loaded by View Controller only if a View with the {view} value is loaded, so you can make sure that bloated functionality of one View does not affect other Views in the system.</p>
+
+ <p>Other JavaScript and PHP files can also be stored in this folder. You can add other files by naming them just '{name}.php' or '{name}.js' and these files are loaded if they are defined in the Sitemap file as 'additional-js' or 'additional-php' Sitemap settings for any URL. This allows you to share some functionality across different Views, but without bloating the global namespace for every other request.</p>
+
+ <p>This folder can also include libraries or frameworks such as jQuery, which are loaded by View Controller too.</p>
+
+ <p>All of these scripts are stored in '/resources/scripts/' subfolder.</p>
+
+ <h3>Styles</h3>
+
+ <p>This folder is similar to JavaScript and PHP scripts folder, except it is for CSS stylesheets only. This folder should include all the files that you wish to include as part of your Views. The file 'style.css' is loaded with every request and by default the 'reset.css' file is also loaded by View Controller. You can change this behavior however if you change the Controller.</p>
+
+ <p>You can also load View-specific stylesheets when you add a file to this folder with naming standard of '{view}.style.css'. This file is loaded by View Controller if a View by the name of {view} gets loaded. This allows you to separate some stylesheet files from the main file, reducing possible bloat and namespace conflicts.</p>
+
+ <p>You can store additional stylesheet files here too when you add a file there as '{name}.css'. This file can then be loaded automatically if it is set as part of 'additional-css' value in Sitemap configuration. This allows multiple different Views share some stylesheets.</p>
+
+ <p>All of these stylesheets are stored in '/resources/styles/' subfolder.</p>
+
+ <h3>Static</h3>
+
+ <p>Static folder in '/resources/static/' is meant for storing any and all files that you wish to load as resources, but without using PHP to serve these files. Since Wave Framework serves all files through PHP by default, then this can improve performance in some cases when you have pre-compiled or minified some files and wish to improve their loading speed.</p>
+
+ <p>But note that the benefits may not outweigh the benefits of serving files through Wave Framework Handlers, since the control over caching and unifying requests may be better for the project in some cases.</p>
+
+ <h2>Filesystem</h2>
+
+ <p>There are a multiple folders and subfolders stored in '/filesystem/' folder. This folder is required to be writable by Wave Framework, since this is the place where the system stores cache and other related files.</p>
+
+ <p>You can add new folders here and do with them whatever you want, the idea of this folder is that you can always know that this is the folder where your software writes or uploads various files to.</p>
+
+ <p>Some of the folders are used by Wave Framework internally, other folders are assigned for use by software functionality. This is a brief overview of each folder and their purpose:</p>
+
+ <ul>
+ <li><b>backups</b> - This should be used to store various backups. Developer tool for backups (from '/tools/' folder) stores files in this folder.</li>
+ <li><b>cache</b> - This folder and its subfolders are used to store various cache files. It should be safe to empty these folders every now and then without the software breaking.</li>
+ <li><b>data</b> - This is meant for any filesystem specific databases - such as SQLite - and other data storage.</li>
+ <li><b>errors</b> - Wave Framework stores logs about error messages in this folder.</li>
+ <li><b>keys</b> - Various certificates - such as for SSL - and other security related keys should be stored here.</li>
+ <li><b>limiter</b> - If request limiter is used, then Wave Framework stores request information and blocks in this folder.</li>
+ <li><b>logs</b> - This folder is used for storing various system logs and internal debugging messages and should be safe to delete every now and then.</li>
+ <li><b>messenger</b> - This is a folder for State Messenger storage, which is a special functionality that can be used by Wave Framework across requests.</li>
+ <li><b>sessions</b> - This is custom session storage folder.</li>
+ <li><b>static</b> - Any files that are uploaded to this folder are never served by PHP when a request is made to these files.</li>
+ <li><b>tmp</b> - Any temporary files should be stored here. Files in this folder should not expect to be there the next time a request is made. This is a safe folder for writing anything into that you know you will not use later on.</li>
+ <li><b>tokens</b> - API session tokens are stored in this folder.</li>
+ <li><b>updates</b> - The developer tool for updates from '/tools/' subfolder stores the update archives in this folder.</li>
+ <li><b>userdata</b> - This is a folder that is suitable for various end-user file uploads and file storage.</li>
+ </ul>
+
+ <h2>Overrides</h2>
+
+ <p>Overrides are a very useful part of Wave Framework. The idea behind overrides is that you have the ability to override any and every part of your systems functionality except the framework itself. This means that if you place a file with the same name and the same location in '/overrides/' folder or subfolders and a request is made to the original file over HTTP or from within Factory, then the override will be loaded instead.</p>
+
+ <p>This has two really good benefits. First is that you can deploy beta's to live software in this manner, as the beta updates could simply be deployed in the overrides folders and everything will work as expected. But do remember that framework itself and the Configuration file cannot have overrides.</p>
+
+ <p>Second benefit is that overrides allow you to have the same software in multiple servers, but with slight changes. For example, if you have built an intranet software on Wave Framework and one client wishes to use some functionality that they custom-ordered, then this can be stored in overrides folder. This is beneficial because the same software itself can still be updated through the core update cycle, since the updates would not overwrite the override.</p>
+
+ <h2>Summary</h2>
+
+ <p>As you can see the structure of a project in filesystem follows only a few very easy to follow rules. If you start a new project with Wave Framework or inherit an existing one, then these are the folders that actually affect the software functionality that is built on top of Wave.</p>
+
+ <p>These details are good to remember, especially when updating the framework itself. The main folder for the framework is the '/engine/' folder and the '.htaccess' file in the root folder (for Apache and if it exists and the rules have not been written to servers own configuration as would be the case with Nginx server).</p>
+
+ <p>Last but not least, do not forget to pay attention to the 'readme.txt' file that should carry both the license for Wave Framework and the license for whatever project you are building or what you inherited. It is always a good idea to pay attention to the legal aspect of the software that you are building or maintaining.</p>
+
+ </body>
+</html>
View
61 doc/pages/guide_tools.htm
@@ -16,6 +16,8 @@
<p>Wave Framework comes with a suite of administrative tools that are useful for debugging, maintenance, compatibility testing and more. These scripts are all stored in /tools/ subfolder and every script is protected with a username and password. Username and password of most of those tools are stored in main /config.ini file and are used regardless whether http-authentication is turned on or off in configuration. Despite being protected by username and password, it is highly recommended to remove developer tools subfolder entirely before deploying project live.</p>
+ <p>Some developer tools are also integrated in Wave Framework Factory and can be called using that factory. For example, you can return an index of files recursively from a folder or delete all files from a specific folder, as long as PHP has rights to this activity. Details about such functionality called through Wave Framework API are in the very bottom of this document.</p>
+
<h2>Adminer</h2>
<p><b>Location: /tools/adminer.php</b></p>
@@ -83,10 +85,34 @@
<p>Cleaner is used to delete various temporary files - that have been generated by Wave Framework - from the <a href="filesystem.htm">Filesystem</a> - and it returns log of all files that have been removed. Script requires a specific mode to work properly and all the modes are available when the script is run without a mode set. It can clean the entire '/filesystem/' folder and subfolders, only temporary files from '/filesystem/' folder and subfolders or specific folders from '/filesystem/'.</p>
- <p>It is also possible to send a cut-off timestamp, by assigning a 'cutoff' GET variable to the request. This Unix timestamp will be compared against every file in those assigned folders and if the file is newer or has been modified since that timestamp, then the file is not deleted.</p>
+ <p>These are all the cleaner modes that are available:</p>
- <p>There is also a file 'www-cleaner.php' that can be run exactly the same way, but this script requires manual configuration for the 'cutoff' timestamp value and shows log only if it is run from the same server that it is on. The actual modes are the same as they are in regular cleaner tool, but again have to be defined in the script in order to make it as secure as possible from outside requests.</p>
+ <ul>
+ <li><b>all</b> - Empties all folders from /filesystem/ directory.</li>
+ <li><b>maintenance</b> - Empties all non-critical folders from /filesystem/ directory (including sessions).</li>
+ <li><b>cache</b> - Empties all cache-related folders from /filesystem/ directory.</li>
+ <li><b>output</b> - Output cache</li>
+ <li><b>images</b> - Image cache</li>
+ <li><b>resources</b> - Resource file cache.</li>
+ <li><b>custom</b> - Custom cache.</li>
+ <li><b>tags</b> - Cache tags.</li>
+ <li><b>sessions</b> - Session storage.</li>
+ <li><b>messenger</b> - State messenger.</li>
+ <li><b>errors</b> - Error reports.</li>
+ <li><b>logs</b> - Log files.</li>
+ <li><b>tmp</b> - Temporary files.</li>
+ <li><b>limiter</b> - Request limiter storage.</li>
+ <li><b>tokens</b> - API access tokens.</li>
+ <li><b>backups</b> - Backup archives.</li>
+ <li><b>updates</b> - Update archives.</li>
+ <li><b>data</b> - Custom database folder.</li>
+ <li><b>userdata</b> - Custom userdata folder.</li>
+ <li><b>keys</b> - Folder for certificates and keys.</li>
+ <li><b>static</b> - Filesystem static folder.</li>
+ </ul>
+ <p>It is also possible to send a cut-off timestamp, by assigning a 'cutoff' GET variable to the request. This Unix timestamp will be compared against every file in those assigned folders and if the file is newer or has been modified since that timestamp, then the file is not deleted.</p>
+
<h2>Backup</h2>
<p><b>Location: /tools/backup.php</b></p>
@@ -203,6 +229,37 @@
<p>If you want to run the same command multiple times, then add a postfix #1 (or some other number) into the group name.</p>
<p>After the tests are run, the Test Suite shows a summary of how many tests failed and gives detailed information about each failed test.</p>
+
+ <h2>Calling Tools Through Wave Framework Factory</h2>
+
+ <p>If you are building models, views and controllers, then sometimes it's necessary to call some of the usual developer tools within those objects as well. This is especially useful if you wish to clean all cache through the system rather than developer tool, since it is recommended to remove the /tools/ directory entirely from a live project.</p>
+
+ <p>When you are writing functionality for Wave Framework MVC objects and for example you wish to clean all cache set by the system, then you can easily do it like this:</p>
+
+<pre>
+ <code>
+ // This removes contents of all cache folders in /filesystem/ directory
+ $this->callTool('cleaner','cache');
+ </code>
+</pre>
+
+ <p>Other methods are also available, like:</p>
+
+<pre>
+ <code>
+ // Returns an array that includes all the files and folders from specified folder
+ $index=$this->callTool('indexer','/filesystem/');
+ // Returns only an index of files
+ $index=$this->callTool('indexer','/filesystem/','files');
+ // .. and just folders
+ $index=$this->callTool('indexer','/filesystem/','folders');
+ // Gives the total filesize in bytes of all files in specified folder and its subfolders
+ $size=$this->callTool('sizer','/filesystem/');
+ // Deletes all cache (keywords work similarly to the cleaner Developer Tool
+ $size=$this->callTool('cleaner','cache');
+ </code>
+</pre>
+
</body>
</html>
View
6 doc/pages/guide_url.htm
@@ -89,9 +89,11 @@
<li><b>last-modified</b> - Time in YYYY-MM-DD format for the last time content of this page was modified. This is shown in automatically generated sitemap.xml files.</li>
<li><b>frame-permissions</b> - Either 'deny' or 'sameorigin', if this is set then that URL has a different frame-permission rule from configuration file.</li>
<li><b>content-security-policy</b> - This is the content security policy rule for loading external content, it overwrites the default configuration.</li>
- <li><b>additional-php</b> - This is a comma-separated list of Factory loadLibrary() calls that are made when the view is loaded.</li>
- <li><b>additional-js</b> - This is a comma-separated list of JavaScript Factory loadLibrary() calls that are made when the view is loaded.</li>
+ <li><b>additional-php</b> - This is a comma-separated list of PHP scripts loaded from /resources/scripts/ directory.</li>
+ <li><b>additional-js</b> - This is a comma-separated list of JavaScript files loaded from /resources/scripts/ directory.</li>
<li><b>additional-css</b> - This is a comma-separated list of CSS stylesheets (without extensions) that are also loaded when the view is loaded.</li>
+ <li><b>external-js</b> - This is a comma-separated list of URL's where additional JavaScript is loaded from, such as external libraries.</li>
+ <li><b>external-css</b> - This is a comma-separated list of URL's where additional stylesheets are loaded from, such as external libraries.</li>
<li><b>appcache</b> - If set to 1, the URL will be served with cache manifest either from root or with Appcache Handler.</li>
</ul>
View
2 doc/pages/handler_api.htm
@@ -28,7 +28,7 @@
<p>If database settings are set in configuration, then it also loads <a href="database.htm">Database</a> class and creates a new database object which is stored in <a href="state.htm">State</a>.</p>
- <p>API Handler also loads autoload script from either '/overrides/resources/autoload.php' or from '/resources/autoload.php', this file can include function definitions or other PHP-related functionality. It is only recommended to store additional functionality in Autoload script if absolutely necessary, such as for functions that are used by every <a href="guide_api.htm">API</a> call.</p>
+ <p>API Handler also loads autoload script from either '/overrides/resources/scripts/script.php' or from '/resources/scripts/script.php', this file can include function definitions or other PHP-related functionality. It is only recommended to store additional functionality in Autoload script if absolutely necessary, such as for functions that are used by every <a href="guide_api.htm">API</a> call.</p>
<p>API Handler loads <a href="api.htm">API</a> Class and creates a new API object with the current <a href="state.htm">State</a>.</p>
View
2 doc/pages/handler_data.htm
@@ -30,7 +30,7 @@
<p>If database settings are set in configuration, then it also loads <a href="database.htm">Database</a> class and creates a new database object which is stored in <a href="state.htm">State</a>.</p>
- <p>Data Handler also loads autoload script from either /overrides/resources/autoload.php or from /resources/autoload.php, this file can include function definitions or other PHP-related functionality. It is only recommended to store additional functionality in Autoload script if absolutely necessary, such as for functions that are used by every page call.</p>
+ <p>Data Handler also loads autoload script from either /overrides/resources/scripts/script.php or from /resources/scripts/script.php, this file can include function definitions or other PHP-related functionality. It is only recommended to store additional functionality in Autoload script if absolutely necessary, such as for functions that are used by every page call.</p>
<p>Data Handler loads <a href="api.htm">API</a> Class and creates a new API object with the current <a href="state.htm">State</a>.</p>
View
6 doc/pages/history.htm
@@ -17,13 +17,15 @@
<ul>
<li><b>Q4 2012</b> - AJAX Tutorial</li>
<li><b>Q4 2012</b> - Users/Permissions Tutorial</li>
- <li><b>Q4 2012</b> - OpenSSL Tools</li>
- <li><b>Q4 2012</b> - Java API Wrapper</li>
+ <li><b>Q1 2013</b> - WebSockets Integration</li>
+ <li><b>Q1 2013</b> - OpenSSL Tools</li>
+ <li><b>Q1 2013</b> - Java API Wrapper</li>
</ul>
<h2>3.x.x</h2>
<ul>
+ <li><b>3.4.2</b> - Integrated a new method callTool() to Factory and State, which allows you to call system specific functions such as filesystem cleaner or to get an index of files. More tools will be added in the future. The additional JavaScript and PHP loading now targets /scripts/ folder and not /libraries/ folder. Added the option to load external JS and CSS based on sitemap URL. File handler can also use overrides now, if a file is in resources folder. Moved '/resources/autoload.php' to '/resources/scripts/script.php'.</li>
<li><b>3.4.1</b> - Added options for serving Appcache manifests. Fixed some dynamic URL routing bugs in URL Controller.</li>
<li><b>3.4.0</b> - A new Factory JavaScript class is now available, which allows you to dynamically load classes from /resources/classes/ subfolder (or another folder, since it is configurable within Factory). It is now also possible to dynamically load class.www-wrapper.js and class.www-factory.js together with other main JavaScript files, Resource Handler tests for this internally and loads them from /engine/ folder instead. Also JavaScript and CSS files have a separate folder now under /resources/ subfolder. Added the ability to also dynamically load function libraries from both PHP and JavaScript. Documentation updated. Added options that allow to load a set of libraries as defined in Sitemap as well as allowing View Controller to also load view-specific PHP autoload-style scripts. Updated state messenger and its documentation to work so that it 'makes more sense'.</li>
<li><b>3.2.8</b> - Fixed a minor bug in resource file request versioning.</li>
View
11 doc/pages/state.htm
@@ -198,6 +198,7 @@
<li><b>sitemap-cache-timeout</b> - Cache lifetime of sitemap.xml files.</li>
<li><b>sitemap-raw</b> - Raw sitemap data in an array.</li>
<li><b>static-root</b> - <a href="filesystem.htm">Filesystem</a> folder for static files.</li>
+ <li><b>storage</b> - This holds temporary global storage that can be written to and read through Factory.</li>
<li><b>system-root</b> - Root folder of the system.</li>
<li><b>test-database-host</b> - Test database host name.</li>
<li><b>test-database-name</b> - Test database name.</li>
@@ -244,7 +245,11 @@
<h3>private $messengerData=array()</h3>
- <p>This holds <a href="guide_messenger.htm">State Messenger</a> data as an array.</p>
+ <p>This holds <a href="guide_messenger.htm">State Messenger</a> data as an array.</p>
+
+ <h3>private $tools=false</h3>
+
+ <p>This holds system <a href="tool.htm">Tool Class</a> object, if it exists.</p>
<h2>Logger Class Methods</h2>
@@ -386,6 +391,10 @@
<h3>final public function unsetHeader($header)</h3>
<p>This method is a wrapper function for simply removing a previously set header. $header is the header that should be removed.</p>
+
+ <h3>final public function callTool($type,$arg1=false,$arg2=false)</h3>
+
+ <p>This method loads tools object if it doesn't exist yet and then allows to call various methods of the tool. You can call filesystem cleaner, indexer or a file-size calculator (and each work recursively).</p>
<h3>final public function terminal($command)</h3>
View
57 doc/pages/tools.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title>Tools Class - Wave Framework</title>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width"/>
+ <link type="text/css" href="../style.css" rel="stylesheet" media="all"/>
+ <link rel="icon" href="../../favicon.ico" type="image/x-icon"/>
+ <link rel="icon" href="../../favicon.ico" type="image/vnd.microsoft.icon"/>
+ </head>
+ <body>
+
+ <h1>Tools Class</h1>
+
+ <h2>Files</h2>
+
+ <h3>/engine/class.www-tools.php</h3>
+
+ <h2>Introduction</h2>
+
+ <p>This class holds various functionality that also the /tools/ folder has itself. This allows the system to implement some of the tools functionality within the actual website itself, such as things like clearing cache in bulk, or returning an index of files from a folder.</p>
+
+ <h2>Using Tools Class</h2>
+
+ <p>To use Minifier class, it is recommended to load Minifier class and then call the static methods of that class. For example, to minify JavaScript text content, you can do as follows:</p>
+
+<pre>
+ <code>
+ require('/engine/class.www-minifier.php');
+ $minifiedJavaScript=WWW_Minifier::minifyJS($originalJavaScript);
+ </code>
+</pre>
+
+ <h2>Minifier Class Parameters</h2>
+
+ <p>Minifier class implements no parameters.</p>
+
+ <h2>Minifier Class Methods</h2>
+
+ <h3>public static function minifyCSS($data)</h3>
+
+ <p>This method removes comments, tabs, spaces, new-lines and various other spaces from text. It assumes that text is in a CSS-like format.</p>
+
+ <h3>public static function minifyJS($data)</h3>
+
+ <p>This method removes comments, tabs, spaces, new-lines and various other spaces from text. It assumes that text is in a JavaScript-like format.</p>
+
+ <h3>public static function minifyHTML($data)</h3>
+
+ <p>This method removes comments, tabs, spaces, new-lines and various other spaces from text. It assumes that text is in a HTML-like format.</p>
+
+ <h3>public static function minifyXML($data)</h3>
+
+ <p>This method removes comments, tabs, spaces, new-lines and various other spaces from text. It assumes that text is in a XML-like format.</p>
+
+ </body>
+</html>
View
6 doc/pages/update.htm
@@ -38,6 +38,12 @@
<p>This means that when updating, you can safely ignore these folders from update archives and focus on actual core files that might need updating, namely the '/index.php' file and files from '/engine/' folder. Core files of Wave Framework also have version information listed in their file headers as of 3.1.4 and you can refer to this header information to know if your file needs to be updated or not, when comparing it against the latest release.</p>
+ <h3>How to Update to 3.4.2</h3>
+
+ <ul>
+ <li>The Autoload script '/resources/autoload.php' has now been moved to '/resources/scripts/script.php' file. This makes it more standard to what 'script.js' file is and does. So please move and rename the file accordingly, the behavior is exactly the same.</li>
+ </ul>
+
<h3>How to Update to 3.4.1</h3>
<ul>
View
30 engine/class.www-api.php
@@ -17,7 +17,7 @@
* @license GNU Lesser General Public License Version 3
* @tutorial /doc/pages/api.htm
* @since 1.0.0
- * @version 3.4.1
+ * @version 3.4.2
*/
final class WWW_API {
@@ -310,7 +310,8 @@
// Various defaults are loaded from State
$apiState=array(
'call-index'=>$this->callIndex,
- 'cache-timeout'=>false,
+ 'cache-timeout'=>0,
+ 'cache-load-timeout'=>0,
'command'=>false,
'content-type-header'=>(isset($apiInputData['www-content-type']))?$apiInputData['www-content-type']:false,
'custom-header'=>false,
@@ -391,8 +392,15 @@
}
// This tests if cache value sent through input is valid
- if($apiState['command']!='www-create-session' && isset($apiInputData['www-cache-timeout']) && $apiInputData['www-cache-timeout']>=0){
- $apiState['cache-timeout']=$apiInputData['www-cache-timeout'];
+ if($apiState['command']!='www-create-session'){
+ if(isset($apiInputData['www-cache-timeout']) && $apiInputData['www-cache-timeout']>=0){
+ $apiState['cache-timeout']=$apiInputData['www-cache-timeout'];
+ $apiState['cache-load-timeout']=$apiInputData['www-cache-timeout'];
+ }
+ // Loading cache timestamp must be less than the actual cache timeout setting that is set
+ if(isset($apiInputData['www-cache-load-timeout']) && $apiInputData['www-cache-load-timeout']>=0 && $apiInputData['www-cache-load-timeout']<=$apiState['cache-timeout']){
+ $apiState['cache-load-timeout']=$apiState['cache-timeout'];
+ }
}
// VALIDATING PROFILE BASED INPUT DATA
@@ -701,12 +709,12 @@
// If cache timeout is set
// If this value is 0, then no cache is used for command
- if($apiState['cache-timeout']){
+ if($apiState['cache-load-timeout']){
// Calculating cache validation string
$cacheValidator=$apiInputData;
// If session namespace is defined, it is removed from cookies for cache validation
- unset($cacheValidator[$this->state->data['session-name']],$cacheValidator['www-headers'],$cacheValidator['www-cache-tags'],$cacheValidator['www-hash'],$cacheValidator['www-state'],$cacheValidator['www-timestamp'],$cacheValidator['www-crypt-output'],$cacheValidator['www-cache-timeout'],$cacheValidator['www-return-type'],$cacheValidator['www-output'],$cacheValidator['www-return-hash'],$cacheValidator['www-return-timestamp'],$cacheValidator['www-content-type'],$cacheValidator['www-minify'],$cacheValidator['www-crypt-input'],$cacheValidator['www-xml'],$cacheValidator['www-json'],$cacheValidator['www-ip-session'],$cacheValidator['www-disable-callbacks'],$cacheValidator[$this->state->data['session-token-key']]);
+ unset($cacheValidator[$this->state->data['session-name']],$cacheValidator['www-headers'],$cacheValidator['www-cache-tags'],$cacheValidator['www-hash'],$cacheValidator['www-state'],$cacheValidator['www-timestamp'],$cacheValidator['www-crypt-output'],$cacheValidator['www-cache-timeout'],$cacheValidator['www-cache-load-timeout'],$cacheValidator['www-return-type'],$cacheValidator['www-output'],$cacheValidator['www-return-hash'],$cacheValidator['www-return-timestamp'],$cacheValidator['www-content-type'],$cacheValidator['www-minify'],$cacheValidator['www-crypt-input'],$cacheValidator['www-xml'],$cacheValidator['www-json'],$cacheValidator['www-ip-session'],$cacheValidator['www-disable-callbacks'],$cacheValidator[$this->state->data['session-token-key']]);
// MD5 is used for slight performance benefits over sha1() when calculating cache validation hash string
$cacheValidator=md5($apiState['command'].serialize($cacheValidator).$apiState['return-type'].$apiState['push-output'].$this->state->data['version']);
@@ -726,7 +734,7 @@
$apiState['last-modified']=$this->cacheTime($cacheFolder.$cacheFile);
// If server detects its cache to still within cache limit
- if($apiState['last-modified']>=($this->state->data['request-time']-$apiState['cache-timeout'])){
+ if($apiState['last-modified']>=($this->state->data['request-time']-$apiState['cache-load-timeout'])){
// If this request has already been made and the last-modified timestamp is exactly the same
if($apiState['push-output'] && $this->state->data['http-if-modified-since'] && $this->state->data['http-if-modified-since']>=$apiState['last-modified']){
// Adding log data
@@ -1125,9 +1133,6 @@
if($apiState['custom-header']){
header($apiState['custom-header']);
}
-
- // Removing all Pragma headers if server has set them
- header_remove('Pragma');
// CONTENT TYPE HEADERS
@@ -1994,6 +1999,11 @@
*/
final public function filter($string,$type,$exceptions=false){
+ // If exceptions are set they will be escaped
+ if($exceptions){
+ $exceptions=implode('\\',str_split($exceptions));
+ }
+
// If exceptions are set, then we escape any non alphanumeric character in the exception string
if($exceptions){
$exceptions=preg_replace('/[^[:alnum:]]/ui','\\\\\0',$exceptions);
View
6 engine/class.www-database.php
@@ -16,7 +16,7 @@
* @license GNU Lesser General Public License Version 3
* @tutorial /doc/pages/database.htm
* @since 1.1.2
- * @version 3.2.6
+ * @version 3.4.2
*/
class WWW_Database {
@@ -394,7 +394,7 @@ public function dbCommand($queryString,$variables=array()){
* @param boolean $unique if returned array should only have only unique values
* @return array or mixed if source is not an array
*/
- public function dbArray($array,$key,$unique=true){
+ public function dbArray($array,$key,$unique=false){
// Result will be an array
$result=array();
@@ -420,6 +420,8 @@ public function dbArray($array,$key,$unique=true){
$result=array_unique($result);
}
}
+
+ // Returning all the column values as an array
return $result;
}
View
63 engine/class.www-factory.php
@@ -15,7 +15,7 @@
* @license GNU Lesser General Public License Version 3
* @tutorial /doc/pages/factory.htm
* @since 1.0.0
- * @version 3.4.0
+ * @version 3.4.2
*/
class WWW_Factory {
@@ -152,6 +152,53 @@ class WWW_Factory {
// STATE DATA SET AND GET
/**
+ * This is just a wrapper function for getting state data for view. This method
+ * returns $variable from the current view settings or the entire view data array,
+ * if this is not set.
+ *
+ * @param string $variable key of view data to get
+ * @return mixed
+ */
+ final protected function viewData($variable=false){
+ // If variable is set
+ if($variable){
+ return $this->getState('view',$variable);
+ } else {
+ return $this->getState('view');
+ }
+ }
+
+ /**
+ * This is just a wrapper function for getting state from global state storage. This
+ * method returns $variable from the storage or the whole storage at once if this is
+ * not set.
+ *
+ * @param string $key key of view data to get
+ * @return mixed
+ */
+ final protected function getStorage($key=false){
+ if(isset($this->WWW_API->state->data['storage'][$key])){
+ return $this->WWW_API->state->data['storage'][$key];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * This is just a wrapper function for getting state from global state storage. This
+ * method returns $variable from the storage or the whole storage at once if this is
+ * not set.
+ *
+ * @param string $key key of storage data to set
+ * @param string $value value of the key in storage
+ * @return mixed
+ */
+ final protected function setStorage($key,$value=true){
+ $this->WWW_API->state->data['storage'][$key]=$value;
+ return true;
+ }
+
+ /**
* This is the basic call to return a State variable from the object. When call is made
* without any parameters, then the entire State data variable is returned. When
* $variable is set, then this method returns key of that $variable from $data array.
@@ -504,6 +551,20 @@ class WWW_Factory {
}
/**
+ * This method loads tools object if it doesn't exist yet and then allows to
+ * call various methods of the tool. You can call filesystem cleaner, indexer
+ * or a file-size calculator (and each work recursively).
+ *
+ * @param string $type the type of tool to be loaded
+ * @param mixed $arg1 additional parameter for the tool
+ * @param mixed $arg2 additional parameter for the tool
+ * @return mixed based on the tool
+ */
+ final protected function callTool($type,$arg1=false,$arg2=false){
+ return $this->WWW_API->state->callTool($type,$arg1,$arg2);
+ }
+
+ /**
* This is a wrapper method for Imager class method commands(). This method allows to load
* a file, edit a file and store a file in filesystem in just a single method call. $source
* should be the image file in filesystem, $command is the Wave Framework styled Image
View
67 engine/class.www-state.php
@@ -19,7 +19,7 @@
* @license GNU Lesser General Public License Version 3
* @tutorial /doc/pages/state.htm
* @since 1.0.0
- * @version 3.4.1
+ * @version 3.4.2
*/
class WWW_State {
@@ -65,6 +65,11 @@ class WWW_State {
private $messengerData=array();
/**
+ * This holds system Tool Class object, if it exists.
+ */
+ private $tools=false;
+
+ /**
* Construction of State object initializes the defaults for $data variable. A lot of the
* data is either loaded from /config.ini file or initialized based on server environment
* variables. Fingerprint string is also created during construction as well as input data
@@ -204,6 +209,7 @@ class WWW_State {
'sitemap-cache-timeout'=>14400,
'sitemap-raw'=>array(),
'static-root'=>false,
+ 'storage'=>array(),
'system-root'=>str_replace('engine'.DIRECTORY_SEPARATOR.'class.www-state.php','',__FILE__),
'test-database-host'=>false,
'test-database-name'=>false,
@@ -495,7 +501,7 @@ class WWW_State {
* @param mixed $value value of the new data
* @return boolean
*/
- final public function setState($variable,$value=true){
+ final public function setState($variable,$value=true,$subvalue=false){
// If variable is an array with values it assumes that array keys are variables and values are to be set for those variables
if(is_array($variable)){
@@ -1593,6 +1599,63 @@ class WWW_State {
return true;
}
+
+ // TOOLS
+
+ /**
+ * This method loads tools object if it doesn't exist yet and then allows to
+ * call various methods of the tool. You can call filesystem cleaner, indexer
+ * or a file-size calculator (and each work recursively).
+ *
+ * @param string $type the type of tool to be loaded
+ * @param mixed $arg1 additional parameter for the tool
+ * @param mixed $arg2 additional parameter for the tool
+ * @return mixed based on the tool
+ */
+ final public function callTool($type,$arg1=false,$arg2=false){
+
+ // If tool does not exist yet
+ if(!$this->tools){
+
+ // Loading the Imager class
+ if(!class_exists('WWW_Tools')){
+ require($this->data['system-root'].'engine'.DIRECTORY_SEPARATOR.'class.www-tools.php');
+ }
+
+ // Creating a new tool object
+ $this->tools=new WWW_Tools();
+
+ }
+
+ // Calling the method based on selected tool
+ switch($type){
+ case 'cleaner':
+ // This variable defines the cut-off time of the cleaner
+ if($arg2){
+ return $this->tools->cleaner($arg1,$arg2);
+ } else {
+ return $this->tools->cleaner($arg1);
+ }
+ break;
+ case 'indexer':
+ // This variable defines the mode of the index method
+ if($arg2){
+ return $this->tools->indexer($arg1,$arg2);
+ } else {
+ return $this->tools->indexer($arg1);
+ }
+ break;
+ case 'sizer':
+ // Takes just the directory variable
+ return $this->tools->sizer($arg1);
+ break;
+ default:
+ trigger_error('This tool does not exist: '.$type,E_USER_WARNING);
+ return false;
+ break;
+ }
+
+ }
// TERMINAL
View
298 engine/class.www-tools.php
@@ -0,0 +1,298 @@
+<?php
+
+/**
+ * Wave Framework <http://www.waveframework.com>
+ * Tools Class
+ *
+ * This class holds various functionality that also the /tools/ folder has itself. This allows
+ * the system to implement some of the tools functionality within the actual website itself, such
+ * as things like clearing cache in bulk, or returning an index of files from a folder.
+ *
+ * @package Tools
+ * @author Kristo Vaher <kristo@waher.net>
+ * @copyright Copyright (c) 2012, Kristo Vaher
+ * @license GNU Lesser General Public License Version 3
+ * @tutorial /doc/pages/tools.htm
+ * @since 3.4.2
+ * @version 3.4.2
+ */
+
+class WWW_Tools {
+
+ /**
+ * This is the filesystem directory of the website
+ */
+ public $filesystemDirectory=false;
+
+ /**
+ * During object construction you can set the filesystem directory that the tools can
+ * operate on.
+ *
+ * @param string $filesystemDirectory optional filesystem directory
+ * @return object
+ */
+ public function __construct($filesystemDirectory=false){
+ if(!$filesystemDirectory){
+ if(!defined('__ROOT__')){
+ define('__ROOT__',__DIR__.DIRECTORY_SEPARATOR);
+ }
+ $this->filesystemDirectory=__ROOT__.'filesystem'.DIRECTORY_SEPARATOR;
+ } else {
+ $this->filesystemDirectory=$filesystemDirectory;
+ }
+ }
+
+
+ /**
+ * This method cleans certain folders in filesystem. A cut-off timestamp can be set, which
+ * tells the cleaner not to delete certain files if their modification timestamp is newer.
+ *
+ * @param string|array $mode keywords for folders that will be cleaned
+ * @param integer $cutOff timestamp of last-modified on the files, after which the file will not be deleted
+ * @return array as a log
+ */
+ public function cleaner($mode='maintenance',$cutoff=false){
+
+ // This log array will be returned as a response
+ $log=array();
+
+ // If cutoff timestamp is not set, then every date is considered valid for cutoff
+ if(!$cutoff){
+ $cutoff=$_SERVER['REQUEST_TIME'];
+ }
+
+ // Mode can also be sent with an array
+ if(!is_array($mode)){
+ $mode=explode(',',$mode);
+ }
+
+ // Clears /filesystem/cache/output/
+ if(in_array('all',$mode) || in_array('output',$mode) || in_array('cache',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'cache'.DIRECTORY_SEPARATOR.'output'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears images cache
+ if(in_array('all',$mode) || in_array('images',$mode) || in_array('cache',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'cache'.DIRECTORY_SEPARATOR.'images'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears cache of JavaScript and CSS
+ if(in_array('all',$mode) || in_array('resources',$mode) || in_array('cache',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'cache'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears cache of JavaScript and CSS
+ if(in_array('all',$mode) || in_array('custom',$mode) || in_array('cache',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'cache'.DIRECTORY_SEPARATOR.'custom'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears cache tags
+ if(in_array('all',$mode) || in_array('tags',$mode) || in_array('cache',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'cache'.DIRECTORY_SEPARATOR.'tags'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears user sessions
+ if(in_array('all',$mode) || in_array('sessions',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'sessions'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears API session tokens
+ if(in_array('all',$mode) || in_array('tokens',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'tokens'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears cache of JavaScript and CSS
+ if(in_array('all',$mode) || in_array('messenger',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'messenger'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears request data of user agent IP's
+ if(in_array('all',$mode) || in_array('errors',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'errors'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears system log
+ if(in_array('all',$mode) || in_array('logs',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'logs'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears folder from everything that might be stored here
+ if(in_array('all',$mode) || in_array('tmp',$mode) || in_array('maintenance',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'tmp'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears request data of user agent IP's
+ if(in_array('all',$mode) || in_array('limiter',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'limiter'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears backups
+ if(in_array('all',$mode) || in_array('backups',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'backups'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears update archive
+ if(in_array('all',$mode) || in_array('updates',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'updates'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears database folder
+ if(in_array('all',$mode) || in_array('data',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'data'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears custom user data folder
+ if(in_array('all',$mode) || in_array('userdata',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'userdata'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears certificate and key folder
+ if(in_array('all',$mode) || in_array('keys',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'keys'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Clears static files from filesystem
+ if(in_array('all',$mode) || in_array('static',$mode)){
+ $log=array_merge($log,$this->directoryCleaner($this->filesystemDirectory.'static'.DIRECTORY_SEPARATOR,$cutoff));
+ }
+
+ // Returning the actions
+ return $log;
+
+ }
+
+ /**
+ * This function returns an index of files, folders or both recursively from the
+ * requested folder.
+ *
+ * @param string $directory the folder to browse through
+ * @param string $mode the mode that is used
+ * @return array as a list of files and folders found
+ */
+ public function indexer($directory,$mode='both'){
+
+ // File names are stored in this array
+ $index=array();
+
+ // Scanning the current directory
+ $files=scandir($directory);
+
+ // This will loop over all the files if files were found in this directory
+ if(!empty($files)){
+ foreach($files as $f){
+ // As long as the current file is not the current or parent directory
+ if($f!='.' && $f!='..'){
+ // If file is another directory then this is parsed recursively
+ if(is_dir($directory.$f)){
+ // File data from recursive parsing is merged with current files list
+ $index=array_merge($index,$this->indexer($directory.$f.DIRECTORY_SEPARATOR,$mode));
+ // Adding directory to index, if supported
+ if($mode=='both' || $mode=='folders'){
+ $index[]=$directory.$f.DIRECTORY_SEPARATOR;
+ }
+ } else {
+ // Adding file to index, if supported
+ if($mode=='both' || $mode=='files'){
+ $index[]=$directory.$f;
+ }
+ }
+ }
+ }
+ }
+
+ // Index is returned
+ return $index;
+
+ }
+
+ /**
+ * This function calculates the total file size in a folder and all of its subfolders.
+ *
+ * @param string $directory the file directory to check
+ * @return integer total size in bytes
+ */
+ public function sizer($directory){
+
+ // This variable will hold the total size
+ $size=0;
+
+ // Making sure that the directory exists
+ if(is_dir($directory)){
+ // Getting a list of all files in the folder
+ $files=$this->indexer($directory,'files');
+ if(!empty($files)){
+ // Adding each file size to the total
+ foreach($files as $file){
+ $size+=filesize($file);
+ }
+ }
+ } else {
+ // Throwing a warning
+ trigger_error('This folder does not exist: '.$directory,E_USER_WARNING);
+ }
+
+ // Returning the final file size in bytes
+ return $size;
+
+ }
+
+ /**
+ * This is an internal function used by cleaner() method to remove files and folders
+ * and return a log of the result.
+ *
+ * @param string $directory that will be cleaned
+ * @param integer $cutoff the cut-off timestamp
+ * @return array of all the files and what it did to those files
+ */
+ private function directoryCleaner($directory,$cutoff=0){
+
+ // Log will be stored in this array
+ $log=array();
+ // Scanning the directory for files
+ $files=$this->indexer($directory,'files');
+ // Scanning the directory for files
+ $folders=$this->indexer($directory,'folders');
+
+ // This will loop over all the files if files were found in this directory
+ if($files && !empty($files)){
+ foreach($files as $file){
+ // Testing if file modification date is older than the $cutoff timestamp
+ if(filemtime($file)<=$cutoff){
+ // Attempting to remove the file
+ if(unlink($file)){
+ $log[]='DELETED '.$file;
+ } else {
+ $log[]='FAILED '.$file;
+ }
+ } else {
+ $log[]='KEPT '.$file;
+ }
+ }
+ }
+
+ // This will loop over all the folders if folders were found in this directory
+ if($folders && !empty($folders)){
+ foreach($folders as $folder){
+ // Testing if the directory is empty
+ $contents=scandir($folder);
+ if(count($contents)<=2){
+ // Attempting to remove the folder
+ if(rmdir($folder)){
+ $log[]='DELETED '.$folder;
+ } else {
+ $log[]='FAILED '.$folder;
+ }
+ } else {
+ $log[]='NOT EMPTY '.$folder;
+ }
+ }
+ }
+
+ // Log is returned
+ return $log;
+
+ }
+
+}
+
+?>
View
10 engine/handler.api.php
@@ -15,7 +15,7 @@
* @license GNU Lesser General Public License Version 3
* @tutorial /doc/pages/handler_api.htm
* @since 1.5.0
- * @version 3.2.4
+ * @version 3.4.2
*/
//INITIALIZATION
@@ -53,10 +53,10 @@
// This functions file is not required, but can be used for system wide functions
// If you want to include additional libraries, do so here
- if(file_exists(__ROOT__.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'autoload.php')){
- require(__ROOT__.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'autoload.php');
- } else {
- require(__ROOT__.'resources'.DIRECTORY_SEPARATOR.'autoload.php');
+ if(file_exists(__ROOT__.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'script.php')){
+ require(__ROOT__.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'script.php');
+ } elseif(file_exists(__ROOT__.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'script.php')){
+ require(__ROOT__.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'script.php');
}
// LOADING API AND GATHERING INPUT DATA
View
2 engine/handler.appcache.php
@@ -1 +1 @@
-<?php
+<?php
View
30 engine/handler.data.php
@@ -16,7 +16,7 @@
* @license GNU Lesser General Public License Version 3
* @tutorial /doc/pages/handler_data.htm
* @since 1.5.0
- * @version 3.2.4
+ * @version 3.4.2
*/
// INITIALIZATION
@@ -31,6 +31,22 @@
if(isset($config['access-control'])){
header('Access-Control-Allow-Origin: '.$config['access-control']);
}
+
+ // This stores request header based cache timeout
+ $cacheLoad=-1;
+
+ // Setting cache timeout for HTTP request, used by Data Handler
+ if(isset($_SERVER['HTTP_CACHE_CONTROL'])){
+ if(trim($_SERVER['HTTP_CACHE_CONTROL'])=='no-cache'){
+ $cacheLoad=0;
+ } else {
+ // Finding the amount of allowed seconds
+ $raw=trim(str_replace('max-age=','',$_SERVER['HTTP_CACHE_CONTROL']));
+ if(is_numeric($raw)){
+ $cacheLoad=$raw;
+ }
+ }
+ }
// If index URL cache is not configured, it is turned off by default
if(!isset($config['index-url-cache-timeout'])){
@@ -64,10 +80,10 @@
// This functions file is not required, but can be used for system wide functions
// If you want to include additional libraries, do so here
- if(file_exists(__ROOT__.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'autoload.php')){
- require(__ROOT__.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'autoload.php');
- } else {
- require(__ROOT__.'resources'.DIRECTORY_SEPARATOR.'autoload.php');
+ if(file_exists(__ROOT__.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'script.php')){
+ require(__ROOT__.'overrides'.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'script.php');
+ } elseif(file_exists(__ROOT__.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'script.php')) {
+ require(__ROOT__.'resources'.DIRECTORY_SEPARATOR.'scripts'.DIRECTORY_SEPARATOR.'script.php');
}
// LOADING API AND CALLING URL SOLVING/ROUTING CONTROLLER
@@ -78,7 +94,7 @@
// This uses current request URI to find out which view should be loaded, by default it uses the request set by State
// API check is turned off, since index.php is considered a public gateway
- $view=$api->command(array('url'=>$state->data['true-request'],'www-command'=>'url-solve','www-output'=>0,'www-return-type'=>'php','www-cache-timeout'=>$config['index-url-cache-timeout']),false,false,true);
+ $view=$api->command(array('url'=>$state->data['true-request'],'www-command'=>'url-solve','www-output'=>0,'www-return-type'=>'php','www-cache-timeout'=>$config['index-url-cache-timeout'],'www-cache-load-timeout'=>$cacheLoad),false,false,true);
// CALLING DEFAULT VIEW CONTROLLER IF URL DID NOT ORDER A REDIRECTION
@@ -113,7 +129,7 @@
}
// API check is turned off, since index.php is considered a public gateway
- $api->command(array('www-command'=>$view['controller'].'-'.$view['controller-method'],'www-request'=>$state->data['true-request'],'www-return-type'=>'html','www-cache-tags'=>((isset($view['cache-tag']))?$view['cache-tag']:''),'www-cache-timeout'=>$config['index-view-cache-timeout'])+$inputData,false,false,true);
+ $api->command(array('www-command'=>$view['controller'].'-'.$view['controller-method'],'www-request'=>$state->data['true-request'],'www-return-type'=>'html','www-cache-tags'=>((isset($view['cache-tag']))?$view['cache-tag']:''),'www-cache-timeout'=>$config['index-view-cache-timeout'],'www-cache-load-timeout'=>$cacheLoad)+$inputData,false,false,true);
}
View
2 engine/handler.file.php
@@ -1 +1 @@
-<?php
+<?php
View
2 engine/handler.image.php
@@ -1 +1 @@
-<?php
+<?php
View
2 engine/handler.resource.php
@@ -1 +1 @@
-<?php
+<?php
View
2 engine/handler.robots.php
@@ -1 +1 @@
-<?php
+<?php
View
2 engine/handler.sitemap.php
@@ -1 +1 @@
-<?php
+<?php
View
132 models/model.example.php
@@ -36,8 +36,10 @@ class WWW_model_example extends WWW_Factory {
* @return boolean
*/
public function __initialize(){
+
// Do something here
return true;
+
}
/**
@@ -47,14 +49,23 @@ public function __initialize(){
* @return boolean
*/
public function load($id){
+
+ // Attempting to find the table row
// $data=$this->dbSingle('SELECT * FROM table WHERE id=?',array($id));
// if($data){
+ // Assigning data to object parameters
+ // $this->id=$data['id'];
+ // $this->name=$data['name'];
+
+ // This below is just an example without database, used in some tutorials
$this->id=$id;
$this->name='Lorem Ipsum #'.rand(1,1000); // This is used for simply testing cache
return true;
+
// } else {
// return false;
// }
+
}
/**
@@ -63,25 +74,130 @@ public function load($id){
* @return array
*/
public function get(){
+
// Current Data is returned as an array
return array(
- 'id' => $this->id,
+ 'id'=>$this->id,
'name'=>$this->name
);
+
+ }
+