initial commit
This commit is contained in:
commit
1cc4bf3572
254 changed files with 63622 additions and 0 deletions
htdocs/libraries/Nibble-Forms/Nibble/NibbleForms
570
htdocs/libraries/Nibble-Forms/Nibble/NibbleForms/NibbleForm.php
Normal file
570
htdocs/libraries/Nibble-Forms/Nibble/NibbleForms/NibbleForm.php
Normal file
|
@ -0,0 +1,570 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Nibble Forms 2 library
|
||||
* Copyright (c) 2013 Luke Rotherfield, Nibble Development
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Nibble\NibbleForms;
|
||||
|
||||
class NibbleForm
|
||||
{
|
||||
|
||||
protected $action, $method, $submit_value, $fields, $sticky, $format, $message_type, $multiple_errors, $html5;
|
||||
protected $valid = true;
|
||||
protected $name = 'nibble_form';
|
||||
protected $messages = array();
|
||||
protected $data = array();
|
||||
protected $formats
|
||||
= array(
|
||||
'list' => array(
|
||||
'open_form' => '<ul>',
|
||||
'close_form' => '</ul>',
|
||||
'open_form_body' => '',
|
||||
'close_form_body' => '',
|
||||
'open_field' => '',
|
||||
'close_field' => '',
|
||||
'open_html' => "<li>\n",
|
||||
'close_html' => "</li>\n",
|
||||
'open_submit' => "<li>\n",
|
||||
'close_submit' => "</li>\n"
|
||||
),
|
||||
'table' => array(
|
||||
'open_form' => '<table>',
|
||||
'close_form' => '</table>',
|
||||
'open_form_body' => '<tbody>',
|
||||
'close_form_body' => '</tbody>',
|
||||
'open_field' => "<tr>\n",
|
||||
'close_field' => "</tr>\n",
|
||||
'open_html' => "<td>\n",
|
||||
'close_html' => "</td>\n",
|
||||
'open_submit' => '<tfoot><tr><td>',
|
||||
'close_submit' => '</td></tr></tfoot>'
|
||||
)
|
||||
);
|
||||
protected static $instance = array();
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @param string $submit_value
|
||||
* @param string $method
|
||||
* @param boolean $sticky
|
||||
* @param string $message_type
|
||||
* @param string $format
|
||||
* @param string $multiple_errors
|
||||
*
|
||||
* @return NibbleForm
|
||||
*/
|
||||
public function __construct(
|
||||
$action,
|
||||
$submit_value,
|
||||
$html5,
|
||||
$method,
|
||||
$sticky,
|
||||
$message_type,
|
||||
$format,
|
||||
$multiple_errors
|
||||
) {
|
||||
$this->fields = new \stdClass();
|
||||
$this->action = $action;
|
||||
$this->method = $method;
|
||||
$this->html5 = $html5;
|
||||
$this->submit_value = $submit_value;
|
||||
$this->sticky = $sticky;
|
||||
$this->format = $format;
|
||||
$this->message_type = $message_type;
|
||||
$this->multiple_errors = $multiple_errors;
|
||||
spl_autoload_register(array($this, 'nibbleLoader'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton method
|
||||
*
|
||||
* @param string $action
|
||||
* @param string $method
|
||||
* @param boolean $sticky
|
||||
* @param string $submit_value
|
||||
* @param string $message_type
|
||||
* @param string $format
|
||||
* @param string $multiple_errors
|
||||
*
|
||||
* @return NibbleForm
|
||||
*/
|
||||
public static function getInstance(
|
||||
$name = '',
|
||||
$action = '',
|
||||
$html5 = true,
|
||||
$method = 'post',
|
||||
$submit_value = 'Submit',
|
||||
$format = 'list',
|
||||
$sticky = true,
|
||||
$message_type = 'list',
|
||||
$multiple_errors = false
|
||||
) {
|
||||
if (!isset(self::$instance[$name])) {
|
||||
self::$instance[$name]
|
||||
= new NibbleForm($action, $submit_value, $html5, $method, $sticky, $message_type, $format, $multiple_errors);
|
||||
}
|
||||
|
||||
return self::$instance[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Autoloader for nibble forms
|
||||
*
|
||||
* @param string $class
|
||||
*/
|
||||
public static function nibbleLoader($class)
|
||||
{
|
||||
$namespace = explode('\\', trim($class));
|
||||
foreach ($namespace as $key => $value) {
|
||||
if (empty($value)) {
|
||||
unset($namespace[$key]);
|
||||
}
|
||||
}
|
||||
$filepath = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $namespace) . '.php';
|
||||
if (file_exists($filepath)) {
|
||||
require_once $filepath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a field to the form instance
|
||||
*
|
||||
* @param string $field_name
|
||||
* @param string $type
|
||||
* @param array $attributes
|
||||
* @param boolean $overwrite
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function addField($field_name, $type = 'text', array $attributes = array(), $overwrite = false)
|
||||
{
|
||||
$namespace = "\\Nibble\\NibbleForms\\Field\\" . ucfirst($type);
|
||||
if (isset($attributes['label'])) {
|
||||
$label = $attributes['label'];
|
||||
} else {
|
||||
$label = ucfirst(str_replace('_', ' ', $field_name));
|
||||
}
|
||||
$field_name = Useful::slugify($field_name, '_');
|
||||
if (isset($this->fields->$field_name) && !$overwrite) {
|
||||
return false;
|
||||
}
|
||||
$this->fields->$field_name = new $namespace($label, $attributes);
|
||||
$this->fields->$field_name->setForm($this);
|
||||
|
||||
return $this->fields->$field_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the form
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get form name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get form method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data to populate the form
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function addData(array $data)
|
||||
{
|
||||
$this->data = array_merge($this->data, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the submitted form
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
$request = strtoupper($this->method) == 'POST' ? $_POST : $_GET;
|
||||
if (isset($request[$this->name])) {
|
||||
$form_data = $request[$this->name];
|
||||
} else {
|
||||
$this->valid = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
if ((isset($_SESSION["nibble_forms"]["_crsf_token"], $_SESSION["nibble_forms"]["_crsf_token"][$this->name])
|
||||
&& $form_data["_crsf_token"] !== $_SESSION["nibble_forms"]["_crsf_token"][$this->name])
|
||||
|| !isset($_SESSION["nibble_forms"]["_crsf_token"])
|
||||
|| !isset($form_data["_crsf_token"])
|
||||
) {
|
||||
$this->setMessages('CRSF token invalid', 'CRSF error');
|
||||
$this->valid = false;
|
||||
}
|
||||
$_SESSION["nibble_forms"]["_crsf_token"] = array();
|
||||
if ($this->sticky) {
|
||||
$this->addData($form_data);
|
||||
}
|
||||
foreach ($this->fields as $key => $value) {
|
||||
if (!$value->validate(
|
||||
(isset($form_data[$key])
|
||||
? $form_data[$key] : (isset($_FILES[$this->name][$key]) ? $_FILES[$this->name][$key] : ''))
|
||||
)
|
||||
) {
|
||||
$this->valid = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->valid;
|
||||
}
|
||||
|
||||
public function getData($key)
|
||||
{
|
||||
return isset($this->data[$key]) ? $this->data[$key] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the entire form including submit button, errors, form tags etc
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$fields = '';
|
||||
$error = $this->valid ? ''
|
||||
: '<p class="error">Sorry there were some errors in the form, problem fields have been highlighted</p>';
|
||||
$format = (object) $this->formats[$this->format];
|
||||
$this->setToken();
|
||||
|
||||
foreach ($this->fields as $key => $value) {
|
||||
$format = (object) $this->formats[$this->format];
|
||||
$temp = isset($this->data[$key]) ? $value->returnField($this->name, $key, $this->data[$key])
|
||||
: $value->returnField($this->name, $key);
|
||||
$fields .= $format->open_field;
|
||||
if ($temp['label']) {
|
||||
$fields .= $format->open_html . $temp['label'] . $format->close_html;
|
||||
}
|
||||
if (isset($temp['messages'])) {
|
||||
foreach ($temp['messages'] as $message) {
|
||||
if ($this->message_type == 'inline') {
|
||||
$fields .= "$format->open_html <p class=\"error\">$message</p> $format->close_html";
|
||||
} else {
|
||||
$this->setMessages($message, $key);
|
||||
}
|
||||
if (!$this->multiple_errors) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$fields .= $format->open_html . $temp['field'] . $format->close_html . $format->close_field;
|
||||
}
|
||||
|
||||
if (!empty($this->messages)) {
|
||||
$this->buildMessages();
|
||||
} else {
|
||||
$this->messages = false;
|
||||
}
|
||||
self::$instance = false;
|
||||
$attributes = $this->getFormAttributes();
|
||||
|
||||
return <<<FORM
|
||||
$error
|
||||
$this->messages
|
||||
<form class="form" action="$this->action" method="$this->method" {$attributes['enctype']} {$attributes['html5']}>
|
||||
$format->open_form
|
||||
$format->open_form_body
|
||||
$fields
|
||||
$format->close_form_body
|
||||
$format->open_submit
|
||||
<input type="submit" name="submit" value="$this->submit_value" />
|
||||
$format->close_submit
|
||||
$format->close_form
|
||||
</form>
|
||||
FORM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML for a specific form field ususally in the form of input tags
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderField($name)
|
||||
{
|
||||
return $this->getFieldData($name, 'field');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML for a specific form field's label
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderLabel($name)
|
||||
{
|
||||
return $this->getFieldData($name, 'label');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error string for a specific form field
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderError($name)
|
||||
{
|
||||
$error_string = '';
|
||||
if (!is_array($this->getFieldData($name, 'messages'))) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->getFieldData($name, 'messages') as $error) {
|
||||
$error_string .= "<li>$error</li>";
|
||||
}
|
||||
|
||||
return $error_string === '' ? false : "<ul>$error_string</ul>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the boolean depending on existance of errors for specified
|
||||
* form field
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasError($name)
|
||||
{
|
||||
$errors = $this->getFieldData($name, 'messages');
|
||||
if (!$errors || !is_array($errors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entire HTML structure for a form field
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderRow($name)
|
||||
{
|
||||
$row_string = $this->renderError($name);
|
||||
$row_string .= $this->renderLabel($name);
|
||||
$row_string .= $this->renderField($name);
|
||||
|
||||
return $row_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML for all hidden fields including crsf protection
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderHidden()
|
||||
{
|
||||
$this->setToken();
|
||||
$fields = array();
|
||||
foreach ($this->fields as $name => $field) {
|
||||
if (get_class($field) == 'Nibble\\NibbleForms\\Field\\Hidden') {
|
||||
if (isset($this->data[$name])) {
|
||||
$field_data = $field->returnField($this->name, $name, $this->data[$name]);
|
||||
} else {
|
||||
$field_data = $field->returnField($this->name, $name);
|
||||
}
|
||||
$fields[] = $field_data['field'];
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n", $fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML string for all errors in the form
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderErrors()
|
||||
{
|
||||
$error_string = '';
|
||||
foreach (array_keys($this->fields) as $name) {
|
||||
foreach ($this->getFieldData($name, 'messages') as $error) {
|
||||
$error_string .= "<li>$error</li>\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $error_string === '' ? false : "<ul>$error_string</ul>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML string for opening a form with the correct enctype, action and method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function openForm()
|
||||
{
|
||||
$attributes = $this->getFormAttributes();
|
||||
|
||||
return "<form class=\"form\" action=\"$this->action\" method=\"$this->method\" {$attributes['enctype']} {$attributes['html5']}>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return close form tag
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function closeForm()
|
||||
{
|
||||
return "</form>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a field exists
|
||||
*
|
||||
* @param string $field
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkField($field)
|
||||
{
|
||||
return isset($this->fields->$field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attributes for the form tag
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getFormAttributes()
|
||||
{
|
||||
$enctype = '';
|
||||
foreach ($this->fields as $field) {
|
||||
if (get_class($field) == 'File') {
|
||||
$enctype = 'enctype="multipart/form-data"';
|
||||
}
|
||||
}
|
||||
$html5 = $this->html5 ? '' : 'novalidate';
|
||||
|
||||
return array(
|
||||
'enctype' => $enctype,
|
||||
'html5' => $html5
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a message string to the class messages array
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $title
|
||||
*/
|
||||
private function setMessages($message, $title)
|
||||
{
|
||||
$title = preg_replace('/_/', ' ', ucfirst($title));
|
||||
if ($this->message_type == 'list') {
|
||||
$this->messages[] = array('title' => $title, 'message' => ucfirst($message));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the messages array as an HTML string
|
||||
*/
|
||||
private function buildMessages()
|
||||
{
|
||||
$messages = '<ul class="error">';
|
||||
foreach ($this->messages as $message_array) {
|
||||
$messages .= sprintf(
|
||||
'<li>%s: %s</li>%s',
|
||||
ucfirst(preg_replace('/_/', ' ', $message_array['title'])),
|
||||
ucfirst($message_array['message']),
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
$this->messages = $messages . '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a specific field HTML string from the field class
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getFieldData($name, $key)
|
||||
{
|
||||
if (!$this->checkField($name)) {
|
||||
return false;
|
||||
}
|
||||
$field = $this->fields->$name;
|
||||
if (isset($this->data[$name])) {
|
||||
$field = $field->returnField($this->name, $name, $this->data[$name]);
|
||||
} else {
|
||||
$field = $field->returnField($this->name, $name);
|
||||
}
|
||||
|
||||
return $field[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CRSF token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function setToken()
|
||||
{
|
||||
if (!isset($_SESSION["nibble_forms"])) {
|
||||
$_SESSION["nibble_forms"] = array();
|
||||
}
|
||||
if (!isset($_SESSION["nibble_forms"]["_crsf_token"])) {
|
||||
$_SESSION["nibble_forms"]["_crsf_token"] = array();
|
||||
}
|
||||
$_SESSION["nibble_forms"]["_crsf_token"][$this->name] = Useful::randomString(20);
|
||||
$this->addField("_crsf_token", "hidden");
|
||||
$this->addData(array("_crsf_token" => $_SESSION["nibble_forms"]["_crsf_token"][$this->name]));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue