This commit is contained in:
2026-05-27 11:44:10 -04:00
commit 414f85ad05
31452 changed files with 3580409 additions and 0 deletions

510
lib/common/Curl.php Normal file
View File

@ -0,0 +1,510 @@
<?php
namespace Common;
class Curl {
/**
* cURL request method
*
* @var string
*/
protected $_method = 'GET';
/**
* Currently accepted cURL request method types
*
* @var string
*/
protected $_methods = array('POST', 'GET');
/**
* cURL URL
*
* @var string
*/
protected $_url = '';
/**
* cURL data params
*
* @var string
*/
protected $_params;
/**
* cURL options
*
* @var array
*/
protected $_options = array();
/**
* cURL user agent
*
* @var array
*/
protected $_agent = 'lodev09 engine';
/**
* GET request
*
* @param string $url
* @param array $params
* @param array $options
* @return mixed
*/
static public function get($url = '', $params = array(), $options = array()) {
return self::make($url, $params, $options, 'GET');
}
/**
* POST request
*
* @param string $url
* @param array $params
* @param array $options
* @return mixed
*/
static public function post($url = '', $params = array(), $options = array()) {
return self::make($url, $params, $options, 'POST');
}
/**
* Make request
*
* @param string $url
* @param array $params
* @param array $options
* @param string $method
* @return Curl
*/
static public function make($url = '', $params = array(), $options = array(), $method = null) {
return new self($url, $params, $options, $method);
}
public function __construct($url = '', $params = array(), $options = array(), $method = null) {
// Set request method
if ($method) {
$this->_method = $method;
}
$this->_params = $params;
if ($this->_method == 'GET') {
// Explode the URL to get the URL params
$url_split = explode('?', $url);
// Request URL is everything before the ? (if it exists)
$this->_url = $url_split[0];
// If there were URL params, add it to the params array
$this->_params = array_merge($this->_params, $this->_queryString($url), (array) $params);
} else {
$this->_url = $url;
}
// Set the passed options
$this->_options($options);
}
/**
* Add multiple params
*
* @param array $keys
* @return Curl
*/
public function params($keys = array()) {
$this->_params = array_merge((array) $this->_params, (array) $keys);
return $this;
}
/**
* Add a single param
*
* @param string $key
* @param string $value
* @return Curl
*/
public function param($key = '', $value = '') {
if ( ! empty($key) && is_string($key)) {
$key = array(
$key => (string) $value
);
}
return $this->params($key);
}
/**
* Add multiple options
*
* @param array $options
* @return Curl
*/
public function options($options = array()) {
$this->_options($options);
return $this;
}
/**
* Add single option
*
* @param string $key
* @param string $value
* @return Curl
*/
public function option($key = '', $value = '') {
$this->_option($key, $value);
return $this;
}
/**
* Request method
*
* @param string $method
* @return Curl
*/
public function method($method = null) {
$this->_method = $method;
return $this;
}
/**
* User agent
*
* @param string $agent
* @return Curl
*/
public function agent($agent = '') {
if ($agent) {
return $this->option('CURLOPT_USERAGENT', $agent);
}
return $this;
}
/**
* Proxy helper
*
* @param string $url
* @param int $port
* @return Curl
*/
public function proxy($url = '', $port = 80) {
return $this->options(array(
'CURLOPT_HTTPPROXYTUNNEL' => true,
'CURLOPT_PROXY' => $url.':'.$port
));
}
/**
* Custom header helper
*
* @param string $header
* @param string $content
* @return Curl
*/
public function httpHeader($header, $content = null) {
$header = ($content) ? $header.':'.$content : $header;
return $this->option('CURLOPT_HTTPHEADER', $header);
}
/**
* HTTP login helper
*
* @param string $username
* @param string $password
* @param string $type
* @return Curl
*/
public function httpLogin($username = '', $password = '', $type = 'ANY') {
return $this->options(array(
'CURLOPT_HTTPAUTH' => constant('CURLAUTH_'.strtoupper($type)),
'CURLOPT_USERPWD' => $username.':'.$password
));
}
/**
* Proxy login helper
*
* @param string $username
* @param string $password
* @return Curl
*/
public function proxyLogin($username = '', $password = '') {
return $this->option('CURLOPT_PROXYUSERPWD', $username.':'.$password);
}
/**
* SSL helper
*
* @param bool $verify_peer
* @param int $verify_host
* @param string $path_to_cert
* @return Curl
*/
public function ssl($verify_peer = true, $verify_host = 2, $path_to_cert = null) {
if ($verify_peer) {
$options = array(
'CURLOPT_SSL_VERIFYPEER' => true,
'CURLOPT_SSL_VERIFYHOST' => $verify_host,
'CURLOPT_CAINFO' => $path_to_cert
);
}
else {
$options = array(
'CURLOPT_SSL_VERIFYPEER' => false
);
}
return $this->options($options);
}
/**
* Execute request
*
* @return Curl
* @throws Exception
*/
public function call() {
// cURL is not enabled
if ( ! $this->_isEnabled()) {
throw new Exception(__CLASS__.': PHP was not built with cURL enabled. Rebuild PHP with --with-curl to use cURL.');
}
// Request method
$method = ($this->_method) ? strtoupper($this->_method) : 'GET';
// Unrecognized request method?
if ( ! in_array($method, $this->_methods)) {
throw new Exception(__CLASS__.': Unrecognized request method of '.$this->_method);
}
return $this->_execute($method);
}
/**
* Alias for call();
*
* @return Curl
*/
public function execute() {
return $this->call();
}
/**
* Execute request
*
* @param string $method
* @return Curl
*/
private function _execute($method) {
// Method specific options
switch ($method) {
case 'GET' :
// Append GET params to URL
$this->_url .= '?'.http_build_query($this->_params);
// Set options
$this->options('CURLOPT_HTTPGET', 1);
break;
case 'POST' :
// Set options
$this->options(array(
'CURLOPT_POST' => true,
'CURLOPT_POSTFIELDS' => $this->_params
));
break;
// Mostly for future use
case 'PUT' :
// Set options
$this->options(array(
'CURLOPT_PUT' => true,
'CURLOPT_HTTPHEADER' => array('Content-Type: '.strlen($this->_params)),
'CURLOPT_POSTFIELDS' => $this->_params
));
break;
// Mostly for future use
case 'DELETE' :
// Set options
$this->option('CURLOPT_CUSTOMREQUEST', 'DELETE');
$this->option('CURLOPT_POSTFIELDS', $this->_params);
break;
}
// Set timeout option if it isn't already set
if ( ! array_key_exists('CURLOPT_TIMEOUT', $this->_options)) {
$this->option('CURLOPT_TIMEOUT', 30);
}
// Set returntransfer option if it isn't already set
if ( ! array_key_exists('CURLOPT_RETURNTRANSFER', $this->_options)) {
$this->option('CURLOPT_RETURNTRANSFER', true);
}
// Set failonerror option if it isn't already set
if ( ! array_key_exists('CURLOPT_FAILONERROR', $this->_options)) {
$this->option('CURLOPT_FAILONERROR', true);
}
// Set user agent option if it isn't already set
if ( ! array_key_exists('CURLOPT_USERAGENT', $this->_options)) {
$this->option('CURLOPT_USERAGENT', $this->_agent);
}
// Only set follow location if not running securely
if ( ! ini_get('safe_mode') && ! ini_get('open_basedir')) {
// Ok, follow location is not set already so lets set it to true
if ( ! array_key_exists('CURLOPT_FOLLOWLOCATION', $this->_options)) {
$this->option('CURLOPT_FOLLOWLOCATION', true);
}
}
// Initialize cURL request
$ch = curl_init($this->_url);
// Can't set the options in batch
if ( ! function_exists('curl_setopt_array')) {
foreach ($this->_options as $key => $value) {
curl_setopt($ch, $key, $value);
}
}
// Set options in batch
else {
curl_setopt_array($ch, $this->_options);
}
// Execute
$response = new stdClass();
$response->result = curl_exec($ch);
$response->info = curl_getinfo($ch);
$response->error = curl_error($ch);
$response->error_code = curl_errno($ch);
// Reset the options
$this->_url = '';
$this->_params = '';
$this->_options = array();
// Close cURL request
curl_close($ch);
return $response;
}
/**
* Add multiple options
*
* @param array $options
*/
protected function _options($options = array()) {
foreach ((array) $options as $key => $value) {
$this->_option($key, $value);
}
}
/**
* Add single option
*
* @param string $key
* @param string $value
* @throws Exception
*/
protected function _option($key = '', $value = '') {
if (is_string($key) && ! is_numeric($key)) {
$const = strtoupper($key);
if (defined($const)) {
$key = constant(strtoupper($key));
}
else {
throw new Exception('Curl: Constant ['.$const.'] not defined.');
}
}
// Custom header
if ($key == CURLOPT_HTTPHEADER) {
$this->_options[$key][] = $value;
}
// Not a custom header
else {
$this->_options[$key] = $value;
}
}
/**
* Get query string from URL
*
* @param $uri
* @return array
*/
protected function _queryString($uri) {
$query_data = array();
$query_array = html_entity_decode(parse_url($uri, PHP_URL_QUERY));
if ( ! empty($query_array)) {
$query_array = explode('&', $query_array);
foreach($query_array as $val) {
$x = explode('=', $val);
$query_data[$x[0]] = $x[1];
}
}
return $query_data;
}
/**
* Check if cURL is enabled
*
* @return bool
*/
protected function _isEnabled() {
return function_exists('curl_init');
}
}

501
lib/common/Date.php Normal file
View File

@ -0,0 +1,501 @@
<?php
namespace Common;
/**
* Date class
*/
class Date {
/**
* Fuzzy date strings
*
* @var array
*/
protected $_time_formats = array(
array(60, 'just now'),
array(90, '1 minute'),
array(3600, 'minutes', 60),
array(5400, '1 hour'),
array(86400, 'hours', 3600),
array(129600, '1 day'),
array(604800, 'days', 86400),
array(907200, '1 week'),
array(2628000, 'weeks', 604800),
array(3942000, '1 month'),
array(31536000, 'months', 2628000),
array(47304000, '1 year'),
array(3153600000, 'years', 31536000)
);
protected $_time_format = 'H:i';
/**
* Timestamp
*
* @var DateTime
*/
protected $_timestamp = null;
/**
* Use current timestamp
*
* @return Date
*/
static public function now() {
return self::with('now');
}
/**
* Specified time
*
* @param int|string $date
* @return Date
*/
static public function with($date) {
return new self($date);
}
/**
* Constructor
*
* @param int|string $date
*/
public function __construct($date) {
// If the timestamp is not valid, set the timestamp to now
if (($this->_timestamp = strtotime($date)) === false) {
$this->_timestamp = strtotime('now');
}
}
/**
* Pretty formatted date. Yes, this is an actual method. Deal with it!
*
* @return string
*/
public function pretty_date($time = true) {
return $this->formatted('F j, Y'.($time ? ' '.$this->_time_format : ''));
}
/**
* Timezone string. Or timezone abbreviation
*
* @param bool $abbrev
* @return string
*/
public function timezone($abbrev = false) {
$abbrev = ($abbrev) ? 'T' : 'e';
return $this->formatted($abbrev);
}
/**
* Timezone offset in seconds
*
* @return string
*/
public function timezone_offset() {
return $this->formatted('z');
}
/**
* Difference to Greenwich time (GMT)
*
* @param bool $colon
* @return string
*/
public function gmt_diff($colon = false) {
$colon = ($colon) ? 'P' : 'O';
return $this->formatted($colon);
}
/**
* Current timestamp
*
* @return int
*/
public function timestamp() {
return (int) $this->formatted('U');
}
/**
* Day
*
* @param bool $text
* @param bool $full
* @return string
*/
public function day($text = false, $full = true) {
if ($text) {
return $this->day_text($full);
}
return $this->day_num($full);
}
/**
* Day of month. Optionally with leading 0
*
* @param bool $leading
* @return string
*/
public function day_num($leading = false) {
$leading = ($leading) ? 'd' : 'j';
return $this->formatted($leading);
}
/**
* A textual representation of a day
*
* @param bool $full
* @return string
*/
public function day_text($full = true) {
$full = ($full) ? 'l' : 'D';
return $this->formatted($full);
}
/**
* English ordinal suffix for the day of the month, 2 characters
*
* @return string
*/
public function ordinal() {
return $this->formatted('S');
}
/**
* Numeric representation of the day of the week
*
* @param bool $iso8601
* @return string
*/
public function day_of_week($iso8601 = false) {
$iso8601 = ($iso8601) ? 'N' : 'w';
return $this->formatted($iso8601);
}
/**
* The day of the year (starting from 0)
*
* @return string
*/
public function day_of_year() {
return $this->formatted('z');
}
/**
* Number of days in the given month
*
* @return string
*/
public function days_in_month() {
return $this->formatted('t');
}
/**
* Month
*
* @param bool $text
* @param bool $full
* @return string
*/
public function month($text = false, $full = true) {
if ($text) {
return $this->monthText($full);
}
return $this->month_num($full);
}
/**
* Numeric representation of a month
*
* @param bool $leading
* @return string
*/
public function month_num($leading = true) {
$leading = ($leading) ? 'm' : 'n';
return $this->formatted($leading);
}
/**
* A textual representation of a month
*
* @param bool $abbrev
* @return string
*/
public function monthText($abbrev = true) {
$abbrev = ($abbrev) ? 'M' : 'F';
return $this->formatted($abbrev);
}
/**
* ISO-8601 week number of year, weeks starting on Monday
*
* @return string
*/
public function week_of_year() {
return $this->formatted('W');
}
/**
* Year representation
*
* @param bool $full
* @return string
*/
public function year($full = true) {
$full = ($full) ? 'Y' : 'y';
return $this->formatted($full);
}
/**
* Whether it's a leap year
*
* @return bool
*/
public function leapyear() {
return (bool) $this->formatted('L');
}
/**
* 12 or 24-hour format of an hour with or without leading zeros
*
* @param bool $leading
* @param bool $military
* @return string
*/
public function hour($leading = true, $military = true) {
if ($military) {
return $this->hour12($leading);
}
return $this->hour24($leading);
}
/**
* 12-hour format of an hour with or without leading zeros
*
* @param bool $leading
* @return string
*/
public function hour12($leading = true) {
$format = ($leading) ? 'h' : 'g';
return $this->formatted($format);
}
/**
* 24-hour format of an hour with or without leading zeros
*
* @param bool $leading
* @return string
*/
public function hour24($leading = true) {
$format = ($leading) ? 'H' : 'G';
return $this->formatted($format);
}
/**
* Minutes with leading zeros
*
* @return string
*/
public function minutes() {
return $this->formatted('i');
}
/**
* Seconds with leading zeros
*
* @return string
*/
public function seconds() {
return $this->formatted('s');
}
/**
* Microseconds
*
* @return string
*/
public function microseconds() {
return $this->formatted('u');
}
/**
* Ante meridiem or Post meridiem
*
* @param bool $upper
* @return string
*/
public function meridiem($upper = true) {
$upper = ($upper) ? 'A' : 'a';
return $this->formatted($upper);
}
/**
* Whether or not the date is in daylight saving time
*
* @return bool
*/
public function daylight_saving() {
return (bool) $this->formatted('I');
}
/**
* ISO 8601 date (eg. 2004-02-12T15:19:21+00:00)
*
* @param bool $utc
* @return string
*/
public function iso8601($utc = false) {
return $utc ? gmdate('c', $this->_timestamp) : $this->formatted('c');
}
/**
* RFC 2822 formatted date (eg. Thu, 21 Dec 2000 16:01:07 +0200)
*
* @return string
*/
public function rfc2822() {
return $this->formatted('r');
}
/**
* Find the age in years
*
* @return int
*/
public function age() {
// Current
$now = self::now();
// Differences
$year_diff = $now->year() - $this->year();
$month_diff = $now->month_num() - $this->month_num();
$day_diff = $now->day_num() - $this->day_num();
if ($day_diff < 0 || $month_diff < 0) {
$year_diff --;
}
return $year_diff;
}
/**
* Find MySQL Date format (eg. 2014-02-25 00:00:00)
*
* @return string
*/
public function mysql($time = true) {
return $this->formatted('Y-m-d'.($time ? ' H:i:s' : ''));
}
/**
* Find the relative date
*
* @return string
*/
public function fuzzy($append = 'ago') {
// Difference between now and the passed date
$diff = time() - $this->_timestamp;
$val = '';
// Waaaayyyy to long ago (earlier than 1970)
if ($this->_timestamp <= 0) {
// A long time ago... in a galaxy far, far away
$val = 'a long time '.$append;
}
// Future date
else if ($diff < 0) {
$val = 'in the future';
}
// Past date
else {
// Loop through each format measurement
foreach ($this->_time_formats as $format) {
// if the difference from now and passed time is less than first option in format measurement
if ($diff < $format[0]) {
// If the format array item has no calculation value
if (count($format) == 2) {
$val = $format[1].($format[0] === 60 ? '' : ' '.$append);
break;
}
// Divide difference by format item value to get number of units
else {
$val = ceil($diff / $format[2]).' '.$format[1].' '.$append;
break;
}
}
}
}
return $val;
}
public function short($time = true) {
return $this->formatted('m/d/Y'.($time ? ' '.$this->_time_format : ''));
}
/**
* Generic date format. See http://php.net/manual/en/function.date.php
*
* @param string $format
* @return mixed
*/
public function formatted($format = null) {
$format = $format ? : 'F j, Y, '.$this->_time_format.' T';
return date($format, $this->_timestamp);
}
}

443
lib/common/File.php Normal file
View File

