First commit
This commit is contained in:
1
vendor/.htaccess
vendored
Normal file
1
vendor/.htaccess
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Deny from all
|
||||
20
vendor/Parsedown/LICENSE.txt
vendored
Normal file
20
vendor/Parsedown/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Emanuil Rusev, erusev.com
|
||||
|
||||
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.
|
||||
991
vendor/Parsedown/Parsedown.php
vendored
Normal file
991
vendor/Parsedown/Parsedown.php
vendored
Normal file
@@ -0,0 +1,991 @@
|
||||
<?php
|
||||
|
||||
#
|
||||
#
|
||||
# Parsedown
|
||||
# http://parsedown.org
|
||||
#
|
||||
# (c) Emanuil Rusev
|
||||
# http://erusev.com
|
||||
#
|
||||
# For the full license information, please view the LICENSE file that was
|
||||
# distributed with this source code.
|
||||
#
|
||||
#
|
||||
|
||||
class Parsedown
|
||||
{
|
||||
#
|
||||
# Multiton (http://en.wikipedia.org/wiki/Multiton_pattern)
|
||||
#
|
||||
|
||||
static function instance($name = 'default')
|
||||
{
|
||||
if (isset(self::$instances[$name]))
|
||||
return self::$instances[$name];
|
||||
|
||||
$instance = new Parsedown();
|
||||
|
||||
self::$instances[$name] = $instance;
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
private static $instances = array();
|
||||
|
||||
#
|
||||
# Setters
|
||||
#
|
||||
|
||||
private $break_marker = " \n";
|
||||
|
||||
function set_breaks_enabled($breaks_enabled)
|
||||
{
|
||||
$this->break_marker = $breaks_enabled ? "\n" : " \n";
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
#
|
||||
# Fields
|
||||
#
|
||||
|
||||
private $reference_map = array();
|
||||
private $escape_sequence_map = array();
|
||||
|
||||
#
|
||||
# Public Methods
|
||||
#
|
||||
|
||||
function parse($text)
|
||||
{
|
||||
# removes UTF-8 BOM and marker characters
|
||||
$text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
|
||||
|
||||
# removes \r characters
|
||||
$text = str_replace("\r\n", "\n", $text);
|
||||
$text = str_replace("\r", "\n", $text);
|
||||
|
||||
# replaces tabs with spaces
|
||||
$text = str_replace("\t", ' ', $text);
|
||||
|
||||
# encodes escape sequences
|
||||
|
||||
if (strpos($text, '\\') !== FALSE)
|
||||
{
|
||||
$escape_sequences = array('\\\\', '\`', '\*', '\_', '\{', '\}', '\[', '\]', '\(', '\)', '\>', '\#', '\+', '\-', '\.', '\!');
|
||||
|
||||
foreach ($escape_sequences as $index => $escape_sequence)
|
||||
{
|
||||
if (strpos($text, $escape_sequence) !== FALSE)
|
||||
{
|
||||
$code = "\x1A".'\\'.$index.';';
|
||||
|
||||
$text = str_replace($escape_sequence, $code, $text);
|
||||
|
||||
$this->escape_sequence_map[$code] = $escape_sequence;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ~
|
||||
|
||||
$text = preg_replace('/\n\s*\n/', "\n\n", $text);
|
||||
$text = trim($text, "\n");
|
||||
|
||||
$lines = explode("\n", $text);
|
||||
|
||||
$text = $this->parse_block_elements($lines);
|
||||
|
||||
# decodes escape sequences
|
||||
|
||||
foreach ($this->escape_sequence_map as $code => $escape_sequence)
|
||||
{
|
||||
$text = str_replace($code, $escape_sequence[1], $text);
|
||||
}
|
||||
|
||||
# ~
|
||||
|
||||
$text = rtrim($text, "\n");
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
#
|
||||
# Private Methods
|
||||
#
|
||||
|
||||
private function parse_block_elements(array $lines, $context = '')
|
||||
{
|
||||
$elements = array();
|
||||
|
||||
$element = array(
|
||||
'type' => '',
|
||||
);
|
||||
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
# fenced elements
|
||||
|
||||
switch ($element['type'])
|
||||
{
|
||||
case 'fenced_code_block':
|
||||
|
||||
if ( ! isset($element['closed']))
|
||||
{
|
||||
if (preg_match('/^[ ]*'.$element['fence'][0].'{3,}[ ]*$/', $line))
|
||||
{
|
||||
$element['closed'] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$element['text'] !== '' and $element['text'] .= "\n";
|
||||
|
||||
$element['text'] .= $line;
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'markup':
|
||||
|
||||
if ( ! isset($element['closed']))
|
||||
{
|
||||
if (preg_match('{<'.$element['subtype'].'>$}', $line)) # opening tag
|
||||
{
|
||||
$element['depth']++;
|
||||
}
|
||||
|
||||
if (preg_match('{</'.$element['subtype'].'>$}', $line)) # closing tag
|
||||
{
|
||||
$element['depth'] > 0
|
||||
? $element['depth']--
|
||||
: $element['closed'] = true;
|
||||
}
|
||||
|
||||
$element['text'] .= "\n".$line;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
# *
|
||||
|
||||
if ($line === '')
|
||||
{
|
||||
$element['interrupted'] = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
# composite elements
|
||||
|
||||
switch ($element['type'])
|
||||
{
|
||||
case 'blockquote':
|
||||
|
||||
if ( ! isset($element['interrupted']))
|
||||
{
|
||||
$line = preg_replace('/^[ ]*>[ ]?/', '', $line);
|
||||
|
||||
$element['lines'] []= $line;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'li':
|
||||
|
||||
if (preg_match('/^([ ]{0,3})(\d+[.]|[*+-])[ ](.*)/', $line, $matches))
|
||||
{
|
||||
if ($element['indentation'] !== $matches[1])
|
||||
{
|
||||
$element['lines'] []= $line;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($element['last']);
|
||||
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'li',
|
||||
'indentation' => $matches[1],
|
||||
'last' => true,
|
||||
'lines' => array(
|
||||
preg_replace('/^[ ]{0,4}/', '', $matches[3]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if (isset($element['interrupted']))
|
||||
{
|
||||
if ($line[0] === ' ')
|
||||
{
|
||||
$element['lines'] []= '';
|
||||
|
||||
$line = preg_replace('/^[ ]{0,4}/', '', $line);
|
||||
|
||||
$element['lines'] []= $line;
|
||||
|
||||
unset($element['interrupted']);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$line = preg_replace('/^[ ]{0,4}/', '', $line);
|
||||
|
||||
$element['lines'] []= $line;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
# indentation sensitive types
|
||||
|
||||
$deindented_line = $line;
|
||||
|
||||
switch ($line[0])
|
||||
{
|
||||
case ' ':
|
||||
|
||||
# ~
|
||||
|
||||
$deindented_line = ltrim($line);
|
||||
|
||||
if ($deindented_line === '')
|
||||
{
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# code block
|
||||
|
||||
if (preg_match('/^[ ]{4}(.*)/', $line, $matches))
|
||||
{
|
||||
if ($element['type'] === 'code_block')
|
||||
{
|
||||
if (isset($element['interrupted']))
|
||||
{
|
||||
$element['text'] .= "\n";
|
||||
|
||||
unset ($element['interrupted']);
|
||||
}
|
||||
|
||||
$element['text'] .= "\n".$matches[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'code_block',
|
||||
'text' => $matches[1],
|
||||
);
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '#':
|
||||
|
||||
# atx heading (#)
|
||||
|
||||
if (preg_match('/^(#{1,6})[ ]*(.+?)[ ]*#*$/', $line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$level = strlen($matches[1]);
|
||||
|
||||
$element = array(
|
||||
'type' => 'h.',
|
||||
'text' => $matches[2],
|
||||
'level' => $level,
|
||||
);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '-':
|
||||
|
||||
# setext heading (---)
|
||||
|
||||
if ($line[0] === '-' and $element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[-]+[ ]*$/', $line))
|
||||
{
|
||||
$element['type'] = 'h.';
|
||||
$element['level'] = 2;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '=':
|
||||
|
||||
# setext heading (===)
|
||||
|
||||
if ($line[0] === '=' and $element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[=]+[ ]*$/', $line))
|
||||
{
|
||||
$element['type'] = 'h.';
|
||||
$element['level'] = 1;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
# indentation insensitive types
|
||||
|
||||
switch ($deindented_line[0])
|
||||
{
|
||||
case '<':
|
||||
|
||||
# self-closing tag
|
||||
|
||||
if (preg_match('{^<.+?/>$}', $deindented_line))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => '',
|
||||
'text' => $deindented_line,
|
||||
);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# opening tag
|
||||
|
||||
if (preg_match('{^<(\w+)(?:[ ].*?)?>}', $deindented_line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'markup',
|
||||
'subtype' => strtolower($matches[1]),
|
||||
'text' => $deindented_line,
|
||||
'depth' => 0,
|
||||
);
|
||||
|
||||
preg_match('{</'.$matches[1].'>\s*$}', $deindented_line) and $element['closed'] = true;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '>':
|
||||
|
||||
# quote
|
||||
|
||||
if (preg_match('/^>[ ]?(.*)/', $deindented_line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'blockquote',
|
||||
'lines' => array(
|
||||
$matches[1],
|
||||
),
|
||||
);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '[':
|
||||
|
||||
# reference
|
||||
|
||||
if (preg_match('/^\[(.+?)\]:[ ]*(.+?)(?:[ ]+[\'"](.+?)[\'"])?[ ]*$/', $deindented_line, $matches))
|
||||
{
|
||||
$label = strtolower($matches[1]);
|
||||
|
||||
$this->reference_map[$label] = array(
|
||||
'»' => trim($matches[2], '<>'),
|
||||
);
|
||||
|
||||
if (isset($matches[3]))
|
||||
{
|
||||
$this->reference_map[$label]['#'] = $matches[3];
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '`':
|
||||
case '~':
|
||||
|
||||
# fenced code block
|
||||
|
||||
if (preg_match('/^([`]{3,}|[~]{3,})[ ]*(\S+)?[ ]*$/', $deindented_line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'fenced_code_block',
|
||||
'text' => '',
|
||||
'fence' => $matches[1],
|
||||
);
|
||||
|
||||
isset($matches[2]) and $element['language'] = $matches[2];
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '*':
|
||||
case '+':
|
||||
case '-':
|
||||
case '_':
|
||||
|
||||
# hr
|
||||
|
||||
if (preg_match('/^([-*_])([ ]{0,2}\1){2,}[ ]*$/', $deindented_line))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'hr',
|
||||
);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# li
|
||||
|
||||
if (preg_match('/^([ ]*)[*+-][ ](.*)/', $line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'li',
|
||||
'ordered' => false,
|
||||
'indentation' => $matches[1],
|
||||
'last' => true,
|
||||
'lines' => array(
|
||||
preg_replace('/^[ ]{0,4}/', '', $matches[2]),
|
||||
),
|
||||
);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
# li
|
||||
|
||||
if ($deindented_line[0] <= '9' and $deindented_line >= '0' and preg_match('/^([ ]*)\d+[.][ ](.*)/', $line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'li',
|
||||
'ordered' => true,
|
||||
'indentation' => $matches[1],
|
||||
'last' => true,
|
||||
'lines' => array(
|
||||
preg_replace('/^[ ]{0,4}/', '', $matches[2]),
|
||||
),
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
# paragraph
|
||||
|
||||
if ($element['type'] === 'p')
|
||||
{
|
||||
if (isset($element['interrupted']))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element['text'] = $line;
|
||||
|
||||
unset($element['interrupted']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$element['text'] .= "\n".$line;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'p',
|
||||
'text' => $line,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$elements []= $element;
|
||||
|
||||
unset($elements[0]);
|
||||
|
||||
#
|
||||
# ~
|
||||
#
|
||||
|
||||
$markup = '';
|
||||
|
||||
foreach ($elements as $element)
|
||||
{
|
||||
switch ($element['type'])
|
||||
{
|
||||
case 'p':
|
||||
|
||||
$text = $this->parse_span_elements($element['text']);
|
||||
|
||||
if ($context === 'li' and $markup === '')
|
||||
{
|
||||
if (isset($element['interrupted']))
|
||||
{
|
||||
$markup .= "\n".'<p>'.$text.'</p>'."\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= $text;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= '<p>'.$text.'</p>'."\n";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'blockquote':
|
||||
|
||||
$text = $this->parse_block_elements($element['lines']);
|
||||
|
||||
$markup .= '<blockquote>'."\n".$text.'</blockquote>'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'code_block':
|
||||
case 'fenced_code_block':
|
||||
|
||||
$text = htmlspecialchars($element['text'], ENT_NOQUOTES, 'UTF-8');
|
||||
|
||||
strpos($text, "\x1A\\") !== FALSE and $text = strtr($text, $this->escape_sequence_map);
|
||||
|
||||
$markup .= isset($element['language'])
|
||||
? '<pre><code class="language-'.$element['language'].'">'.$text.'</code></pre>'
|
||||
: '<pre><code>'.$text.'</code></pre>';
|
||||
|
||||
$markup .= "\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'h.':
|
||||
|
||||
$text = $this->parse_span_elements($element['text']);
|
||||
|
||||
$markup .= '<h'.$element['level'].'>'.$text.'</h'.$element['level'].'>'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'hr':
|
||||
|
||||
$markup .= '<hr />'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'li':
|
||||
|
||||
if (isset($element['ordered'])) # first
|
||||
{
|
||||
$list_type = $element['ordered'] ? 'ol' : 'ul';
|
||||
|
||||
$markup .= '<'.$list_type.'>'."\n";
|
||||
}
|
||||
|
||||
if (isset($element['interrupted']) and ! isset($element['last']))
|
||||
{
|
||||
$element['lines'] []= '';
|
||||
}
|
||||
|
||||
$text = $this->parse_block_elements($element['lines'], 'li');
|
||||
|
||||
$markup .= '<li>'.$text.'</li>'."\n";
|
||||
|
||||
isset($element['last']) and $markup .= '</'.$list_type.'>'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'markup':
|
||||
|
||||
$markup .= $this->parse_span_elements($element['text'])."\n";
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
$markup .= $element['text']."\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $markup;
|
||||
}
|
||||
|
||||
# ~
|
||||
|
||||
private $strong_regex = array(
|
||||
'*' => '/^[*]{2}([^*]+?)[*]{2}(?![*])/s',
|
||||
'_' => '/^__([^_]+?)__(?!_)/s',
|
||||
);
|
||||
|
||||
private $em_regex = array(
|
||||
'*' => '/^[*]([^*]+?)[*](?![*])/s',
|
||||
'_' => '/^_([^_]+?)[_](?![_])\b/s',
|
||||
);
|
||||
|
||||
private $strong_em_regex = array(
|
||||
'*' => '/^[*]{2}(.*?)[*](.+?)[*](.*?)[*]{2}/s',
|
||||
'_' => '/^__(.*?)_(.+?)_(.*?)__/s',
|
||||
);
|
||||
|
||||
private $em_strong_regex = array(
|
||||
'*' => '/^[*](.*?)[*]{2}(.+?)[*]{2}(.*?)[*]/s',
|
||||
'_' => '/^_(.*?)__(.+?)__(.*?)_/s',
|
||||
);
|
||||
|
||||
private function parse_span_elements($text, $markers = array('![', '&', '*', '<', '[', '_', '`', 'http', '~~'))
|
||||
{
|
||||
if (isset($text[2]) === false or $markers === array())
|
||||
{
|
||||
return $text;
|
||||
}
|
||||
|
||||
# ~
|
||||
|
||||
$markup = '';
|
||||
|
||||
while ($markers)
|
||||
{
|
||||
$closest_marker = null;
|
||||
$closest_marker_index = 0;
|
||||
$closest_marker_position = null;
|
||||
|
||||
foreach ($markers as $index => $marker)
|
||||
{
|
||||
$marker_position = strpos($text, $marker);
|
||||
|
||||
if ($marker_position === false)
|
||||
{
|
||||
unset($markers[$index]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($closest_marker === null or $marker_position < $closest_marker_position)
|
||||
{
|
||||
$closest_marker = $marker;
|
||||
$closest_marker_index = $index;
|
||||
$closest_marker_position = $marker_position;
|
||||
}
|
||||
}
|
||||
|
||||
# ~
|
||||
|
||||
if ($closest_marker === null or isset($text[$closest_marker_position + 2]) === false)
|
||||
{
|
||||
$markup .= $text;
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= substr($text, 0, $closest_marker_position);
|
||||
}
|
||||
|
||||
$text = substr($text, $closest_marker_position);
|
||||
|
||||
# ~
|
||||
|
||||
unset($markers[$closest_marker_index]);
|
||||
|
||||
# ~
|
||||
|
||||
switch ($closest_marker)
|
||||
{
|
||||
case '![':
|
||||
case '[':
|
||||
|
||||
if (strpos($text, ']') and preg_match('/\[((?:[^][]|(?R))*)\]/', $text, $matches))
|
||||
{
|
||||
$element = array(
|
||||
'!' => $text[0] === '!',
|
||||
'a' => $matches[1],
|
||||
);
|
||||
|
||||
$offset = strlen($matches[0]);
|
||||
|
||||
$element['!'] and $offset++;
|
||||
|
||||
$remaining_text = substr($text, $offset);
|
||||
|
||||
if ($remaining_text[0] === '(' and preg_match('/\([ ]*(.*?)(?:[ ]+[\'"](.+?)[\'"])?[ ]*\)/', $remaining_text, $matches))
|
||||
{
|
||||
$element['»'] = $matches[1];
|
||||
|
||||
if (isset($matches[2]))
|
||||
{
|
||||
$element['#'] = $matches[2];
|
||||
}
|
||||
|
||||
$offset += strlen($matches[0]);
|
||||
}
|
||||
elseif ($this->reference_map)
|
||||
{
|
||||
$reference = $element['a'];
|
||||
|
||||
if (preg_match('/^\s*\[(.*?)\]/', $remaining_text, $matches))
|
||||
{
|
||||
$reference = $matches[1] ? $matches[1] : $element['a'];
|
||||
|
||||
$offset += strlen($matches[0]);
|
||||
}
|
||||
|
||||
$reference = strtolower($reference);
|
||||
|
||||
if (isset($this->reference_map[$reference]))
|
||||
{
|
||||
$element['»'] = $this->reference_map[$reference]['»'];
|
||||
|
||||
if (isset($this->reference_map[$reference]['#']))
|
||||
{
|
||||
$element['#'] = $this->reference_map[$reference]['#'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($element);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($element);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($element))
|
||||
{
|
||||
$element['»'] = str_replace('&', '&', $element['»']);
|
||||
$element['»'] = str_replace('<', '<', $element['»']);
|
||||
|
||||
if ($element['!'])
|
||||
{
|
||||
$markup .= '<img alt="'.$element['a'].'" src="'.$element['»'].'" />';
|
||||
}
|
||||
else
|
||||
{
|
||||
$element['a'] = $this->parse_span_elements($element['a'], $markers);
|
||||
|
||||
$markup .= isset($element['#'])
|
||||
? '<a href="'.$element['»'].'" title="'.$element['#'].'">'.$element['a'].'</a>'
|
||||
: '<a href="'.$element['»'].'">'.$element['a'].'</a>';
|
||||
}
|
||||
|
||||
unset($element);
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= $closest_marker;
|
||||
|
||||
$offset = $closest_marker === '![' ? 2 : 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '&':
|
||||
|
||||
$markup .= '&';
|
||||
|
||||
$offset = substr($text, 0, 5) === '&' ? 5 : 1;
|
||||
|
||||
break;
|
||||
|
||||
case '*':
|
||||
case '_':
|
||||
|
||||
if ($text[1] === $closest_marker and preg_match($this->strong_regex[$closest_marker], $text, $matches))
|
||||
{
|
||||
$matches[1] = $this->parse_span_elements($matches[1], $markers);
|
||||
|
||||
$markup .= '<strong>'.$matches[1].'</strong>';
|
||||
}
|
||||
elseif (preg_match($this->em_regex[$closest_marker], $text, $matches))
|
||||
{
|
||||
$matches[1] = $this->parse_span_elements($matches[1], $markers);
|
||||
|
||||
$markup .= '<em>'.$matches[1].'</em>';
|
||||
}
|
||||
elseif ($text[1] === $closest_marker and preg_match($this->strong_em_regex[$closest_marker], $text, $matches))
|
||||
{
|
||||
$matches[2] = $this->parse_span_elements($matches[2], $markers);
|
||||
|
||||
$matches[1] and $matches[1] = $this->parse_span_elements($matches[1], $markers);
|
||||
$matches[3] and $matches[3] = $this->parse_span_elements($matches[3], $markers);
|
||||
|
||||
$markup .= '<strong>'.$matches[1].'<em>'.$matches[2].'</em>'.$matches[3].'</strong>';
|
||||
}
|
||||
elseif (preg_match($this->em_strong_regex[$closest_marker], $text, $matches))
|
||||
{
|
||||
$matches[2] = $this->parse_span_elements($matches[2], $markers);
|
||||
|
||||
$matches[1] and $matches[1] = $this->parse_span_elements($matches[1], $markers);
|
||||
$matches[3] and $matches[3] = $this->parse_span_elements($matches[3], $markers);
|
||||
|
||||
$markup .= '<em>'.$matches[1].'<strong>'.$matches[2].'</strong>'.$matches[3].'</em>';
|
||||
}
|
||||
|
||||
if (isset($matches) and $matches)
|
||||
{
|
||||
$offset = strlen($matches[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= $closest_marker;
|
||||
|
||||
$offset = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '<':
|
||||
|
||||
if (strpos($text, '>') !== false)
|
||||
{
|
||||
if ($text[1] === 'h' and preg_match('/^<(https?:[\/]{2}[^\s]+?)>/i', $text, $matches))
|
||||
{
|
||||
$element_url = $matches[1];
|
||||
$element_url = str_replace('&', '&', $element_url);
|
||||
$element_url = str_replace('<', '<', $element_url);
|
||||
|
||||
$markup .= '<a href="'.$element_url.'">'.$element_url.'</a>';
|
||||
|
||||
$offset = strlen($matches[0]);
|
||||
}
|
||||
elseif (preg_match('/^<\/?\w.*?>/', $text, $matches))
|
||||
{
|
||||
$markup .= $matches[0];
|
||||
|
||||
$offset = strlen($matches[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= '<';
|
||||
|
||||
$offset = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= '<';
|
||||
|
||||
$offset = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '`':
|
||||
|
||||
if (preg_match('/^`(.+?)`/', $text, $matches))
|
||||
{
|
||||
$element_text = $matches[1];
|
||||
$element_text = htmlspecialchars($element_text, ENT_NOQUOTES, 'UTF-8');
|
||||
|
||||
if ($this->escape_sequence_map and strpos($element_text, "\x1A") !== false)
|
||||
{
|
||||
$element_text = strtr($element_text, $this->escape_sequence_map);
|
||||
}
|
||||
|
||||
$markup .= '<code>'.$element_text.'</code>';
|
||||
|
||||
$offset = strlen($matches[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= '`';
|
||||
|
||||
$offset = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'http':
|
||||
|
||||
if (preg_match('/^https?:[\/]{2}[^\s]+\b/i', $text, $matches))
|
||||
{
|
||||
$element_url = $matches[0];
|
||||
$element_url = str_replace('&', '&', $element_url);
|
||||
$element_url = str_replace('<', '<', $element_url);
|
||||
|
||||
$markup .= '<a href="'.$element_url.'">'.$element_url.'</a>';
|
||||
|
||||
$offset = strlen($matches[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= 'http';
|
||||
|
||||
$offset = 4;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '~~':
|
||||
|
||||
if (preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $text, $matches))
|
||||
{
|
||||
$matches[1] = $this->parse_span_elements($matches[1], $markers);
|
||||
|
||||
$markup .= '<del>'.$matches[1].'</del>';
|
||||
|
||||
$offset = strlen($matches[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= '~~';
|
||||
|
||||
$offset = 2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($offset))
|
||||
{
|
||||
$text = substr($text, $offset);
|
||||
}
|
||||
|
||||
$markers[$closest_marker_index] = $closest_marker;
|
||||
}
|
||||
|
||||
$markup = str_replace($this->break_marker, '<br />'."\n", $markup);
|
||||
|
||||
return $markup;
|
||||
}
|
||||
}
|
||||
108
vendor/PicoDb/Database.php
vendored
Normal file
108
vendor/PicoDb/Database.php
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace PicoDb;
|
||||
|
||||
class Database
|
||||
{
|
||||
private $logs = array();
|
||||
private $pdo;
|
||||
|
||||
|
||||
public function __construct(array $settings)
|
||||
{
|
||||
if (! isset($settings['driver'])) {
|
||||
|
||||
throw new \LogicException('You must define a database driver.');
|
||||
}
|
||||
|
||||
switch ($settings['driver']) {
|
||||
|
||||
case 'sqlite':
|
||||
require_once __DIR__.'/Drivers/Sqlite.php';
|
||||
$this->pdo = new Sqlite($settings['filename']);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \LogicException('This database driver is not supported.');
|
||||
}
|
||||
|
||||
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
}
|
||||
|
||||
|
||||
public function setLogMessage($message)
|
||||
{
|
||||
$this->logs[] = $message;
|
||||
}
|
||||
|
||||
|
||||
public function getLogMessages()
|
||||
{
|
||||
return $this->logs;
|
||||
}
|
||||
|
||||
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->pdo;
|
||||
}
|
||||
|
||||
|
||||
public function escapeIdentifier($value)
|
||||
{
|
||||
return $this->pdo->escapeIdentifier($value);
|
||||
}
|
||||
|
||||
|
||||
public function execute($sql, array $values = array())
|
||||
{
|
||||
try {
|
||||
|
||||
$this->setLogMessage($sql);
|
||||
$this->setLogMessage(implode(', ', $values));
|
||||
|
||||
$rq = $this->pdo->prepare($sql);
|
||||
$rq->execute($values);
|
||||
|
||||
return $rq;
|
||||
}
|
||||
catch (\PDOException $e) {
|
||||
|
||||
if ($this->pdo->inTransaction()) $this->pdo->rollback();
|
||||
$this->setLogMessage($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function startTransaction()
|
||||
{
|
||||
$this->pdo->beginTransaction();
|
||||
}
|
||||
|
||||
|
||||
public function closeTransaction()
|
||||
{
|
||||
$this->pdo->commit();
|
||||
}
|
||||
|
||||
|
||||
public function cancelTransaction()
|
||||
{
|
||||
$this->pdo->rollback();
|
||||
}
|
||||
|
||||
|
||||
public function table($table_name)
|
||||
{
|
||||
require_once __DIR__.'/Table.php';
|
||||
return new Table($this, $table_name);
|
||||
}
|
||||
|
||||
|
||||
public function schema()
|
||||
{
|
||||
require_once __DIR__.'/Schema.php';
|
||||
return new Schema($this);
|
||||
}
|
||||
}
|
||||
48
vendor/PicoDb/Drivers/Sqlite.php
vendored
Normal file
48
vendor/PicoDb/Drivers/Sqlite.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace PicoDb;
|
||||
|
||||
class Sqlite extends \PDO {
|
||||
|
||||
|
||||
public function __construct($filename)
|
||||
{
|
||||
parent::__construct('sqlite:'.$filename);
|
||||
|
||||
$this->exec('PRAGMA foreign_keys = ON');
|
||||
}
|
||||
|
||||
|
||||
public function getSchemaVersion()
|
||||
{
|
||||
$rq = $this->prepare('PRAGMA user_version');
|
||||
$rq->execute();
|
||||
$result = $rq->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
if (isset($result['user_version'])) {
|
||||
|
||||
return $result['user_version'];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public function setSchemaVersion($version)
|
||||
{
|
||||
$this->exec('PRAGMA user_version='.$version);
|
||||
}
|
||||
|
||||
|
||||
public function getLastId()
|
||||
{
|
||||
return $this->lastInsertId();
|
||||
}
|
||||
|
||||
|
||||
public function escapeIdentifier($value)
|
||||
{
|
||||
if (strpos($value, '.') !== false) return $value;
|
||||
return '"'.$value.'"';
|
||||
}
|
||||
}
|
||||
60
vendor/PicoDb/Schema.php
vendored
Normal file
60
vendor/PicoDb/Schema.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace PicoDb;
|
||||
|
||||
class Schema
|
||||
{
|
||||
protected $db = null;
|
||||
|
||||
|
||||
public function __construct(Database $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
|
||||
public function check($last_version = 1)
|
||||
{
|
||||
$current_version = $this->db->getConnection()->getSchemaVersion();
|
||||
|
||||
if ($current_version < $last_version) {
|
||||
|
||||
return $this->migrateTo($current_version, $last_version);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function migrateTo($current_version, $next_version)
|
||||
{
|
||||
try {
|
||||
|
||||
$this->db->startTransaction();
|
||||
|
||||
for ($i = $current_version + 1; $i <= $next_version; $i++) {
|
||||
|
||||
$function_name = '\Schema\version_'.$i;
|
||||
|
||||
if (function_exists($function_name)) {
|
||||
|
||||
call_user_func($function_name, $this->db->getConnection());
|
||||
$this->db->getConnection()->setSchemaVersion($i);
|
||||
}
|
||||
else {
|
||||
|
||||
throw new \LogicException('To execute a database migration, you need to create this function: "'.$function_name.'".');
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->closeTransaction();
|
||||
}
|
||||
catch (\PDOException $e) {
|
||||
|
||||
$this->db->cancelTransaction();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
430
vendor/PicoDb/Table.php
vendored
Normal file
430
vendor/PicoDb/Table.php
vendored
Normal file
@@ -0,0 +1,430 @@
|
||||
<?php
|
||||
|
||||
namespace PicoDb;
|
||||
|
||||
class Table
|
||||
{
|
||||
private $table_name = '';
|
||||
private $sql_limit = '';
|
||||
private $sql_offset = '';
|
||||
private $sql_order = '';
|
||||
private $joins = array();
|
||||
private $conditions = array();
|
||||
private $or_conditions = array();
|
||||
private $is_or_condition = false;
|
||||
private $columns = array();
|
||||
private $values = array();
|
||||
private $distinct = false;
|
||||
private $group_by = array();
|
||||
|
||||
private $db;
|
||||
|
||||
|
||||
public function __construct(Database $db, $table_name)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->table_name = $table_name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function save(array $data)
|
||||
{
|
||||
if (! empty($this->conditions)) {
|
||||
|
||||
return $this->update($data);
|
||||
}
|
||||
else {
|
||||
|
||||
return $this->insert($data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function update(array $data)
|
||||
{
|
||||
$columns = array();
|
||||
$values = array();
|
||||
|
||||
foreach ($data as $column => $value) {
|
||||
|
||||
$columns[] = $this->db->escapeIdentifier($column).'=?';
|
||||
$values[] = $value;
|
||||
}
|
||||
|
||||
foreach ($this->values as $value) {
|
||||
|
||||
$values[] = $value;
|
||||
}
|
||||
|
||||
$sql = sprintf(
|
||||
'UPDATE %s SET %s %s',
|
||||
$this->db->escapeIdentifier($this->table_name),
|
||||
implode(', ', $columns),
|
||||
$this->conditions()
|
||||
);
|
||||
|
||||
$result = $this->db->execute($sql, $values);
|
||||
|
||||
if ($result !== false && $result->rowCount() > 0) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function insert(array $data)
|
||||
{
|
||||
$columns = array();
|
||||
|
||||
foreach ($data as $column => $value) {
|
||||
|
||||
$columns[] = $this->db->escapeIdentifier($column);
|
||||
}
|
||||
|
||||
$sql = sprintf(
|
||||
'INSERT INTO %s (%s) VALUES (%s)',
|
||||
$this->db->escapeIdentifier($this->table_name),
|
||||
implode(', ', $columns),
|
||||
implode(', ', array_fill(0, count($data), '?'))
|
||||
);
|
||||
|
||||
return false !== $this->db->execute($sql, array_values($data));
|
||||
}
|
||||
|
||||
|
||||
public function remove()
|
||||
{
|
||||
$sql = sprintf(
|
||||
'DELETE FROM %s %s',
|
||||
$this->db->escapeIdentifier($this->table_name),
|
||||
$this->conditions()
|
||||
);
|
||||
|
||||
return false !== $this->db->execute($sql, $this->values);
|
||||
}
|
||||
|
||||
|
||||
public function listing($key, $value)
|
||||
{
|
||||
$this->columns($key, $value);
|
||||
|
||||
$listing = array();
|
||||
$results = $this->findAll();
|
||||
|
||||
if ($results) {
|
||||
|
||||
foreach ($results as $result) {
|
||||
|
||||
$listing[$result[$key]] = $result[$value];
|
||||
}
|
||||
}
|
||||
|
||||
return $listing;
|
||||
}
|
||||
|
||||
|
||||
public function findAll()
|
||||
{
|
||||
$rq = $this->db->execute($this->buildSelectQuery(), $this->values);
|
||||
if (false === $rq) return false;
|
||||
|
||||
return $rq->fetchAll(\PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
public function findAllByColumn($column)
|
||||
{
|
||||
$this->columns = array($column);
|
||||
$rq = $this->db->execute($this->buildSelectQuery(), $this->values);
|
||||
if (false === $rq) return false;
|
||||
|
||||
return $rq->fetchAll(\PDO::FETCH_COLUMN, 0);
|
||||
}
|
||||
|
||||
|
||||
public function findOne()
|
||||
{
|
||||
$this->limit(1);
|
||||
$result = $this->findAll();
|
||||
|
||||
return isset($result[0]) ? $result[0] : null;
|
||||
}
|
||||
|
||||
|
||||
public function findOneColumn($column)
|
||||
{
|
||||
$this->limit(1);
|
||||
$this->columns = array($column);
|
||||
|
||||
$rq = $this->db->execute($this->buildSelectQuery(), $this->values);
|
||||
if (false === $rq) return false;
|
||||
|
||||
return $rq->fetchColumn();
|
||||
}
|
||||
|
||||
|
||||
public function buildSelectQuery()
|
||||
{
|
||||
return sprintf(
|
||||
'SELECT %s %s FROM %s %s %s %s %s %s %s',
|
||||
$this->distinct ? 'DISTINCT' : '',
|
||||
empty($this->columns) ? '*' : implode(', ', $this->columns),
|
||||
$this->db->escapeIdentifier($this->table_name),
|
||||
implode(' ', $this->joins),
|
||||
$this->conditions(),
|
||||
empty($this->group_by) ? '' : 'GROUP BY '.implode(', ', $this->group_by),
|
||||
$this->sql_order,
|
||||
$this->sql_limit,
|
||||
$this->sql_offset
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function count()
|
||||
{
|
||||
$sql = sprintf(
|
||||
'SELECT COUNT(*) FROM %s'.$this->conditions().$this->sql_order.$this->sql_limit.$this->sql_offset,
|
||||
$this->db->escapeIdentifier($this->table_name)
|
||||
);
|
||||
|
||||
$rq = $this->db->execute($sql, $this->values);
|
||||
if (false === $rq) return false;
|
||||
|
||||
$result = $rq->fetchColumn();
|
||||
return $result ? (int) $result : 0;
|
||||
}
|
||||
|
||||
|
||||
public function join($table, $foreign_column, $local_column)
|
||||
{
|
||||
$this->joins[] = sprintf(
|
||||
'LEFT JOIN %s ON %s=%s',
|
||||
$this->db->escapeIdentifier($table),
|
||||
$this->db->escapeIdentifier($table).'.'.$this->db->escapeIdentifier($foreign_column),
|
||||
$this->db->escapeIdentifier($this->table_name).'.'.$this->db->escapeIdentifier($local_column)
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function conditions()
|
||||
{
|
||||
if (! empty($this->conditions)) {
|
||||
|
||||
return ' WHERE '.implode(' AND ', $this->conditions);
|
||||
}
|
||||
else {
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function addCondition($sql)
|
||||
{
|
||||
if ($this->is_or_condition) {
|
||||
|
||||
$this->or_conditions[] = $sql;
|
||||
}
|
||||
else {
|
||||
|
||||
$this->conditions[] = $sql;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function beginOr()
|
||||
{
|
||||
$this->is_or_condition = true;
|
||||
$this->or_conditions = array();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function closeOr()
|
||||
{
|
||||
$this->is_or_condition = false;
|
||||
|
||||
if (! empty($this->or_conditions)) {
|
||||
|
||||
$this->conditions[] = '('.implode(' OR ', $this->or_conditions).')';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function orderBy($column, $order = 'ASC')
|
||||
{
|
||||
$order = strtoupper($order);
|
||||
$order = $order === 'ASC' || $order === 'DESC' ? $order : 'ASC';
|
||||
|
||||
if ($this->sql_order === '') {
|
||||
$this->sql_order = ' ORDER BY '.$this->db->escapeIdentifier($column).' '.$order;
|
||||
}
|
||||
else {
|
||||
$this->sql_order .= ', '.$this->db->escapeIdentifier($column).' '.$order;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function asc($column)
|
||||
{
|
||||
if ($this->sql_order === '') {
|
||||
$this->sql_order = ' ORDER BY '.$this->db->escapeIdentifier($column).' ASC';
|
||||
}
|
||||
else {
|
||||
$this->sql_order .= ', '.$this->db->escapeIdentifier($column).' ASC';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function desc($column)
|
||||
{
|
||||
if ($this->sql_order === '') {
|
||||
$this->sql_order = ' ORDER BY '.$this->db->escapeIdentifier($column).' DESC';
|
||||
}
|
||||
else {
|
||||
$this->sql_order .= ', '.$this->db->escapeIdentifier($column).' DESC';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function limit($value)
|
||||
{
|
||||
if (! is_null($value)) $this->sql_limit = ' LIMIT '.(int) $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function offset($value)
|
||||
{
|
||||
if (! is_null($value)) $this->sql_offset = ' OFFSET '.(int) $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function groupBy()
|
||||
{
|
||||
$this->group_by = \func_get_args();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function columns()
|
||||
{
|
||||
$this->columns = \func_get_args();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function distinct()
|
||||
{
|
||||
$this->columns = \func_get_args();
|
||||
$this->distinct = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function __call($name, array $arguments)
|
||||
{
|
||||
$column = $arguments[0];
|
||||
$sql = '';
|
||||
|
||||
switch (strtolower($name)) {
|
||||
|
||||
case 'in':
|
||||
if (isset($arguments[1]) && is_array($arguments[1])) {
|
||||
|
||||
$sql = sprintf(
|
||||
'%s IN (%s)',
|
||||
$this->db->escapeIdentifier($column),
|
||||
implode(', ', array_fill(0, count($arguments[1]), '?'))
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'notin':
|
||||
if (isset($arguments[1]) && is_array($arguments[1])) {
|
||||
|
||||
$sql = sprintf(
|
||||
'%s NOT IN (%s)',
|
||||
$this->db->escapeIdentifier($column),
|
||||
implode(', ', array_fill(0, count($arguments[1]), '?'))
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'like':
|
||||
$sql = sprintf('%s LIKE ?', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
|
||||
case 'eq':
|
||||
case 'equal':
|
||||
case 'equals':
|
||||
$sql = sprintf('%s = ?', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
|
||||
case 'gt':
|
||||
case 'greaterthan':
|
||||
$sql = sprintf('%s > ?', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
|
||||
case 'lt':
|
||||
case 'lowerthan':
|
||||
$sql = sprintf('%s < ?', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
|
||||
case 'gte':
|
||||
case 'greaterthanorequals':
|
||||
$sql = sprintf('%s >= ?', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
|
||||
case 'lte':
|
||||
case 'lowerthanorequals':
|
||||
$sql = sprintf('%s <= ?', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
|
||||
case 'isnull':
|
||||
$sql = sprintf('%s IS NULL', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
|
||||
case 'notnull':
|
||||
$sql = sprintf('%s IS NOT NULL', $this->db->escapeIdentifier($column));
|
||||
break;
|
||||
}
|
||||
|
||||
if ($sql !== '') {
|
||||
|
||||
$this->addCondition($sql);
|
||||
|
||||
if (isset($arguments[1])) {
|
||||
|
||||
if (is_array($arguments[1])) {
|
||||
|
||||
foreach ($arguments[1] as $value) {
|
||||
$this->values[] = $value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
$this->values[] = $arguments[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
44
vendor/SimpleValidator/Base.php
vendored
Normal file
44
vendor/SimpleValidator/Base.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
abstract class Base
|
||||
{
|
||||
protected $field = '';
|
||||
protected $error_message = '';
|
||||
protected $data = array();
|
||||
|
||||
|
||||
abstract public function execute(array $data);
|
||||
|
||||
|
||||
public function __construct($field, $error_message)
|
||||
{
|
||||
$this->field = $field;
|
||||
$this->error_message = $error_message;
|
||||
}
|
||||
|
||||
|
||||
public function getErrorMessage()
|
||||
{
|
||||
return $this->error_message;
|
||||
}
|
||||
|
||||
|
||||
public function getField()
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
}
|
||||
67
vendor/SimpleValidator/Validator.php
vendored
Normal file
67
vendor/SimpleValidator/Validator.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Validator
|
||||
{
|
||||
private $data = array();
|
||||
private $errors = array();
|
||||
private $validators = array();
|
||||
|
||||
|
||||
public function __construct(array $data, array $validators)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->validators = $validators;
|
||||
}
|
||||
|
||||
|
||||
public function execute()
|
||||
{
|
||||
$result = true;
|
||||
|
||||
foreach ($this->validators as $validator) {
|
||||
|
||||
if (! $validator->execute($this->data)) {
|
||||
|
||||
$this->addError(
|
||||
$validator->getField(),
|
||||
$validator->getErrorMessage()
|
||||
);
|
||||
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function addError($field, $message)
|
||||
{
|
||||
if (! isset($this->errors[$field])) {
|
||||
|
||||
$this->errors[$field] = array();
|
||||
}
|
||||
|
||||
$this->errors[$field][] = $message;
|
||||
}
|
||||
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
}
|
||||
33
vendor/SimpleValidator/Validators/Alpha.php
vendored
Normal file
33
vendor/SimpleValidator/Validators/Alpha.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Alpha extends Base
|
||||
{
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
if (! ctype_alpha($data[$this->field])) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
33
vendor/SimpleValidator/Validators/AlphaNumeric.php
vendored
Normal file
33
vendor/SimpleValidator/Validators/AlphaNumeric.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class AlphaNumeric extends Base
|
||||
{
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
if (! ctype_alnum($data[$this->field])) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
81
vendor/SimpleValidator/Validators/Email.php
vendored
Normal file
81
vendor/SimpleValidator/Validators/Email.php
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Email extends Base
|
||||
{
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
// I use the same validation method as Firefox
|
||||
// http://hg.mozilla.org/mozilla-central/file/cf5da681d577/content/html/content/src/nsHTMLInputElement.cpp#l3967
|
||||
|
||||
$value = $data[$this->field];
|
||||
$length = strlen($value);
|
||||
|
||||
// If the email address begins with a '@' or ends with a '.',
|
||||
// we know it's invalid.
|
||||
if ($value[0] === '@' || $value[$length - 1] === '.') {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the username
|
||||
for ($i = 0; $i < $length && $value[$i] !== '@'; ++$i) {
|
||||
|
||||
$c = $value[$i];
|
||||
|
||||
if (! (ctype_alnum($c) || $c === '.' || $c === '!' || $c === '#' || $c === '$' ||
|
||||
$c === '%' || $c === '&' || $c === '\'' || $c === '*' || $c === '+' ||
|
||||
$c === '-' || $c === '/' || $c === '=' || $c === '?' || $c === '^' ||
|
||||
$c === '_' || $c === '`' || $c === '{' || $c === '|' || $c === '}' ||
|
||||
$c === '~')) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// There is no domain name (or it's one-character long),
|
||||
// that's not a valid email address.
|
||||
if (++$i >= $length) return false;
|
||||
if (($i + 1) === $length) return false;
|
||||
|
||||
// The domain name can't begin with a dot.
|
||||
if ($value[$i] === '.') return false;
|
||||
|
||||
// Parsing the domain name.
|
||||
for (; $i < $length; ++$i) {
|
||||
|
||||
$c = $value[$i];
|
||||
|
||||
if ($c === '.') {
|
||||
|
||||
// A dot can't follow a dot.
|
||||
if ($value[$i - 1] === '.') return false;
|
||||
}
|
||||
elseif (! (ctype_alnum($c) || $c === '-')) {
|
||||
|
||||
// The domain characters have to be in this list to be valid.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
43
vendor/SimpleValidator/Validators/Equals.php
vendored
Normal file
43
vendor/SimpleValidator/Validators/Equals.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Equals extends Base
|
||||
{
|
||||
private $field2;
|
||||
|
||||
|
||||
public function __construct($field1, $field2, $error_message)
|
||||
{
|
||||
parent::__construct($field1, $error_message);
|
||||
|
||||
$this->field2 = $field2;
|
||||
}
|
||||
|
||||
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
if (! isset($data[$this->field2])) return false;
|
||||
|
||||
return $data[$this->field] === $data[$this->field2];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
42
vendor/SimpleValidator/Validators/Integer.php
vendored
Normal file
42
vendor/SimpleValidator/Validators/Integer.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Integer extends Base
|
||||
{
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
if (is_string($data[$this->field])) {
|
||||
|
||||
if ($data[$this->field][0] === '-') {
|
||||
|
||||
return ctype_digit(substr($data[$this->field], 1));
|
||||
}
|
||||
|
||||
return ctype_digit($data[$this->field]);
|
||||
}
|
||||
else {
|
||||
|
||||
return is_int($data[$this->field]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
33
vendor/SimpleValidator/Validators/Ip.php
vendored
Normal file
33
vendor/SimpleValidator/Validators/Ip.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Ip extends Base
|
||||
{
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
if (! filter_var($data[$this->field], FILTER_VALIDATE_IP)) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
48
vendor/SimpleValidator/Validators/Length.php
vendored
Normal file
48
vendor/SimpleValidator/Validators/Length.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Length extends Base
|
||||
{
|
||||
private $min;
|
||||
private $max;
|
||||
|
||||
|
||||
public function __construct($field, $error_message, $min, $max)
|
||||
{
|
||||
parent::__construct($field, $error_message);
|
||||
|
||||
$this->min = $min;
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
$length = mb_strlen($data[$this->field], 'UTF-8');
|
||||
|
||||
if ($length < $this->min || $length > $this->max) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
37
vendor/SimpleValidator/Validators/MacAddress.php
vendored
Normal file
37
vendor/SimpleValidator/Validators/MacAddress.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class MacAddress extends Base
|
||||
{
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
$groups = explode(':', $data[$this->field]);
|
||||
|
||||
if (count($groups) !== 6) return false;
|
||||
|
||||
foreach ($groups as $group) {
|
||||
|
||||
if (! ctype_xdigit($group)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
46
vendor/SimpleValidator/Validators/MaxLength.php
vendored
Normal file
46
vendor/SimpleValidator/Validators/MaxLength.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class MaxLength extends Base
|
||||
{
|
||||
private $max;
|
||||
|
||||
|
||||
public function __construct($field, $error_message, $max)
|
||||
{
|
||||
parent::__construct($field, $error_message);
|
||||
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
$length = mb_strlen($data[$this->field], 'UTF-8');
|
||||
|
||||
if ($length > $this->max) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
46
vendor/SimpleValidator/Validators/MinLength.php
vendored
Normal file
46
vendor/SimpleValidator/Validators/MinLength.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class MinLength extends Base
|
||||
{
|
||||
private $min;
|
||||
|
||||
|
||||
public function __construct($field, $error_message, $min)
|
||||
{
|
||||
parent::__construct($field, $error_message);
|
||||
|
||||
$this->min = $min;
|
||||
}
|
||||
|
||||
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
$length = mb_strlen($data[$this->field], 'UTF-8');
|
||||
|
||||
if ($length < $this->min) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
33
vendor/SimpleValidator/Validators/Numeric.php
vendored
Normal file
33
vendor/SimpleValidator/Validators/Numeric.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Numeric extends Base
|
||||
{
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
if (! is_numeric($data[$this->field])) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
51
vendor/SimpleValidator/Validators/Range.php
vendored
Normal file
51
vendor/SimpleValidator/Validators/Range.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Range extends Base
|
||||
{
|
||||
private $min;
|
||||
private $max;
|
||||
|
||||
|
||||
public function __construct($field, $error_message, $min, $max)
|
||||
{
|
||||
parent::__construct($field, $error_message);
|
||||
|
||||
$this->min = $min;
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
if (! is_numeric($data[$this->field])) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($data[$this->field] < $this->min || $data[$this->field] > $this->max) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
30
vendor/SimpleValidator/Validators/Required.php
vendored
Normal file
30
vendor/SimpleValidator/Validators/Required.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Required extends Base
|
||||
{
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (! isset($data[$this->field]) || $data[$this->field] === '') {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
78
vendor/SimpleValidator/Validators/Unique.php
vendored
Normal file
78
vendor/SimpleValidator/Validators/Unique.php
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
*/
|
||||
class Unique extends Base
|
||||
{
|
||||
private $pdo;
|
||||
private $primary_key;
|
||||
private $table;
|
||||
|
||||
|
||||
public function __construct($field, $error_message, \PDO $pdo, $table, $primary_key = 'id')
|
||||
{
|
||||
parent::__construct($field, $error_message);
|
||||
|
||||
$this->pdo = $pdo;
|
||||
$this->primary_key = $primary_key;
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
if (! isset($data[$this->primary_key])) {
|
||||
|
||||
$rq = $this->pdo->prepare('SELECT COUNT(*) FROM '.$this->table.' WHERE '.$this->field.'=?');
|
||||
|
||||
$rq->execute(array(
|
||||
$data[$this->field]
|
||||
));
|
||||
|
||||
$result = $rq->fetch(\PDO::FETCH_NUM);
|
||||
|
||||
if (isset($result[0]) && $result[0] === '1') {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
$rq = $this->pdo->prepare(
|
||||
'SELECT COUNT(*) FROM '.$this->table.'
|
||||
WHERE '.$this->field.'=? AND '.$this->primary_key.' != ?'
|
||||
);
|
||||
|
||||
$rq->execute(array(
|
||||
$data[$this->field],
|
||||
$data[$this->primary_key]
|
||||
));
|
||||
|
||||
$result = $rq->fetch(\PDO::FETCH_NUM);
|
||||
|
||||
if (isset($result[0]) && $result[0] === '1') {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
32
vendor/SimpleValidator/Validators/Version.php
vendored
Normal file
32
vendor/SimpleValidator/Validators/Version.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Simple Validator.
|
||||
*
|
||||
* (c) Frédéric Guillot <contact@fredericguillot.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace SimpleValidator\Validators;
|
||||
|
||||
use SimpleValidator\Base;
|
||||
|
||||
/**
|
||||
* @author Frédéric Guillot <contact@fredericguillot.com>
|
||||
* @link http://semver.org/
|
||||
*/
|
||||
class Version extends Base
|
||||
{
|
||||
public function execute(array $data)
|
||||
{
|
||||
if (isset($data[$this->field]) && $data[$this->field] !== '') {
|
||||
|
||||
$pattern = '/^[0-9]+\.[0-9]+\.[0-9]+([+-][^+-][0-9A-Za-z-.]*)?$/';
|
||||
return (bool) preg_match($pattern, $data[$this->field]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
227
vendor/password.php
vendored
Normal file
227
vendor/password.php
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
/**
|
||||
* A Compatibility library with PHP 5.5's simplified password hashing API.
|
||||
*
|
||||
* @author Anthony Ferrara <ircmaxell@php.net>
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @copyright 2012 The Authors
|
||||
*/
|
||||
|
||||
if (!defined('PASSWORD_BCRYPT')) {
|
||||
|
||||
define('PASSWORD_BCRYPT', 1);
|
||||
define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
|
||||
|
||||
define('PASSWORD_PREFIX', '$2a$');
|
||||
}
|
||||
else {
|
||||
|
||||
define('PASSWORD_PREFIX', '$2y$');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash the password using the specified algorithm
|
||||
*
|
||||
* @param string $password The password to hash
|
||||
* @param int $algo The algorithm to use (Defined by PASSWORD_* constants)
|
||||
* @param array $options The options for the algorithm to use
|
||||
*
|
||||
* @return string|false The hashed password, or false on error.
|
||||
*/
|
||||
function password_hash($password, $algo, array $options = array()) {
|
||||
if (!function_exists('crypt')) {
|
||||
trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!is_string($password)) {
|
||||
trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!is_int($algo)) {
|
||||
trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
switch ($algo) {
|
||||
case PASSWORD_BCRYPT:
|
||||
// Note that this is a C constant, but not exposed to PHP, so we don't define it here.
|
||||
$cost = 10;
|
||||
if (isset($options['cost'])) {
|
||||
$cost = $options['cost'];
|
||||
if ($cost < 4 || $cost > 31) {
|
||||
trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$required_salt_len = 22;
|
||||
$hash_format = sprintf("%s%02d$", PASSWORD_PREFIX, $cost);
|
||||
break;
|
||||
default:
|
||||
trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (isset($options['salt'])) {
|
||||
switch (gettype($options['salt'])) {
|
||||
case 'NULL':
|
||||
case 'boolean':
|
||||
case 'integer':
|
||||
case 'double':
|
||||
case 'string':
|
||||
$salt = (string) $options['salt'];
|
||||
break;
|
||||
case 'object':
|
||||
if (method_exists($options['salt'], '__tostring')) {
|
||||
$salt = (string) $options['salt'];
|
||||
break;
|
||||
}
|
||||
case 'array':
|
||||
case 'resource':
|
||||
default:
|
||||
trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (strlen($salt) < $required_salt_len) {
|
||||
trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING);
|
||||
return null;
|
||||
} elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
|
||||
$salt = str_replace('+', '.', base64_encode($salt));
|
||||
}
|
||||
} else {
|
||||
$buffer = '';
|
||||
$raw_length = (int) ($required_salt_len * 3 / 4 + 1);
|
||||
$buffer_valid = false;
|
||||
if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
|
||||
$buffer = mcrypt_create_iv($raw_length, MCRYPT_DEV_URANDOM);
|
||||
if ($buffer) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
|
||||
$buffer = openssl_random_pseudo_bytes($raw_length);
|
||||
if ($buffer) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid && is_readable('/dev/urandom')) {
|
||||
$f = fopen('/dev/urandom', 'r');
|
||||
$read = strlen($buffer);
|
||||
while ($read < $raw_length) {
|
||||
$buffer .= fread($f, $raw_length - $read);
|
||||
$read = strlen($buffer);
|
||||
}
|
||||
fclose($f);
|
||||
if ($read >= $raw_length) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid || strlen($buffer) < $raw_length) {
|
||||
$bl = strlen($buffer);
|
||||
for ($i = 0; $i < $raw_length; $i++) {
|
||||
if ($i < $bl) {
|
||||
$buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
|
||||
} else {
|
||||
$buffer .= chr(mt_rand(0, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
$salt = str_replace('+', '.', base64_encode($buffer));
|
||||
|
||||
}
|
||||
$salt = substr($salt, 0, $required_salt_len);
|
||||
|
||||
$hash = $hash_format . $salt;
|
||||
|
||||
$ret = crypt($password, $hash);
|
||||
|
||||
if (!is_string($ret) || strlen($ret) <= 13) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about the password hash. Returns an array of the information
|
||||
* that was used to generate the password hash.
|
||||
*
|
||||
* array(
|
||||
* 'algo' => 1,
|
||||
* 'algoName' => 'bcrypt',
|
||||
* 'options' => array(
|
||||
* 'cost' => 10,
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* @param string $hash The password hash to extract info from
|
||||
*
|
||||
* @return array The array of information about the hash.
|
||||
*/
|
||||
function password_get_info($hash) {
|
||||
$return = array(
|
||||
'algo' => 0,
|
||||
'algoName' => 'unknown',
|
||||
'options' => array(),
|
||||
);
|
||||
if (substr($hash, 0, 4) == PASSWORD_PREFIX && strlen($hash) == 60) {
|
||||
$return['algo'] = PASSWORD_BCRYPT;
|
||||
$return['algoName'] = 'bcrypt';
|
||||
list($cost) = sscanf($hash, PASSWORD_PREFIX."%d$");
|
||||
$return['options']['cost'] = $cost;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the password hash needs to be rehashed according to the options provided
|
||||
*
|
||||
* If the answer is true, after validating the password using password_verify, rehash it.
|
||||
*
|
||||
* @param string $hash The hash to test
|
||||
* @param int $algo The algorithm used for new password hashes
|
||||
* @param array $options The options array passed to password_hash
|
||||
*
|
||||
* @return boolean True if the password needs to be rehashed.
|
||||
*/
|
||||
function password_needs_rehash($hash, $algo, array $options = array()) {
|
||||
$info = password_get_info($hash);
|
||||
if ($info['algo'] != $algo) {
|
||||
return true;
|
||||
}
|
||||
switch ($algo) {
|
||||
case PASSWORD_BCRYPT:
|
||||
$cost = isset($options['cost']) ? $options['cost'] : 10;
|
||||
if ($cost != $info['options']['cost']) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a password against a hash using a timing attack resistant approach
|
||||
*
|
||||
* @param string $password The password to verify
|
||||
* @param string $hash The hash to verify against
|
||||
*
|
||||
* @return boolean If the password matches the hash
|
||||
*/
|
||||
function password_verify($password, $hash) {
|
||||
if (!function_exists('crypt')) {
|
||||
trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
$ret = crypt($password, $hash);
|
||||
if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$status = 0;
|
||||
for ($i = 0; $i < strlen($ret); $i++) {
|
||||
$status |= (ord($ret[$i]) ^ ord($hash[$i]));
|
||||
}
|
||||
|
||||
return $status === 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user