@ -0,0 +1,443 @@
<?php
namespace Common;
class File {
public $_exif = null;
private $_mime_types = array(
'.txt' => 'text/plain',
'.htm' => 'text/html',
'.html' => 'text/html',
'.php' => 'text/html',
'.css' => 'text/css',
'.js' => 'application/javascript',
'.json' => 'application/json',
'.xml' => 'application/xml',
'.swf' => 'application/x-shockwave-flash',
'.flv' => 'video/x-flv',
// images
'.png' => 'image/png',
'.jpe' => 'image/jpeg',
'.jpeg' => 'image/jpeg',
'.jpg' => 'image/jpeg',
'.gif' => 'image/gif',
'.bmp' => 'image/bmp',
'.ico' => 'image/vnd.microsoft.icon',
'.tiff' => 'image/tiff',
'.tif' => 'image/tiff',
'.svg' => 'image/svg+xml',
'.svgz' => 'image/svg+xml',
// archives
'.zip' => 'application/zip',
'.rar' => 'application/x-rar-compressed',
'.exe' => 'application/x-msdownload',
'.msi' => 'application/x-msdownload',
'.cab' => 'application/vnd.ms-cab-compressed',
// audio/video
'.mp3' => 'audio/mpeg',
'.qt' => 'video/quicktime',
'.mov' => 'video/quicktime',
'.wmv' => 'video/x-ms-wmv',
'.mp4' => 'video/mp4',
'.mp4a' => 'audio/mp4',
'.mpeg' => 'video/mpeg',
// adobe
'.pdf' => 'application/pdf',
'.psd' => 'image/vnd.adobe.photoshop',
'.ai' => 'application/postscript',
'.eps' => 'application/postscript',
'.ps' => 'application/postscript',
'.tiff' => 'image/tiff',
// ms office
'.doc' => 'application/msword',
'.rtf' => 'application/rtf',
'.xls' => 'application/vnd.ms-excel',
'.xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'.docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'.ppt' => 'application/vnd.ms-powerpoint',
// open office
'.odt' => 'application/vnd.oasis.opendocument.text',
'.ods' => 'application/vnd.oasis.opendocument.spreadsheet',
);
/**
* default structure of the validations array
* @var array
*/
private $_validations = array(
'extension' => array(),
'category' => array(),
'size' => 200,
'custom' => null
);
private $_default_properties = array(
'name' => '',
'tmp_name' => '',
'size' => 0,
'error' => UPLOAD_ERR_OK,
'extension' => ''
);
// custom filtered errors
const UPLOAD_ERR_EXTENSION_FILTER = 100;
const UPLOAD_ERR_CATEGORY_FILTER = 101;
const UPLOAD_ERR_SIZE_FILTER = 102;
/**
* errors container array
* @var array
*/
private $_errors = array();
/**
* error messages container array
* @var array
*/
private $_error_messages = array(
UPLOAD_ERR_OK => "There is no error, the file uploaded with success.",
UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini.",
UPLOAD_ERR_FORM_SIZE => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.",
UPLOAD_ERR_PARTIAL => "The uploaded file was only partially uploaded.",
UPLOAD_ERR_NO_FILE => "No file was uploaded.",
UPLOAD_ERR_NO_TMP_DIR => "Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.",
UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk. Introduced in PHP 5.1.0.",
UPLOAD_ERR_EXTENSION => "A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop;examining the list of loaded extensions with phpinfo() may help. Introduced in PHP 5.2.0.",
self::UPLOAD_ERR_EXTENSION_FILTER => "File type not allowed",
self::UPLOAD_ERR_CATEGORY_FILTER => "File not allowed",
self::UPLOAD_ERR_SIZE_FILTER => "File size not allowed"
);
/**
* initialize the File class
* @param array $properties file data
* @param array $validations validation array
*/
public function __construct($properties, $validations = array()) {
$this->_validations = self::_set_array_defaults($this->_validations, $validations);
$this->_default_properties = self::_set_array_defaults($this->_default_properties, $properties);
// set this instance's properties from the provided data
foreach ($this->_default_properties as $key => $value) {
$this->{$key} = $value;
}
// get the file info and add them as this instance's properties
$info = $this->get_info();
foreach ($info as $key => $info) {
$this->{$key} = $info;
}
// see if Exif class exists and if it's an image file
if (class_exists('Exif') && $this->tmp_name) {
switch ($this->extension) {
case '.jpg':
case '.jpeg':
case '.tiff':
$this->_exif = new Exif($this->tmp_name);
break;
}
}
}
/**
* set the default values to an input array
* @param array $default_structure the default structure of the array
* @param array $array_value the input value
* @param string $set_to_key_if_fail set to a default key if failed to set appropriate value
*/
private static function _set_array_defaults($default_structure, $array_value, $set_to_key_if_fail = "") {
if ($set_to_key_if_fail != "") {
if (!is_array($array_value) || !isset($array_value[$set_to_key_if_fail])) {
if (isset($default_structure[$set_to_key_if_fail]))
$default_structure[$set_to_key_if_fail] = $array_value;
return $default_structure;
}
}
foreach ($array_value as $key => $value) {
$default_structure[$key] = $value;
}
return $default_structure;
}
/**
* put the tmp_name somewhere
* @param string $dest_path the destination path
* @param string $filename the filename, leave blank to use the upload's name
* @return boolean true if success, otherwise false
*/
public function put($dest_path, $filename = '') {
if (is_dir($dest_path)) {
if (!$filename) $filename = $this->name;
return move_uploaded_file($this->tmp_name, $dest_path.'/'.$filename);
} return false;
}
/**
* get error messages
* @param boolean $return_str should it return an string or array
* @return string/array returns the error string or errors array
*/
public function get_error($return_str = true) {
$messages = $this->_error_messages;
$errors = array_map(function($error) use ($messages) {
if (isset($messages[$error])) return $messages[$error];
else return is_int($error) ? 'Unknown File Error' : $error;
}, $this->_errors);
return $return_str ? implode('; ', $errors) : $errors;
}
/**
* set the error message of the error type
* @param int $error_num error type
* @param string $message error message
*/
public function set_error_message($error_num, $message = '') {
$this->_error_messages[$error_num] = $message;
}
/**
* validate the file
* @return boolean true if valid, otherwise false
*/
public function validate() {
if ($this->error !== UPLOAD_ERR_OK) {
$this->_errors[] = $this->error;
}
// filter size
$def_size_filter = array(
'max' => 200, // 200 MB
'min' => 0,
'unit' => 'MB',
'message' => '[size (kb): '.$this->size.'] '.$this->_error_messages[self::UPLOAD_ERR_SIZE_FILTER]
);
$size_filter = self::_set_array_defaults($def_size_filter, $this->_validations['size'], 'max');
$this->set_error_message(self::UPLOAD_ERR_SIZE_FILTER, $size_filter['message']);
$get_actual_size = function($size, $unit) {
switch (strtolower($unit)) {
case 'mb':
$size = $size * 1048576;
break;
case 'kb':
$size = $size * 1024;
case 'gb':
$size = $size * 1073741824;
}
return $size;
};
$max_actual_size = $get_actual_size($size_filter['max'], $size_filter['unit']);
$min_actual_size = $get_actual_size($size_filter['min'], $size_filter['unit']);
if ($this->size > $max_actual_size || $this->size < $min_actual_size)
$this->_errors[] = self::UPLOAD_ERR_SIZE_FILTER;
// filter extension
if ($this->_validations['extension']) {
$def_ext_filter = array(
'is' => array(),
'not' => array(),
'message' => '[extension: '.$this->extension.'] '.$this->_error_messages[self::UPLOAD_ERR_EXTENSION_FILTER]
);
$ext_filter = self::_set_array_defaults($def_ext_filter, $this->_validations['extension'], 'is');
$this->set_error_message(self::UPLOAD_ERR_EXTENSION_FILTER, $ext_filter['message']);
if (!is_array($ext_filter['is'])) $ext_filter['is'] = array($ext_filter['is']);
if (!is_array($ext_filter['not'])) $ext_filter['not'] = array($ext_filter['not']);
if (!in_array($this->extension, $ext_filter['is']) || in_array($this->extension, $ext_filter['not']))
$this->_errors[] = self::UPLOAD_ERR_EXTENSION_FILTER;
}
// filter category
if ($this->_validations['category']) {
$def_cat_filter = array(
'is' => array(),
'not' => array(),
'message' => '[category: '.$this->category.'] '.$this->_error_messages[self::UPLOAD_ERR_CATEGORY_FILTER]
);
$cat_filter = self::_set_array_defaults($def_cat_filter, $this->_validations['category'], 'is');
$this->set_error_message(self::UPLOAD_ERR_CATEGORY_FILTER, $cat_filter['message']);
if (!is_array($cat_filter['is'])) $cat_filter['is'] = array($cat_filter['is']);
if (!is_array($cat_filter['not'])) $cat_filter['not'] = array($cat_filter['not']);
if (!in_array($this->category, $cat_filter['is']) || in_array($this->category, $cat_filter['not']))
$this->_errors[] = self::UPLOAD_ERR_CATEGORY_FILTER;
}
if ($this->_validations['custom']) {
$custom_validations = is_array($this->_validations['custom']) ? $this->_validations['custom'] : array($this->_validations['custom']);
foreach ($custom_validations as $validation) {
$result = $this->_validations['custom']($this);
if ($result != '' && $result !== true && $result !== null) {
$this->_errors[] = $result;
}
}
}
return !$this->_errors;
}
/**
* get the exif GPS data (if the file is an image)
* @return array array of lat/lng if success, otherwise false
*/
public function get_exif_gps() {
return $this->_exif ? $this->_exif->get_gps() : false;
}
/**
* get the exif data (if the file is an image)
* @return array array of exif info if success, otherwise false
*/
public function get_exif() {
return $this->_exif ? $this->_exif->get_data() : false;
}
/**
* is category
* @param string $category test if the file is this category
* @return boolean true if it is, otherwise false
*/
public function is($category) {
return $category == $this->category;
}
/**
* get the file info evaluated from the $name property
* @return stdClass file info
*/
public function get_info($icon_prefix = 'octicon') {
preg_match('/\.[^\.]+$/i', $this->name, $ext);
preg_match('/\.\w+/i', isset($ext[0]) ? $ext[0] : '', $ext);
$return = new \stdClass;
$extension = isset($ext[0]) ? $ext[0] : '';
$category = "";
switch (strtolower($extension)) {
case '.pdf':
case '.doc':
case '.rtf':
case '.txt':
case '.docx':
case '.xls':
case '.xlsx':
$category = 'document';
break;
case '.png':
case '.jpg':
case '.jpeg':
case '.gif':
case '.bmp':
case '.psd':
case '.tif':
case '.tiff':
$category = 'image';
break;
case '.mp3':
case '.wav':
case '.wma':
case '.m4a':
case '.m3u':
$category = 'audio';
break;
case '.3g2':
case '.3gp':
case '.asf':
case '.asx':
case '.avi':
case '.flv':
case '.m4v':
case '.mov':
case '.mp4':
case '.mpg':
case '.srt':
case '.swf':
case '.vob':
case '.wmv':
$category = 'video';
break;
case '.css':
case '.php':
case '.php3':
case '.sql':
case '.cs':
case '.html':
case '.less':
case '.xml':
$category = 'code';
break;
case '.zip':
case '.gzip':
case '.7z':
case '.tar':
case '.rar':
$category = 'compressed';
break;
default:
$category = 'other';
break;
}
$return->extension = $extension;
$return->category = $category;
$return->type = isset($this->_mime_types[$extension]) ? $this->_mime_types[$extension] : 'application/octet-stream';
return $return;
}
public function get_mime_type() {
return mime_content_type($this->tmp_name);
}
/**
* get base64_encode of the file
* @return string base64 encoded string
*/
public function get_base64() {
return base64_encode(file_get_contents($this->tmp_name));
}
/**
* format the size of the file to a readable string
* @return string formatted file size
*/
public function format_size() {
$bytes = $this->size;
if ($bytes >= 1073741824) {
$format = number_format($bytes / 1073741824, 2) . ' GB';
} elseif ($bytes >= 1048576) {
$format = number_format($bytes / 1048576, 2) . ' MB';
} elseif ($bytes >= 1024) {
$format = number_format($bytes / 1024, 2) . ' KB';
} elseif ($bytes > 1) {
$format = $bytes . ' bytes';
} elseif ($bytes == 1) {
$format = $bytes . ' byte';
} else {
$format = '0 bytes';
}
return $format;
}
}
?>

89
lib/common/Gravatar.php Normal file
View File

@ -0,0 +1,89 @@
<?php
namespace Common;
class Gravatar {
const URL = 'https://www.gravatar.com';
const RATING_G = 'g';
const RATING_PG = 'pg';
const RATING_R = 'r';
const RATING_X = 'x';
// 404 | mm | identicon | monsterid | wavatar
const IMAGESET_MM = 'mm';
const IMAGESET_404 = '404';
const IMAGESET_IDENTICON = 'identicon';
const IMAGESET_MONSTERID = 'monsterid';
const IMAGESET_WAVATAR = 'wavatar';
private $_email = '';
private $_properties = array();
function __construct($email, $s = 80, $d = self::IMAGESET_IDENTICON, $r = self::RATING_G) {
$this->_email = $email;
$this->_properties['hash'] = md5(strtolower(trim($email)));
$this->_properties['imageset'] = $d;
$this->_properties['size'] = $s;
$this->_properties['rating'] = $r;
}
function get_url() {
$url = self::URL.'/avatar/'.$this->_properties['hash'];
$url .= '?s='.$this->_properties['size'].'&d='.$this->_properties['imageset'].'&r='.$this->_properties['rating'];
return $url;
}
function get_profile() {
$str = @file_get_contents(self::URL.'/'.$this->_properties['hash'].'.php');
$profile = unserialize($str);
return $profile ? $profile['entry'][0] : false;
}
function get_img($attrs = array()) {
$url = $this->get_url();
$arr_attrs = array();
foreach ($attrs as $key => $value) {
$arr_attrs[] = $key.'="'.$value.'"';
}
$result = '<img src="'.$url.'" '.implode(' ', $arr_attrs).' style="width: '.$this->_properties['size'].'px !important;" />';
return $result;
}
function __call($name, $args) {
$call = explode('_', $name);
if ($call) {
$method = $call[0];
$property = $call[1];
switch ($method) {
case 'get':
if (isset($this->_properties[$property])) {
return $this->_properties[$property];
} else if ($property == 'img') {
$size = $call[2];
$this->_properties['size'] = (int)$size;
return $this->get_img(($args[0]) ? $args[0] : array());
}
break;
case 'set':
if (isset($this->_properties[$property]) && $args) {
$this->_properties[$property] = $args[0];
return true;
} else return false;
break;
default:
return null;
break;
}
} else return null;
}
}
?>

141
lib/common/HTMLIndent.php Normal file
View File

@ -0,0 +1,141 @@
<?php
namespace Common;
/**
* @link https://github.com/gajus/dintent for the canonical source repository
* @license https://github.com/gajus/dintent/blob/master/LICENSE BSD 3-Clause
*/
class HTMLIndent {
private
$log = array(),
$indent = ' ',
$temporary_replacements_script = array(),
$temporary_replacements_inline = array();
const MATCH_INDENT_NO = 0;
const MATCH_INDENT_DECREASE = 1;
const MATCH_INDENT_INCREASE = 2;
const MATCH_DISCARD = 3;
public function indent ($input) {
$this->log = array();
// Dindent does not indent <script> body. Instead, it temporary removes it from the code, indents the input, and restores the script body.
if (preg_match_all('/<script\b[^>]*>([\s\S]*?)<\/script>/mi', $input, $matches)) {
$this->temporary_replacements_script = $matches[0];
foreach ($matches[0] as $i => $match) {
$input = str_replace($match, '<script>' . ($i + 1) . '</script>', $input);
}
}
// Removing double whitespaces to make the source code easier to read.
// With exception of <pre>/ CSS white-space changing the default behaviour, double whitespace is meaningless in HTML output.
// This reason alone is sufficient not to use Dindent in production.
$input = str_replace("\t", '', $input);
$input = preg_replace('/\s{2,}/', ' ', $input);
// Remove inline tags and replace them with text entities.
if (preg_match_all('/<(b|i|abbr|em|strong|a|span)[^>]*>(?:[^<]*)<\/\1>/', $input, $matches)) {
$this->temporary_replacements_inline = $matches[0];
foreach ($matches[0] as $i => $match) {
$input = str_replace($match, 'ᐃ' . ($i + 1) . 'ᐃ', $input);
}
}
$subject = $input;
$output = '';
$next_line_indentation_level = 0;
do {
$indentation_level = $next_line_indentation_level;
$patterns = array(
// block tag
'/^(<([a-z]+)(?:[^>]*)>(?:[^<]*)<\/(?:\2)>)/' => static::MATCH_INDENT_NO,
// DOCTYPE
'/^<!([^>]*)>/' => static::MATCH_INDENT_NO,
// tag with implied closing
'/^<(input|link|meta|base|br|img|hr)([^>]*)>/' => static::MATCH_INDENT_NO,
// opening tag
'/^<[^\/]([^>]*)>/' => static::MATCH_INDENT_INCREASE,
// closing tag
'/^<\/([^>]*)>/' => static::MATCH_INDENT_DECREASE,
// self-closing tag
'/^<(.+)\/>/' => static::MATCH_INDENT_DECREASE,
// whitespace
'/^(\s+)/' => static::MATCH_DISCARD,
// text node
'/([^<]+)/' => static::MATCH_INDENT_NO
);
$rules = array('NO', 'DECREASE', 'INCREASE', 'DISCARD');
foreach ($patterns as $pattern => $rule) {
if ($match = preg_match($pattern, $subject, $matches)) {
$this->log[] = array(
'rule' => $rules[$rule],
'pattern' => $pattern,
'subject' => $subject,
'match' => $matches[0]
);
$subject = mb_substr($subject, mb_strlen($matches[0]));
if ($rule === static::MATCH_DISCARD) {
break;
}
if ($rule === static::MATCH_INDENT_NO) {
} else if ($rule === static::MATCH_INDENT_DECREASE) {
$next_line_indentation_level--;
$indentation_level--;
} else {
$next_line_indentation_level++;
}
if ($indentation_level < 0) {
$indentation_level = 0;
}
#$output .= str_repeat($this->indent, $indentation_level) . 'A:' . $indentation_level . "\n";
$output .= str_repeat($this->indent, $indentation_level) . $matches[0] . "\n";
break;
}
}
} while ($match);
$interpreted_input = '';
foreach ($this->log as $e) {
$interpreted_input .= $e['match'];
}
if ($interpreted_input !== $input) {
throw new \RuntimeException('Did not reproduce the exact input.');
}
$output = preg_replace('/(<(\w+)[^>]*>)\s*(<\/\2>)/', '\\1\\3', $output);
foreach ($this->temporary_replacements_script as $i => $original) {
$output = str_replace('<script>' . ($i + 1) . '</script>', $original, $output);
}
foreach ($this->temporary_replacements_inline as $i => $original) {
$output = str_replace('ᐃ' . ($i + 1) . 'ᐃ', $original, $output);
}
return trim($output);
}
/**
* Debugging utility. Get log for the last indent operation.
*
* @return array
*/
public function getLog () {
return $this->log;
}
}

117
lib/common/Upload.php Normal file
View File

@ -0,0 +1,117 @@
<?php
namespace Common;
/**
* @package FileUpload Class in PHP5
* @author Jovanni Lo
* @link http://www.lodev09.com
* @copyright 2014 Jovanni Lo, all rights reserved
* @license
* The MIT License (MIT)
* Copyright (c) 2014 Jovanni Lo
*
* 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.
*/
class Upload {
/**
* files array for mutliple
* @var array
*/
public $files = array();
/**
* file for single
* @var [type]
*/
public $file;
/**
* raw data of the file upload
* @var [type]
*/
private $_raw;
/**
* construct the class
* @param array $files_data data from $_FILES['name']
* @param array $validations validation array
*/
public function __construct($files_data, $validations = array()) {
$this->_raw = $files_data;
if ($this->_raw ) {
// check if it's multiple or single file upload
if ($this->_is_multiple()) {
foreach ($this->_raw["error"] as $key => $error) {
$file_info = new \stdClass;
$file_info->name = $this->_raw['name'][$key];
$file_info->type = $this->_raw['type'][$key];
$file_info->tmp_name = $this->_raw['tmp_name'][$key];
$file_info->error = $error;
$file_info->size = $this->_raw['size'][$key];
$file = new File($file_info, $validations);
$this->files[] = $file;
}
// let the single "file" property be the first file (index 0)
if ($this->files) $this->file = $this->files[0];
} else {
$file_info = new \stdClass;
foreach ($this->_raw as $key => $value) {
$file_info->{$key} = $value;
}
$file = new File($file_info, $validations);
$this->files[] = $file;
$this->file = $this->files[0];
}
}
}
/**
* loop through each file
* @param closure $callback callback function for each file
*/
public function each($callback) {
if (!$this->_is_closure($callback)) return;
foreach ($this->files as $file) {
$callback($file);
}
}
/**
* check if the upload data is multiple or not
* @return boolean true if multiple, otherwise false
*/
private function _is_multiple() {
return is_array($this->_raw["name"]);
}
/**
* check if a value is a closure object
* @param object $obj object to test
* @return boolean true if it's a closure object, otherwise false
*/
private function _is_closure($obj) {
return (is_object($obj) && ($obj instanceof \Closure));
}
}
?>

1042
lib/common/Util.php Normal file

File diff suppressed because it is too large Load Diff

10
lib/config.php Normal file
View File

@ -0,0 +1,10 @@
<?php
// configure database connection
defined("DB_HOST") ? null : define("DB_HOST", "127.0.0.1");
defined("DB_USER") ? null : define("DB_USER", "root");
defined("DB_PASSWORD") ? null : define("DB_PASSWORD", "root_password");
defined("DB_NAME") ? null : define("DB_NAME", "db");
?>

27
lib/func.php Normal file
View File

@ -0,0 +1,27 @@
<?php
function debug($msg, $options = null, $return = false) {
return \Common\Util::debug($msg, $options, $return);
}
function plog($msg, $return = false) {
return \Common\Util::debug($msg, array('dismiss' => false), $return);
}
function clog($msg, $newline = true, $return = false) {
return \Common\Util::debug($msg, array('newline' => $newline, 'dismiss' => false), $return);
}
function get($field, $data = null, $default = null) {
return \Common\Util::get($field, $data, $default);
}
function br2nl($text) {
return \Common\Util::br2nl($text);
}
function array_delete($array, $items) {
return array_diff($array, is_array($items) ? $items : array($items));
}
?>

View File

@ -0,0 +1,155 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class Accordion extends UI {
private $_options_map = array(
'global_icons' => array()
);
private $_structure = array(
'panel' => array(),
'id' => '',
'header' => array(),
'content' => array(),
'expand' => array(),
'padding' => array(),
'icons' => array(),
'options' => array()
);
public function __construct($panels, $options = array()) {
$this->_options_map['global_icons'] = array(parent::$icon_source.'-lg '.parent::$icon_source.'-chevron-down pull-right', ''.parent::$icon_source.'-lg '.parent::$icon_source.'-chevron-up pull-right');
$this->_init_structure($panels, $options);
}
private function _init_structure($panels, $user_options = array()) {
$this->_structure = Util::array_to_object($this->_structure);
$this->_structure->options = Util::set_array_prop_def($this->_options_map, $user_options);
$this->_structure->id = Util::create_id(true);
$this->_structure->panel = $panels;
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
parent::err('Undefined structure property: '.$name);
return null;
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
parent::err('Undefined structure property: '.$name);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
public function print_html($return = false) {
$structure = $this->_structure;
$panels = Util::get_property_value($structure->panel, array(
'if_closure' => function($panels) {
return Util::run_callback($panels, array($this));
},
'if_other' => function($panels) {
parent::err('parent::Accordion:panel requires array');
return null;
}
));
if (!is_array($panels)) {
parent::err("parent::Accordion:panel requires array");
return null;
}
$panel_html_list = array();
foreach ($panels as $panel_id => $panel_prop) {
$panel_structure = array(
'header' => isset($structure->header[$panel_id]) ? $structure->header[$panel_id] : '',
'content' => isset($structure->content[$panel_id]) ? $structure->content[$panel_id] : '',
'expand' => isset($structure->expand[$panel_id]) ? $structure->expand[$panel_id] : false,
'padding' => isset($structure->padding[$panel_id]) ? $structure->padding[$panel_id] : null,
);
$new_panel_prop = Util::get_clean_structure($panel_structure, $panel_prop, array($this, $panels), 'header');
foreach ($new_panel_prop as $panel_prop_key => $panel_prop_vaue) {
$new_panel_prop_value = Util::get_property_value($panel_prop_vaue, array(
'if_closure' => function($prop_value) use ($panels) {
return Util::run_callback($prop_value, array($this, $panels));
}
));
$new_panel_prop[$panel_prop_key] = $new_panel_prop_value;
}
// header
$header_structure = array(
'content' => '',
'container' => 'h4',
'icons' => isset($structure->icons[$panel_id]) ? $structure->icons[$panel_id] : $structure->options['global_icons']
);
$new_header_prop = Util::get_clean_structure($header_structure, $new_panel_prop['header'], array($this, $panels), 'content');
$a_classes = array();
if (!$new_panel_prop['expand']) $a_classes[] = 'collapsed';
$a_attr = array();
$a_attr[] = 'data-parent="#'.$structure->id.'"';
$a_attr[] = 'href="#'.$panel_id.'"';
$a_attr[] = 'data-toggle="collapse"';
$icons = is_array($new_header_prop['icons']) ? implode(' ', array_map(function($icon){
return '<i class="'.parent::$icon_source.' '.$icon.'"></i> ';
}, $new_header_prop['icons'])) : $new_header_prop['icons'];
$body_classes = array();
$body_classes[] = 'panel-body';
if (isset($new_panel_prop['padding'])) {
$body_classes[] = $new_panel_prop['padding'] ? 'padding-'.$new_panel_prop['padding'] : 'no-padding';
}
$panel_html = '<div class="panel panel-default">';
$panel_html .= ' <div class="panel-heading">';
$panel_html .= ' <'.$new_header_prop['container'].' class="panel-title">';
$panel_html .= ' <a '.implode(' ', $a_attr).' class="'.implode(' ', $a_classes).'"> ';
$panel_html .= $icons;
$panel_html .= $new_header_prop['content'];
$panel_html .= ' </a>';
$panel_html .= ' </'.$new_header_prop['container'].'>';
$panel_html .= ' </div>';
$panel_html .= ' <div id="'.$panel_id.'" class="panel-collapse collapse '.($new_panel_prop['expand'] ? 'in' : '').'">';
$panel_html .= ' <div class="'.implode(' ', $body_classes).'">';
$panel_html .= $new_panel_prop['content'];
$panel_html .= ' </div>';
$panel_html .= ' </div>';
$panel_html .= '</div>';
$panel_html_list[] = $panel_html;
}
$result = '<div class="panel-group smart-accordion-default" id="'.$structure->id.'">';
$result .= implode('', $panel_html_list);
$result .= '</div>';
if ($return) return $result;
else echo $result;
}
}
?>

View File

@ -0,0 +1,241 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class Button extends UI {
const BUTTON_CONTAINER_ANCHOR = 'a';
const BUTTON_CONTAINER_BUTTON = 'button';
const BUTTON_SIZE_LARGE = 'lg';
const BUTTON_SIZE_SMALL = 'sm';
const BUTTON_SIZE_XSMALL = 'xs';
const BUTTON_SIZE_MEDIUM = 'md';
private $_options_map = array(
'disabled' => false,
'labeled' => false
);
private $_structure = array(
'options' => array(),
'content' => '',
'icon' => '',
'type' => '',
'container' => self::BUTTON_CONTAINER_BUTTON,
'size' => self::BUTTON_SIZE_MEDIUM,
'attr' => array(),
'id' => '',
'class' => '',
'dropdown' => array()
);
public function __construct($content = '', $type = 'default', $options = array()) {
$this->_init_structure($type, $content, $options);
}
private function _init_structure($type, $content, $user_options) {
$this->_structure = Util::array_to_object($this->_structure);
$this->_structure->type = $type;
$this->_structure->content = $content;
$this->_structure->options = Util::set_array_prop_def($this->_options_map, $user_options);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
parent::err('Undefined structure property: '.$name);
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
parent::err('Undefined structure property: '.$name);
return null;
}
public function print_html($return = false) {
$structure = $this->_structure;
$icon = Util::get_property_value($structure->icon, array(
'if_closure' => function($icon) { return Util::run_callback($icon, array($this)); },
'if_array' => function($icon) {
parent::err('parent::Widget::icon requires string.');
return '';
}
));
$container = Util::get_property_value($structure->container, array(
'if_closure' => function($container) { return Util::run_callback($container, array($this)); },
'if_array' => function($container) {
parent::err('parent::Widget::container requires string.');
return '';
}
));
$content = Util::get_property_value($structure->content, array(
'if_closure' => function($content) { return Util::run_callback($content, array($this)); },
'if_array' => function($content) {
parent::err('parent::Widget::content requires string.');
return '';
}
));
$attr = Util::get_property_value($structure->attr, array(
'if_closure' => function($attr) {
$callback_return = Util::run_callback($attr, $array($this));
if (is_array($callback_return)) return $callback_return;
else return array($callback_return);
},
'if_array' => function($attr) {
$attrs = array();
foreach ($attr as $key => $value) {
$attrs[] = $key.'="'.$value.'"';
}
return $attrs;
},
'if_other' => function($attr) {
return array($attr);
}
));
$class = Util::get_property_value($structure->class, array(
"if_closure" => function($class) { return Util::run_callback($class, array($this)); },
"if_array" => function($class) {
return implode(' ', $class);
}
));
$type = Util::get_property_value($structure->type, array(
'if_array' => function($class) {
parent::err('parent::Button:type requires string.');
return parent::BUTTON_TYPE_DEFAULT;
}
));
$classes = array();
// labeled and icon
if (trim($icon)) {
$icon = '<i class="'.parent::$icon_source.' '.$icon.'"></i>';
if ($structure->options['labeled']) {
$classes[] = 'btn-labeled';
$icon = $structure->options['labeled'] ? '<span class="btn-label">'.$icon.'</span>' : $icon;
}
$content = $icon.' '.$content;
}
// custom class
if ($class) $classes[] = $class;
// size
$size_class = '';
if ($structure->size) {
$size_class = 'btn-'.$structure->size;
$classes[] = $size_class;
}
// disabled
$disabled = $structure->options['disabled'] ? 'disabled' : '';
$classes[] = $disabled;
$class_htm = $classes ? ' '.implode(' ', $classes) : '';
$result = '';
if ($structure->id) $attr[] = 'id="'.$structure->id.'"';
if ($structure->dropdown) {
$dd_prop = array(
'items' => array(),
'multilevel' => false,
'split' => false,
'attr' => array(),
'class' => '',
'id' => ''
);
$new_dd_prop = Util::get_clean_structure($dd_prop, $structure->dropdown, array($this), 'items');
if (is_array($new_dd_prop['items'])) {
$dropdown_html = parent::print_dropdown($new_dd_prop['items'], array(
'multilevel' => $new_dd_prop['multilevel'],
'class' => $new_dd_prop['class'],
'attr' => $new_dd_prop['attr'],
'id' => $new_dd_prop['id']
), true);
} else {
$dropdown_html = $new_dd_prop['items'];
}
if ($new_dd_prop['split']) {
$split_prop = array(
'type' => $type,
'disabled' => false,
'dropup' => false,
'class' => array(),
'attr' => array()
);
$new_split_prop = Util::get_clean_structure($split_prop, $new_dd_prop['split'], array($this, $new_dd_prop), 'type');
$split_attrs = array();
if (is_array($new_split_prop['attr'])) {
foreach ($new_split_prop['attr'] as $split_attr => $value) {
$split_attrs[] = $split_attr.'="'.$value.'"';
}
} else {
$split_attrs[] = $new_split_prop['attr'];
}
$split_classes = array();
if (is_array($new_split_prop['class'])) $split_classes[] = implode(' ', $new_split_prop['class']);
else $split_classes[] = $new_split_prop['class'];
$split_classes[] = $size_class;
$split_class_htm = $split_classes ? ' '.implode(' ', $split_classes) : '';
$btn_main = '<'.$container.' class="btn btn-'.$type.$class_htm.'" '.implode(' ', $attr).'>';
$btn_main .= $content;
$btn_main .= '</'.$container.'>';
$btn_dd = '<'.$container.' class="btn btn-'.$new_split_prop['type'].$split_class_htm.' dropdown-toggle" data-toggle="dropdown" '.implode(' ', $split_attrs).'>';
$btn_dd .= '<span class="caret"></span>';
$btn_dd .= '</'.$container.'>';
$btn_dd .= $dropdown_html;
$result .= '<div class="btn-group'.($new_split_prop['dropup'] ? ' dropup' : '').'">'.$btn_main.$btn_dd.'</div>';
} else {
$result .= '<div class="dropdown">';
$result .= '<'.$container.' class="btn btn-'.$type.$class_htm.' dropdown-toggle" '.implode(' ', $attr).' data-toggle="dropdown">';
$result .= $content.' <span class="caret"></span>';
$result .= '</'.$container.'>';
$result .= $dropdown_html;
$result .= '</div>';
}
} else {
$result .= '<'.$container.' class="btn btn-'.$type.$class_htm.'" '.implode(' ', $attr).'>';
$result .= $content;
$result .= '</'.$container.'>';
}
if ($return) return $result;
else echo $result;
}
}
?>

View File

@ -0,0 +1,148 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class Carousel extends UI {
private $_options_map = array(
'style' => 'slide',
'controls' => array('<span class="glyphicon glyphicon-chevron-left"></span>', '<span class="glyphicon glyphicon-chevron-right"></span>')
);
private $_structure = array(
'item' => array(),
'id' => '',
'active' => array(),
'caption' => array(),
'img' => array(),
'options' => array()
);
public function __construct($items, $style='slide', $options = array()) {
$this->_init_structure($items, $style, $options);
}
private function _init_structure($items, $style='slide', $user_options = array()) {
$this->_structure = Util::array_to_object($this->_structure);
$this->_structure->options = Util::set_array_prop_def($this->_options_map, $user_options);
$this->_structure->id = Util::create_id(true);
$this->_structure->item = $items;
$this->_structure->options['style'] = $style;
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
parent::err('Undefined structure property: '.$name);
return null;
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
parent::err('Undefined structure property: '.$name);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
public function print_html($return = false) {
$structure = $this->_structure;
$items = Util::get_property_value($structure->item, array(
'if_closure' => function($items) {
return Util::run_callback($items, array($this));
},
'if_other' => function($items) {
parent::err('parent::Carousel:item requires array');
return null;
}
));
if (!is_array($items)) {
parent::err("parent::Carousel:item requires array");
return null;
}
$indicators_list = array();
$items_list = array();
$has_active = false;
$index = 0;
foreach ($items as $item_key => $item) {
$item_structure = array(
'img' => isset($structure->img[$item_key]) ? $structure->img[$item_key] : '',
'caption' => isset($structure->caption[$item_key]) ? $structure->caption[$item_key] : '',
'active' => isset($structure->active[$item_key]) ? $structure->active[$item_key] : '',
);
$new_item_prop = Util::get_clean_structure($item_structure, $item, array($this, $items), 'img');
foreach ($new_item_prop as $tab_item_key => $item_prop_value) {
$new_item_prop_value = Util::get_property_value($item_prop_value, array(
'if_closure' => function($prop_value) use ($items) {
return Util::run_callback($prop_value, array($this, $items));
}
));
$new_item_prop[$tab_item_key] = $new_item_prop_value;
}
$image_prop = array('src' => '', 'alt' => '');
$new_image_prop = Util::get_clean_structure($image_prop, $new_item_prop['img'], array($this, $items, $new_item_prop), 'src');
$indicator_classes = array();
$item_classes = array();
$item_classes[] = 'item';
if ((!$structure->active && !$has_active) || ($new_item_prop['active'] === true && !$has_active)) {
$has_active = true;
$indicator_classes[] = 'active';
$item_classes[] = 'active';
}
$indicators_list[] = '<li data-target="#'.$structure->id.'" data-slide-to="'.$index.'" class="'.implode(' ', $indicator_classes).'"></li>';
$item_html = '<div class="'.implode(' ', $item_classes).'">';
$item_html .= ' <img src="'.$new_image_prop['src'].'" alt="'.$new_image_prop['alt'].'">';
$item_html .= ' <div class="carousel-caption">';
$item_html .= $new_item_prop['caption'];
$item_html .= ' </div>';
$item_html .= '</div>';
$items_list[] = $item_html;
$index++;
}
$controls_html = '';
if (($structure->options['controls'])) {
$controls_html .= ' <a class="left carousel-control" href="#'.$structure->id.'" data-slide="prev">';
$controls_html .= $structure->options['controls'][0];
$controls_html .= ' </a>';
$controls_html .= ' <a class="right carousel-control" href="#'.$structure->id.'" data-slide="next">';
$controls_html .= $structure->options['controls'][1];
$controls_html .= ' </a>';
}
$result = '<div id="'.$structure->id.'" class="carousel '.$structure->options['style'].'">';
$result .= ' <ol class="carousel-indicators">';
$result .= implode('', $indicators_list);
$result .= ' </ol>';
$result .= ' <div class="carousel-inner">';
$result .= implode('', $items_list);
$result .= ' </div>';
$result .= $controls_html;
$result .= '</div>';
if ($return) return $result;
else echo $result;
}
}
?>

View File

@ -0,0 +1,704 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class DataTable extends UI {
private $_options_map = array(
"in_widget" => true,
"row_details" => false,
"row_details_opened" => false,
"row_detail_icons" => array('closed' => 'chevron-right', 'opened' => 'chevron-down'),
"checkboxes" => false,
"static" => false,
"paginate" => true,
"columns" => true,
"table" => true,
"striped" => true,
"bordered" => true,
"hover" => true,
"condensed" => false,
"forum" => false,
"default_col" => "No Data"
);
private $_structure = array(
"cell" => array(),
"col" => array(),
"options" => array(),
"data" => array(),
"widget" => null,
"each" => array(),
"id" => "",
"row" => array(),
"hidden" => array(),
"hide" => array(),
"js" => array(),
"sort" => array(),
"toolbar" => array(),
"class" => array()
);
private $_uid = '';
private $_data = array();
private $_cells_map = array();
private $_cols_map = array();
private $_hide_map = array();
public function __construct($data, $options = array(), $widget_title = '<h2>DataTable Result Set</h2>', $widget_icon = 'table') {
$this->_init_structure($data, $options, $widget_title, $widget_icon);
}
private function _init_structure($data, $user_options, $widget_title, $widget_icon) {
$this->_structure = Util::array_to_object($this->_structure);
$this->_structure->data = $data;
$this->_structure->options = Util::set_array_prop_def($this->_options_map, $user_options);
$uid = Util::create_id(true);
$this->_structure->id = $uid; // set the id as default id
$this->_uid = $uid;
$this->_structure->widget = new Widget();
$this->_structure->widget
->header('title', $widget_title)
->body("class", "no-padding")
->body("editbox", '<input class="form-control" type="text">
<span class="note"><i class="'.parent::$icon_source.' '.parent::$icon_source.'-check text-success"></i> Change title to update and save instantly!</span>');
if ($widget_icon) $this->_structure->widget->header('icon', parent::$icon_source.'-'.$widget_icon);
if (!$this->_structure->data) {
$col_list = $this->_structure->options["default_col"] ? array($this->_structure->options["default_col"]) : array();
} else {
$col_list = array_keys(is_object($data[0]) ? get_object_vars($data[0]) : $data[0]);
}
$cols = array_combine($col_list, $col_list);
$cells = array_fill_keys($col_list, array());
$hide = array_fill_keys($col_list, false);
$this->_cells_map = $cells;
$this->_cols_map = $cols;
$this->_hide_map = $hide;
$this->_structure->col = $cols;
$this->_structure->cell = $cells;
$this->_structure->hide = $hide;
$this->_structure->row = array_fill(1, count($data) + 1, array());
$this->_structure->js = array(
"properties" => array(),
"oTable" => 'oTable_'.$this->_uid,
"custom" => ""
);
}
public function rows() {
return count($this->_structure->row);
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
parent::err('Undefined structure property: '.$name);
return null;
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
parent::err('Undefined structure property: '.$name);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
public function is_with_details() {
return isset($this->_structure->options["row_details"]) && $this->_structure->options["row_details"];
}
public function is_with_checkboxes() {
return isset($this->_structure->options["checkboxes"]) && $this->_structure->options["checkboxes"];
}
public function print_js($return = false, $jquery_enclosed = true) {
$structure = $this->_structure;
$table_id = $structure->id;
$dtable_js = '';
if ($structure->options["static"]) {
if ($structure->options['row_details_opened']) {
$row_detail_code = Util::is_closure($structure->options['row_details_opened']) ? $structure->options['row_details_opened']($table_id) : $structure->options['row_details_opened'];
} else {
$row_detail_code = 'nTr.after("<tr class=\"details\"><td class=\"details\" colspan='.count($structure->col).'>" + value + "</td></tr>");';
}
$dtable_js = '
function fnFormatDetails (nTr ) {
var aData = nTr.find("td").map(function() {
return $(this).html();
}).get();
'.($this->is_with_details() ? $this->_get_detail_content($structure->options["row_details"], array_keys($structure->col)) : '').'
}
$("#'.$table_id.' a i[data-toggle=\'row-detail\']").on("click", function (e) {
e.preventDefault();
var nTr = $(this).parents("tr"),
details = nTr.nextUntil(":not(.details)", ".details");
if (details.length > 0) {
/* This row is already open - close it */
$(this).removeClass("'.parent::$icon_source.'-'.$this->options['row_detail_icons']['opened'].'").addClass("'.parent::$icon_source.'-'.$this->options['row_detail_icons']['closed'].'");
this.title = "Show Details";
details.remove();
} else {
/* Open this row */
$(this).removeClass("'.parent::$icon_source.'-'.$this->options['row_detail_icons']['closed'].'").addClass("'.parent::$icon_source.'-'.$this->options['row_detail_icons']['opened'].'");
this.title = "Hide Details";
var value = fnFormatDetails(nTr);
'.$row_detail_code.'
}
});
';
} else {
$otable_var = $structure->js["oTable"];
$dtable_js = '
$(".desktop[data-rel=\'tooltip\']").tooltip();
$(".phone[data-rel=\'tooltip\']").tooltip({placement: tooltip_placement});
function tooltip_placement(context, source) {
var $source = $(source);
var $parent = $source.closest("table")
var off1 = $parent.offset();
var w1 = $parent.width();
var off2 = $source.offset();
var w2 = $source.width();
if( parseInt(off2.left) < parseInt(off1.left) + parseInt(w1 / 2) ) return "right";
return "left";
}
$("#'.$table_id.' a i[data-toggle=\'row-detail\']").on("click", function () {
var nTr = $(this).parents("tr")[0];
if ( '.$otable_var.'.fnIsOpen(nTr) )
{
/* This row is already open - close it */
$(this).removeClass("'.parent::$icon_source.'-'.$this->options['row_detail_icons']['opened'].'").addClass("'.parent::$icon_source.'-'.$this->options['row_detail_icons']['closed'].'");
this.title = "Show Details";
'.$otable_var.'.fnClose( nTr );
}
else
{
/* Open this row */
$(this).removeClass("'.parent::$icon_source.'-'.$this->options['row_detail_icons']['closed'].'").addClass("'.parent::$icon_source.'-'.$this->options['row_detail_icons']['opened'].'");
this.title = "Hide Details";
'.$otable_var.'.fnOpen( nTr, fnFormatDetails('.$otable_var.', nTr), "details" );
}
return false;
});
var '.$otable_var.' = $("#'.$table_id.'").dataTable({
'.(!isset($structure->js['properties']) || !$structure->js['properties'] ? '' :
implode(', ', array_map(function($key, $js) {
return "'$key' : $js";
}, array_keys($structure->js['properties']), $structure->js['properties'])).',').'
'.(!$structure->options["paginate"] ? '"bPaginate": false, "bInfo": false,' : '').'
aoColumns: [
'.($this->is_with_details() ? '{"bSortable": false},' : '').'
'.($this->is_with_checkboxes() ? '{"bSortable": false},' : '').'
'.implode(', ', array_map(function($col) use ($structure) {
if (isset($structure->sort[$col]) && $structure->sort[$col] === false) return '{ "bSortable": false }';
else return 'null';
}, array_keys($structure->col))).'
],
aaSorting: ['.implode(', ', array_filter(array_map(function($col_index, $col) use ($structure) {
$col_index = $this->is_with_details() ? $col_index + 1 : $col_index;
$col_index = $this->is_with_checkboxes() ? $col_index + 1 : $col_index;
if (isset($structure->sort[$col]) && $structure->sort[$col]) {
$sorting = $structure->sort[$col];
return "[$col_index, '$sorting']";
} else return null;
}, array_keys(array_keys($structure->col)), array_keys($structure->col)))).'],
});
// remove pagination div row ? TO-DO
$("#'.$structure->id.'_cols li label input[type=checkbox]").on("click", function() {
fnShowHideCol($(this).data("column-toggle"), $(this).prop("checked"));
});
function fnShowHideCol(iCol, bVis) {
/* Get the DataTables object again - this is not a recreation, just a get of the object */
//var bVis = '.$otable_var.'.fnSettings().aoColumns[iCol].bVisible;
'.$otable_var.'.fnSetColumnVis(iCol, bVis);
}
function fnFormatDetails ( '.$otable_var.', nTr ) {
var aData = '.$otable_var.'.fnGetData( nTr );
'.($this->is_with_details() ? $this->_get_detail_content($structure->options["row_details"], array_keys($structure->col)) : '').'
}
$("#'.$table_id.' th input:checkbox").on("click" , function(){
var that = this;
$(this).closest("table").find("tr > td input:checkbox").each(function(){
this.checked = that.checked;
//$(this).closest("tr").toggleClass("selected");
});
});
'.(isset($structure->toolbar) ? implode("\n", array_map(function($toolbar) {
return $toolbar['js'];
}, $structure->toolbar)) : "" ).'
'.(isset($structure->js["custom"]) ? $structure->js['custom'] : '');
}
if ($jquery_enclosed) {
$result = '$(function() {
'.$dtable_js.'
});';
} else $result = $dtable_js;
if ($return) return $result;
else echo $result;
}
private function _get_detail_content($detail, $cols) {
$result = "";
if (Util::is_closure($detail)) { // improve this TO-DO
$cols_list = new \stdClass;
foreach ($cols as $col)
$cols_list->{$col} = '{'.$col.'}';
$str = $detail($cols_list);
$result = 'return \''.$this->_replace_detail_codes($str, $cols).'\';';
} else if (is_array($detail)) {
if (isset($detail["custom"])) {
$result = $this->_replace_detail_codes($detail['code'], $cols, true);
}
} else $result = 'return \''.$this->_replace_detail_codes($detail, $cols).'\';';
return $result;
}
private function _replace_detail_codes($str, $cols, $custom_code = false) {
preg_match_all("/\{([^{{}}]+)\}/", $str, $matched_cols);
$col_replace = array();
$col_search = array();
foreach($matched_cols[1] as $matched_col) {
$arr_col_index = array_keys($cols, $matched_col);
if ($arr_col_index) {
$col_index = self::is_with_details() ? $arr_col_index[0] + 1 : $arr_col_index[0];
$col_index = self::is_with_checkboxes() ? $col_index + 1 : $col_index;
$col_replace[] = $custom_code ? 'aData['.$col_index.']' : '\'+aData['.$col_index.']+\'';
$col_search[] = "/{{".$matched_col."}}/";
}
}
$result = preg_replace($col_search, $col_replace, $str);
return preg_replace('/\s+/', ' ', $result); //remove white spaces
}
public function print_html($return = false) {
$structure = $this->_structure;
$rows = Util::get_property_value($structure->data, array(
"if_array" => function($data) use ($structure) {
$html_rows = array();
foreach ($data as $row_index => $row_data) {
$row_prop = array(
"hidden" => false,
"checkbox" => array(),
"detail" => true,
"class" => "",
"attr" => array(),
"content" => true
);
if (isset($structure->each['row']) && $structure->each['row']) {
$structure->row[$row_index + 1] = Util::set_closure_prop_def($row_prop, $structure->each['row'], array($row_data, $row_index), 'class');
}
$new_row_prop = $row_prop;
if (isset($structure->row[$row_index + 1])) {
$row_prop_value = $structure->row[$row_index + 1];
if ($row_prop_value === false) {
$new_row_prop["hidden"] = true;
} else if ($row_prop_value === "") {
$new_row_prop["content"] = "";
} else {
$new_row_prop = Util::get_clean_structure($row_prop, $row_prop_value, array($row_data, $row_index), 'class');
}
}
$rows_html = '';
foreach ($row_data as $col_name => $cell_value) {
$cell_classes = array();
$cell_attrs = array();
if ((isset($structure->hide[$col_name]) && $structure->hide[$col_name] === true) || in_array($col_name, $structure->hidden)) {
$cell_classes[] = 'hidden';
}
if (isset($new_row_prop["content"]) && !$new_row_prop["content"]) {
$rows_html .= '<td class="'.implode(' ', $cell_classes).'"></td>';
continue;
}
$cell_html = $cell_value;
if (isset($structure->cell[$col_name])) {
$cell_prop = $structure->cell[$col_name];
$cell_html = Util::get_property_value($cell_prop, array(
"if_closure" => function($prop) use ($row_data, $row_index, $cell_value) {
return Util::run_callback($prop, array($row_data, $cell_value, $row_index));
},
"if_array" => function($cell_prop) use ($row_data, $row_index, $cell_value, &$cell_classes, &$cell_attrs) {
//icon, content, color, url[href, title, tooltip, attr]
$cell_html = $cell_value;
//content
if (isset($cell_prop["content"])) {
$cell_html = Util::get_property_value($cell_prop["content"], array(
"if_closure" => function($content) use ($row_data, $row_index, $cell_value) {
$content_value = Util::replace_col_codes(Util::run_callback($content, array($row_data, $cell_value, $row_index)), $row_data);
return $content_value;
},
"if_other" => function($content) use ($row_data, $cell_html) {
$cell_html = Util::replace_col_codes($content, $row_data);
return $cell_html;
}
));
}
//url
if (isset($cell_prop["url"])) {
$map_url_prop = array(
"href" => "#",
"target" => "_self",
"title" => "",
"attr" => ""
);
$map_url_prop = Util::get_property_value($cell_prop["url"], array(
"if_closure" => function($prop) use ($row_data, $row_index, $cell_value, $map_url_prop) {
$url = Util::run_callback($prop, array($row_data, $cell_value, $row_index));
$map_url_prop["href"] = $url;
return $map_url_prop;
},
"if_array" => function($url_prop) use ($row_data, $cell_html, $map_url_prop) {
$map_url_prop["target"] = isset($url_prop['target']) ? $url_prop['target'] : "_self";
$map_url_prop["href"] = isset($url_prop['href']) ? Util::replace_col_codes($url_prop['href'], $row_data, true) : '#';
$map_url_prop["attr"] = isset($url_prop['attr']) && $url_prop['attr'] ? $url_prop['attr'] : '';
$map_url_prop["title"] = isset($url_prop['title']) ? Util::replace_col_codes($url_prop['title'], $row_data, true) : '';
return $map_url_prop;
},
"if_other" => function($url_prop) use ($row_data, $cell_html, $map_url_prop) {
$map_url_prop["href"] = Util::replace_col_codes($url_prop, Util::object_to_array($row_data), true);
return $map_url_prop;
}
));
$cell_html = '<a href="'.$map_url_prop["href"].'" target="'.$map_url_prop["target"].'" '.$map_url_prop["attr"].' title="'.$map_url_prop["title"].'">'.$cell_html.'</a>';
}
//icon
if (isset($cell_prop["icon"])) {
$cell_html = Util::get_property_value($cell_prop["icon"], array(
"if_closure" => function($icon) use ($row_data, $row_index, $cell_value, $cell_html) {
$icon_value = Util::run_callback($prop, array($row_data, $cell_value, $row_index));
return '<i class="'.parent::$icon_source.' '.$icon_value.'"></i> '.$cell_html;
},
"if_other" => function($icon) use ($cell_html) {
return '<i class="'.parent::$icon_source.' '.$icon.'"></i> '.$cell_html;
}
));
}
//color
if (isset($cell_prop["color"])) {
$cell_html = Util::get_property_value($cell_prop["color"], array(
"if_closure" => function($color) use ($row_data, $row_index, $cell_value, $cell_html) {
$color_value = Util::run_callback($color, array($row_data, $cell_value, $row_index));
return '<span class="'.$color_value.'">'.$cell_html.'</span>';
},
"if_other" => function($color) use ($cell_html) {
return '<span class="'.$color.'">'.$cell_html.'</span>';
}
));
}
//class
if (isset($cell_prop["class"])) {
if (is_array($cell_prop["class"])) {
$cell_classes = array_merge($cell_classes, $cell_prop["class"]);
} else $cell_classes[] = $cell_prop["class"];
}
if (isset($cell_prop["attr"])) {
if (is_array($cell_prop["attr"])) {
foreach ($cell_prop["attr"] as $attr => $value) {
$cell_attrs[] = $attr.'="'.$value.'"';
}
} else $cell_attrs[] = $cell_prop["attr"];
}
//callback
if (isset($cell_prop["callback"]) && Util::is_closure($cell_prop["callback"])) {
$new_cell_html = Util::run_callback($cell_prop["callback"], array($row_data, $cell_html, $row_index));
if (trim($new_cell_html) != "") {
$cell_html = $new_cell_html;
}
}
return $cell_html;
},
"if_other" => function($cell_prop) use ($row_data) {
return Util::replace_col_codes($cell_prop, $row_data);
}
));
}
$rows_html .= '<td'.($cell_classes ? ' class="'.implode(' ', $cell_classes).'"' : '').($cell_attrs ? ' '.implode(' ', $cell_attrs) : '').'> '.$cell_html.' </td>';
}
$row_classes = array();
if ($new_row_prop["class"]) $row_classes[] = $new_row_prop["class"];
if ($new_row_prop["hidden"] === true) $row_classes[] = 'hidden';
$attrs = array();
if (is_array($new_row_prop["attr"])) {
foreach ($new_row_prop["attr"] as $attr => $value) {
$attrs[] = $attr.'="'.$value.'"';
}
} else {
$attrs[] = $new_row_prop["attr"];
}
$attr = $attrs ? ' '.implode(' ', $attrs) : '';
$row_class = $row_classes ? ' class="'.implode(' ', $row_classes).'"' : '';
$row_checkbox = '';
$row_details = '';
if (isset($structure->options["checkboxes"]) && $structure->options["checkboxes"]) {
if ($new_row_prop["checkbox"] === false)
$checkbox_content = '';
else {
// global checkboxes configuration
$option = $structure->options["checkboxes"];
$checkbox_prop = array(
"name" => $structure->id."_checkbox",
"id" => "",
"checked" => false,
"value" => "on"
);
$new_checkbox_prop = Util::get_clean_structure($checkbox_prop, $option, array($this, $row_data, $row_index), 'name');
// override global checkbox settings if configured
$this_row_checkbox_prop = Util::get_clean_structure($new_checkbox_prop, $new_row_prop['checkbox'], array($this, $row_data, $row_index), 'name');
$id = $this_row_checkbox_prop["id"] ? 'id="'.$this_row_checkbox_prop["id"].'"' : '';
$value = '';
if (Util::is_closure($this_row_checkbox_prop['value']))
$value = Util::run_callback($this_row_checkbox_prop['value'], array($row_data));
else $value = $this_row_checkbox_prop['value'];
$value = Util::replace_col_codes($value, $row_data);
$checkbox_content = '<label class="checkbox-inline">
<input type="checkbox" '.($this_row_checkbox_prop["checked"] ? 'checked' : '' ).' class="checkbox style-0" name="'.$this_row_checkbox_prop["name"].'[]" '.$id.' value="'.$value.'" />
<span></span>
</label>';
}
$row_checkbox = '<td class="center table-checkbox" width="20px"> '.$checkbox_content.' </td>';
}
if (isset($structure->options["row_details"]) && $structure->options["row_details"]) {
$option = $structure->options["row_details"];
$detail_prop = array(
"id" => "",
"icon" => parent::$icon_source."-".$this->options["row_detail_icons"]["closed"],
"title" => 'Show Details'
);
$new_detail_prop = Util::get_clean_structure($detail_prop, $option, array($this, $row_data, $row_index), 'icon');
$id = $new_detail_prop["id"] ? 'id="'.$new_detail_prop["id"].'"' : '';
$content = '<a href="#" '.$id.'>
<i class="'.parent::$icon_source.' '.$detail_prop['icon'].' '.parent::$icon_source.'" data-toggle="row-detail" title="'.$detail_prop['title'].'"></i>
</a>';
if ($new_row_prop["detail"] === false)
$content = '';
$row_details =
'<td class="center" width="20px"> '.$content.' </td>';
}
$html_rows[] = '<tr'.$row_class.$attr.'>'.$row_details.$row_checkbox.$rows_html.'</tr>';
}
return implode('', $html_rows);
},
"if_closure" => function($data) {
parent::err('SmartUI::DataTable::data requires an array of objects/array');
return '';
},
"if_other" => function($data) {
parent::err('SmartUI::DataTable::data requires an array of objects/array');
return '';
}
));
if ($structure->options['columns']) {
$cols = Util::get_property_value($structure->col, array(
"if_array" => function($cols) use ($structure) {
$html_col_list = array();
foreach ($cols as $col_name => $col_value) {
if (is_null($col_value) || $col_value === false) continue;;
$col_value_prop = array(
"title" => $col_name,
"class" => "",
"attr" => array(),
"icon" => "",
"hidden" => (isset($structure->hide[$col_name]) && $structure->hide[$col_name] === true) || in_array($col_name, $structure->hidden)
);
$new_col_value = Util::get_clean_structure($col_value_prop, $col_value, array($this, $cols), 'title');
if ($new_col_value['attr']) {
if (is_array($new_col_value["attr"])) {
foreach ($new_col_value["attr"] as $attr => $value) {
$attrs[] = $attr.'="'.$value.'"';
}
} else {
$attrs[] = $new_col_value["attr"];
}
$new_col_value["attr"] = $attrs;
}
$classes = array();
if ($new_col_value['class'])
$classes[] = $new_col_value['class'];
if ($new_col_value['hidden'] === true)
$classes[] = "hidden";
$class = $classes ? 'class="'.implode(' ', $classes).'"' : '';
$main_attributes = array($class, implode(' ', $new_col_value['attr']));
$htm_attrs = trim(implode(' ', $main_attributes));
$htm_attrs = $htm_attrs ? ' '.$htm_attrs : '';
$html_col_list[] = '<th'.$htm_attrs.'>'.$new_col_value['icon'].' '.$new_col_value['title'].' </th>';
}
$html_cols = implode('', $html_col_list);
$checkbox_header = '';
$detail_header = '';
if (isset($structure->options["checkboxes"]) && ($structure->options["checkboxes"])) {
$checkbox_header = '
<th class="center table-checkbox" width="20px">
<label class="checkbox-inline">
<input type="checkbox" class="checkbox style-0">
<span></span>
</label>
</th>';
}
if (isset($structure->options["row_details"]) && ($structure->options["row_details"])) {
$detail_header = '
<th class="center" width="20px"></th>';
}
return '<tr>'.$detail_header.$checkbox_header.$html_cols.'</tr>';
}
));
} else $cols = '';
$id = Util::get_property_value(
$structure->id,
array(
"if_closure" => function($prop) { return Util::run_callback($prop, array($this)); },
"if_other" => function($prop) { return $prop; },
"if_array" => function($prop) use ($structure) {
parent::err('SmartUI::Widget::id requires string.');
return $structure->id;
}
)
);
$id = $id ? 'id="'.$id.'"' : '';
$classes = array();
if ($structure->options['table']) $classes[] = 'table';
if ($structure->options['striped']) $classes[] = 'table-striped';
if ($structure->options['bordered']) $classes[] = 'table-bordered';
if ($structure->options['hover']) $classes[] = 'table-hover';
if ($structure->options['condensed']) $classes[] = 'table-condensed';
if ($structure->options['forum']) $classes[] = 'table-forum';
if ($structure->class) {
$classes[] = is_array($structure->class) ? implode(' ', $structure->class) : $structure->class;
}
$table_html = '<table '.$id.' class="'.implode(' ', $classes).'">';
$table_html .= '<thead>';
$table_html .= $cols;
$table_html .= '</thead>';
$table_html .= '<tbody>';
$table_html .= $rows;
$table_html .= '</tbody>';
$table_html .= '</table>';
$result = $table_html;
if (isset($structure->options["in_widget"]) && $structure->options["in_widget"]) {
// no need for widget's toolbar for datatable 1.10.x
// if (!$structure->options["static"])
// $structure->widget->body('toolbar', '');
$structure->widget->body("content", $table_html);
$result = $structure->widget->print_html(true);
}
if ($return) return $result;
else echo $result;
}
}
?>

View File

@ -0,0 +1,115 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class Info extends UI {
private $_options_map = array(
'stripped' => false,
'grouped' => false,
'class' => ''
);
private $_structure = array(
'row' => array(),
'options' => array(),
'value' => array(),
'name' => array(),
'icon' => array(),
'action' => array(),
'title' => ''
);
public function __construct($rows, $options = array()) {
$this->_init_structure($rows, $options);
}
private function _init_structure($rows, $user_options = array()) {
$this->_structure = parent::array_to_object($this->_structure);
$this->_structure->options = parent::set_array_prop_def($this->_options_map, $user_options);
$this->_structure->row = $rows;
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
parent::err('Undefined structure property: '.$name);
return null;
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
parent::err('Undefined structure property: '.$name);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
public function print_html($return = false) {
$structure = $this->_structure;
$rows = Util::get_property_value($structure->row, array(
'if_closure' => function($rows) {
return Util::run_callback($rows, array($this));
},
'if_other' => function($rows) {
parent::err('SmartUI::ProfileInfo::row requires array');
return null;
}
));
if (!is_array($rows)) {
parent::err("SmartUI::ProfileInfo::row requires array");
return null;
}
$rows_html_list = array();
foreach ($rows as $key => $info) {
$row_prop = array(
'icon' => isset($structure->icon[$key]) ? $structure->icon[$key] : '',
'value' => isset($structure->value[$key]) ? $structure->value[$key] : '',
'name' => isset($structure->name[$key]) ? $structure->name[$key] : $key,
'action' => isset($structure->action[$key]) ? $structure->action[$key] : '',
'class' => null
);
$new_row_prop = Util::get_clean_structure($row_prop, $info, array($this, $rows, $key), 'value');
$icon = $new_row_prop['icon'] ? '<i class="'.parent::$icon_source.' '.$new_row_prop['icon'].'"></i> ' : '';
$row_html = '<div class="info-row'.($new_row_prop['class'] ? ' '.$new_row_prop['class'] : '').'">';
$row_html .= ' <div class="info-name"> '.$new_row_prop['name'].' </div>';
$row_html .= ' <div class="info-action"> '.$new_row_prop['action'].' </div>';
$row_html .= ' <div class="info-value"> '.$icon.$new_row_prop['value'].' </div>';
$row_html .= '</div>';
$rows_html_list[] = $row_html;
}
$classes = array();
if ($structure->options['stripped']) $classes[] = 'info-stripped';
if ($structure->options['grouped']) $classes[] = 'info-grouped';
$classes[] = $structure->options['class'];
$result = '<div class="info'.($classes ? ' '.implode(' ', $classes) : '').'">';
$result .= $structure->title ? '<div class="info-title">'.$structure->title.'</div>' : '';
$result .= implode('', $rows_html_list);
$result .= '</div>';
if ($return) return $result;
else echo $result;
}
}
?>

View File

@ -0,0 +1,167 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class Nav extends UI {
private $_structure = array(
'nav' => array(),
'id' => ''
);
public function __construct($nav_items = array()) {
$this->_init_structure($nav_items);
}
private function _init_structure($nav_items) {
$this->_structure = Util::array_to_object($this->_structure);
$this->_structure->nav = $nav_items;
$this->_structure->id = Util::create_id(true);
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
parent::err('Undefined structure property: '.$name);
return null;
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
parent::err('Undefined structure property: '.$name);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
public function print_html($return = false) {
$structure = $this->_structure;
$nav_items = Util::get_property_value($structure->nav, array(
'if_closure' => function($nav_items) {
return Util::run_callback($nav_items, array($this));
},
'if_other' => function($nav_items) {
parent::err('SmartUI::Nav:nav requires array');
return null;
}
));
if (!is_array($nav_items)) {
parent::err("SmartUI::Nav:nav requires array");
return null;
}
$list_items = $this->parse_nav($nav_items, true);
$result = parent::print_list($list_items, null, true);
if ($return) return $result;
else echo $result;
}
private function parse_nav($nav_item, $is_parent = false) {
if (!$nav_item) return '';
$nav_items_list = array();
foreach ($nav_item as $name => $nav) {
$nav_prop = array(
'url' => '#',
'url_target' => '',
'icon' => '',
'icon_badge' => '',
'label_htm' => '',
'title' => $name,
'title_append' => '',
'label' => '',
'active' => false,
'sub' => array(),
'attr' => array(),
'class' => array(),
'li_class' => array()
);
$new_nav_prop = Util::set_array_prop_def($nav_prop, $nav, 'title');
$icon_badge_prop = array(
'content' => '',
'class' => ''
);
$icon_badge_prop = Util::set_array_prop_def($icon_badge_prop, $new_nav_prop['icon_badge'], 'content');
$badge = '';
if ($icon_badge_prop['content']) {
$badge_class = $icon_badge_prop['class'] ? 'class="'.$icon_badge_prop['class'].'"' : '';
$badge = '<em '.$badge_class.'>'.$icon_badge_prop['content'].'</em>';
}
$icon = $new_nav_prop['icon'] ? '<i class="'.parent::$icon_source.' '.parent::$icon_source.'-lg '.parent::$icon_source.'-fw '.$new_nav_prop['icon'].'">'.$badge.'</i>' : '';
$title = $new_nav_prop['title'];
$title_append = $new_nav_prop['title_append'];
$display_title = $title.' '.$title_append;
$label_htm = $new_nav_prop['label_htm'] ? ' '.$new_nav_prop['label_htm'] : '';
$display_text = $is_parent ? '<span class="menu-item-parent">'.$display_title.'</span>' : $display_title;
$display_text .= $label_htm;
$attrs = array_map(function($attr, $value) {
return $attr.'="'.$value.'"';
}, array_keys($new_nav_prop['attr']), $new_nav_prop['attr']);
if ($new_nav_prop['class']) $attrs[] = 'class="'.$new_nav_prop['class'].'"';
$nav_htm = '<a ';
$nav_htm .= 'href="'.$new_nav_prop['url'].'" ';
$nav_htm .= ($new_nav_prop['url_target'] ? 'target="'.$new_nav_prop['url_target'].'"' : '').' ';
$nav_htm .= implode(' ', $attrs).'> ';
$nav_htm .= $icon.' '.$display_text.' '.$new_nav_prop['label'];
$nav_htm .= '</a>';
$li_classes = array();
if ($new_nav_prop["active"]) $li_classes[] = 'active';
if ($new_nav_prop['li_class']) {
if (is_string($new_nav_prop['li_class'])) $li_classes[] = $new_nav_prop['li_class'];
else if (is_array($new_nav_prop['li_class'])) $li_classes = array_merge($li_classes, $new_nav_prop['li_class']);
}
$nav_item_structure = array(
'content' => $nav_htm,
'class' => implode(' ', $li_classes)
);
if (isset($new_nav_prop['sub'])) {
if (is_string($new_nav_prop['sub'])) {
$subitems = array($new_nav_prop['sub']);
} else {
foreach ($new_nav_prop['sub'] as $subitem) {
if (isset($subitem['active'])) {
$nav_item_structure['class'] .= ' active open';
$nav_item_structure['subitem_options'] = array('attr' => array('style' => 'display: block;'));
break;
}
}
$subitems = $this->parse_nav($new_nav_prop['sub']);
}
$nav_item_structure['subitems'] = $subitems;
}
$nav_items_list[] = $nav_item_structure;
}
return $nav_items_list;
}
}
?>

View File

@ -0,0 +1,888 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class SmartForm extends UI {
const FORM_FIELD_INPUT = 'input';
const FORM_FIELD_TEXTAREA = 'textarea';
const FORM_FIELD_CHECKBOX = 'checkbox';
const FORM_FIELD_RADIO ='radio';
const FORM_FIELD_SELECT = 'select';
const FORM_FIELD_SELECT2 = 'select2';
const FORM_FIELD_SELECT2_MULTI = 'select2-multi';
const FORM_FIELD_MULTISELECT = 'multi-select';
const FORM_FIELD_RATING = 'rating';
const FORM_FIELD_RATINGS = 'ratings';
const FORM_FIELD_FILEINPUT = 'file-input';
const FORM_FIELD_LABEL = 'label';
const FORM_FIELD_HIDDEN = 'hidden';
const FORM_FIELD_BLANK = 'blank';
private $_options_map = array(
'in_widget' => true,
'wrapper' => 'form'
);
private $_structure = array(
'field' => array(),
'fieldset' => array(),
'type' => array(),
'property' => array(),
'footer' => '',
'header' => '',
'widget' => null,
'title' => '',
'col' => array(),
'section' => array(),
'options' => array(),
'attr' => array(),
'id' => '',
'class' => array()
);
public function __construct($fields, $options = array()) {
$this->_init_structure($fields, $options);
}
private function _init_structure($fields, $user_options = array()) {
$this->_structure = Util::array_to_object($this->_structure);
$this->_structure->options = Util::set_array_prop_def($this->_options_map, $user_options);
$this->_structure->field = $fields;
$widget = new Widget();
$widget->options('editbutton', false)
->body('class', 'no-padding')
->header('title', '<h2></h2>');
$this->_structure->widget = $widget;
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
parent::err('Undefined structure property: '.$name);
return null;
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
parent::err('Undefined structure property: '.$name);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
private function _create_field_group($collumed, $field_html, $col) {
$group = new \stdClass;
$group->collumned = $collumed;
$group->items = array($field_html);
$group->total = (int)$col;
return $group;
}
public function print_html($return = false) {
$structure = $this->_structure;
$fields = Util::get_property_value($structure->field, array(
'if_closure' => function($fields) {
return Util::run_callback($fields, array($this));
},
'if_other' => function($fields) {
parent::err('SmartUI::SmartForm:field requires array');
return null;
}
));
if (!is_array($fields)) {
parent::err("SmartUI::SmartForm:field requires array");
return null;
}
if (!$structure->fieldset || !is_array($structure->fieldset)) {
$structure->fieldset[] = array_keys($fields);
}
$fieldsets_html_list = array();
$hidden_fields_list = array();
$fieldsets = count($structure->fieldset);
for ($fs_index = 0; $fs_index < $fieldsets; $fs_index++) {
$fs_fields = $structure->fieldset[$fs_index];
$groups = array();
$with_col_cntr = 0;
$grouped = false;
if (is_string($fs_fields)) $fs_fields = array($fs_fields);
foreach ($fs_fields as $field_name) {
$field = $structure->field[$field_name];
$field_prop = array(
'type' => self::FORM_FIELD_INPUT,
'col' => 0,
'section' => array(),
'properties' => array()
);
$new_field_prop = Util::get_clean_structure($field_prop, $field, array($this, $fs_index, $fs_fields), 'type');
if ($new_field_prop['type'] == self::FORM_FIELD_HIDDEN) {
$field_html = self::print_field($field_name, self::FORM_FIELD_HIDDEN, $new_field_prop['properties'], true);
$hidden_fields_list[] = $field_html;
continue;
}
if (isset($structure->property[$field_name])) $new_field_prop['properties'] = $structure->property[$field_name];
if (isset($structure->col[$field_name])) $new_field_prop['col'] = $structure->col[$field_name];
if (isset($structure->type[$field_name])) $new_field_prop['type'] = $structure->type[$field_name];
if (isset($structure->section[$field_name])) $new_field_prop['section'] = $$structure->section[$field_name];
$new_prop_col = (int)$new_field_prop['col'];
$field_html = self::print_field($field_name, $new_field_prop['type'], $new_field_prop['properties'], array(
'col' => $new_prop_col,
'section' => $new_field_prop['section']
), true);
$collumned = $new_field_prop['col'] > 0 && $new_prop_col < 12;
if (!$grouped) {
$last_group_key = Util::create_id();
$group = self::_create_field_group($collumned, $field_html, $new_prop_col);
$groups[$last_group_key] = $group;
$grouped = true;
} else {
$last_group = $groups[$last_group_key];
if ($last_group->collumned === $collumned && $last_group->total < 12 && ($last_group->total + $new_prop_col) <= 12) {
$last_group->items[] = $field_html;
$last_group->total = $last_group->total + $new_prop_col;
} else {
$last_group_key = Util::create_id();
$group = self::_create_field_group($collumned, $field_html, $new_prop_col);
$groups[$last_group_key] = $group;
$grouped = true;
}
}
}
$fields_html_list = array();
foreach($groups as $group) {
$group_html = '';
$fields_html = implode('', $group->items);
if ($group->collumned) {
$group_html .= '<div class="row">';
$group_html .= $fields_html;
$group_html .= '</div>';
} else {
$group_html .= $fields_html;
}
$fields_html_list[] = $group_html;
}
$fieldsets_html_list[] = '<fieldset>'.implode('', $fields_html_list).'</fieldset>';
}
$header = Util::get_property_value($structure->header, array(
'if_closure' => function($header) {
return Util::run_callback($header, array($this));
}
));
$footer = Util::get_property_value($structure->footer, array(
'if_closure' => function($footer) {
return Util::run_callback($footer, array($this));
}
));
$form_attrs = array();
$form_attrs[] = 'class="smart-form '.(is_array($structure->class) ? implode(' ', $structure->class) : $structure->class).'"';
$form_attrs[] = 'id="'.($structure->id ? $structure->id : Util::create_id()).'"';
$form_attrs = array_merge($form_attrs, array_map(function($attr, $value) {
return $attr.'="'.$value.'"';
}, array_keys($structure->attr), $structure->attr));
$fields_content = $header ? '<header>'.$header.'</header>' : '';
$fields_content .= implode('', $fieldsets_html_list);
$fields_content .= implode(' ', $hidden_fields_list);
$fields_content .= $footer ? '<footer>'.$footer.'</footer>' : '';
if ($structure->options['wrapper']) {
$form_html = '<'.$structure->options['wrapper'].' '.implode(' ', $form_attrs).'>';
$form_html .= $fields_content;
$form_html .= '</'.$structure->options['wrapper'].'>';
} else {
$form_html = $fields_content;
}
if (isset($structure->options["in_widget"]) && $structure->options["in_widget"]) {
$structure->widget->body("content", $form_html);
if ($structure->title) {
$structure->widget->header('title', $structure->title);
}
$result = $structure->widget->print_html(true);
} else $result = $form_html;
if ($return) return $result;
else echo $result;
}
public static function print_field($name, $type = self::FORM_FIELD_INPUT, $properties = array(), $options = false, $return = false) {
$field_html = self::_get_field_html($name, $type, $properties);
if ($type == self::FORM_FIELD_HIDDEN) return $field_html;
$classes = array();
$section = array();
if (is_array($options)) {
$col = isset($options['col']) ? $options['col'] : null;
$section = isset($options['section']) ? $options['section'] : array();
} else $col = $options;
if ($col && $col < 12) $classes[] = 'col col-'.$col;
if ($type == self::FORM_FIELD_LABEL) $classes[] = 'label';
$attr = array();
if ($section) {
if (is_string($section)) $classes[] = $section;
else {
if (isset($section['attr'])) $attr = array_merge($attr, $section['attr']);
if (isset($section['class'])) $classes[] = is_string($section['class']) ? $section['class'] : implode(' ', $section['class']);
if (isset($section['id'])) $attr['id'] = $section['id'];
}
}
if ($classes) {
if (isset($attr['class'])) $attr['class'] .= implode(' ', $classes);
else $attr['class'] = implode(' ', $classes);
}
$attr_list = array_map(function($attr, $value) {
return $attr.'="'.$value.'"';
}, array_keys($attr), $attr);
$result = '<section '.implode(' ', $attr_list).'>';
$result .= $field_html;
$result .= '</section>';
if ($return) return $result;
else echo $result;
}
private static function _get_field_html($name, $field_type = self::FORM_FIELD_INPUT, $properties = array(), $field_html_only = false) {
$field_class_map = array(
self::FORM_FIELD_INPUT => 'input',
self::FORM_FIELD_FILEINPUT => 'input input-file',
self::FORM_FIELD_SELECT => 'select',
self::FORM_FIELD_SELECT2 => 'select',
self::FORM_FIELD_SELECT2_MULTI => 'select select-multiple',
self::FORM_FIELD_MULTISELECT => 'select select-multiple',
self::FORM_FIELD_TEXTAREA => 'textarea',
self::FORM_FIELD_CHECKBOX => 'checkbox',
self::FORM_FIELD_RADIO => 'radio',
self::FORM_FIELD_RATING => 'rating',
self::FORM_FIELD_RATINGS => 'rating',
self::FORM_FIELD_HIDDEN => '',
self::FORM_FIELD_BLANK => ''
);
$result = '';
$field_html = '';
$result_html = '';
$notes = '';
$label = '';
$attrs = array();
switch ($field_type) {
case self::FORM_FIELD_LABEL:
$default_prop = array(
'label' => ''
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'label');
$result_html = $new_prop['label'];
break;
case self::FORM_FIELD_BLANK:
$default_prop = array(
'content' => ''
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'content');
$result_html = $new_prop['content'];
break;
case self::FORM_FIELD_RATINGS:
$default_prop = array(
'items' => array(),
'icon' => parent::$icon_source.'-star'
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'max');
if (!is_array($new_prop['items'])) $new_prop['items'] = array($new_prop['items']);
$items = $new_prop['items'];
$rating_html_list = array();
foreach ($items as $item) {
$item_prop = array(
'max' => 5,
'icon' => $new_prop['icon'],
'name' => $name.'-'.Util::create_id(),
'label' => ''
);
$new_item_prop = Util::set_array_prop_def($item_prop, $item, 'max');
$field_html = self::_get_field_html($new_item_prop['name'], self::FORM_FIELD_RATING, $new_item_prop, true);
$field_html .= $new_item_prop['label'] ? $new_item_prop['label'] : '&nbsp;';
$result_html = ' <div class="'.$field_class_map[$field_type].'">';
$result_html .= $field_html;
$result_html .= ' </div>';
$rating_html_list[] = $result_html;
}
$result_html = implode('', $rating_html_list);
break;
case self::FORM_FIELD_RATING:
$default_prop = array(
'max' => 5,
'icon' => parent::$icon_source.'-star'
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'max');
$rating_html_list = array();
for ($i = $new_prop['max']; $i >= 1; $i--) {
$rate_id = $name.'-'.$i;
$rating_html = self::_get_field_html($name, self::FORM_FIELD_INPUT, array(
'type' => 'radio',
'id' => $rate_id
), true);
$rating_html .= '<label for="'.$rate_id.'"><i class="'.parent::$icon_source.' '.$new_prop['icon'].'"></i></label>';
$rating_html_list[] = $rating_html;
}
$field_html .= implode('', $rating_html_list);
if ($field_html_only) return $field_html;
$result_html .= ' <label class="'.$field_class_map[$field_type].'">';
$result_html .= $field_html;
$result_html .= ' </label>';
break;
case self::FORM_FIELD_TEXTAREA:
$default_prop = array(
'rows' => 3,
'attr' => array(),
'class' => array(),
'icon' => '',
'icon_append' => true,
'value' => '',
'id' => '',
'type' => '',
'placeholder' => '',
'disabled' => false,
'wrapper' => 'label'
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'placeholder');
$classes = array();
$classes[] = 'custom-scroll';
if ($new_prop['class']) array_push($classes, $new_prop['class']);
$attrs = array();
$attrs[] = 'class="'.implode(' ', $classes).'"';
$attrs[] = 'rows="'.$new_prop['rows'].'"';
$attrs[] = 'name="'.$name.'"';
if ($new_prop['disabled']) $attrs[] = 'disabled="disabled"';
if ($new_prop['id']) $attrs[] = 'id="'.$new_prop['id'].'"';
if ($new_prop['placeholder']) $attrs[] = 'placeholder="'.$new_prop['placeholder'].'"';
if ($new_prop['attr']) $attrs[] = implode(' ', $new_prop['attr']);
if ($new_prop['icon'])
$field_html .= '<i class="icon-'.($new_prop['icon_append'] ? 'append' : 'prepend').' '.parent::$icon_source.' '.$new_prop['icon'].'"></i>';
$field_html .= '<textarea '.implode(' ', $attrs).'>';
$field_html .= $new_prop['value'];
$field_html .= '</textarea>';
$field_class_map[self::FORM_FIELD_TEXTAREA] = 'textarea'.($new_prop['type'] ? ' textarea-'.$new_prop['type'] : '');
if ($field_html_only) return $field_html;
$result_html .= ' <'.$new_prop['wrapper'].' class="'.$field_class_map[$field_type].' '.($new_prop['disabled'] ? 'state-disabled' : '').'">';
$result_html .= $field_html;
$result_html .= ' </'.$new_prop['wrapper'].'>';
break;
case self::FORM_FIELD_MULTISELECT:
if (isset($properties['attr'])) {
array_push($properties['attr'], array('multiple="multiple"', 'class="custom-scroll"'));
} else {
$properties['attr'] = array('multiple="multiple"');
}
if (isset($properties['class'])) array_push($properties['class'], array('custom-scroll'));
else $properties['class'] = array('custom-scroll');
$properties['icon'] = '';
$field_html = self::_get_field_html($name, self::FORM_FIELD_SELECT, $properties, true);
if ($field_html_only) return $field_html;
$result_html .= ' <label class="'.$field_class_map[$field_type].'">';
$result_html .= $field_html;
$result_html .= ' </label>';
break;
case self::FORM_FIELD_SELECT2_MULTI:
if (isset($properties['attr'])) {
array_push($properties['attr'], array('multiple="multiple"', 'class="custom-scroll"'));
} else {
$properties['attr'] = array('multiple="multiple"');
}
if (isset($properties['class'])) array_push($properties['class'], array('select2 custom-scroll'));
else $properties['class'] = array('select2 custom-scroll');
$properties['icon'] = '';
$field_html = self::_get_field_html($name, self::FORM_FIELD_SELECT, $properties, true);
if ($field_html_only) return $field_html;
$result_html .= ' <label class="'.$field_class_map[$field_type].'">';
$result_html .= $field_html;
$result_html .= ' </label>';
break;
case self::FORM_FIELD_SELECT2:
if (isset($properties['class'])) {
if (!is_array($properties['class'])) $properties['class'] = array($properties['class']);
array_push($properties['class'], 'select2');
} else $properties['class'] = array('select2');
$properties['icon'] = '';
$field_html = self::_get_field_html($name, self::FORM_FIELD_SELECT, $properties, true);
if ($field_html_only) return $field_html;
$result_html .= ' <label class="'.$field_class_map[$field_type].'">';
$result_html .= $field_html;
$result_html .= ' </label>';
break;
case self::FORM_FIELD_SELECT:
$default_prop = array(
'data' => array(),
'display' => '',
'value' => '',
'container' => 'select',
'selected' => array(),
'id' => '',
'attr' => array(),
'class' => array(),
'icon' => '<i></i>',
'item_attr' => null,
'disabled' => false
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'data');
$data = $new_prop['data'];
if (!is_array($data)) {
parent::err('SmartUI::Form "data" is required for "select" field.');
return '';
}
if (!$data) $data = array(array('No Data'));
$arr_data = (array)$data;
if (!$new_prop['display']) {
$display_key = is_array($arr_data[0]) ? array_keys($arr_data[0]) : 0;
$new_prop['display'] = $display_key ? $display_key[0] : 0;
}
if (!$new_prop['value']) {
$value_key = is_array($arr_data[0]) ? array_keys($arr_data[0]) : 0;
$new_prop['value'] = $value_key ? $value_key[0] : 0;
}
$selected_list = is_array($new_prop['selected']) ? $new_prop['selected'] : array($new_prop['selected']);
$option_list = array();
foreach ($data as $row) {
$item_attr = '';
$arr_row = (array)$row;
if (isset($new_prop['item_attr'])) {
$item_attr = Util::get_property_value($new_prop['item_attr'], array(
'if_closure' => function($item_attr) use ($row) {
return Util::run_callback($item_attr, array($row));
},
'if_array' => function($item_attr) use ($row) {
$attrs = array();
foreach ($item_attr as $attr) {
$attrs[] = Util::replace_col_codes($attr, $row);
}
return implode(' ', $attrs);
},
'if_other' => function($item_attr) use ($row) {
return Util::replace_col_codes($item_attr, $row);
}
));
}
if (Util::is_closure($new_prop['value'])) $value = $new_prop['value']($row);
else $value = $arr_row[$new_prop['value']];
if (Util::is_closure($new_prop['display'])) $display = $new_prop['display']($row);
else $display = $arr_row[$new_prop['display']];
$selected = in_array($value, $selected_list);
$option_list[] = '<option value="'.$value.'"'.($selected ? ' selected' : '').($item_attr ? ' '.$item_attr : '').'>'.$display.'</option>';
}
$attrs = array();
$attrs[] = 'name="'.$name.'"';
$classes = is_array($new_prop['class']) ? $new_prop['class'] : array($new_prop['class']);
if ($new_prop['disabled']) $attrs[] = 'disabled="disabled"';
if ($new_prop['id']) $attrs[] = 'id="'.$new_prop['id'].'"';
if ($new_prop['attr']) $attrs[] = implode(' ', $new_prop['attr']);
if ($new_prop['class']) $attrs[] = 'class="'.implode(' ', $classes).'"';
$field_html = '<'.$new_prop['container'].' '.implode(' ', $attrs).'>';
$field_html .= implode('', $option_list);
$field_html .= '</'.$new_prop['container'].'>'.$new_prop['icon'];
if ($field_html_only) return $field_html;
$result_html .= ' <label class="'.$field_class_map[$field_type].' '.($new_prop['disabled'] ? 'state-disabled' : '').'">';
$result_html .= $field_html;
$result_html .= ' </label>';
break;
case self::FORM_FIELD_FILEINPUT:
$file_button = self::_get_field_html($name, self::FORM_FIELD_INPUT, array(
'type' => 'file',
'attr' => array_merge(array('onchange="this.parentNode.nextSibling.value = this.value"'), isset($properties['attr']) ? $properties['attr'] : array())
), true);
$field_html = '<span class="button">';
$field_html .= $file_button;
$field_html .= 'Browse</span>';
$default_prop = array(
'icon' => false,
'tooltip' => false,
'attr' => array('readonly'),
'type' => 'text'
);
if ($properties) {
foreach ($properties as $key => $value) {
if (!isset($default_prop[$key])) {
$default_prop[$key] = $value;
}
}
}
$field_html .= self::_get_field_html($name.'-display', self::FORM_FIELD_INPUT, $default_prop, true);
if ($field_html_only) return $field_html;
$result_html .= ' <label class="'.$field_class_map[$field_type].'">';
$result_html .= $field_html;
$result_html .= ' </label>';
break;
case self::FORM_FIELD_HIDDEN:
$default_prop = array(
'icon' => false,
'tooltip' => false,
'type' => 'hidden',
'value' => ''
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'value');
$field_html .= self::_get_field_html($name, self::FORM_FIELD_INPUT, $new_prop, true);
return $field_html;
break;
case self::FORM_FIELD_INPUT:
$default_prop = array(
'type' => 'text',
'attr' => array(),
'id' => '',
'icon' => '',
'icon_append' => true,
'icon_attr' => array(),
'append' => '',
'placeholder' => '',
'value' => '',
'tooltip' => array(),
'disabled' => false,
'autocomplete' => false,
'size' => '',
'class' => array()
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'placeholder');
$classes = array();
if ($new_prop['class']) array_push($classes, $new_prop['class']);
if ($new_prop['size']) $classes[] = 'input-'.$new_prop['size'];
$attrs = array();
$attrs[] = $classes ? 'class="'.implode(' ', $classes).'"' : '';
$attrs[] = 'type="'.$new_prop['type'].'"';
$attrs[] = 'name="'.$name.'"';
if ($new_prop['attr']) $attrs[] = implode(' ', $new_prop['attr']);
if ($new_prop['id']) $attrs[] = 'id="'.$new_prop['id'].'"';
$attrs[] = 'value="'.$new_prop['value'].'"';
if ($new_prop['placeholder']) $attrs[] = 'placeholder="'.$new_prop['placeholder'].'"';
if ($new_prop['disabled']) $attrs[] = 'disabled="disabled"';
$ac_html = '';
if ($new_prop['autocomplete']) {
$ac_prop = array(
'data' => array(),
'display' => '',
'value' => ''
);
if (!isset($new_prop['autocomplete']['data']))
$ac_prop['data'] = $new_prop['autocomplete'];
else {
$ac_prop['data'] = $new_prop['autocomplete']['data'];
$ac_prop['display'] = isset($new_prop['autocomplete']['display']) ? $new_prop['autocomplete']['display'] : '';
$ac_prop['value'] = isset($new_prop['autocomplete']['value']) ? $new_prop['autocomplete']['value'] : '';
}
$list_name = 'list-'.$name.'-'.Util::create_id();
$ac_html = self::_get_field_html('', self::FORM_FIELD_SELECT, array(
'container' => 'datalist',
'data' => $ac_prop['data'],
'display' => $ac_prop['display'],
'value' => $ac_prop['value'],
'id' => $list_name
), true);
$attrs[] = 'list="'.$list_name.'"';
}
if ($new_prop['icon']) {
$def_icon_prop = array(
'class' => '',
'append' => $new_prop['icon_append'],
'attr' => array(),
'tag' => 'i'
);
$icon_prop = Util::set_array_prop_def($def_icon_prop, $new_prop['icon'], 'class');
$icon_attrs = implode(' ', $icon_prop['attr']);
$field_html .= '<'.$icon_prop['tag'].' class="icon-'.($icon_prop['append'] ? 'append' : 'prepend').' '.parent::$icon_source.' '.$icon_prop['class'].'" '.$icon_attrs.'></'.$icon_prop['tag'].'>';
}
$field_html .= '<input '.implode(' ', $attrs).' />';
$field_html .= $ac_html;
$field_html .= $new_prop['append'];
if ($new_prop['tooltip']) {
$tooltip_prop = array(
'content' => '',
'position' => 'top-right'
);
$new_tooltip_prop = Util::set_array_prop_def($tooltip_prop, $new_prop['tooltip'], 'content');
$field_html .= '<b class="tooltip tooltip-'.$new_tooltip_prop['position'].'">'.$new_tooltip_prop['content'].'</b>';
}
if ($field_html_only) return $field_html;
$result_html .= ' <label class="'.$field_class_map[$field_type].' '.($new_prop['disabled'] ? 'state-disabled' : '').'">';
$result_html .= $field_html;
$result_html .= ' </label>';
break;
case self::FORM_FIELD_RADIO:
$default_prop = array(
'items' => array(),
'cols' => 0,
'inline' => false,
'toggle' => false
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'items');
if (!is_array($new_prop['items'])) $new_prop['items'] = array($new_prop['items']);
$items = $new_prop['items'];
$item_list_html = array();
foreach ($items as $item) {
$items_prop = array(
'name' => $name,
'checked' => false,
'value' => '',
'label' => '',
'id' => '',
'disabled' => false
);
$new_item_prop = Util::set_array_prop_def($items_prop, $item, 'label');
$item_html = self::_get_field_html($new_item_prop['name'], self::FORM_FIELD_INPUT, array(
'type' => 'radio',
'attr' => $new_item_prop['checked'] ? array('checked') : null,
'value' => $new_item_prop['value'],
'id' => $new_item_prop['id']
), true);
if ($new_prop['toggle']) {
$text_off = is_array($new_prop['toggle']) && isset($new_prop['toggle']['text-off']) ? $new_prop['toggle']['text-off'] : 'OFF';
$text_on = is_array($new_prop['toggle']) && isset($new_prop['toggle']['text-on']) ? $new_prop['toggle']['text-on'] : 'ON';
$item_html .= '<i data-swchon-text="'.$text_on.'" data-swchoff-text="'.$text_off.'"></i>';
} else $item_html .= '<i></i>';
$item_html .= $new_item_prop['label'];
$field_html = ' <label class="'.($new_prop['toggle'] ? 'toggle' : $field_class_map[$field_type]).' '.($new_item_prop['disabled'] ? 'state-disabled' : '').'">';
$field_html .= $item_html;
$field_html .= ' </label>';
$item_list_html[] = $field_html;
}
if ($new_prop['cols']) {
$result_html .= '<div class="row">';
$result_html .= self::print_col_items($item_list_html, function($item) { return $item; }, $new_prop['cols'], true);
$result_html .= '</div>';
} else {
$list_html = implode('', $item_list_html);
if ($new_prop['inline']) {
$result_html .= '<div class="inline-group">';
$result_html .= $list_html;
$result_html .= '</div>';
} else $result_html .= $list_html;
}
if ($field_html_only) return $result_html;
break;
case self::FORM_FIELD_CHECKBOX:
$default_prop = array(
'items' => array(),
'cols' => 0,
'inline' => false,
'toggle' => false
);
$new_prop = Util::get_clean_structure($default_prop, $properties, array(), 'items');
if (!is_array($new_prop['items'])) $new_prop['items'] = array($new_prop['items']);
$items = $new_prop['items'];
$item_list_html = array();
foreach ($items as $item) {
$items_prop = array(
'name' => $name,
'checked' => false,
'value' => '',
'label' => '',
'id' => '',
'disabled' => false
);
$new_item_prop = Util::set_array_prop_def($items_prop, $item, 'label');
$item_html = self::_get_field_html($new_item_prop['name'], self::FORM_FIELD_INPUT, array(
'type' => 'checkbox',
'attr' => $new_item_prop['checked'] ? array('checked') : null,
'value' => $new_item_prop['value'],
'id' => $new_item_prop['id']
), true);
if ($new_prop['toggle']) {
$text_off = is_array($new_prop['toggle']) && isset($new_prop['toggle']['text-off']) ? $new_prop['toggle']['text-off'] : 'OFF';
$text_on = is_array($new_prop['toggle']) && isset($new_prop['toggle']['text-on']) ? $new_prop['toggle']['text-on'] : 'ON';
$item_html .= '<i data-swchon-text="'.$text_on.'" data-swchoff-text="'.$text_off.'"></i>';
} else $item_html .= '<i></i>';
$item_html .= $new_item_prop['label'];
$field_html = ' <label class="'.($new_prop['toggle'] ? 'toggle' : $field_class_map[$field_type]).' '.($new_item_prop['disabled'] ? 'state-disabled' : '').'">';
$field_html .= $item_html;
$field_html .= ' </label>';
$item_list_html[] = $field_html;
}
if ($new_prop['cols']) {
$result_html .= '<div class="row">';
$result_html .= self::print_col_items($item_list_html, function($item) { return $item; }, $new_prop['cols'], true);
$result_html .= '</div>';
} else {
$list_html = implode('', $item_list_html);
if ($new_prop['inline']) {
$result_html .= '<div class="inline-group">';
$result_html .= $list_html;
$result_html .= '</div>';
} else $result_html .= $list_html;
}
if ($field_html_only) return $result_html;
break;
}
if (is_array($properties)) {
$notes = isset($properties['note']) ? '<div class="note">'.$properties['note'].'</div>' : '';
$label = isset($properties['label']) && $properties['label'] ? '<label class="label">'.$properties['label'].'</label>' : '';
}
$result .= $label;
$result .= $result_html;
$result .= $notes;
return $result;
}
public static function print_col_items($items, $closure_content, $columns = 1, $return = false) {
$htm_result = '';
$arr_htm_items = array();
$col_cntr = 0;
$row_cntr = 0;
$result_count = 0;
for ($i=0; $i < $columns;$i++) {
$arr_htm_items[$i] = "";
}
$htm_item = "";
if ($items) {
$result_count = count($items);
foreach ($items as $item_data) {
if ($row_cntr >= ($result_count / $columns)) {
$col_cntr++;
$row_cntr = 0;
$htm_item = "";
}
$row_cntr++;
$htm_item .= $closure_content($item_data);
$arr_htm_items[$col_cntr] = '<div class="col col-'.(12 / $columns).'">'.$htm_item.'</div>';
}
foreach ($arr_htm_items as $item_content) {
$htm_result .= $item_content;
}
}
if ($return) return $htm_result;
else echo $htm_result;
}
}
?>

View File

@ -0,0 +1,255 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class Tab extends UI {
private $_options_map = array(
'bordered' => true,
'position' => '',
'pull' => '',
'padding' => 10,
'widget' => false,
'toggle' => true,
'titles' => 'text',
'class' => ''
);
private $_structure = array(
'tab' => array(),
'content' => array(),
'html' => array(),
'url' => array(),
'content_id' => '',
'content_class' => '',
'icon' => array(),
'tabs_id' => '',
'title' => array(),
'options' => array(),
'active' => array(),
'dropdown' => array(),
'position' => array()
);
public function __construct($tabs, $options = array()) {
$this->_init_structure($tabs, $options);
}
private function _init_structure($tabs, $user_options = array()) {
$this->_structure = Util::array_to_object($this->_structure);
$this->_structure->options = Util::set_array_prop_def($this->_options_map, $user_options);
$this->_structure->tab = $tabs;
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
parent::err('Undefined structure property: '.$name);
return null;
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
parent::err('Undefined structure property: '.$name);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
public function print_html($return = false) {
$structure = $this->_structure;
$structure->options = Util::set_array_prop_def($this->_options_map, $structure->options);
$tabs = Util::get_property_value($structure->tab, array(
'if_closure' => function($tabs) {
return Util::run_callback($tabs, array($this));
},
'if_other' => function($tabs) {
parent::err('SmartUI::Tab::tab requires array');
return null;
}
));
if (!is_array($tabs)) {
parent::err("SmartUI::Tab::tab requires array");
return null;
}
$li_list = array();
$tab_content_list = array();
$has_active = false;
foreach ($tabs as $tab_id => $tab_prop) {
$tab_structure = array(
'content' => isset($structure->content[$tab_id]) ? $structure->content[$tab_id] : '',
'title' => isset($structure->title[$tab_id]) ? $structure->title[$tab_id] : '',
'icon' => isset($structure->icon[$tab_id]) ? $structure->icon[$tab_id] : '',
'dropdown' => isset($structure->dropdown[$tab_id]) ? $structure->dropdown[$tab_id] : '',
'position' => isset($structure->position[$tab_id]) ? $structure->position[$tab_id] : '',
'active' => isset($structure->active[$tab_id]) && $structure->active[$tab_id] === true,
'fade' => false,
'url' => isset($structure->url[$tab_id]) ? $structure->url[$tab_id] : '#'.$tab_id,
'toggle' => true,
'id' => false,
'attr' => array(),
'content_class' => array(),
'html' => isset($structure->html[$tab_id]) ? $structure->html[$tab_id] : ''
);
$new_tab_prop = Util::get_clean_structure($tab_structure, $tab_prop, array($this, $tabs, $tab_id), 'title');
foreach ($new_tab_prop as $tab_prop_key => $tab_prop_vaue) {
$new_tab_prop_value = Util::get_property_value($tab_prop_vaue, array(
'if_closure' => function($prop_value) use ($tabs) {
return Util::run_callback($prop_value, array($this, $tabs));
}
));
$new_tab_prop[$tab_prop_key] = $new_tab_prop_value;
}
$tab_content_classes = is_array($new_tab_prop['content_class']) ? $new_tab_prop['content_class'] : array($new_tab_prop['content_class']);
$tab_content_classes[] = 'tab-pane';
$li_classes = array();
$a_classes = array();
$a_attr = array_map(function($attr, $value) {
return $attr.'="'.$value.'"';
}, array_keys($new_tab_prop['attr']), $new_tab_prop['attr']);
if ($new_tab_prop['active'] === true && !$has_active) {
$li_classes[] = 'active';
$tab_content_classes[] = 'in active';
$has_active = true;
}
// $a_attr[] = 'title="'.$new_tab_prop['title'].'"';
if (!$structure->options['titles']) {
$title = '';
} else if ($structure->options['titles'] == 'tooltip') {
$title = '';
$a_attr[] = 'rel="tooltip"';
$a_attr[] = 'data-placement="top"';
$a_attr[] = 'title="'.$new_tab_prop['title'].'"';
} else {
$title = $new_tab_prop['title'];
}
$dropdown_html = '';
if ($new_tab_prop['dropdown']) {
$dropdown = $new_tab_prop['dropdown'];
$li_classes[] = 'dropdown';
$href = 'javascript:void(0);';
$dropdown_html = is_array($dropdown) ? parent::print_dropdown($dropdown, false, true) : $dropdown;
$a_classes[] = 'dropdown-toggle';
$a_attr[] = 'data-toggle="dropdown"';
$title .= ' <b class="caret"></b>';
} else {
$href = $new_tab_prop['url'];
if ($structure->options['toggle'] && $new_tab_prop['toggle'])
$a_attr[] = 'data-toggle="tab"';
}
if ($new_tab_prop['id']) $a_attr[] = 'id="'.$new_tab_prop['id'].'"';
if ($new_tab_prop['position']) $li_classes[] = 'pull-'.$new_tab_prop['position'];
$icon = $new_tab_prop['icon'] ? '<i class="'.parent::$icon_source.' '.$new_tab_prop['icon'].'"></i> ' : '';
$class = $li_classes ? ' class="'.implode(' ', $li_classes).'"' : '';
$li_html = '<li'.$class.'>';
if ($new_tab_prop['html']) {
$li_html .= $new_tab_prop['html'];
} else {
$li_html .= '<a href="'.$href.'" '.($a_classes ? 'class="'.implode(' ', $a_classes).'"' : '').($a_attr ? ' '.implode(' ', $a_attr) : '').' rel="tooltip" data-placement="top">'.$icon.$title.'</a>';
$li_html .= $dropdown_html;
}
$li_html .= '</li>';
$li_list[] = $li_html;
if ($new_tab_prop['fade']) $tab_content_classes[] = 'fade';
$tab_content_html = '<div class="'.implode(' ', $tab_content_classes).'" id="'.$tab_id.'">';
$tab_content_html .= $new_tab_prop['content'];
$tab_content_html .= '</div>';
$tab_content_list[] = $tab_content_html;
}
$ul_classes = array();
$ul_attr = array();
$ul_classes[] = 'nav nav-tabs '.$structure->options['class'];
$ul_id = $structure->tabs_id ? 'id="'.$structure->tabs_id.'"' : '';
$ul_attr[] = $ul_id;
$content_classes = array();
$content_classes[] = 'tab-content';
if ($structure->content_class)
$content_classes[] = is_array($structure->content_class) ? implode(' ', $structure->content_class) : $structure->content_class;
$content_id = $structure->content_id ? 'id="'.$structure->content_id.'"' : '';
if ($structure->options['padding']) $content_classes[] = 'padding-'.$structure->options['padding'];
$content_html = '<div class="'.implode(' ', $content_classes).'" '.$content_id.'>';
$content_html .= implode('', $tab_content_list);
$content_html .= '</div>';
$main_content_html = '';
if ($structure->options['widget']) {
$ul_classes[] = $structure->options['pull'] ? 'pull-'.$structure->options['pull'] : 'pull-left';
$ul_html = '<ul class="'.implode(' ', $ul_classes).'" '.implode(' ', $ul_attr).'>';
$ul_html .= implode('', $li_list);
$ul_html .= '</ul>';
$widget = $structure->options['widget'];
if (!$widget instanceof Widget) {
$widget = new Widget();
}
$widget->body('content', $content_html);
$widget->options('colorbutton', false)->options('editbutton', false);
$widget->header('title', $widget->header('title').' '.$ul_html);
$result = $widget->print_html(true);
} else {
if ($structure->options['bordered']) $ul_classes[] = 'bordered';
if ($structure->options['pull']) $ul_classes[] = 'tabs-pull-'.$structure->options['pull'];
$ul_html = '<ul class="'.implode(' ', $ul_classes).'" '.implode(' ', $ul_attr).'>';
$ul_html .= implode('', $li_list);
$ul_html .= '</ul>';
$container_classes = array();
$container_classes[] = 'tabbable';
switch ($structure->options['position']) {
case 'right':
case 'left':
$container_classes[] = 'tabs-'.$structure->options['position'];
$main_content_html = $ul_html.$content_html;
break;
case 'below':
$container_classes[] = 'tabs-'.$structure->options['position'];
$main_content_html = $content_html.$ul_html;
break;
default:
$main_content_html = $ul_html.$content_html;
break;
}
$result = '<div class="'.implode(' ', $container_classes).'">';
$result .= $main_content_html;
$result .= '</div>';
}
if ($return) return $result;
else echo $result;
}
}
?>

View File

@ -0,0 +1,317 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class Widget extends UI {
private $_options_map = array(
"editbutton" => true,
"colorbutton" => true,
"editbutton" => true,
"togglebutton" => true,
"deletebutton" => true,
"fullscreenbutton" => true,
"custombutton" => true,
"collapsed" => false,
"sortable" => true,
"refreshbutton" => false
);
private $_structure = array(
"class" => "",
"color" => "",
"id" => "",
"attr" => array(),
"options" => array(),
"header" => array(),
"footer" => "",
"footers" => array(),
"body" => array()
);
public function __construct($options = array(), $contents = array()) {
$this->_init_structure($options, $contents);
}
private function _init_structure($user_options, $user_contents) {
$this->_structure = Util::array_to_object($this->_structure);
$user_contents_map = array("header" => array(), "body" => "", "color" => "");
$new_user_contents = Util::set_array_prop_def($user_contents_map, $user_contents);
$this->_structure->options = Util::set_array_prop_def($this->_options_map, $user_options);
$body_structure = array(
"editbox" => "",
"content" => "",
"class" => "",
"toolbar" => null,
"footer" => null
);
$this->_structure->body = Util::set_array_prop_def($body_structure, $new_user_contents["body"], "content");
$header_structure = array(
"icon" => null,
"class" => "",
"title" => "",
"toolbar" => array()
);
$this->_structure->header = Util::set_array_prop_def($header_structure, $new_user_contents["header"], "title");
$this->_structure->color = $new_user_contents["color"];
$this->_structure->id = Util::create_id(true);
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
parent::err('Undefined structure property: '.$name);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
parent::err('Undefined structure property: '.$name);
return null;
}
public function print_html($return = false) {
$structure = $this->_structure;
$attr = Util::get_property_value(
$structure->attr,
array(
"if_closure" => function($attr) { return Util::run_callback($attr, array($this)); }, //if user passes a closure, pass those optional parameters that they can use
"if_other" => function($attr) { return $attr; }, //just directly return the string for this type of structure item
"if_array" => function($attr) {
$props = array_map(function($attr, $attr_value) { //build attribute values from passed array
return $attr.' = "'.$attr_value.'"';
}, array_keys($attr), $attr);
return implode(' ', $props);
}
)
);
$options_map = $this->_options_map;
$options = Util::get_property_value(
$structure->options,
array(
"if_closure" => function($options) { return Util::run_callback($options, array($this)); },
"if_other" => function($options) { return $options; },
"if_array" => function($options) use ($options_map) {
$props = array_map(function($option, $value) use ($options_map) {
if (is_bool($value)) {
$str_val = var_export($value, true);
if (isset($options_map[$option])) {
if ($value !== $options_map[$option]) {
return 'data-widget-'.$option.'="'.$str_val.'"';
} else return '';
} else return 'data-widget-'.$option.'="'.$str_val.'"';
}
return 'data-widget-'.$option.'="'.$value.'"';
}, array_keys($options), $options);
return implode(' ', $props);
}
)
);
$body = Util::get_property_value(
$structure->body,
array(
"if_closure" => function($body) { return Util::run_callback($body, array($this)); },
"if_other" => function($body) {
if ($body === false || is_null($body)) return null;
return '<div class="widget-body">'.$body.'</div>';
},
"if_array" => function($body) {
$editbox = '';
if (isset($body["editbox"])) {
$editbox = '<div class="jarviswidget-editbox">';
$editbox .= $body["editbox"];
$editbox .= '</div>';
}
$content = '';
if (isset($body['content'])) {
if (Util::is_closure($body['content'])) {
$content = Util::run_callback($body['content'], array($this));
} else {
$content = $body['content'];
}
}
$class = 'widget-body';
if (isset($body["class"])) {
if (is_array($body["class"])) {
$class .= ' '.implode(' ', $body["class"]);
} else {
$class .= ' '.$body["class"];
}
}
$toolbar = '';
if (isset($body["toolbar"])) {
$toolbar = '<div class="widget-body-toolbar">';
$toolbar .= $body["toolbar"];
$toolbar .= '</div>';
}
$footer = '';
if (isset($body['footer'])) {
$footer = '<div class="widget-footer">';
$footer .= $body['footer'];
$footer .= '</div>';
}
$result = $editbox;
$result .= '<div class="'.$class.'">';
$result .= $toolbar;
$result .= $content;
$result .= $footer;
$result .= '</div>';
return $result;
}
)
);
$header = Util::get_property_value(
$structure->header,
array(
"if_closure" => function($header) use ($body) { return Util::run_callback($body, array($this)); },
"if_other" => function($body) { return $body; },
"if_array" => function($body) {
$toolbar_htm = '';
if (isset($body["icon"]) && $body['icon']) {
$toolbar_htm .= '<span class="widget-icon"> <i class="'.parent::$icon_source.' '.$body["icon"].'"></i> </span>';
}
if (isset($body["toolbar"])) {
$toolbar_htm .= Util::get_property_value($body["toolbar"], array(
"if_closure" => function($toolbar) { return Util::run_callback($toolbar, array($this, $toolbar)); },
"if_other" => function($toolbar) { return $toolbar; },
"if_array" => function($toolbar) {
$toolbar_props_htm = array();
foreach ($toolbar as $toolbar_prop) {
$id = '';
$class = 'widget-toolbar';
$attrs = array();
$content = '';
if (is_string($toolbar_prop)) {
$content = $toolbar_prop;
} else if (is_array($toolbar_prop)) {
$id = isset($toolbar_prop["id"]) ? $toolbar_prop["id"] : '';
$class .= isset($toolbar_prop["class"]) ? ' '.$toolbar_prop["class"] : '';
if (isset($toolbar_prop["attr"])) {
if (is_array($toolbar_prop["attr"])) {
foreach ($toolbar_prop["attr"] as $attr => $value) {
$attrs[] = $attr.'="'.$value.'"';
}
} else {
$attrs[] = $toolbar_prop["attr"];
}
}
$content = isset($toolbar_prop["content"]) ? $toolbar_prop["content"] : '';
}
$htm = '<div class="'.trim($class).'" id="'.$id.'" '.implode(' ', $attrs).'>';
$htm .= $content;
$htm .= '</div>';
$toolbar_props_htm[] = $htm;
}
return implode(' ', $toolbar_props_htm);
}
));
}
if (isset($body["title"])) {
$toolbar_htm .= $body["title"];
} else
$toolbar_htm .= '<h2><code>SmartUI::Widget->header[content] not defined</code></h2>';
return $toolbar_htm;
}
)
);
$footer_htm = '';
if ($structure->footer) $structure->footers[] = $structure->footer;
foreach ($structure->footers as $footer) {
$footer_prop = array(
'content' => '',
'class' => '',
'attr' => array()
);
$new_footer_prop = Util::get_clean_structure($footer_prop, $footer, array($this), 'content');
$footer_attribues = array_map(function($attr, $value) {
return $attr.'="'.$value.'"';
}, array_keys($new_footer_prop['attr']), $new_footer_prop['attr']);
if ($new_footer_prop['class']) $footer_attribues[] = 'class="'.$new_footer_prop['class'].'"';
$footer_htm .= $new_footer_prop['content'] ? '<footer '.implode(' ', $footer_attribues).'>'.$new_footer_prop['content'].'</footer>' : '';
}
$class = Util::get_property_value($structure->class, array(
"if_closure" => function($class) { return Util::run_callback($class, array($this)); },
"if_array" => function($class) {
return implode(' ', $class);
}
));
$color = Util::get_property_value(
$structure->color,
array(
"if_closure" => function($color) { return Util::run_callback($color, array($this)); },
"if_other" => function($color) { return $color ? 'jarviswidget-color-'.$color : ''; },
"if_array" => function($color) {
parent::err('SmartUI::Widget::color requires string');
}
)
);
$id = Util::get_property_value(
$structure->id,
array(
"if_closure" => function($id) { return Util::run_callback($id, array($this)); },
"if_array" => function($id) {
parent::err('SmartUI::Widget::id requires string.');
return '';
}
)
);
$id = $id ? 'id="'.$id.'"' : '';
$main_classes = array('jarviswidget', $color, $class);
$main_attributes = array('class="'.trim(implode(' ', $main_classes)).'"', $id, $options, $attr);
$result = '<div '.trim(implode(' ', $main_attributes)).'>';
$result .= '<header>'.$header.'</header>';
$result .= is_null($body) ? '' : '<div>'.$body.'</div>';
$result .= $footer_htm;
$result .= '</div>';
if ($return) return $result;
else echo $result;
}
}
?>

View File

@ -0,0 +1,219 @@
<?php
namespace SmartUI\Components;
use \SmartUI\UI;
use \SmartUI\Util;
class Wizard extends UI {
const WIZARD_BOOTSTRAP = 'bootstrap';
const WIZARD_FUEL = 'fuel';
private $_options_map = array(
'in_widget' => true,
'type' => Wizard::WIZARD_BOOTSTRAP
);
private $_structure = array(
'options' => array(),
'step' => array(),
'content' => array(),
'widget' => null,
'active' => array(),
'title' => '',
'tabl_class' => 'form-wizard',
'id' => ''
);
public function __construct($steps, $options = array()) {
$this->_init_structure($steps, $options);
}
private function _init_structure($steps, $user_options = array()) {
$this->_structure = Util::array_to_object($this->_structure);
$this->_structure->options = Util::set_array_prop_def($this->_options_map, $user_options);
$this->_structure->step = $steps;
$this->_structure->id = Util::create_id(true);
$widget = new Widget();
$widget->options('editbutton', false)
->header('title', '<h2></h2>');
$this->_structure->widget = $widget;
}
public function __get($name) {
if (isset($this->_structure->{$name})) {
return $this->_structure->{$name};
}
SmartUI::err('Undefined structure property: '.$name);
return null;
}
public function __set($name, $value) {
if (isset($this->_structure->{$name})) {
$this->_structure->{$name} = $value;
return;
}
SmartUI::err('Undefined structure property: '.$name);
}
public function __call($name, $args) {
return parent::_call($this, $this->_structure, $name, $args);
}
private function _get_bootstrap_result() {
$structure = $this->_structure;
$steps = Util::get_property_value($structure->step, array(
'if_closure' => function($steps) {
return SmartUI::run_callback($steps, array($this));
},
'if_other' => function($steps) {
SmartUI::err('SmartUI::Wizard::step requires array');
return null;
}
));
if (!is_array($steps)) {
parent::err("SmartUI::Wizard::step requires array");
return null;
}
$li_list = array();
$step_content_list = array();
$has_active = false;
$step = 1;
foreach ($steps as $step_id => $step_prop) {
$step_structure = array(
'content' => isset($structure->content[$step_id]) ? $structure->content[$step_id] : '',
'title' => isset($structure->title[$step_id]) ? $structure->title[$step_id] : '',
'step' => $step,
'active' => isset($structure->active[$step_id]) && $structure->active[$step_id] === true,
);
$new_step_prop = Util::get_clean_structure($step_structure, $step_prop, array($this, $steps, $step_id), 'title');
foreach ($new_step_prop as $step_prop_key => $step_prop_vaue) {
$new_step_prop_value = Util::get_property_value($step_prop_vaue, array(
'if_closure' => function($prop_value) use ($steps) {
return SmartUI::run_callback($prop_value, array($this, $steps));
}
));
$new_step_prop[$step_prop_key] = $new_step_prop_value;
}
$step_content_classes = array();
$step_content_classes[] = 'tab-pane';
$li_classes = array();
$a_classes = array();
$a_attr = array();
if ((!$structure->active && !$has_active) || ($new_step_prop['active'] === true && !$has_active)) {
$li_classes[] = 'active';
$step_content_classes[] = 'active';
$has_active = true;
}
$title = $new_step_prop['title'];
$href = '#'.$step_id;
$a_attr[] = 'data-toggle="tab"';
$class = $li_classes ? ' class="'.implode(' ', $li_classes).'"' : '';
$li_html = '<li'.$class.' data-target="#'.$step_id.'">';
$li_html .= '<a href="'.$href.'" '.($a_classes ? 'class="'.implode(' ', $a_classes).'"' : '').($a_attr ? ' '.implode(' ', $a_attr) : '').'>';
$li_html .= '<span class="step">'.$new_step_prop['step'].'</span> <span class="title">'.$title.'</span>';
$li_html .= '</a>';
$li_html .= '</li>';
$li_list[] = $li_html;
$step_content_html = '<div class="'.implode(' ', $step_content_classes).'" id="'.$step_id.'">';
$step_content_html .= $new_step_prop['content'];
$step_content_html .= '</div>';
$step_content_list[] = $step_content_html;
$step++;
}
$ul_classes = array();
$ul_classes[] = 'bootstrapWizard';
$ul_classes[] = $structure->tabl_class;
$content_classes = array();
$content_classes[] = 'tab-content';
$content_html = '<div class="'.implode(' ', $content_classes).'">';
$content_html .= implode('', $step_content_list);
$content_html .= ' <div class="form-actions">
<div class="row">
<div class="col-sm-12">
<ul class="pager wizard no-margin">
<!--<li class="previous first disabled">
<a href="javascript:void(0);" class="btn btn-lg btn-default"> First </a>
</li>-->
<li class="previous disabled">
<a href="javascript:void(0);" class="btn btn-lg btn-default"> Previous </a>
</li>
<!--<li class="next last">
<a href="javascript:void(0);" class="btn btn-lg btn-primary"> Last </a>
</li>-->
<li class="next">
<a href="javascript:void(0);" class="btn btn-lg txt-color-darken"> Next </a>
</li>
</ul>
</div>
</div>
</div>';
$content_html .= '</div>';
$ul_html = '<div class="form-bootstrapWizard">';
$ul_html .= ' <ul class="'.implode(' ', $ul_classes).'">';
$ul_html .= implode('', $li_list);
$ul_html .= ' </ul>';
$ul_html .= ' <div class="clearfix"></div>';
$ul_html .= '</div>';
$main_content_html = '<div class="row">';
$main_content_html .= ' <div class="col-sm-12" id="'.$structure->id.'">';
$main_content_html .= $ul_html.$content_html;
$main_content_html .= ' </div>';
$main_content_html .= '</div>';
if (isset($structure->options["in_widget"]) && $structure->options["in_widget"]) {
$structure->widget->body("content", $main_content_html);
if ($structure->title) {
$structure->widget->header('title', $structure->title);
}
$result = $structure->widget->print_html(true);
} else $result = $main_content_html;
return $result;
}
private function _get_fuel_result() {
}
public function print_html($return = false) {
switch ($this->_structure->options["type"]) {
case Wizard::WIZARD_BOOTSTRAP:
$result = self::_get_bootstrap_result();
break;
default:
parent::err('SmartUI::Wizard Invalid Wizard Type: wizard "'.$this->_structure->options["type"].'" not found.');
break;
}
if ($return) return $result;
else echo $result;
}
}
?>

500
lib/smartui/UI.php Normal file
View File

@ -0,0 +1,500 @@
<?php
namespace SmartUI;
class UI {
const SMARTUI_WIDGET = 'widget';
const SMARTUI_DATATABLE = 'datatable';
const SMARTUI_BUTTON = 'button';
const SMARTUI_TAB = 'tab';
private static $_ui_calls = array('create', 'set', 'get', 'print');
private $_track_start_time;
private static $_uis = array();
private static $_alerts = array('info', 'danger', 'primary', 'default', 'warning', 'success');
public static $icon_source = 'fa';
public static $debug = true;
public static function register($name, $class) {
self::$_uis[$name] = $class;
}
protected function _call($ui_member, $structure, $name, $args) {
if (property_exists($structure, $name)) {
if (!$args) return $structure->{$name};
$value = null;
$key = null;
if (count($args) > 1 && is_array($structure->{$name})) {
$key = $args[0];
$value = $args[1];
if (!is_string($key) && !is_int($key)) {
self::err("SmartUI structure property: $name must be string or int.");
return null;
}
$structure->{$name}[$key] = $value;
if (isset($args[2]) && Util::is_closure($args[2])) {
//process callback
$callback = $args[2];
Util::run_callback($callback, array($ui_member));
}
return $ui_member;
} else {
if (isset($args[1]) && Util::is_closure($args[1])) {
$value = $args[0];
$structure->{$name} = $value;
$callback = $args[1];
Util::run_callback($callback, array($ui_member));
return $ui_member;
} else if (is_array($structure->{$name}) && (is_string($args[0]) || is_int($args[0]))) {
$key = $args[0];
if (!is_string($key) && !is_int($key)) {
self::err("SmartUI property key: $key must be string or int.");
return null;
}
return $structure->{$name}[$key];
} else {
$value = $args[0];
$structure->{$name} = $value;
return $ui_member;
}
}
}
self::err('Undefined structure property: '.$name);
return null;
}
public function start_track() {
$this->_track_start_time = microtime(true);
}
public function __call($name, $args) {
$calls = explode('_', $name);
if (!in_array($calls[0], self::$_ui_calls)) {
self::err("Undefined call: $calls[0]");
return null;
}
$ui_class = strtolower($calls[1]);
if (isset(self::$_uis[$ui_class]) && $calls[0] == 'create') {
$reflection = new \ReflectionClass(self::$_uis[$ui_class]);
$new_ui = $args ? $reflection->newInstanceArgs($args) : $reflection->newInstance();
$this->start_track();
return $new_ui;
} else if ($calls[0] == 'print' && in_array($calls[1], self::$_alerts)) {
$alert_args = array($args[0], $calls[1]);
for ($i = 1; $i < count($args); $i++) {
$alert_args[] = $args[$i];
}
return call_user_func_array(array($this, 'print_alert'), $alert_args);
}
self::err("\"$ui_class\" is not a registered member of SmartUI: Class not found");
}
public function run_time($print = true) {
$time_end = microtime(true);
$execution_time = number_format($time_end - $this->_track_start_time, 4);
if ($print) echo $execution_time.'s';
else return $execution_time.'s';
}
public static function err($message = "SmartUI Error notice:") {
if (self::$debug) {
$trace = debug_backtrace();
trigger_error($message.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE);
}
}
public static function get_progress($value, $type = '', $options = array()) {
$real_value = str_replace('%', '', $value);
$percent_value = $real_value.'%';
$options_map = array(
'transitional' => false,
'class' => array(),
'attr' => array(),
'background' => '',
'container' => 'div'
);
$new_options_map = Util::set_array_prop_def($options_map, $options, 'class');
$classes = array();
$classes[] = 'progress-bar';
if ($type) $classes[] = 'progress-bar-'.$type;
// add additional user classes
if (is_array($new_options_map['class'])) {
array_merge($classes, $new_options_map['class']);
} else {
$classes[] = $new_options_map['class'];
}
if ($new_options_map['background']) $classes[] = 'bg-color-'.$new_options_map['background'];
$attrs = array();
$attrs_html = array();
if ($new_options_map['transitional'])
$attrs['aria-valuetransitiongoal'] = $real_value;
else
$attrs['style'] = 'width: '.$percent_value;
// add additional user attributes
if (is_array($new_options_map['attr'])) {
array_merge($attrs, $new_options_map['attr']);
} else {
$attrs_html[] = $new_options_map['attr'];
}
foreach ($attrs as $attr => $attr_value) {
$attrs_html[] = $attr.'="'.$attr_value.'"';
}
return'<'.$new_options_map['container'].' class="'.implode(' ', $classes).'" '.implode(' ', $attrs_html).'></'.$new_options_map['container'].'>';
}
public static function print_stack_progress($progress_bars, $base_options = array(), $return = false) {
$options_map = array(
'tooltip' => array(),
'position' => 'left', // left, right, bottom (for vertical)
'wide' => false,
'size' => 'md', // sm, xs, md, xl, micro
'striped' => false, // true or 'active'
'vertical' => false
);
$new_options_map = Util::set_array_prop_def($options_map, $base_options, 'class');
$container_classes = array();
$container_classes[] = "progress";
if ($new_options_map['vertical']) $container_classes[] = 'vertical';
if ($new_options_map['position']) $container_classes[] = $new_options_map['position'];
if ($new_options_map['wide']) $container_classes[] = 'wide-bar';
if ($new_options_map['striped']) {
$container_classes[] = 'progress-striped';
if ($new_options_map['striped'] === 'active')
$container_classes[] = 'active';
}
$container_classes[] = 'progress-'.$new_options_map['size'];
$container_attrs = array();
$container_attrs_html = array();
if ($new_options_map['tooltip']) {
$tooltip_prop = array(
'placement' => 'top',
'title' => ''
);
$tooltip = $new_options_map['tooltip'];
$new_tooltip_prop = Util::set_array_prop_def($tooltip_prop, $tooltip, 'title');
$container_attrs['rel'] = 'tooltip';
$container_attrs['data-original-title'] = $new_tooltip_prop['title'];
$container_attrs['data-placement'] = $new_tooltip_prop['placement'];
}
foreach ($container_attrs as $container_attr => $attr_value) {
$container_attrs_html[] = $container_attr.'="'.$attr_value.'"';
}
$result = '<div class="'.implode(' ', $container_classes).'" '.implode(' ', $container_attrs_html).'>';
$result .= implode('', $progress_bars);
$result .= '</div>';
if ($return) return $result;
else echo $result;
}
public static function print_progress($value, $type = '', $options = array(), $return = false) {
$real_value = str_replace('%', '', $value);
$percent_value = $real_value.'%';
$options_map = array(
'transitional' => false,
'class' => array(),
'attr' => array(),
'background' => '',
'tooltip' => array(),
'position' => 'left', // left, right, bottom (for vertical)
'wide' => false,
'size' => 'md', // sm, xs, md, xl, micro
'striped' => false, // true or 'active'
'vertical' => false,
'container' => 'div'
);
$new_options_map = Util::set_array_prop_def($options_map, $options, 'class');
$container_classes = array();
$container_classes[] = "progress";
if ($new_options_map['vertical']) $container_classes[] = 'vertical';
if ($new_options_map['position']) $container_classes[] = $new_options_map['position'];
if ($new_options_map['wide']) $container_classes[] = 'wide-bar';
if ($new_options_map['striped']) {
$container_classes[] = 'progress-striped';
if ($new_options_map['striped'] === 'active')
$container_classes[] = 'active';
}
$container_classes[] = 'progress-'.$new_options_map['size'];
$container_attrs = array();
$container_attrs_html = array();
if ($new_options_map['tooltip']) {
$tooltip_prop = array(
'placement' => 'top',
'title' => $percent_value
);
$tooltip = $new_options_map['tooltip'];
$new_tooltip_prop = Util::set_array_prop_def($tooltip_prop, $tooltip, 'title');
$container_attrs['rel'] = 'tooltip';
$container_attrs['data-original-title'] = $new_tooltip_prop['title'];
$container_attrs['data-placement'] = $new_tooltip_prop['placement'];
}
foreach ($container_attrs as $container_attr => $attr_value) {
$container_attrs_html[] = $container_attr.'="'.$attr_value.'"';
}
$classes = array();
$classes[] = implode(' ', $container_classes);
$classes[] = implode(' ', $new_options_map['class'] ? $new_options_map['class'] : array());
$container_attrs_html[] = implode(' ', $new_options_map['attr']);
$result = '<'.$new_options_map['container'].' class="'.implode(' ', $classes).'" '.implode(' ', $container_attrs_html).'>';
$result .= self::get_progress($value, $type, $options);
$result .= '</'.$new_options_map['container'].'>';
if ($return) return $result;
else echo $result;
}
public static function print_alert($message, $type = 'info', $options = array(), $return = false) {
$options_map = array(
'closebutton' => true,
'block' => false,
'container' => 'div',
'class' => array(),
'fade_in' => true,
'icon' => $type,
'js_escape' => false,
'heading' => false
);
$icon_map = array(
'info' => self::$icon_source.'-info',
'warning' => self::$icon_source.'-alert '.self::$icon_source.'-warning',
'danger' => self::$icon_source.'-times '.self::$icon_source.'-x',
'success' => ''.self::$icon_source.'-check'
);
$new_options_map = Util::set_array_prop_def($options_map, $options, 'class');
$closebutton_html = $new_options_map['closebutton'] ?
'<button class="close" data-dismiss="alert">
×
</button>' : '';
$classes = array();
$classes[] = 'alert';
$classes[] = 'alert-'.$type;
if ($new_options_map['fade_in']) $classes[] = 'fade in';
if ($new_options_map['block']) $classes[] = 'alert-block';
if ($new_options_map['icon']) {
$icon = (isset($icon_map[$new_options_map['icon']]) ? $icon_map[$new_options_map['icon']] : self::$icon_source.'-'.$new_options_map['icon']);
$icon_html = '<i class="'.self::$icon_source.' '.$icon.'"></i>';
} else $icon_html = '';
$heading = '';
if ($new_options_map['heading']) {
$heading = '<h4 class="alert-heading">'.$icon_html.' '.$new_options_map['heading'].'</h4>';
$icon_html = '';
}
$result = '<div class="'.implode(' ', $classes).'">
'.$closebutton_html.'
'.$heading.'
'.$icon_html.'
'.$message.'
</div>';
if ($new_options_map['js_escape']) $result = preg_replace("/\s+/", " ", $result);
if ($return) return $result;
else echo $result;
}
public static function print_list($items, $options = array(), $return = false) {
$items_html = '';
$main_attrs = array();
$default_options = array(
'type' => 'ul',
'attr' => array(),
'class' => array(),
'id' => ''
);
$new_options = Util::set_array_prop_def($default_options, $options, 'class');
foreach ($items as $item) {
$item_html = '';
$item_prop = array(
'content' => '',
'subitems' => array(),
'subitem_options' => array(),
'class' => '',
'attr' => array()
);
$new_item_prop = Util::get_clean_structure($item_prop, $item, array($item), 'content');
$content = $new_item_prop['content'];
if ($new_item_prop['subitems']) {
$content .= self::print_list($new_item_prop['subitems'], $new_item_prop['subitem_options'], true);
}
$attrs = array();
if ($new_item_prop['class']) $attrs[] = 'class="'.(is_array($new_item_prop['class']) ? implode(' ', $new_item_prop['class']) : $new_item_prop['class']).'"';
if ($new_item_prop['attr']) {
foreach ($new_item_prop['attr'] as $key => $value) {
$attrs[] = $key.'="'.$value.'"';
}
}
$items_html .= '
<li'.($attrs ? ' '.implode(' ', $attrs) : '').'>
'.$content.'
</li>
';
}
if ($new_options['class']) $main_attrs[] = 'class="'.(is_array($new_options['class']) ? implode(' ', $new_options['class']) : $new_options['class']).'"';
if ($new_options['attr']) {
foreach ($new_options['attr'] as $key => $value) {
$main_attrs[] = $key.'="'.$value.'"';
}
}
if ($new_options['id']) $main_attrs[] = 'id="'.$new_options['id'].'"';
$result = '
<'.$new_options['type'].($main_attrs ? ' '.implode(' ', $main_attrs) : '').'>
'.$items_html.'
</'.$new_options['type'].'>
';
if ($return) return $result;
else echo $result;
}
public static function print_dropdown($items, $options = array(), $return = false) {
$items_html = '';
$main_attrs = array();
$default_options = array(
'type' => 'ul',
'attr' => array(),
'class' => '',
'id' => '',
'multilevel' => false
);
$new_options = Util::set_array_prop_def($default_options, $options, 'class');
foreach ($items as $item) {
$item_html = '';
$item_prop = array(
'content' => '',
'submenu' => array(),
'class' => array(),
'attr' => array()
);
$new_item_prop = Util::get_property_value($item, array(
'if_array' => function($item) use ($item_prop) {
return Util::set_array_prop_def($item_prop, $item, 'content');
},
'if_closure' => function($item) use ($item_prop) {
return Util::set_closure_prop_def($item_prop, $item);
},
'if_other' => function($item) use ($item_prop) {
$item_prop['content'] = $item;
return $item_prop;
}
));
$classes = array();
if ($new_item_prop['class'])
$classes[] = is_array($new_item_prop['class']) ? implode(' ', $new_item_prop['class']) : $new_item_prop['class'];
$attrs = array();
if ($new_item_prop['attr']) {
foreach ($new_item_prop['attr'] as $key => $value) {
$attrs[] = $key.'="'.$value.'"';
}
}
$content = $new_item_prop['content'];
if ($new_item_prop['submenu']) {
$content .= self::print_dropdown($new_item_prop['submenu'], null, true);
$classes[] = 'dropdown-submenu';
} else if ($content === '-') {
$classes[] = 'divider';
} else if (preg_match("/##(.*)?##/", $content, $header_matches)) {
$classes[] = 'dropdown-header';
$content = trim($header_matches[1]);
}
$attrs[] = $classes ? ' class="'.trim(implode(' ', $classes)).'"' : '';
$item_html = '<li'.($attrs ? ' '.implode(' ', $attrs) : '').'>'.$content.'</li>';
$items_html .= $item_html;
}
$classes = array('dropdown-menu');
if ($new_options['multilevel']) $classes[] = 'multi-level';
$main_attrs[] = 'role="menu"';
if ($new_options['class']) $classes[] = $new_options['class'];
if ($new_options['attr']) {
foreach ($new_options['attr'] as $key => $value) {
$main_attrs[] = $key.'="'.$value.'"';
}
}
if ($new_options['id']) $main_attrs[] = 'id="'.$new_options['id'].'"';
$main_attrs[] = 'class="'.implode(' ', $classes).'"';
$result = '<ul '.implode(' ', $main_attrs).'>';
$result .= $items_html;
$result .= '</ul>';
if ($return) return $result;
else echo $result;
}
}
?>

148
lib/smartui/Util.php Normal file
View File

@ -0,0 +1,148 @@
<?php
namespace SmartUI;
class Util {
public static function is_assoc($array) {
foreach (array_keys($array) as $k => $v) {
if ($k !== $v)
return true;
}
return false;
}
public static function clean_html_string($str_value, $nl2br = true) {
if (is_null($str_value)) $str_value = "";
$new_str = is_string($str_value) ? htmlentities(html_entity_decode($str_value, ENT_QUOTES)) : $str_value;
$new_str = utf8_encode($new_str);
return $nl2br ? nl2br($new_str) : $new_str;
}
public static function is_closure($obj) {
return (is_object($obj) && ($obj instanceof \Closure));
}
public static function array_to_object($array, $recursive = false) {
if (!is_object($array) && !is_array($array))
return $array;
if (!$recursive) return (object)$array;
if (is_array($array))
return (object)array_map(array(__CLASS__, 'array_to_object'), $array);
else return $array;
}
public static function object_to_array($object) {
if (!is_object($object) && !is_array($object))
return $object;
if (is_object($object))
$object = get_object_vars($object);
return array_map(array(__CLASS__, 'object_to_array'), $object);
}
public static function create_id($md5 = false) {
$uid = uniqid((double)microtime() * 10000, true);
$result = str_replace(".", "", $uid);
$result = $md5 ? md5($result) : $result;
return $result;
}
public static function get_property_value($prop, $prop_methods) {
if (self::is_closure($prop)) {
return isset($prop_methods['if_closure']) ? $prop_methods['if_closure']($prop) : $prop($prop);
} else if (is_array($prop) || is_object($prop)) {
if (is_object($prop))
$prop = self::object_to_array($prop);
return isset($prop_methods['if_array']) ? $prop_methods['if_array']($prop) : $prop;
} else {
return isset($prop_methods['if_other']) ? $prop_methods['if_other']($prop) : $prop;
}
}
public static function get_clean_structure($default_prop, $value, $closure_defaults = array(), $default_key = '') {
$structure = self::get_property_value($value, array(
'if_array' => function ($value) use ($default_prop, $default_key) {
return self::set_array_prop_def($default_prop, $value, $default_key);
},
'if_closure' => function($value) use ($closure_defaults, $default_prop, $default_key) {
return self::set_closure_prop_def($default_prop, $value, $closure_defaults, $default_key);
},
'if_other' => function($value) use ($default_prop, $default_key) {
$default_prop[$default_key] = $value;
return $default_prop;
}
));
return $structure;
}
public static function set_closure_prop_def($default_structure, $callback_value, $callback_defaults = array(), $set_to_key_if_fail = "") {
if ($set_to_key_if_fail != "") {
if (!self::is_closure($callback_value)) {
if (isset($default_structure[$set_to_key_if_fail]))
$default_structure[$set_to_key_if_fail] = $callback_value;
return $default_structure;
}
}
$callback_return = self::run_callback($callback_value, $callback_defaults);
if (is_array($callback_return)) {
$default_structure = self::set_array_prop_def($default_structure, $callback_return);
} else if ($set_to_key_if_fail != "" && isset($default_structure[$set_to_key_if_fail])) {
$default_structure[$set_to_key_if_fail] = $callback_return;
}
return $default_structure;
}
public static function set_array_prop_def($default_structure, $array_value, $set_to_key_if_fail = "") {
if ($set_to_key_if_fail != "") {
if (!is_array($array_value)) {
if (isset($default_structure[$set_to_key_if_fail]))
$default_structure[$set_to_key_if_fail] = $array_value;
return $default_structure;
}
}
foreach ($array_value as $key => $value) {
$default_structure[$key] = $value;
}
return $default_structure;
}
public static function run_callback($callback, $default_args) {
$reflection = new \ReflectionFunction($callback);
$params = $reflection->getParameters();
if (!$params || !$default_args) return call_user_func($callback);
$ref_args = array_keys($params);
foreach ($ref_args as $param_index) {
if (isset($default_args[$param_index]))
$ref_args[$param_index] = $default_args[$param_index];
else
$ref_args[$param_index] = null;
}
return call_user_func_array($callback, $ref_args);
}
public static function replace_col_codes($str, $row, $url_encode=false) {
preg_match_all("/\{([^&={{}}]+)\}/", $str, $matched_cols);
$col_replace = array();
$col_search = array();
foreach($matched_cols[1] as $matched_col) {
if (is_array($row)) $row = self::array_to_object($row);
if (isset($row->{$matched_col})) {
$col_replace[] = $url_encode ? urlencode($row->{$matched_col}) : $row->{$matched_col};
$col_search[] = "/{{".$matched_col."}}/";
}
}
return preg_replace($col_search, $col_replace, $str);
}
}
?>