<file_sep><?php

    /**
     * Basic_MySqlManager_Service class file.
     *
     
     */
    
    
    ClassLoader::loadServiceClass('basic.abstract');
    
    
    /**
     * MySql connect exception
     */
    class MySqlConnectException extends Exception {}
    
    
    /**
     * MySql query exception
     */
    class MySqlQueryException extends Exception {}
    
    
    /**
     * MySql function descriptor
     */
    class MySqlFunc
    {
        public $funcName = null;
        public function __construct($_funcName)
        {
            $this->funcName = $_funcName;
        }
    }
    

    /**
     * MySQL manager service
     *
     
     */
    class Basic_MySqlManager_Service extends Basic_Abstract_Service
    {

        /**
         * @var resource Database server link
         */
        private $link;

        
        /**
         * @var resource Query result resource
         */
        private $result = false;


        /**
         * Constructor
         */
        public function __construct()
        {
            $this->link = null;
        }
        
        
        /**
         * Destructor
         */
        public function __destruct()
        {
            // Free last result and close the connection
            $this->freeResult();
            $this->close();
        }
        
        
        /**
         * Tells if MySQL connection has been established
         */
        public function connected()
        {
            return !is_null($this->link);
        }


        /**
         * Performs connection to the database server
         */
        public function connect($_hostName, $_userName, $_password, $_dbName)
        {
            // Connect
            $this->link = @mysql_connect($_hostName, $_userName, $_password);
            if ($this->link === false) throw new MySqlConnectException(mysql_error());

            // Select database
            if (mysql_select_db($_dbName) === false) throw new MySqlConnectException(mysql_error());
            
            // Set encoding & timezone
            $this->query('SET NAMES \'UTF8\'');
            if (defined('MYSQL_TIMEZONE')) $this->query('SET time_zone=\''.MYSQL_TIMEZONE.'\'');
        }


        /**
         * Closes the database server connection
         */
        public function close()
        {
            if($this->link)
            {
                mysql_close($this->link);
                $this->link = null;
            }
        }

        
        /**
         * Accesses the ID generated from the previous INSERT operation
         * @return integer|boolean ID generated from the previous INSERT operation
         */
        public function getInsertId()
        {
            return mysql_insert_id($this->link);
        }

        
        /**
         * Performs SQL query
         * @param string $_query  SQL statemement
         */
        public function query($_query)
        {
            // Free previous result
            $this->freeResult();

            // Perform query
            $this->result = mysql_query($_query, $this->link);
            if ($this->result === false)
                throw new MySqlQueryException(mysql_error());
            
            return $this;
        }
        
        
        /**
         * Frees the result
         */
        public function freeResult()
        {
            if (is_resource($this->result))
            {
                mysql_free_result($this->result);
                $this->result = null;
            }
        }


        /**
         * Extracts record as associative map
         * @return array Record
         */
        public function fetchAssoc()
        {
            return mysql_fetch_assoc($this->result);
        }

        /**
         * Extracts record first column
         */
        public function fetchColumn()
        {
            $result = mysql_fetch_assoc($this->result);
            if($result){
                return reset($result);
            }
            return false;
        }
        
        
        /**
         * Extracts record
         * @param integer $_resultType Mapping type
         * @return array Record
         */
        public function fetchArray($_resultType = MYSQL_BOTH)
        {
            return mysql_fetch_array($this->result, $_resultType);
        }

        
        /**
         * Extracts all records
         * @param integer $_resultType Mapping type
         * @return array Fetched records
         */
        public function fetchAll($_resultType = MYSQL_ASSOC)
        {
            $records = array();
            while ($record = mysql_fetch_array($this->result, $_resultType))
                $records[] = $record;
            $this->freeResult();
            return $records;
        }

        
        /**
         * Extracts all records
         * @param integer $_resultType Mapping type
         * @return array Fetched records
         */
        public function fetchAllCellValue($_fieldKey, $_resultType = MYSQL_ASSOC)
        {
            $records = array();
            while ($record = mysql_fetch_array($this->result, $_resultType))
                $records[] = $record[$_fieldKey];
            $this->freeResult();
            return $records;
        }

        
        /**
         * Extracts all records as key-record map
         * @param string $_key Mapping key
         * @param integer $_resultType Mapping type
         * @return array Fetched records
         */
        public function fetchAllAsMap($_key = 'id', $_resultType = MYSQL_ASSOC)
        {
            $records = array();
            while ($record = mysql_fetch_array($this->result, $_resultType))
                $records[$record[$_key]] = $record;
            $this->freeResult();
            return $records;
        }

        
        /**
         * Extracts all records as key-value map
         * @param string $_keyFieldKey Field key whom value is to be a map key
         * @param string $_valueFieldKey Field key whom value is to be a map value
         * @return array
         */
        public function fetchAllAsKeyValueMap($_keyFieldKey, $_valueFieldKey)
        {
            $records = array();
            while ($record = mysql_fetch_array($this->result, MYSQL_ASSOC))
                $records[$record[$_keyFieldKey]] = $record[$_valueFieldKey];
            $this->freeResult();
            return $records;
        }

        
        /**
         * Extracts all records as name by ID
         * @param array Records set to be extracted
         * @param integer $_resultType Mapping type
         */
        public function fetchAllRecordsAsNameById(&$_records, $_resultType = MYSQL_BOTH)
        {
            $_records = array();
            while ($record = mysql_fetch_array($this->result, $_resultType))
                $_records[$record['id']] = $record['name'];
            $this->freeResult();
        }
        
        
        /**
         * Accesses the number of records in the result
         * @return integer|boolean The number of records in the result or false if no result
         */
        public function getRecordsCount()
        {
            return mysql_num_rows($this->result);
        }
        
        
        /**
         * Accesses the cell value
         * @param string Cell name
         * @return mixed Cell value on success, null otherwise
         */
        public function fetchCellValue($_cellName)
        {
            $record = mysql_fetch_assoc($this->result);
            return $record !== false ? $record[$_cellName] : null;
        }

        
        /**
         * Accesses the number of affected rows
         * @return int Affected rows count
         */
        public function getAffectedRows()
        {
            return mysql_affected_rows();
        }
        
        
        /**
         * Executes insert query
         * @param string $_tableName Table name
         * @param array $_data Data
         */
        public function insert($_tableName, $_data)
        {
            $query = 'INSERT INTO `'.$_tableName.'` SET ';
            foreach ($_data as $key => $value)
            {
                if (is_null($value))
                    $query .= '`'.$key.'` = NULL, ';
                elseif ($value instanceof MySqlFunc)
                    $query .= '`'.$key.'`='.$value->funcName.'(),';
                else
                    $query .= '`'.$key.'` = \''.mysql_real_escape_string($value).'\', ';
            }
            $query = substr($query, 0, strlen($query)-2);
            $this->query($query);
            return $this;
        }

        /**
         * Executes insert query
         * @param string $_tableName Table name
         * @param array $_data Data
         */
        public function insertMulti($_tableName, $_data)
        {
            $query = 'INSERT INTO `'.$_tableName.'` ';
            foreach ($_data as $dataKey => $dataValue)
            {
                foreach($dataValue as $key=>$value){
                    if (is_null($value))
                        $query .= '`'.$key.'` = NULL, ';
                    elseif ($value instanceof MySqlFunc)
                        $query .= '`'.$key.'`='.$value->funcName.'(),';
                    else
                        $query .= '`'.$key.'` = \''.mysql_real_escape_string($value).'\', ';    
                }
                
            }
            $query = substr($query, 0, strlen($query)-2);
            $this->query($query);
            return $this;
        }
        
        
        /**
         * WARNING: This function is deprecated, use insert instead
         * Inserts record
         * @param string $_tableName Table name
         * @param array $_data Data
         */
        public function insertRecord($_tableName, $_data)
        {
            return $this->insert($_tableName, $_data);
        }
        
        
        /**
         * Executes UPDATE query
         * @param string $_tableName Table name
         * @param array $_data Data
         * @param string $_criteria Update criteria (condition)
         */
        public function update($_tableName, $_data, $_criteria = '1')
        {
            $query = 'UPDATE `'.$_tableName.'` SET ';
            foreach ($_data as $key => $value)
            {
                if (is_null($value))
                    $query .= '`'.$key.'`=NULL,';
                elseif ($value instanceof MySqlFunc)
                {
                    $query .= '`'.$key.'`='.$value->funcName.'(),';
                }
                else
                    $query .= '`'.$key.'`=\''.mysql_real_escape_string($value).'\',';
            }
            $query = rtrim($query, ',');
            
            
            // Condition
            if (is_array($_criteria))
            {
                $query .= ' WHERE 1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $query .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $query .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $query = trim($query, ',');
                        $query .= ')';
                    }
                    else
                        $query .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                }
            }
            else
                $query .= ' WHERE '.$_criteria;
                
            
            return $this->query($query);
        }

        
        /**
         * Deletes records with specified criteria
         * @param string $_tableName Table name
         * @param string $_criteria Criteria (condition)
         */
        public function delete($_tableName, $_criteria = '1')
        {
            $query = 'DELETE FROM `'.$_tableName.'`';
            
            
            // Condition
            if (is_array($_criteria))
            {
                $query .= ' WHERE 1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $query .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $query .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $query = trim($query, ',');
                        $query .= ')';
                    }
                    else
                        $query .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                }
            }
            else
                $query .= ' WHERE '.$_criteria;
            
            
            $this->query($query);
        }
        
        
        /**
         * Executes START TRANSACTION query
         */
        public function startTransaction()
        {
            $this->query('START TRANSACTION');
        }
        
        
        /**
         * Executes ROLLBACK query
         */
        public function rollback()
        {
            $this->query('ROLLBACK');
        }
        
        
        /**
         * Executes COMMIT query
         */
        public function commit()
        {
            $this->query('COMMIT');
        }
        
        
        /**
         * Executes COUNT(*) query
         * @param string $_tableName Table name
         * @param string $_criteria Condition
         * @return integer Count value
         */
        public function count($_tableName, $_criteria = '1')
        {
            $query = 'SELECT COUNT(*) AS `c` FROM `'.$_tableName.'`';
            
            // Condition
            if (is_array($_criteria))
            {
                $query .= ' WHERE 1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $query .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $query .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $query = trim($query, ',');
                        $query .= ')';
                    }
                    else
                    {
                        if (is_null($value))
                            $query .= ' AND `'.$key.'` IS NULL';
                        else
                            $query .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                    }
                }
            }
            else
                $query .= ' WHERE '.$_criteria;
            return (int) $this->query($query)->fetchCellValue('c');
        }
        
        
        /**
         * Executes SUM(`field_key`) query
         * @param string $_tableName Table name
         * @param string $_fieldKey Field key to sum
         * @param string $_criteria Condition
         * @return integer Count value
         */
        public function sum($_fieldKey, $_tableName, $_criteria = '1')
        {
            $query = 'SELECT SUM(`'.$_fieldKey.'`) AS `sum` FROM `'.$_tableName.'`';
            
            // Condition
            if (is_array($_criteria))
            {
                $query .= ' WHERE 1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $query .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $query .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $query = trim($query, ',');
                        $query .= ')';
                    }
                    else
                    {
                        if (is_null($value))
                            $query .= ' AND `'.$key.'` IS NULL';
                        else
                            $query .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                    }
                }
            }
            else
                $query .= ' WHERE '.$_criteria;
            
            return $this->query($query)->fetchCellValue('sum');
        }
        
        
        /**
         * Executes MAX(`field_key`) query
         * @param string $_tableName Table name
         * @param string $_fieldKey Field key to sum
         * @param string $_criteria Condition
         * @return integer Max value
         */
        public function max($_fieldKey, $_tableName, $_criteria = '1')
        {
            $query = 'SELECT MAX(`'.$_fieldKey.'`) AS `max` FROM `'.$_tableName.'`';
            
            // Condition
            if (is_array($_criteria))
            {
                $query .= ' WHERE 1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $query .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $query .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $query = trim($query, ',');
                        $query .= ')';
                    }
                    else
                    {
                        if (is_null($value))
                            $query .= ' AND `'.$key.'` IS NULL';
                        else
                            $query .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                    }
                }
            }
            else
                $query .= ' WHERE '.$_criteria;
            
            return $this->query($query)->fetchCellValue('max');
        }
        
        
        /**
         * Executes SUM(`field_key`) query
         * @param string $_tableName Table name
         * @param string $_fieldKey Field key to sum
         * @param string $_criteria Condition
         * @return integer Count value
         */
        public function sumOfProductions($_tableName, $_fieldKey1, $_fieldKey2, $_criteria = '1')
        {
            $query = 'SELECT SUM(`'.$_fieldKey1.'`*`'.$_fieldKey2.'`) AS `sum` FROM `'.$_tableName.'`';
            
            // Condition
            if (is_array($_criteria))
            {
                $query .= ' WHERE 1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $query .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $query .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $query = trim($query, ',');
                        $query .= ')';
                    }
                    else
                    {
                        if (is_null($value))
                            $query .= ' AND `'.$key.'` IS NULL';
                        else
                            $query .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                    }
                }
            }
            else
                $query .= ' WHERE '.$_criteria;
            
            return $this->query($query)->fetchCellValue('sum');
        }
        
        
        /**
         * Executes COUNT(DISTINCT) query
         * @param string $_tableName Table name
         * @param string $_columnName Column name
         * @param string $_criteria Condition
         * @return integer Count value
         */
        public function countDistinct($_tableName, $_columnName, $_criteria = '1')
        {
            return $this->query('SELECT COUNT(DISTINCT `'.$_columnName.'`) AS `c` FROM `'.$_tableName.'` WHERE '.$_criteria)->fetchCellValue('c');
        }
        
        
        public function selectDistinct($_columnName, $_tableName, $_criteria = '1', $_order = null)
        {
            // Condition
            if (is_array($_criteria))
            {
                $criteria = '1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $criteria .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $criteria .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $criteria = trim($criteria, ',');
                        $criteria .= ')';
                    }
                    else
                        $criteria .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                }
            }
            else
                $criteria = $_criteria;
            
            
            // Compose query
            $query = 'SELECT DISTINCT `'.$_columnName.'` FROM `'.$_tableName.'` WHERE '.$criteria.'';
            
            
            // Order clause
            if (!empty($_order))
                $query .= ' ORDER BY '.$_order;
            
            
            return $this->query($query);
        }
        
        
        public function countGroups($_select, $_tableName, $_groupColumnKey, $_criteria = '1')
        {
            return $this->query('SELECT '.$_select.', COUNT(*) AS `count` FROM `'.$_tableName.'` WHERE '.$_criteria.' GROUP BY `'.$_groupColumnKey.'`')->fetchAll();
        }
        
        
        /**
         * Executes SELECT query
         * @param mixed $_select Select clause
         * @param string $_tableName Table name
         * @param string $_criteria Condtion
         * @param mixed $_order Order
         * @return array Extracted records
         */
        public function select($_select, $_tableName, $_criteria = '1', $_order = null, $_limit = null, $_offset = null)
        {
            // Select clause
            $query = 'SELECT ';
            if (is_array($_select))
            {
                foreach ($_select as $_fieldKey)
                    $query .= '`'.$_fieldKey.'`,';
                $query = trim($query, ',');
            }
            else
                $query .= $_select;
            
            
            // From clause
            $query .= ' FROM `'.$_tableName.'`';
            
            
            // Condition
            if (is_array($_criteria))
            {
                $query .= ' WHERE 1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $query .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $query .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $query = trim($query, ',');
                        $query .= ')';
                    }
                    else
                    {
                        if (is_null($value))
                            $query .= ' AND `'.$key.'` IS NULL';
                        else
                            $query .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                    }
                }
            }
            else
                $query .= ' WHERE '.$_criteria;
            
            
            // Order clause
            if (!empty($_order))
                $query .= ' ORDER BY `'.$_order.'`';
            
            
            // LIMIT clause
            if (!empty($_limit))
                $query .= ' LIMIT '.$_limit;
            
            
            // OFFSET clause
            if (!empty($_offset))
                $query .= ' OFFSET '.$_offset;
            
            
            // Execution
            return $this->query($query);
        }
        
        
        /**
         * Sets specified time zone
         * @param string UTC offset
         */
        public function setTimeZone($_utcOffset)
        {
            $this->query('SET time_zone=\''.$_utcOffset.'\'');
        }
        
        
        /**
         * Get record [by specified criteria]
         *
         * @param string $_tableName Table name
         * @param int $_criteria Criteria
         *
         * @return array|boolean Record data as array or false if record is not found
         */
        public function getRecord($_tableName, $_criteria = '1')
        {
            $query = 'SELECT * FROM `'.$_tableName.'`';
            if (is_array($_criteria))
            {
                $query .= ' WHERE 1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $query .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $query .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $query = trim($query, ',');
                        $query .= ')';
                    }
                    else
                        $query .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                }
            }
            else
                $query .= ' WHERE '.$_criteria;
            return $this->query($query)->fetchAssoc();
        }
        
        
        /**
         * Get record by ID
         *
         * @param string $_tableName Table name
         * @param int $_id Record ID
         *
         * @return array|boolean Record data as array or false if record is not found
         */
        public function getRecordById($_tableName, $_id, $_order = null)
        {
            $query = 'SELECT * FROM `'.$_tableName.'` WHERE `id`='.$_id;
            if (!is_null($_order)) $query .= ' ORDER BY '.$_order;
            return $this->query($query)->fetchAssoc();
        }
        
        
        /**
         * Get records
         * 
         * @param string $_tableName Table name
         * @param string $_criteria Criteria (condition)
         *
         * @return array Array of records
         */
        public function getRecords($_tableName, $_criteria = '1', $_order = null)
        {
            if (is_array($_criteria))
            {
                $criteria = '1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $criteria .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $criteria .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $criteria = trim($criteria, ',');
                        $criteria .= ')';
                    }
                    else
                        $criteria .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                }
            }
            else
                $criteria = $_criteria;
            $query = 'SELECT * FROM `'.$_tableName.'` WHERE '.$criteria;
            if (!is_null($_order)) $query .= ' ORDER BY '.$_order;
            return $this->query($query)->fetchAll();
        }

        /**
         * Executes SELECT query
         * @param mixed $_select Select clause
         * @param mixed $_tableName Table name
         * @param string $_criteria Condtion
         * @param mixed $_order Order
         * @return array Extracted records
         */
        public function mixedselectDistinct($_select, $_tableName, $_criteria = '1', $_order = null, $_limit = null, $_offset = null)
        {
            // Select clause
            $query = 'SELECT DISTINCT ';
            if (is_array($_select))
            {
                foreach ($_select as $_fieldKey)
                    $query .= '`'.$_fieldKey.'`,';
                $query = trim($query, ',');
            }
            else
                $query .= $_select;
            
            // From clause
            $query .= ' FROM ';
            if (is_array($_tableName))
            {
                foreach ($_tableName as $_fieldKey1)
                    $query .= '`'.$_fieldKey1.'`,';
                $query = trim($query, ',');
    }
            else
                $query .= '`'.$_tableName.'`';

            // Condition
            if (is_array($_criteria))
            {
                $query .= ' WHERE 1';
                foreach ($_criteria as $key => $value)
                {
                    if (is_array($value))
                    {
                        $query .= ' AND `'.$key.'` IN (';
                        foreach ($value as $valueItem)
                            $query .= '\''.mysql_real_escape_string($valueItem).'\',';
                        $query = trim($query, ',');
                        $query .= ')';
                    }
                    else
                    {
                        if (is_null($value))
                            $query .= ' AND `'.$key.'` IS NULL';
                        else
                            $query .= ' AND `'.$key.'`=\''.mysql_real_escape_string($value).'\'';
                    }
                }
            }
            else
                $query .= ' WHERE '.$_criteria;
            
            
            // Order clause
            if (!empty($_order))
                $query .= ' ORDER BY `'.$_order.'`';
            
            
            // LIMIT clause
            if (!empty($_limit))
                $query .= ' LIMIT '.$_limit;
            
            
            // OFFSET clause
            if (!empty($_offset))
                $query .= ' OFFSET '.$_offset;
            
            
            // Execution
            return $this->query($query);
        }

    }


?><file_sep><?php

    /**
     * Basic_Abstract_Builder class file.
     *
     
     */
    
    
    /**
     * Abstract builder
    
     */
    abstract class Basic_Abstract_Builder
    {
        
        /**
         * General build routine
         * @param array $_params Array of parameters
         * @return AbstractModel Built data model
         */
        public function get(array $_params = array())
        {
            $modelClassName = str_replace('_Builder', '_Model', get_class($this));
            return new $modelClassName($_params);
        }
        
        
        public function getByRequest(Request $_request = null)
        {
            $modelClassName = str_replace('_Builder', '_Model', get_class($this));
            return new $modelClassName(array());
        }
        
        
        /**
         * Debug purpose
         */
        protected function _varDumpExit($_arg)
        {
            echo '<pre>'; var_dump($_arg); exit();
        }
        
        
        /**
         */
        protected function _simpleXmlLoadFileRetriable($_filename)
        {
            $tries = 1;
            while (!($xmlObject = @simplexml_load_file($_filename))  and  (XML_LOAD_MAX_TRIES_NUM==0 or $tries++ < XML_LOAD_MAX_TRIES_NUM))
                sleep(XML_LOAD_DELAY);
            return $xmlObject;
        }
        
    }

?><file_sep><?php
    
    /**
     * Asynchronous action exception
     *
     
     */
    class AsyncActionException extends Exception {}
    class AsyncActionSessionExpireException extends Exception {}
    class AsyncActionAuthException extends Exception {}
     
?><file_sep><?php

    /**
     * Dictionary
     *
     
     */
    final class Dictionary
    {
    
        /**
         * Instance holder
         * @var Dictionary
         */
        private static $instance = null;
        
        
        /**
         * Words container
         * @var array
         */
        private $words;
        
    
        /**
         * Prevent direct object creation
         */
        private function __construct()
        {
            $this->words = array();
        }
        
        
        /**
         * Prevent to clone the instance
         */
        private function __clone() {}
        
        
        /**
         * Instance creator/accessor
         */
        public function getInstance()
        {
            if (self::$instance === null)
                self::$instance = new Dictionary();
            return self::$instance;
        }
        
        
        /**
         * Loads words
         */
        public function loadWords($_dicFilename)
        {
            // Compose dictionary file name
            if (!file_exists($_dicFilename))
                throw new Exception('Failed to load dictionary file.');
            
            // Parse dictionary file
            $this->words = parse_ini_file($_dicFilename);
        }
        
        
        /**
         * Acsesse the word by key
         * @param string Key
         */
        public function getWord($_key)
        {
            return $this->words[$_key];
        }
    
    }
     
?><file_sep><?php

    /**
     * Application class file.
     *
    
     */
    
    
    /**
     * Request
     *
    
     */
    class Request
    {
    
        /**
         * @var string Hostname
         */
        private $hostname = null;
        
        
        /**
         * @var integer Domain ID
         */
        private $domainId = null;
    
        
        /**
         * @var string URL
         */
        private $url = null;
        
        
        /**
         * $var string Method ('GET' or 'POST')
         */
        private $method;
        
        
        /**
         * @var string Referrer
         */
        private $referrer;
        
        
        /**
         * @var array Parameters
         */
        private $params = array();
        
        
        /**
         * Constructor
         */
        public function __construct($_server, $_request)
        {
            $this->hostname = $_server['HTTP_HOST'];
            
            
            // Resolve domain ID
            $mySqlManager = Application::getService('basic.mysqlmanager');
            if (substr($this->hostname, strlen($this->hostname)-strlen(MAIN_DOMAIN)) == MAIN_DOMAIN)
            {
                $subDomainName = substr($this->hostname, 0, strpos($this->hostname, '.'));
                $this->domainId = (int) $mySqlManager->select('id', 'domains', array('name' => $subDomainName))->fetchCellValue('id');
            }
            else
                $this->domainId = (int) $mySqlManager->select('id', 'domains', array('domain' => $this->hostname))->fetchCellValue('id');
            
            
            $this->url = ($url = substr($_server['REQUEST_URI'], 1)) ? $url : '';
            $this->method = $_server['REQUEST_METHOD'];
            $this->params = $_request;
            $this->referrer = array_key_exists('HTTP_REFERER', $_server) ? $_server['HTTP_REFERER'] : null;
        }
        
        
        /**
         * Acceses the Hostname
         * @return string Hostname
         */
        public function getHostname() { return $this->hostname; }
        
        
        /**
         * Accesses the Domain ID
         * @return integer Domain ID
         */
        public function getDomainId() { return $this->domainId; }
        
        
        /**
         * Accesses the URL
         * @param boolean Indicates if URL params should be included
         * @return string request URL
         */
        public function getUrl($_truncateUrlParams = true)
        {
            if ($_truncateUrlParams)
            {
                $p = strpos($this->url, '?');
                if ($p === false)
                    return $this->url;
                else
                    return substr($this->url, 0, $p);
            }
            else
                return $this->url;
        }
        
    
        /**
         * Accesses the query string
         */
        public function getQueryString()
        {
            return $_SERVER['QUERY_STRING'];
        }
        
    
        /**
         * Accesses the URL token on specified position
         * @param integer $position URL token position
         * @return string URL token if $_position valid, empty string otherwise
         */
        public function getUrlToken($_position)
        {
            $tokens = explode('/', $this->url);
            return array_key_exists($_position, $tokens) ? $tokens[$_position] : '';
        }
        
        
        /**
         * Accesses the method
         * @return string Request method
         */
        public function getMethod() { return $this->method; }
        
        
        /**
         * Accesses the referrer
         * @return string Referrer
         */
        public function getReferrer()
        {
            return $this->referrer;
        }
        
        
        /**
         * Tells if parameter with specified key exists
         * @param string $_key Parameter key
         * @return boolean True if parameter exists, false otherwise
         */
        public function paramExists($_key)
        {
            return array_key_exists($_key, $this->params);
        }
        
        
        /**
         * Accesses the parameter value
         * @param string $_key Parameter key
         * @return string Parameter value
         */
        public function getParamValue($_key)
        {
            return $this->params[$_key];
        }
        
        
        /**
         * Accesses the parameter value by key if it exists
         * @param string $_key Parameter key
         * @param mixed $_defaultValue Default parameter value
         * @return mixed Parameter value if it exists, $_defaultValue otherwise
         */
        public function getParamValueIfExists($_key, $_defaultValue = '')
        {
            return $this->paramExists($_key) ? $this->getParamValue($_key) : $_defaultValue;
        }
        
        
        /**
         * Accesses the params
         */
        public function getParams() { return $this->params; }
    
    }

?><file_sep><?php
    
    /**
     * Viewer class file.
     *
     
     */
    
    
    /**
     * Viewer
     *
     
     */
    class Viewer
    {
        
        /**
         * Renders model with specified view
         * @param AbstractModel $_model Data model to be rendered
         * @param string $_viewRef View reference in form of <module_name>.<view_name>
         * @param array $_params Additional optional parameters
         */
        static public function render($_model, $_viewRef, array $_params = array())
        {
            list ($moduleName, $viewName) = explode('.', $_viewRef);
            require(MODULES_DIR_PATH.$moduleName.'/views/'.$viewName.'.htm');
        }
        
        
        /**
         * Renders model with specified XML view
         * @param string        $_resolvedViewName View name in form of <module_name>.<view_name>
         * @param AbstractModel $_model            Data model to be rendered
         * @param array         $_params           Additional parameters
         */
        static public function renderXml($_resolvedViewName, $_model, array $_params = array())
        {
            list ($moduleName, $viewName) = explode('.', $_resolvedViewName);
            echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";
            require(DOCUMENT_ROOT.MODULES_PATH.$moduleName.'/'.VIEWS_PATH.$viewName.'.xml');
        }
        
        
        /**
         * Resolves URL
         * @param $_unresolvedUrl Unresolved URL
         * @return string Resolved URL
         */
        static public function resolveUrl($_unresolvedUrl)
        {
            //return HTTP_HOSTNAME.(MULTILINGUAL ? $router->getLang().'/' : '').$_unresolvedUrl;
            return HTTP_HOSTNAME.SITE_PATH.$_unresolvedUrl;
        }
        
        
        /**
         * Resolves style (css-file) URL
         * @param $_styleRef Style reference in form of <module_name>.<style_name>
         * @return string Resolved style (css-file) URL
         */
        static public function resolveStyleUrl($_styleRef)
        {
            list ($moduleName, $styleName) = explode('.', $_styleRef);
            return MODULES_DIR_URL.$moduleName.'/styles/'.$styleName.'.css';
        }
        
        
        /**
         * Resolves script (js-file) URL
         * @param $_scriptRef Script reference in form of <module_name>.<script_name>
         * @return string Resolved script (js-file) URL
         */
        static public function resolveScriptUrl($_scriptRef)
        {
            list ($moduleName, $scriptName) = explode('.', $_scriptRef);
            return MODULES_DIR_URL.$moduleName.'/scripts/'.$scriptName.'.js';
        }
        
        
        /**
         * Resolves plugin script (js-file) URL
         * @param $_scriptRef Script reference
         * @return string Resolved script (js-file) URL
         */
        static public function resolvePluginScriptUrl($_scriptRef)
        {
            list ($pluginName, $scriptName) = explode('.', $_scriptRef);
            return PLUGINS_DIR_URL.$pluginName.'/'.$scriptName.'.js';
        }
        
        
        /**
         * Resolves plugin style (css-file) URL
         * @param $_styleRef Style reference
         * @return string Resolved style (css-file) URL
         */
        static public function resolvePluginStyleUrl($_styleRef)
        {
            list ($pluginName, $styleName) = explode('.', $_styleRef);
            return PLUGINS_DIR_URL.$pluginName.'/'.$styleName.'.css';
        }
        
    }
     
     
?><file_sep><?php
 
    // Load abstract action
    ClassLoader::loadAsyncActionClass('basic.abstract');
    

    class Googlemaps_GetUser_AsyncAction extends Basic_Abstract_AsyncAction
    {
        
        /**
         * Performs the action
         */
        public function perform($_domainId = null, array $_params = array())
        {
            $mySql = Application::getService('basic.mysqlmanager');
			// Extract inputs
            $id = $this->_getString('id', $_params, false);
            
            $user = $mySql->getRecord('google_maps_users', array('id' => $id));
            
            $this->data['user'] = $user;
            
        }
    }
        

?><file_sep><?php

    
    abstract class Basic_Abstract_AsyncAction
    {
    
        /**
         * @var array Data
         */
        protected $data = array();
        
        
        /**
         * @var array Errors
         */
        protected $errors = array();
        
    
        /**
         * @var string Redirect URL
         */
        protected $redirectUrl = null;
        
    
        /**
         * Performs the action
         * @param Request Request object
         */
        abstract public function perform($_domainId = null, array $_params = array());
        
        
        /**
         * Accesses the data
         * @return array Data
         */
        public function getData() { return $this->data; }
        
        
        /**
         * Accesses the errors
         * @return array Errors
         */
        public function getErrors() { return $this->errors; }
        
        
        /**
         * Accesses the redirect URL
         * @return string Redirect URL
         */
        public function getRedirectUrl() { return $this->redirectUrl; }
        
        
        /**
         */
        protected function getFromArray($_key, $_array, $_default = null)
        {
            return isset($_array[$_key]) ? $_array[$_key] : $_default;
        }
        
        
        /**
         * Sends mail
         */
        public function mail($_to, $_subject, $_message, $_headers = null)
        {
            if (MAIL) mail($_to, $_subject, $_message, $_headers);
            if (LOG_MAIL_TO_FILE) $this->logMail($_to, $_subject, $_message, $_headers);
        }
        
        
        /**
         * Logs mail data to a file
         */
        public function logMail($_to, $_subject, $_message, $_headers, $_attachment = array())
        {
            $logFilename = 'logs/mail.log';
            $logFile = fopen($logFilename, 'ab');
            fwrite($logFile, "\r\n".date('Y-m-d H:i:s')."\r\n"."\r\n");
            fwrite($logFile, 'Headers: '.$_headers."\r\n");
            if (is_array($_to))
                fwrite($logFile, 'To: '.implode(',', $_to)."\r\n");
            else
                fwrite($logFile, 'To: '.$_to."\r\n");
            fwrite($logFile, 'Subject: '.$_subject."\r\n");
            if (count($_attachment)) fwrite($logFile, 'Attachment: \''.implode('\', \'', $_attachment).'\''."\r\n");
            fwrite($logFile, 'Message: '."\r\n".$_message."\r\n"."\r\n");
            fclose($logFile);
        }
        
        
        /**
         * Add tags around all hyperlinks in $string
         */
        public function plainToHtmlHyperlinks($_string)
        {
            // $result = preg_replace(
                // "/(?<![\>https?:\/\/|href=\"'])(?<http>(https?:[\/][\/]|www\.)([a-z]|[A-Z]|[0-9]|[\-\/.&?=_]|[~])*)/",
                // "<a href=\"$1\" target=\"_blank\">$1</a>",
                // $_string
            // );
            $result = preg_replace(
                "/(?<![\>https?:\/\/|href=\"'])(?<http>(https?:[\/][\/]|www\.)([a-z]|[A-Z]|[0-9]|[\-\/.&?=_]|[~])*)/",
                "$1",
                $_string
            );
            if (substr($result, 0, 3) == 'www')
            {
                $result = 'http://'.$result;
                $result = "<a href=\"$result\" target=\"_blank\">$result</a>";
            }
            return $result;
        }

        
        /**
         * Add tags around all email addresses in $string
         */
        public function plainToHtmlEmails($_string)
        {
            return preg_replace(
                "/([^@\s]*@[^@\s]*\.[^@\s]*)/",
                "<a href=\"mailto:$1\">$1</a>",
                $_string
            );
        }

        
        /**
         * Replace all line feeds with HTML '<br />' tag
         */
        public function plainToHtmlLineFeeds($_string)
        {
            $tmp = $_string;
            $tmp = str_replace("\r\n", '<br />', $tmp);
            $tmp = str_replace("\n", '<br />', $tmp);
            $tmp = str_replace("\r", '<br />', $tmp);
            return $tmp;
        }    
        
        
        /**
         * Removes all spaces and replaces them with the specified delimiter
         */
        public function removeSpaces($_emails, $_delimiter = ',')
        {
            $emails = str_replace(array("\r\n", "\n", "\r", "\t"), ' ', $_emails);
            do { $emails = str_replace('  ', ' ', $emails, $c); } while ($c);
            $emails = trim($emails);
            $emails = str_replace(' ', $_delimiter, $emails);
            return $emails;
        }
        
        
        /**
         * Returns current datetime
         */
        public function dateNow()
        {
            return date('Y-m-d H:i:s');
        }
        
        
        /**
         * Exports data to the xls-file
         */
        protected function exportToXls($_exportFilename, $_fields, $_records = array())
        {
            // Create PHPExcel object
            require_once(LIBS_DIR_PATH.'PHPExcel-1.7.9/PHPExcel.php');
            $objPHPExcel = new PHPExcel();
            $objPHPExcel->getProperties()->setCreator('VOS Backend Application');
            $activeSheet = $objPHPExcel->setActiveSheetIndex(0);


            // Put fields
            for ($i = 0, $col = 'A'; $i < count($_fields); ++$i, ++$col)
                $activeSheet->setCellValue($col.'1', $_fields[$i]);
             
            
            // Put records
            $row = 1;
            foreach ($_records as $record)
            {
                $row += 1;
                $col = 'A';
                foreach ($record as $cell)
                    $activeSheet->setCellValue($col++.$row, $cell);
            }


            // Dump data
            $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
            $objWriter->save($_exportFilename);
        }
        
        
        /**
         * Exports data as xls-file to a browser
         */
        protected function exportAsXlsToBrowser($_exportFilename, $_fields, $_records = array())
        {
            set_time_limit(0);
            ini_set('memory_limit', '512M');
            
            // Set header
            header('Content-Type: application/vnd.ms-excel');
            header('Content-Disposition: attachment;filename="'.$_exportFilename.'"');
            header('Cache-Control: max-age=0');
            
            // If you're serving to IE 9, then the following may be needed
            header('Cache-Control: max-age=1');

            // If you're serving to IE over SSL, then the following may be needed
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
            header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // always modified
            header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
            header('Pragma: public'); // HTTP/1.0
            
            
            // Send data to browser
            $this->exportToXls('php://output', $_fields, $_records);
        }
        
        
        /**
         * Reads xls-file
         */
        protected function readFromXls($_filename, $_params = array())
        {
            // This is due to PHPExcel produces PHP Notices and Warnings if provided file is cvs or other non-valid type
            $errorReporting = error_reporting(E_ERROR);
            
            
            // Extract params
            $startRowIndex = $this->getFromArray('startRowIndex', $_params, 1);
            $columnsNumber = $this->getFromArray('columnsNumber', $_params, 3);
            
            
            // Read file
            require_once(LIBS_DIR_PATH.'PHPExcel-1.7.9/PHPExcel.php');
            $phpExcelInput = PHPExcel_IOFactory::load($_filename);
            $phpExcelInputSheet = $phpExcelInput->getActiveSheet();
            $records = array();
            for ($rowIndex = $startRowIndex; $rowIndex <= $phpExcelInputSheet->getHighestRow(); ++$rowIndex)
            {
                $record = array();
                $empty = true;
                for ($columnIndex = 0; $columnIndex < $columnsNumber; ++$columnIndex)
                {
                    $cell = trim($phpExcelInputSheet->getCellByColumnAndRow($columnIndex, $rowIndex)->getValue());
                    $record[] = $cell;
                    $empty = $empty && empty($cell);
                }
                if (!$empty)
                $records[] = $record;
            }
            
            
            error_reporting($errorReporting);
            return $records;
        }
        
        
        protected function getMailTextFromString($_messageTemplate, $_lookups)
        {
            // Replace placeholders with corresponsing values
            $placeholders = array(); $values = array();
            $matches = null;
            preg_match_all('/<!!(.+)!!>/U', $_messageTemplate, $matches);
            for ($i = 0; $i < count($matches[0]); ++$i)
            {
                $placeholder = $matches[0][$i];
                if (!in_array($placeholder, $placeholders))
                {
                    $placeholders[] = $placeholder;
                    $ref = $matches[1][$i];
                    
                    unset($internalLookup);
                    if ($ref{0} == '{') // Internal lookup
                    {
                        $tmp = trim($ref, ' ');
                        $tmp = substr($tmp, 1, strlen($tmp)-2);
                        list($ref, $lookupStr) = explode(':', $tmp, 2);
                        $lookupStr = trim($lookupStr, ' ');
                        $internalLookup = json_decode($lookupStr, true);
                    }
                    
                    $value = null;
                    if (strpos($ref, '.'))
                        list ($lookupKey, $propertyKey) = explode('.', $ref);
                    else
                        list ($lookupKey, $propertyKey) = array('', $ref);
                    if ($lookupKey == 'appConfig')
                        $value = constant($propertyKey);
                    elseif (isset($_lookups[$lookupKey][$propertyKey]))
                        $value = $_lookups[$lookupKey][$propertyKey];
                    else    
                        $value = '';
                    if (isset($internalLookup))
                        $value = $internalLookup[$value];
                    $values[] = $value;
                }
            }
            return str_replace($placeholders, $values, $_messageTemplate);
        }
        
        
        protected function verifyCaptcha(array $_params = array())
        {
            $sessionCaptcha = $this->getFromArray('captcha', $_SESSION, null);
            if (empty($sessionCaptcha))
            {
                $this->errors['captcha'] = 'Verification code has not been generated.';
                throw new AsyncActionException('Verification code has not been generated.');
            }
            $captcha = $this->getFromArray('captcha', $_params, null);
            if (empty($captcha))
            {
                $this->errors['captcha'] = 'Please, enter verification code.';
                throw new AsyncActionException('Please, enter verification code.');
            }
            if ($sessionCaptcha != $captcha)
            {
                $this->errors['captcha'] = 'You have entered the code incorrectly - please try again.';
                throw new AsyncActionException('You have entered the code incorrectly - please try again.');
            }
        }
        
        
        protected function _getPositiveInteger($_key, $_params, $_required = false, $_default = null)
        {
            $value = isset($_params[$_key]) ? $_params[$_key] : $_default;
            if (is_null($value))
            {
                if ($_required)
                    throw new AsyncActionException('Missing required argument: \''.$_key.'\'.');
            }
            else // not null
            {
                if (filter_var($value, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1))) === false)
                    throw new AsyncActionException('Invalid argument (\''.$_key.'\'). Must be positive integer.');
            }
            return $value;
        }
        
        
        protected function _getPositiveFloat($_key, $_params, $_required = false, $_default = null)
        {
            $value = isset($_params[$_key]) ? $_params[$_key] : $_default;
            if (is_null($value))
            {
                if ($_required)
                    throw new AsyncActionException('Missing required argument: \''.$_key.'\'.');
            }
            else // not null
            {
                if (filter_var($value, FILTER_VALIDATE_FLOAT, array('options' => array('min_range' => 1))) === false)
                    throw new AsyncActionException('Invalid argument (\''.$_key.'\'). Must be positive float.');
            }
            return $value;
        }
        
        
        protected function _getNonNegativeInteger($_key, $_params, $_required = false, $_default = null)
        {
            $value = isset($_params[$_key]) ? $_params[$_key] : $_default;
            if (is_null($value))
            {
                if ($_required)
                    throw new AsyncActionException('Missing required argument: \''.$_key.'\'.');
            }
            else // not null
            {
                if (filter_var($value, FILTER_VALIDATE_INT, array('options' => array('min_range' => 0))) === false)
                    throw new AsyncActionException('Invalid argument (\''.$_key.'\'). Must be positive integer.');
            }
            return $value;
        }
        
        
        protected function _getBoolean($_key, $_params, $_required = false, $_default = null)
        {
            $value = isset($_params[$_key]) ? $_params[$_key] : $_default;
            if (is_null($value))
            {
                if ($_required)
                    throw new AsyncActionException('Missing required argument: \''.$_key.'\'.');
            }
            else // not null
            {
                if (filter_var($value, FILTER_VALIDATE_INT, array('options' => array('min_range' => 0, 'max_range' => 1))) === false)
                    throw new AsyncActionException('Invalid argument (\''.$_key.'\'). Must be boolean (0 or 1).');
            }
            return $value;
        }
        
        
        protected function _getString($_key, $_params, $_required = false, $_default = null, $_options = null)
        {
            $label = isset($_options['label']) ? $_options['label'] : $_key;
            $value = isset($_params[$_key]) ? $_params[$_key] : $_default;
            if (!isset($_options['no_trim'])) $value = trim($value);
            if ($_required  and  (is_null($value) or $value == '')) throw new AsyncActionException($label.' is required.');
            if (isset($_options['max_length']) and strlen($value) > $_options['max_length']) throw new AsyncActionException($label.' is too long.');
            return $value;
        }
        
        
        protected function _getArray($_key, $_params, $_required = false, $_default = null)
        {
            $value = isset($_params[$_key]) ? $_params[$_key] : $_default;
            if (is_null($value))
            {
                if ($_required)
                    throw new AsyncActionException('Missing required argument: \''.$_key.'\'.');
            }
            else // not null
            {
                if (!is_array($value))
                    throw new AsyncActionException('Invalid argument (\''.$_key.'\'). Must be array.');
            }
            return $value;
        }

        
        protected function _deleteFile($_filePath)
        {
            if (file_exists($_filePath)) unlink($_filePath);
        }
        
        
        /**
         * Debug purpose
         */
        protected function _varDumpExit($_arg)
        {
            echo '<pre>'; var_dump($_arg); exit();
        }

        
        /**
         * Get image size
         */
        protected function _getImageSize($_src = false)
        {
            $size = array('width' => 200, 'height' => null); // Default image size
            if ($_src)
            {
                $imageFilename = '.'.$_src;
                if (file_exists($imageFilename))
                {
                    $tmp = getimagesize($imageFilename);
                    if ($tmp) $size = array('width' => $tmp[0], 'height' => $tmp[1]);
                }
            }
            return $size;
        }

        /**
         * create Thumb from video
         */

        protected function _createThumb($src, $dest, $width, $height, $quality) {
            if (!file_exists($src)) {
                //echo('Source file isn\'t exists');
                return false;
            }

            $size = getimagesize($src);

            if ($size === false) {
                //echo('Cannot get image info about source');
                return false;
            }

            $format = strtolower(substr($size['mime'], strpos($size['mime'], '/')+1));
            $icfunc = "imagecreatefrom" . $format;
            if (!function_exists($icfunc)) {
                echo('Does not exists the function in GD to create image - "'. $icfunc. '"');
                return false;
            }

            $x_ratio = $width / $size[0];
            $y_ratio = $height / $size[1];

            $ratio       = min($x_ratio, $y_ratio);
            $use_x_ratio = ($x_ratio == $ratio);

            $new_width   = $use_x_ratio  ? $width  : floor($size[0] * $ratio);
            $new_height  = !$use_x_ratio ? $height : floor($size[1] * $ratio);

            $isrc = $icfunc($src);
            $idest = imagecreatetruecolor($new_width, $new_height);

            //    imagefill($idest, 0, 0, $rgb);
            imagecopyresampled($idest, $isrc, 0, 0, 0, 0, $new_width, $new_height, $size[0], $size[1]);

            imagejpeg($idest, $dest, $quality);

            imagedestroy($isrc);
            imagedestroy($idest);

            return array('width' => $new_width, 'height' => $new_height);
        }

    }

?><file_sep><?php

    /**
     * Basic_Abstract_Model class file.
     
     */
    
    
    /**
     * Abstract model
     *
    
     */
    abstract class Basic_Abstract_Model
    {
    
        /**
         * Constructor
         * @param array $_params Parameters
         */
        public function __construct(array $_params = array())
        {
            foreach ($_params as $key => $value)
            {
                if (!property_exists($this, $key))
                    throw new Exception('Model property \''.get_class($this).'::'.$key.'\' does not exists.');
                $this->$key = $value;
            }
        }
    
    }

?><file_sep><?php

    /**
     * Class loader
     *
     
     */
    final class ClassLoader
    {
        
        /**
         * Loads core class
         * @param string $_className Class name to be loaded
         */
        public static function loadCoreClass($_className)
        {
            $filename = CORE_DIR_PATH.$_className.'.php';
            if (file_exists($filename))
                require_once($filename);
            else
                throw new Exception('Core class does not exists (\''.$filename.'\').');
        }
        
        
        /**
         * Loads builder class
         * @param string $_builderRef Builder reference in form of <module_key>.<builder_key>
         */
        public static function loadBuilderClass($_builderRef)
        {
            list($moduleKey, $builderKey) = explode('.', $_builderRef);
            $filename = MODULES_DIR_PATH.$moduleKey.'/builders/'.$builderKey.'.php';
            if (!file_exists($filename))
                throw new Exception('Failed to load builder class (\''.$_builderRef.'\').');
            require_once($filename);
        }
        
        
        /**
         * Loads service class
         * @param string $_serviceRef Service reference in form of <module_key>.<builder_key>
         */
        public static function loadServiceClass($_serviceRef)
        {
            list($moduleKey, $serviceKey) = explode('.', $_serviceRef);
            $filename = MODULES_DIR_PATH.$moduleKey.'/services/'.$serviceKey.'.php';
            if (!file_exists($filename))
                throw new Exception('Failed to load service class (\''.$_serviceRef.'\').');
            require_once($filename);
        }
        
        
        /**
         * Loads model class
         * @param string $_modelRef Model reference in form of <module_key>.<model_key>
         */
        public static function loadModelClass($_modelRef)
        {
            list($moduleKey, $modelKey) = explode('.', $_modelRef);
            $filename = MODULES_DIR_PATH.$moduleKey.'/models/'.$modelKey.'.php';
            if (!file_exists($filename))
                throw new Exception('Failed to load model class (\''.$_modelRef.'\').');
            require_once($filename);
        }
        
        
        /**
         * Loads async action class
         * @param string $_actionRef Action reference in form of <module_key>.<action_key>
         */
        public static function loadAsyncActionClass($_actionRef)
        {
            list($moduleKey, $actionKey) = explode('.', $_actionRef);
            $filename = MODULES_DIR_PATH.$moduleKey.'/async/'.$actionKey.'.php';
            if (!file_exists($filename))
                throw new Exception('Failed to load async action class (\''.$_actionRef.'\').');
            require_once($filename);
        }
        
    }

?><file_sep><?php
 
    // Load abstract action
    ClassLoader::loadAsyncActionClass('basic.abstract');
    

    class Googlemaps_CreateUser_AsyncAction extends Basic_Abstract_AsyncAction
    {
        
        /**
         * Performs the action
         */
        public function perform($_domainId = null, array $_params = array())
        {
            $mySql = Application::getService('basic.mysqlmanager');
			// Extract inputs
            $errorFlag = false;
            $errormessagearray = array();

            $data = $this->_getArray('data', $_params, true);
            $nameStr = $data['name'];
            $nameStr = trim($nameStr);
            $nameStr = preg_replace("/\s{2,}/"," ",$nameStr);
            $nameArr = preg_split('/ /', $nameStr);
            foreach ($nameArr as $key => $name) {
                $nameValid = preg_match('/^[A-Za-zА-Яа-я]+$/msiu', $name);
                if (!$nameValid) {
                    $errorFlag = true;
                    $errormessagearray['name'] = 'Vvedite korrektno name!';
                }
            }
            $addressStr = trim($data['address']);
            $addressStr = str_replace(',', ' ', $addressStr);
            $addressStr = preg_replace("/\s{2,}/"," ",$addressStr);
            
            $addressArr = preg_split('/ /', $addressStr);
            $addressArrLenght = count($addressArr);
            $index = $addressArr[0];
            $country = $addressArr[1];
            // var_dump($country);exit();
            $city = $addressArr[2];
            foreach ($addressArr as $key2 => $value2) {
                if (($key2>2) and ($key2<$addressArrLenght-1)) {
                    $street.= ' '.$value2;
                }
            }
            $street = trim($street);
            $house = $addressArr[$addressArrLenght-1];
            $indexValid = preg_match("/[0-9]{5}/i", $index);
            if (!$indexValid) {
                $errorFlag = true;
                $errormessagearray['address'] = 'Vvedite korrektno index!';
            }
            $countryValid = preg_match('/^[A-Za-zА-Яа-я]+$/msiu',$country);
            if (!$countryValid) {
                $errorFlag = true;
                $errormessagearray['address'] = 'Vvedite korrektno country!';
            }
            $cityValid = preg_match('/^[A-Za-zА-Яа-я]+$/msiu', $city);
            if (!$cityValid) {
                $errorFlag = true;
                $errormessagearray['address'] = 'Vvedite korrektno city!';
            }

            $stretValid = preg_match('/^[A-Za-zА-ЯЁа-яё0-9\s]+/msi', $street);
            if (!$stretValid) {
                $errorFlag = true;
                $errormessagearray['address'] = 'Vvedite korrektno street!';
            }
            $street_geo = str_replace(' ', '+', $street);
            if(preg_match('/\//i', $house)) {
                $houseArr = explode("/", $house);
                foreach ($houseArr as $key => $value) {
                    $houseValid = preg_match("/^[a-zа-яё\d]{1}[a-zа-яё\d\s]*[a-zа-яё\d]{1}$/i", $value);
                    if (!$houseValid) {
                        $errorFlag = true;
                        $errormessagearray['address'] = 'Vvedite korrektno house!';
                    }
                }
            }else{
                $houseValid = preg_match('|^[A-Z0-9]+$|i', $house);
                if (!$houseValid) {
                    $errorFlag = true;
                    $errormessagearray['address'] = 'Vvedite korrektno house!';
                }
            }
            $address_geo = $country.'+'.$city.'+'.$street_geo.'+'.$house;
            
            $user_api_key = '<KEY>'; //GOOGLE API KEY
            $xml = simplexml_load_file('http://maps.google.com/maps/api/geocode/xml?address='.$address_geo.'&sensor=false');
            $json_string = json_encode($xml);    
            $result_array = json_decode($json_string, TRUE);
            $status = $xml->status;
            // print_r($xml);
            if ($status == 'OK') {
                $lat = $result_array['result']['geometry']['location']['lat'];
                $lng = $result_array['result']['geometry']['location']['lng'];
                
                $data['lat'] = $lat;
                $data['lng'] = $lng;
                
            }else{
                $errorFlag = true;
                $errormessagearray['address'] = 'Can`t get coordinats! Iput correct address!';
            }
            
            $json = json_encode($errormessagearray);
            if ($errorFlag) {
                $errorFlag = false;
                throw new AsyncActionException($json);
            }
            
            $mySql->insert('google_maps_users', array('name'=>$nameStr,'index'=>$index, 'country'=>$country, 'city'=>$city,
                'street'=>$street,'house'=>$house, 'lat'=>$lat,'lng'=>$lng));
            
            $userid = $mySql->getInsertId();
            
            $user = $mySql->getRecord('google_maps_users', array('id' => $userid));
            
            $this->data['user'] = $user;
            
        }
    }
        

?><file_sep><?php

    define('DEBUG', true);
    define('LF', "\n");
    
    define('MAIN_DOMAIN', 'googlemaps.local');
    define('HTTP_HOSTNAME', ((isset($_SERVER['HTTPS']) and $_SERVER['HTTPS']=='on')?'https':'http').'://'.$_SERVER['HTTP_HOST'].'/');
    define('SITE_PATH', substr($_SERVER['SCRIPT_NAME'], 1, strrpos($_SERVER['SCRIPT_NAME'], '/')));
    define('DOCUMENT_ROOT', $_SERVER['DOCUMENT_ROOT'].'/'.SITE_PATH);

    define('APP_DIR_PATH', DOCUMENT_ROOT.APP_DIR_NAME.'/');
    define('CORE_DIR_PATH', APP_DIR_PATH.'core/');
    define('MODULES_DIR_PATH', APP_DIR_PATH.'modules/');
    define('PLUGINS_DIR_PATH', DOCUMENT_ROOT.'plugins/');
    define('LIBS_DIR_PATH', DOCUMENT_ROOT.'libs/');
    define('LOGS_DIR_PATH', DOCUMENT_ROOT.'logs/');
    define('TMP_DIR_PATH', DOCUMENT_ROOT.'tmp/');
    define('UPLOADS_DIR_PATH', DOCUMENT_ROOT.'uploads/');
    define('FFMPEG_DIR', '/usr/local/bin/ffmpeg');
    
    define('APP_DIR_URL', HTTP_HOSTNAME.SITE_PATH.APP_DIR_NAME.'/');
    define('MODULES_DIR_URL', APP_DIR_URL.'modules/');
    define('PLUGINS_DIR_URL', APP_DIR_URL.'plugins/');
    define('ADMIN_PANEL_URL', APP_DIR_URL.'backend/');
    define('LOGS_DIR_URL', APP_DIR_URL.'logs/');
    define('UPLOADS_DIR_URL', HTTP_HOSTNAME.SITE_PATH.'uploads/');
    
    define('MYSQL_HOSTNAME', 'localhost');
    define('MYSQL_USERNAME', 'horses');
    define('MYSQL_PASSWORD', '<PASSWORD>');
    define('MYSQL_DBNAME', 'horses');
    define('MYSQL_TIMEZONE', '+2:00');
    
    define('MULTILINGUAL', true);
    define('ML', MULTILINGUAL);
    define('DEFAULT_LANG', 'en');
    define('DICS_PATH', 'dics/');
    
    // Regular expressions
    define('RE_EMAIL', '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/i');
    define('RE_DATE', '/^\d{4}-\d{2}-\d{2}$/');

    define('SALT', '6347fujdkjfgjdr879457848');
    define('STATUS_ACTIVE', 'active');
    define('STATUS_NEW', 'new');
    define('STATUS_UNCONFIRMED', 'unconfirmed');
    define('REGISTRATIONS_PER_DAY', 4);
    
    define('VIDEOS_V2_PATH', '/uploads/videos_v2/');
    define('PHOTOS_ORIGINAL_PATH', 'uploads/photos/original/');
    define('PHOTOS_THUMBS_PATH', 'uploads/photos/thumbs/');
    define('PHOTOS_LARGE_PATH', 'uploads/photos/large/');
    define('PHOTOS_MEDIUM_PATH', 'uploads/photos/medium/');

    
?><file_sep><?php

    /**
     * Basic_HttpResponse_Builder class file.
     *
     
     */
    
    
    // Load required classes
    ClassLoader::loadCoreClass('notfoundexception');
    ClassLoader::loadBuilderClass('basic.abstract');
    ClassLoader::loadModelClass('basic.htmlresponse');
    
    
    /**
     * HTML response builder
     *
     
     */
    class Basic_HttpResponse_Builder extends Basic_Abstract_Builder
    {
        public function getByRequest(Request $_request = NULL)
        {
            $response = new Basic_HtmlResponse_Model();
            
            try
            {
                // Extract request URL
                $url = $_request->getUrl();
                
                
                // Extract first URL token
                $firstUrlToken = ($p = strpos($url, '/')) ? substr($url, 0, $p) : substr($url, 0);
                
                
                if ($firstUrlToken == 'async') // JSON (asynchronous) request
                {
                    // Load async action exception class
                    ClassLoader::loadCoreClass('asyncactionexception');
            
            
                    // Create async action object
                    $restUrl = ($t = substr($url, strlen($firstUrlToken)+1)) ? $t : '';
                    $asyncActionRef = ($p = strpos($restUrl, '/')) ? substr($restUrl, 0, $p) : substr($restUrl, 0);
                    ClassLoader::loadAsyncActionClass($asyncActionRef);
                    list($moduleKey, $asyncActionKey) = explode('.', $asyncActionRef);
                    $asyncActionClassName = $moduleKey.'_'.$asyncActionKey.'_AsyncAction';
                    $action = new $asyncActionClassName();
                    
                    
                    // Set response properties
                    $response->messageBodyFormat = $response->dataType = 'json';
                    if ($asyncActionRef == 'basic.fileupload') $response->dataType = 'html'; //! Old IE uses iframe for async file upload
            
                    // Response success by default
                    $response->messageBody = new stdClass();
                    $response->messageBody->success = true;
                    $response->messageBody->message = 'OK';
                    
                    
                    try
                    {
                        //! Ensure action privileges
                        
                        
                        // Perform the action
                        $action->perform($_request->getDomainId(), $_request->getParams());
                    
                        
                        // Set the response data
                        $data = $action->getData();
                        if (count($data)) $response->messageBody->data = $data;
                    }
                    
                    catch (AsyncActionAuthException $e)
                    {
                        $response->messageBody->success = false;
                        $response->messageBody->auth = false;
                        $response->messageBody->message = 'You are not authorized to perform this action.';
                    }
                    
                    catch (AsyncActionSessionExpireException $e)
                    {
                        $response->messageBody->success = false;
                        $response->messageBody->expired = true;
                        $response->messageBody->message = 'Session has been expired.';
                    }
                    
                    catch (AsyncActionException $e)
                    {
                        $response->messageBody->success = false;
                        $response->messageBody->message = $e->getMessage();
                        
                        
                        // Set the response errors
                        $errors = $action->getErrors();
                        if (count($errors))
                            $response->messageBody->errors = $errors;
                    }
                }
                
                else // HTML request
                {
                    // Extract request URL
                    $url = $_request->getUrl();
                        
                        
                    // Skip site path
                    if (strlen(SITE_PATH))
                    {
                        $skipUrlToken = ($p = strpos($url, '/')) ? substr($url, 0, $p) : substr($url, 0);
                        $url = ($t = substr($url, strlen($skipUrlToken)+1)) ? $t : '';
                    }
                    
                    
                    // Extract first URL token
                    $firstUrlToken = ($p = strpos($url, '/')) ? substr($url, 0, $p) : substr($url, 0);
                    
                    
                    if ($firstUrlToken == 'backend')
                    {
                        $response->messageBody = new ModelViewPair(
                            Application::getBuilder('backend.htmldocument')->getByRequest($_request),
                            'backend.htmldocument'
                        );
                    }
                    else
                    {
                        $response->messageBody = new ModelViewPair(
                            Application::getBuilder('main.htmldocument')->getByRequest($_request),
                            'main.htmldocument'
                        );
                    }
                }
            }
            
            catch (NotFoundException $e)
            {
                $response->statusCode = 404;
                $response->dataType = 'html';
                $response->messageBody = new ModelViewPair(
                    null,
                    'basic.notfoundhtmldocument'
                );
            }
            
            catch (Exception $e)
            {
                echo '<h1>Exception</h1>';
                echo '<p>'.$e->getMessage().'</p>';
                echo '<pre>'.$e->getTraceAsString().'</pre>';
                exit();
                // $response->statusCode = 500;
                // $response->dataType = 'html';
                // $response->model = GeneratorsFactory::getGenerator('basic.exceptionhtmldocument')->get(array('exception' => $e));
                // $response->view = 'basic.exceptionhtmldocument';
            }
            
            return $response;
        }
    }

?><file_sep><?php

    /**
     * Application class file.
     
     */
    
    
    // Load core classes
    ClassLoader::loadCoreClass('request');
    ClassLoader::loadCoreClass('viewer');
    
    
    /**
     * Application
     *
     */
    class Application
    {
    
        /**
         * @var array Builders collection
         */
        private static $builders = array();
        
        
        /**
         * @var array Services collection
         */
        private static $services = array();
        
        
        /**
         * @var array User (null stand for guest)
         */
        // private static $user = null;
        
        
        /**
         * @var Dictionary Dictionary
         */
        // private static $dic = null;
        
        
        /**
         * @var array Languages set (for ML mode only)
         */
        // private static $langs = array('ru' => 'Русский', 'en' => 'English');
        
        
        /**
         * @var string Current language
         */
        // private static $lang = DEFAULT_LANG;
        
        
        /**
         * @var array Application settings
         */
        // private static $settings = array();
        
        
        /**
         * @var array Action privileges
         */
        // private static $actionPrivileges = array
        // (
            // 'login' => array('allow' => 0),
            // 'logout' => array('allow' => 0),
            // 'create' => array('allow' => array(UR_ADMIN)),
            // 'update' => array('allow' => array(UR_ADMIN)),
            // 'delete' => array('allow' => array(UR_ADMIN)),
            // 'moveup' => array('allow' => array(UR_ADMIN)),
            // 'movedown' => array('allow' => array(UR_ADMIN)),
            // 'delete' => array('allow' => array(UR_ADMIN)),
            // 'password' => array('allow' => array(UR_ADMIN)),
        // );

        
        /**
         * Prevent direct object creation
         */
        private function __construct() {}
        
        
        /**
         * Prevent to clone the instance
         */
        private function __clone() {}
        
        
        /**
         * Application runner
         */
        public static function run()
        {
            try
            {
                // Start a session
                session_start();
                
                
                // Init MySQL service
                $mySqlManager = Application::getService('basic.mysqlmanager');
                $mySqlManager->connect(MYSQL_HOSTNAME, MYSQL_USERNAME, MYSQL_PASSWORD, MYSQL_DBNAME);
                
                
                // Create request object
                $request = new Request($_SERVER, $_REQUEST);
                
                
                // Build HTML response
                $response = Application::getBuilder('basic.httpresponse')->getByRequest($request);
                
                
                // Send status line
                header('HTTP/1.1 '.$response->statusCode);
                
                
                // -- Send headers --
                
                // Send 'Content-Type' header
                if ($response->dataType == 'html') header('Content-Type: text/html; charset=utf-8');
                elseif ($response->dataType == 'json') header('Content-Type: application/json; charset=utf-8');
                // elseif ($response->dataType == 'xml') header('Content-Type: application/xml; charset=utf-8');
                else header('Content-Type: text/html; charset=utf-8'); // default

                // Send 'Location' header if any
                if (!is_null($response->location)) header('Location: '.$response->location);
                    
                
                // Send message body
                if ($response->messageBodyFormat == 'html')
                    Viewer::render($response->messageBody, 'main.htmldocument');
                elseif ($response->messageBodyFormat == 'json') echo json_encode($response->messageBody);
                // elseif ($response->messageBodyFormat == 'xml')
                    // Viewer::renderXml($response->view, $response->model);
                else // default
                    Viewer::render($response->messageBody->view, $response->messageBody->model);
            }
            
            catch (Exception $e)
            {
                echo '<h1>Exception</h1>';
                echo '<p>'.$e->getMessage().'</p>';
                echo '<pre>'.$e->getTraceAsString().'</pre>';
                exit();
                // $response->statusCode = 500;
                // $response->dataType = 'html';
                // $response->model = GeneratorsFactory::getGenerator('basic.exceptionhtmldocument')->get(array('exception' => $e));
                // $response->view = 'basic.exceptionhtmldocument';
            }
        }


        /**
         * Accesses the builder
         * @var sting $_builderRef Builder reference in form of <module_key>.<builder_key>
         * @return AbstractBuilder Builder object
         */
        public static function getBuilder($_builderRef)
        {
            if (!array_key_exists($_builderRef, self::$builders))
            {
                ClassLoader::loadBuilderClass($_builderRef);
                list($moduleKey, $builderKey) = explode('.', $_builderRef);
                $builderClassName = $moduleKey.'_'.$builderKey.'_builder';
                self::$builders[$_builderRef] = new $builderClassName();
            }
            return self::$builders[$_builderRef];
        }


        /**
         * Accesses the service
         * @var sting $_serviceRef Service reference in form of <module_key>.<builder_key>
         * @return AbstractService Service object
         */
        public static function getService($_serviceRef)
        {
            if (!array_key_exists($_serviceRef, self::$services))
            {
                ClassLoader::loadServiceClass($_serviceRef);
                list($moduleKey, $serviceKey) = explode('.', $_serviceRef);
                $serviceClassName = $moduleKey.'_'.$serviceKey.'_service';
                self::$services[$_serviceRef] = new $serviceClassName();
            }
            return self::$services[$_serviceRef];
        }
        
        
        /**
         * Accesses the application user
         */
        // public static function getUser()
        // {
            // $user = null;
            // if (isset($_SESSION['user']))
            // {
                // $mySqlManager = self::getService('basic.mysqlmanager');
                // $user = $mySqlManager->select('*', 'users', array('id' => $_SESSION['user']['id']))->fetchAssoc();
            // }
            // return $user;
        // }
        
        
        /**
         * Tells if action is allowed for the specific user
         * @param string $actionKey Action key
         * @param integer $userRoleId User role ID or NULL (for non-authorized)
         */
        // public static function isActionAllowed($_actionKey, $_userRoleId)
        // {
            // if (array_key_exists($_actionKey, self::$actionPrivileges))
            // {
                // foreach (array_reverse(self::$actionPrivileges[$_actionKey]) as $accessType => $userRoleIds)
                // {
                    // if (is_array($userRoleIds) ? in_array($_userRoleId, $userRoleIds) : ($userRoleIds == 0  or  $_userRoleId == $userRoleIds))
                        // return $accessType == 'allow';
                // }
            // }
            // return false;
        // }
    
    }

?><file_sep><?php
    
    /**
     * NotFoundException class file.
     
     */
    
    
    /**
     * Not found exception
     *
     
     */
    class NotFoundException extends Exception {}
     
?><file_sep><?php
 
    // Load abstract action
    ClassLoader::loadAsyncActionClass('basic.abstract');
    

    class Googlemaps_DelUser_AsyncAction extends Basic_Abstract_AsyncAction
    {
        
        /**
         * Performs the action
         */
        public function perform($_domainId = null, array $_params = array())
        {
            $mySql = Application::getService('basic.mysqlmanager');
			// Extract inputs
            $id = $this->_getString('id', $_params, true);
            $mySql->delete('google_maps_users', array('id'=>$id));
            
            $this->data['success'] = true;
            
        }
    }
        

?><file_sep><?php

    /**
     * Basic_Abstract_Service class file.
     *
     
     */
    
    
    /**
     * Service exception
     */
    class ServiceException extends Exception {}
    
    
    /**
     * Abstract service
     *
    
     */
    abstract class Basic_Abstract_Service
    {
        /**
         * Returns current date and time as string
         */
        public function dateNow()
        {
            return date('Y-m-d H:i:s');
        }
    }

?><file_sep><?php

/**
 * Basic_MySqlManager_Service class file.
 *
 
 */


ClassLoader::loadServiceClass('basic.abstract');


class Basic_QueryBuilder_Service extends Basic_Abstract_Service
{

    public static function escape($value)
    {
        return '"' . mysql_real_escape_string($value) . '"';
    }

    public static function escapeKey($key, $table_name = false)
    {
        return '`' . $key . '`';
    }

    public static function buildQueryList($params = array())
    {
        foreach ($params as &$param) {
            if ($param === null) {
                $param = 'NULL';
            }
        }
        return ' (' . implode(',', $params) . ') ';
    }

    public static function buildQuery($query, $params = false, $row = false)
    {
        return $query . (self::buildQueryKeyEqualValue($params, true)) . ($row ? " LIMIT 1 " : "");
    }

    public static function buildQueryTable($table_name, $params = false)
    {
        return self::buildQueryTableColumn($table_name, false, $params);
    }

    public static function buildQueryTableColumn($table_name, $column_name = false, $params = false)
    {
        return "Select " . ($column_name ? self::escapeKey($column_name) : "*") . " from " . self::escapeKey($table_name,
            1) . (self::buildQueryKeyEqualValue($params, 1));
    }

    public static function buildQueryTableColumns($table_name, $columns = [], $params = false, $connectors = [])
    {
        foreach ($columns as &$column) {
            $column = static::escapeKey($column);
        }
        return "Select " . (!empty($columns) ? implode(',', $columns) : "*") . " from " . self::escapeKey($table_name,
            1) . self::buildQueryJoin($connectors) . (self::buildQueryKeyEqualValue($params,
            1)) . self::buildQueryGroup($connectors);
    }

    public static function buildQueryTableFunction($table_name, $function = false, $params = false)
    {
        return "Select " . $function . " from " . self::escapeKey($table_name,
            1) . (self::buildQueryKeyEqualValue($params, 1));
    }

    public static function buildQueryKeyEqualValue($fields = array(), $where = false, $exclude_key = false)
    {
        $query = '';
        if (is_array($fields)) {
            $queryPieces = [];
            foreach ($fields as $key => $value) {
                $queryPieces [] = self::buildQueryKeyEqualValueCondition($where, $exclude_key, $key, $value);
            }
            $query = implode(' AND ', $queryPieces);
        }
        if ($where && !empty($query)) {
            $query = ' WHERE ' . $query;
        }
        return $query;
    }

    public static function buildQueryKeyEqualValueCondition($where, $exclude_key, $key, $value)
    {
        $query = '';
        if ($exclude_key === $key) {
            return $query;
        }
        if ($key === 'OR') {
            $queryPieces = [];
            foreach ($value as $orKey => $orValue) {
                $queryAndPieces = [];
                foreach ($orValue as $andKey => $andValue) {
                    $queryAndPieces [] = self::buildQueryKeyEqualValueCondition($where, $exclude_key, $andKey,
                        $andValue);
                }
                $queryPieces[] = ' ( ' . implode(' AND ', $queryAndPieces) . ' ) ';
            }
            $query .= implode(' ' . $key . ' ', $queryPieces);
            return $query;
        } else {
            $query .= (empty($query) ? '' : ($where ? ' AND ' : ' , '));
        }
        $qKey = self::escapeKey($key);
        if (is_array($value) && $where) {
            $queryArray = [];
            foreach ($value as $kkey => $vvalue) {
                $kkey = strtolower($kkey);
                if ($kkey == 'in') {
                    $queryArray[] = $qKey . ' IN ' . self::buildQueryList($vvalue);
                } elseif (in_array($kkey, ['=', '!=', '<>', '<', '>', 'like'])) {
                    if ($vvalue === null) {
                        if ($kkey == '=') {
                            $newKey = ' is ';
                        } else {
                            $newKey = ' NOT is ';
                        }
                        $queryArray[] = $qKey . $newKey . ' NULL ';
                    } else {
                        if ($kkey == 'like') {
                            $queryArray[] = $qKey . $kkey . ' ' . self::escape('%' . $vvalue . '%');
                        } else {
                            $queryArray[] = $qKey . $kkey . ' ' . self::escape($vvalue);
                        }
                    }
                }
            }
            if (!empty($queryArray)) {
                $query .= '( ' . implode(' AND ', $queryArray) . ' ) ';
            }
        } elseif (!is_array($value)) {
            $query .= ($qKey . (($value === null && $where) ? ' is ' : ' = ') . ($value === null ? ' NULL ' : self::escape($value)));
        }
        return $query;
    }

    public static function buildQueryUpdate($table, $fields = array(), $where = array())
    {
        return "UPDATE " . self::escapeKey($table,
            1) . " SET " . self::buildQueryKeyEqualValue($fields) . ' ' . self::buildQueryKeyEqualValue($where,
            true);
    }

    public static function buildQueryDelete($table, $where = array())
    {
        return "DELETE FROM " . self::escapeKey($table, 1) . ' ' . self::buildQueryKeyEqualValue($where, true);
    }

    public static function buildQueryDuplicateUpdate($fields, $exclude_key)
    {
        $query = self::buildQueryKeyEqualValue($fields, false, $exclude_key);
        return (empty($query) ? '' : (" ON DUPLICATE KEY UPDATE " . $query));
    }

    public static function buildQueryInsert($table, $fields)
    {
        $arguments = array();
        $keys = array();
        foreach ($fields as $field_key => $field) {
            if (is_array($field)) {
                foreach ($field as $key => $value) {
                    $field[$key] = static::escape($value);
                }
                if (empty($keys)) {
                    $keys = array_keys($field);
                    foreach ($keys as &$_key) {
                        $_key = self::escapeKey($_key);
                    }
                }
                $arguments[] = self::buildQueryList($field);
            } else {
                $keys[] = self::escapeKey($field_key);
                $fields[$field_key] = static::escape($field);

            }
        }
        if (empty($arguments)) {
            $arguments[] = self::buildQueryList($fields);
        }
        return "INSERT INTO " . self::escapeKey($table, 1) . self::buildQueryList($keys) . ' VALUES ' . (implode(',',
            $arguments));
    }

    public static function buildQuerySort($fields)
    {
        $order = "";
        if (is_array($fields) && !empty($fields)) {
            $new_arr = array();
            $order = " ORDER BY ";
            foreach ($fields as $key => $value) {
                $new_arr[] = self::escapeKey($key) . (strtoupper($value) == 'DESC' ? ' DESC ' : ' ASC ');
            }
            $order .= implode(',', $new_arr);
        }
        return $order;
    }

    public static function buildQueryGroup($connectors = [])
    {
        $group = "";
        if (is_array($connectors) && !empty($connectors)) {
            $new_arr = array();
            $group = " GROUP BY ";
            foreach ($connectors as $key => $value) {
                $new_arr[] = $value['externalField'];
            }
            $group .= implode(',', $new_arr);
        }
        return $group;
    }

    public static function buildQueryJoin($connectors = [])
    {
        $join = "";
        if (is_array($connectors) && !empty($connectors)) {
            $new_arr = array();

            foreach ($connectors as $key => $value) {
                $new_arr[] = ' left join ' . self::escapeKey($value['table']) . ' on ' .
                    self::escapeKey($value['externalField']) . ' = ' . self::escapeKey($value['internalField']) . ' ';
            }
            $join .= implode(' ', $new_arr);
        }
        return $join;
    }

    public static function buildQueryPagination($params = [])
    {
        if (!empty($params['row'])) {
            return ' LIMIT 1 ';
        }
        if (!empty($params['all'])) {
            return ' ';
        }
        $page = isset($params['page']) ? $params['page'] : 1;
        $page_count = isset($params['page_count']) ? $params['page_count'] : 20;
        $count_all = isset($params['count_all']) ? $params['count_all'] : 20;
        if (($count_all % $page_count) > 0) {
            $pages_count = floor($count_all / $page_count) + 1;
        } else {
            $pages_count = floor($count_all / $page_count);
        }
        $page_current = $page;
        if ($page_current < 0) {
            $page_current = 1;
        }
        if ($page_current > $pages_count) {
            $page_current = $pages_count;
        }
        if (is_numeric($page) && is_numeric($page_count)) {
            return " LIMIT " . ((($page_current - 1) * $page_count)) . "," . $page_count . " ";
        }
        return " LIMIT 0," . $page_count . " ";
    }

    public function buildQueryFull($table, $columns = [], $params = false, $order = [], $paging = [], $connectors = [])
    {
        return self::buildQueryTableColumns($table, $columns, $params,
            $connectors) . self::buildQuerySort($order) . self::buildQueryPagination($paging);
    }

    public function buildQueryCount($table, $params = false)
    {
        return self::buildQueryTableFunction($table, 'count(*)', $params);
    }

    public static function buildQueryInsertFull($table, $fields, $duplicate = array())
    {
        $query = self::buildQueryInsert($table, $fields);
        if (!empty($duplicate) && $duplicate['type'] == 'update') {
            $query .= self::buildQueryDuplicateUpdate($fields, $duplicate['key']);
        }
        return $query;
    }

    public static function buildQueryInsertMulti($table, $fields)
    {
        $query = self::buildQueryInsert($table, $fields);
        return $query;
    }
}

<file_sep>/**
* Google Maps User Manager
* @author  <NAME>   <<EMAIL>>
* @copyright Copyright &copy; 2017 <NAME> 
* @created 2017.11.28
*/
$.widget('nm.googlemapsusermanager', {

    options: {
        dummy: 'dummy',
        markers:[],
        markerPr:null,
        infowindow:null,
        contentInfowindow:'',
        users:{},
        map:null,
    },

    _create: function () {
        var widget = this;
        
        this.element.on('click','.switch-lang button',function(e){
            e.preventDefault();
            widget.changeLang($(this));
        });

        this.element.on('click','#manage-users',function(e){
            e.preventDefault();
            widget.clearMarkers();
            widget.showManager();
        });
        
        this.element.on('click','#back-to-map',function(e){
            e.preventDefault();
            widget.showMap();
            widget.clearMarkers();
            widget.getUsers(false);
        });

        this.element.on('click','a.edit-user',function(e){
            e.preventDefault();
            var id = $(this).closest('tr').data('id');
            widget.getUser(id);
        });

        this.element.on('click','#back-to-usermanager',function(e){
            e.preventDefault();
            $('#add-user-block').hide();
            $('#usermanager').show();
        });

        this.element.on('click','.delete-user',function(e){
            e.preventDefault();
            var id = $(this).closest('tr').data('id');
            widget.deleteUser(id);
            widget.options.markers.splice(id, 1);
        });

        this.element.on('click','#add-user',function(e){
            e.preventDefault();
            widget.clearFormForAddUser();
            widget.showAddUserFrom();
        });

        this.element.on('click','button.send-add',function(e){
            e.preventDefault();
            widget.clearFormError();
            widget.addNewUser();
        });

        this.element.on('click','button.send-edit',function(e){
            e.preventDefault();
            var id = $(this).closest('form.form-horizontal').attr('data-id');
            widget.clearFormError();
            widget.updateUser(id);
        });

        this.element.on('click','#update-users',function(e){
            widget.clearMarkers();
            widget.getUsers(false);
        });

        this.element.on('change','#users-select',function(e){
            var id = $(this).val();
            widget.showUserMap(widget.options.users[id]);
        });
        
        this._initApp();
    },

    _initApp:function(){
        var widget = this;
        widget.drawBlockAddUser();
        widget.drawBlockUserManager();
        widget.drawBlockApp();

        widget.getUsers(true, function(){widget.initMap()});
        widget.addUserForm();
    },
	
    drawBlockAddUser:function(){
        var widget = this;
        widget.element.append(
            $('<div/>',{id:'add-user-block'}).css('display','none').append(
                $('<form/>',{class:'form-horizontal', role:'form'})
            )
        )
    },

    drawBlockUserManager:function(){
        var widget = this;
        widget.element.append(
            $('<div/>',{id:'usermanager'}).css('display','none').append(
                $('<div/>',{class:'header-usermanager'}).append(
                    $('<a/>',{href:'#', id:'back-to-map'}).text('Back'),
                    $('<a/>',{href:'#', id:'add-user'}).text('Add new user')
                ),
                $('<div/>',{class:'user-table-block'}).append(
                    $('<table/>',{id:'user-table', class:'table table-bordered'}).append(
                        $('<thead/>').append(
                            $('<tr/>').append(
                                $('<td/>').text('Image'),
                                $('<td/>').text('Name'),
                                $('<td/>').text('Address'),
                                $('<td/>').text('Action')
                            )
                        ),
                        $('<tbody/>')
                    )
                )
            )
        )
    },

    drawBlockApp:function(){
        var widget = this;
        widget.element.append(
            $('<div/>',{id:'application'}).append(
                $('<div/>',{id:'application'}).append(
                    $('<div/>',{id:'header'}).append(
                        $('<a/>',{href:'#', id:'manage-users'}).text('Manage users'),
                    ),
                    $('<p/>',{class:'title'}).text('Выберите пользователя:'),
                    $('<div/>',{id:'users'}).append(
                        $('<select/>',{name:'users-select',id:'users-select'}).append(
                            $('<option/>',{id:'default-option'}).text('----')
                        )
                    ),
                    $('<button/>',{id:'update-users',class:'btn btn-primary', type:'submit'}).text('Update users'),
                    $('<div/>',{id:'map'})
                )
            )
        );
    },

    getUsers:function(createmarkers, _callBackFn){
        var widget = this;
        widget.options.users = [];
        sendRequest({
            action: 'googlemaps.getusers',
            successHandler: function (_callbackParams) {
                var response = _callbackParams.response;
                if (!response.success) {
                    alert(response.message);
                }
                else{
                    var resp = response.data.users;
                    for (var i = 0; i < resp.length; i++) {
                        widget.options.users[resp[i].id] = resp[i];
                    }
                    widget.refreshSelectUser(widget.options.users);
                    if (createmarkers) widget.createMarkers();
                    if (_callBackFn) _callBackFn();
                }
            }
        });
    },

    initMap:function (){
        var widget =this;
        for (var i in widget.options.users) {
            var lat = Number(widget.options.users[i].lat);
            var lng = Number(widget.options.users[i].lng);
            break;
        };
        var latLng = {lat: lat, lng: lng};
        widget.options.map = new google.maps.Map(document.getElementById('map'), {
            zoom: 15,
            center: latLng,
            mapTypeId: 'terrain'
        });
        widget.options.infowindow = new google.maps.InfoWindow({
            content: widget.options.contentInfowindow
        });
    },

    showUserMap:function (_user){
        var widget = this;
        var marker = widget.options.markers[_user.id];
        if (widget.options.markerPr) widget.setMarkerMap(null,widget.options.markerPr);
        widget.setMarkerMap(widget.options.map, marker);
        widget.options.markerPr = widget.options.markers[_user.id];
        widget.showMessage(marker,_user);
    },
    
    // Adds a marker to the map and push to the array.
    addMarker:function(user) {
        var widget =this;
        var location = {lat:Number(user.lat),lng:Number(user.lng)};
        var marker = new google.maps.Marker({
          position: location,
            animation: google.maps.Animation.DROP,
            map: widget.options.map
        });
        widget.options.markers[user.id] = marker;
    },

    createMarkers:function (){
        var widget = this;
        widget.deleteMarkers();
        widget.options.markers.length = 0;
        for (var i in widget.options.users) {
            var user = widget.options.users[i];
            var marker = new google.maps.Marker({
                position: {lat:Number(user.lat),lng:Number(user.lng)},
                map: widget.options.map
            });
        widget.options.markers[user.id] = marker;
        }
    },

    setMapOnAll:function (_map) {
        var widget = this;
        // var map = _map || widget.options.map;
        for (var i in widget.options.markers) {
            widget.options.markers[i].setMap(_map);
        }
    },

    setMarkerMap:function (map, marker) {
        var widget = this;
        marker.setMap(map);
    },
    
    // Removes the markers from the map, but keeps them in the array.
    clearMarkers:function () {
        var widget = this;
       widget.setMapOnAll(null);
    },

    // Deletes all markers in the array by removing references to them.
    deleteMarkers:function () {
        var widget = this;
        widget.clearMarkers();
        widget.options.markers = [];
        // markers.length = 0;
    },

    showMessage:function (_marker, user){
        var widget = this;
        var contentInfowindow = '<div id="content">'+
            '<h5 id="firstHeading" class="firstHeading">'+user.name+'</h5>'+
            '<div id="bodyContent">'+
            '<p>'+user.index+' '+user.country+' '+user.city+'<br>'+user.street+','+user.house+'</p>'+
            '</div>'+
            '</div>';
        widget.options.infowindow.setContent(contentInfowindow);
        widget.options.infowindow.open(map, _marker);
        _marker.addListener('click', function() {
            widget.options.infowindow.open(map, _marker);
        });
    },
  
    addNewUser:function (){
        var widget = this;
        var form = $('#add-user-block form');
        var data = form.serializeObject();
        sendRequest({
            action: 'googlemaps.createuser',
            data: {data:data},
    
            successHandler: function (_callbackParams) {
                var response = _callbackParams.response;
                if (!response.success) {
                    var errors = JSON.parse(response.message);
                    $.each(errors, function(i, val) {
                        widget.element.find('form #input'+i).closest('div.form-group').addClass('has-error');
                        widget.element.find('form #input'+i).next().text(val).css('color','red');
                    });
                    
                }
                else{
                    var user = response.data.user;
                    widget.drawRowTable(user);
                    widget.addMarker(user);
                    $('#add-user-block').hide();
                    $('#usermanager').show();
                }
            }
        });
    },

    updateUser:function (_id){
        var widget =this;
        var form = $('#add-user-block form');
        var data = form.serializeObject();
        data['id'] = _id;
        sendRequest({
            action: 'googlemaps.updateuser',
            data: {data:data},
    
            successHandler: function (_callbackParams) {
                var response = _callbackParams.response;
                if (!response.success) {
                    var errors = JSON.parse(response.message);
                    $.each(errors, function(i, val) {
                        widget.element.find('form #input'+i).closest('div.form-group').addClass('has-error');
                        widget.element.find('form #input'+i).next().text(val).css('color','red');
                    });
                }
                else{
                    widget.getUsers(true, function(){widget.showManager()});
                    $('#add-user-block').hide();
                    $('#usermanager').show();
                }
            }
        });
    },

    clearFormError:function(){
        var widget = this;
        var form = widget.element.find('#add-user-block form');
        form.find('span.error-form').text('');
        form.find('div.form-group').removeClass('has-error');
    },

    showAddUserFrom:function (){
        var widget = this;
        $('#usermanager').hide();
        $('#add-user-block').show();
    },

    addUserForm:function (){
        $('#add-user-block').prepend(
            $('<div/>',{id:'header-add-user-block'}).append(
                $('<a/>',{id:'back-to-usermanager', href:'#'}).text('Back')
            )
        );
        var form = $('#add-user-block form').empty();
        form.append(
            $('<h1/>',{class:'col-sm-offset-3 col-sm-6'}).text('Add user'),
            $('<div/>',{class:'form-group responsive-label'}).append(
                $('<label/>',{class:'col-sm-offset-3 col-sm-6 control-label'}).attr('for','inputname').text('Name').css('text-align','left'),
                $('<div/>',{class:'col-sm-offset-3 col-sm-6'}).append(
                    $('<input/>',{class:'form-control', type:'text', id:'inputname', name:'name'}),
                    $('<span/>',{class:'error-form'})
                )
            ),
            $('<div/>',{class:'form-group responsive-label'}).append(
                $('<label/>',{class:'col-sm-offset-3 col-sm-6 control-label'}).attr('for','inputaddress').text('Address Example:12345 Ukraine Kharkiv Plekhanivska,135/139').css('text-align','left'),
                $('<div/>',{class:'col-sm-offset-3 col-sm-6'}).append(
                    $('<input/>',{class:'form-control', type:'text', id:'inputaddress', name:'address'}),
                    $('<span/>',{class:'error-form'})
                )
            ),
            $('<div/>',{class:'footer-form col-sm-offset-3 col-sm-6'}).append(
                $('<button>',{class:'btn btn-primary send-edit'}).text('Submit')
            )
        );
    },

    deleteUser:function (_id){
        var widget = this;
        sendRequest({
            action: 'googlemaps.deluser',
            data: {id: _id},
    
          successHandler: function (_callbackParams) {
                var response = _callbackParams.response;
                if (!response.success) {
                    alert(response.message);
                }
                else{
                    $('tr[data-id='+_id+']').remove();
                }
            }
        });
    },

    getUser:function (_id){
        var widget = this;
        sendRequest({
            action: 'googlemaps.getuser',
            data: {id: _id},
        
              successHandler: function (_callbackParams) {
                var response = _callbackParams.response;
                if (!response.success) {
                    alert(response.message);
                }
                else{
                    var user = response.data.user;
                    widget.editUserForm(user);
                }
            }
        });
    },

    clearFormForAddUser:function (){
        var widget = this;
        var form = $('#add-user-block form'); 
        form.find('#inputname').val('');
        form.find('#inputaddress').val('');
        form.find('button').removeClass('send-edit').addClass('send-add');
        form.find('h1').text('Add user');
    },

    editUserForm:function (_user){
        var widget = this;
        $('#usermanager').hide();
        var form = $('#add-user-block form'); 
        var address = _user.index+' '+_user.country+' '+_user.city+' '+_user.street+', '+_user.house;
        form.attr('data-id',_user.id);
        form.find('button').removeClass('send-add').addClass('send-edit');
        $('#inputname').val(_user.name);
        $('#inputaddress').val(address);
        form.find('h1').text('Edit user');
        $('#add-user-block').show();
    },

    showManager:function (){
        var widget = this;
        $('#application').hide();
        $('#usermanager').show();
        var tbody = $('#user-table tbody').empty();
        for (var i in widget.options.users) {
            var user = widget.options.users[i];
            widget.drawRowTable(user);
        }
    },

    showMap:function (){
        var widget = this;
        $('#usermanager').hide();
        $('#application').show();
    },
  
    drawRowTable:function (_user){
        var widget = this;
        var tbody = $('#user-table tbody');
        var address = _user.index+' '+_user.country+' '+_user.city+' '+_user.street+', '+_user.house;
        tbody.append(
            $('<tr/>').attr('data-id',_user.id).append(
                $('<td/>').text(_user.image),
                $('<td/>').text(_user.name),
                $('<td/>').text(address),
                $('<td/>').append(
                    $('<a/>',{href:'#', class:'edit-user'}).text('Edit'),
                    $('<a/>',{href:'#', class:'delete-user'}).text('Delete')
                )   
            )
        )
    },

    refreshSelectUser:function (_items){
        var widget = this;
        var selectEl = $('#users-select');
        selectEl.find('option:not(#default-option)').remove();
        for (var i in _items) {
            var user = _items[i];
            selectEl.append(
                $('<option/>').attr({'data-lat':user.lat,'data-lng':user.lng}).text(user.name).val(user.id)
            )
        };
        selectEl.find('#default-option').attr({'selected':'selected','disabled':'disabled'});
    },

    testFn:function(){
    	var widget = this;

        console.log(this);
    }

});
(function($) {      // поиск и удаление класса по шаблону // $('p').removeClassWild("status_*");
    $.fn.removeClassWild = function(mask) {
        return this.removeClass(function(index, cls) {
            var re = mask.replace(/\*/g, '\\S+');
            return (cls.match(new RegExp('\\b' + re + '', 'g')) || []).join(' ');
        });
    };
})(jQuery);
<file_sep><?php

    error_reporting(E_ALL^E_NOTICE);
    ini_set('display_errors', 1);
    
    // Load config
    define('APP_DIR_NAME', 'application_v2');
    require_once(APP_DIR_NAME.'/configs/config.php');
    
    // Load class loader
    require_once(CORE_DIR_PATH.'classloader.php');
    
    // Load application
    ClassLoader::loadCoreClass('application');
    
    // Run the application
    Application::run();
    
?><file_sep><?php

    /**
     * Basic_HtmlResponse_Model class file.
     *
    
     */
    
    
    // Load abstract HTML document model class
    ClassLoader::loadModelClass('basic.abstract');
    
    
    /**
     * Response model
     *
    
     */
    class Basic_HtmlResponse_Model extends Basic_Abstract_Model
    {

        /**
         * @var integer HTTP status code
         */
        public $statusCode = 200;
        
        
        /**
         * @var string Reason message
         */
        public $reasonMessage = 'OK';
        
        
        /**
         * @var string Data type
         */
        public $dataType = 'html';
        
        
        /**
         * @var string Location header value
         */
        public $location = null;
        
        
        /**
         * @var string Message body data format (e.g. json could be passed withing html body)
         */
        public $messageBodyFormat = 'html';
        
        
        /**
         * @var mixed Message body
         */
        public $messageBody = null;

    }

?><file_sep><?php
 
    // Load abstract action
    ClassLoader::loadAsyncActionClass('basic.abstract');
    

    class Googlemaps_GetUsers_AsyncAction extends Basic_Abstract_AsyncAction
    {
        
        /**
         * Performs the action
         */
        public function perform($_domainId = null, array $_params = array())
        {
            $mySql = Application::getService('basic.mysqlmanager');
			// Extract inputs
            $usersSort = array();
            $users = $mySql->getRecords('google_maps_users', '`id`');
            // var_dump($users);
            foreach ($users as $key => $value) {
                $usersSort[$value['id']] = $value;
            }
            
            $this->data['users'] = $users;
            
        }
    }
        

?><file_sep>var guid = (function() {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000)
                   .toString(16)
                   .substring(1);
    }
    return function() {
        return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
               s4() + '-' + s4() + s4() + s4();
    };
})();


$(document).ajaxStart(function() {
    $.blockUI({message: '<div style="padding: 12px; background-color: #d9dde2"><span style="font-size: 20px">Loading...</span></div>'});
});

$(document).ajaxStop(function() {
    $.unblockUI();
});


$(document).ready(function(){
    $('form').on('click', 'input:checkbox.radio', function() {
        $this = $(this);
        $('input:checkbox[name=\''+$this.attr('name')+'\']').prop('checked', false);
        $this.prop('checked', true);
    });
    
    $('form').on('click', 'input:checkbox.boolean', function() {
        var $this = $(this);
        if ($this.prop('checked'))
            $this.val(1);
        else
            $this.val(0);
    });
});


$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    a = a.concat(
        $(this).find('input[type=checkbox]:not(:checked, .radio)').map(function() {
            return {'name': this.name, 'value': this.value};
        }).get()
    );
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};


function sendRequest(_params)
{
    if (_params.action)
    {
        var url = _params.action.charAt(0)=='/' ? _params.action : '/async/'+_params.action;
        var ajaxGlobal = _params.ajaxGlobal == undefined ? true : _params.ajaxGlobal;
        var ajaxAsync = _params.ajaxAsync == undefined ? true : _params.ajaxAsync;
    /* --- Modify by <NAME> 09-05-2017 for upload file  (start) --- */    
        var processData = _params.processData == undefined ? true : _params.processData;
        var contentType = _params.contentType == undefined ? 'application/x-www-form-urlencoded; charset=UTF-8' : _params.contentType;
    /* --- Modify by <NAME> 09-05-2017 for upload file  (end) --- */
        $.ajax({
            async: ajaxAsync,
            global: ajaxGlobal,
            type: 'POST',
            url: url,
            dataType: 'json',
            
            processData: processData,
            contentType: contentType,

            data: _params.data,
            cache: false,
            success: function(_response, _textStatus, _jqXHR) {
                //alert('Success: ' + _jqXHR.responseText);
                _params.successHandler({response: _response, requestData: _params.data});
            },
            error: function(_jqXHR, _textStatus, _errorThrown) {
                if (isBeforeunloadSupported()) {
                        if (! beforeunloadCalled) {
                            alert('Error: ' + _jqXHR.responseText);
                        }
                    } else {
                        setTimeout(function () {
                            alert('Error: ' + _jqXHR.responseText);
                        }, 1000);
                }
            },
            complete: function(_jqXHR, _textStatus)
            {
                if (_params.completeHandler)
                    _params.completeHandler({requestData: _params.data});
            }
        });
    }
}


function clearForm($_form)
{
    $_form.find('input:text, input:password, input:file, select, textarea').val('');
    $_form.find('input:radio, input:checkbox').removeAttr('checked').removeAttr('selected');
}


function populateForm($form, data)
{
    clearForm($form);
    $.each(data, function(key, value) {
        if (value instanceof Array) {
            var len = value.length;
            for (var i = 0; i < len; i++) {
                var $ctrl = $form.find('[name=\''+key+'['+i+']'+'\']');
                setFormControlValue($ctrl, value[i]);
            }
        } else if (value instanceof Object) {
            for (var i in value) {
                var $ctrl = $form.find('[name=\''+key+'['+i+']'+'\']');
                setFormControlValue($ctrl, value[i]);
            }
        } else {
            var $ctrl = $form.find('[name='+key+']');
            setFormControlValue($ctrl, value);
        }
    });
}


function setFormControlValue($_ctrl, _value)
{
    if ($_ctrl.is('select')){
        $('option', $_ctrl).each(function() {
            if ($(this).val() == _value)
                this.selected = true;
        });
    } else if ($_ctrl.is('textarea')) {
        $_ctrl.val(_value);
    } else {
        switch($_ctrl.attr("type")) {
            case "text":
            case "hidden":
                $_ctrl.val(_value);   
                break;
            case "checkbox":
                if (_value == '1')
                {
                    $_ctrl.prop('checked', true);
                    $_ctrl.val(1);
                }
                else
                {
                    $_ctrl.prop('checked', false);
                    $_ctrl.val(0);
                }
                break;
        } 
    }
}


function getCaptcha($_form)
{
    $captchaBox = $(
'<div style="display: none" id="captcha-box">'+
'    <div style="width: 160px; float: left;">'+
'        <p style="color: #000000; float: none; font: normal 18px \'Times New Roman\'; margin: 0 0 10px; padding: 0; text-align: left; width: auto;">To get your quote please enter the numbers below:</p>'+
'        <form id="captcha-form" action="/async/basic.verifycaptcha" method ="post">'+
'            <div class="captcha"></div>'+
'            <input type="text" name="captcha" value="">'+
'            <input type="submit" value="SEND">'+
'        </form>'+
'    </div>'+
'    <div style="width: 120px; float: left; padding-left: 16px; text-align: center">'+
'        <p style="color: #000000; float: none; font: normal 12px/14px \'Times New Roman\'; margin: 0 0 10px; padding: 0; text-align: justify; width: auto;">This is a verification system to ensure you are a person and not an automated system.</p>'+
'        <p style="color: #000000; float: none; font: normal 18px \'Times New Roman\'; margin: 0; padding: 0; text-align: left; width: auto;"><img src="/application/modules/basic/images/logo-captcha.png"></p>'+
'    </div>'+
'</div>'
    );
    
    
    var $captchaForm = $captchaBox.find('form#captcha-form');
    $captchaForm.off('submit');
    var $submit = $captchaForm.find('input[type=submit]');
    $submit.prop('disabled', false);
    
    
    $captchaForm.submit(function(e) {
        e.preventDefault();
        
        $submit.prop('disabled', true);
        var data = $captchaForm.serializeObject();
        
        sendRequest({
            action: $captchaForm.attr('action'),
            data: data,
            successHandler: function(_callbackParams) {
                var response = _callbackParams.response;
                if (!response.success)
                    alert(response.message);
                else
                {
                    $.modal.close();
                    var $captchaInput = $_form.find('input[name=captcha]');
                    if ($captchaInput.length == 0)
                        $_form.prepend('<input type="hidden" name="captcha" value="'+data.captcha+'" />');
                    else
                        $captchaInput.val(data.captcha);
                    $_form.submit();
                }
            },
            completeHandler: function(_callbackParams) {
                $submit.prop('disabled', false);
            }
        });
    });
    
    
    clearForm($captchaForm);
    $captchaBox.find('div.captcha').html('<img src="/captcha.php?r='+Math.random()+'" />');
    $captchaBox.modal({overflow: 'hidden'});
}


/*(function($) {
    $.fn.ajaxForm = function(_options) {
        // Default settings
		var settings = jQuery.extend({
            dummy: 0,
            clearFormOnSuccess: true,
            onSuccess: function() { alert('Your request has been sent.'); },
            beforeSubmit: function() {}
		}, _options);
        
        
        // Overwrite form's submit method
        this.submit(function(e) {
            e.preventDefault();
            
            var $form = $(this);
            var $submit = $form.find('input[type=submit]');
            $submit.prop('disabled', true);
            
            settings.beforeSubmit();
            sendRequest({
                action: $form.attr('action'),
                data: $form.serializeObject(),
                successHandler: function(_callbackParams) {
                    var response = _callbackParams.response;
                    if (!response.success)
                    {
                        if (response.errors && response.errors.captcha)
                            getCaptcha($form);
                        else
                            alert(response.message);
                    }
                    else
                    {
                        if (settings.clearFormOnSuccess)
                            clearForm($form);
                        settings.onSuccess();
                    }
                },
                completeHandler: function(_callbackParams) {
                    $submit.prop('disabled', false);
                }
            });
        });
        
        
        return this;
    };
})(jQuery);*/


(function($) {
    $.fn.placeholder = function(_options) {
		var settings = jQuery.extend({
            dummy: 0,
            text: 'Enter...',
            className: 'placeholder'
		}, _options);
        
        this.val(settings.text);
        this.addClass(settings.className);
        
        this.focusin(function() {
            if ($(this).hasClass(settings.className)) {
                $(this).removeClass(settings.className);
                $(this).val('');
            }
        });
        
        this.focusout(function() {
            if ($(this).val() == '') {
                $(this).val(settings.text);
                $(this).addClass(settings.className);
            }
        });
        return this;
    };
})(jQuery);


(function($, global) {
    var field = 'beforeunloadSupported';
    if (global.localStorage &&
        global.localStorage.getItem &&
        global.localStorage.setItem &&
        ! global.localStorage.getItem(field)) {
        $(window).on('beforeunload', function () {
            global.localStorage.setItem(field, 'yes');
        });
        $(window).on('unload', function () {
            // If unload fires, and beforeunload hasn't set the field,
            // then beforeunload didn't fire and is therefore not
            // supported (cough * iPad * cough)
            if (! global.localStorage.getItem(field)) {
                global.localStorage.setItem(field, 'no');
            }
        });
    }
    global.isBeforeunloadSupported = function () {
        if (global.localStorage &&
            global.localStorage.getItem &&
            global.localStorage.getItem(field) &&
            global.localStorage.getItem(field) == "yes" ) {
            return true;
        } else {
            return false;
        }
    }
})(jQuery, window);


var beforeunloadCalled = false;
// Beware that 'beforeunload' is not supported in all browsers.
// iPad / iPhone - I'm looking at you.
$(window).on('beforeunload', function () {
    beforeunloadCalled = true;
});


function formatDateMmDdYyyy(date)
{
    return date.substring(5,7)+'-'+date.substring(8,10)+'-'+date.substring(0,4);
}


function formatDateYyyyMmDd(date)
{
    return date.substring(6,10)+'-'+date.substring(0,2)+'-'+date.substring(3,5);
}


function formatDateMmDdYyyyHhIiSs(date)
{
    return date.substring(5,7)+'-'+date.substring(8,10)+'-'+date.substring(0,4)+' '+date.substring(11,19);
}


function getUtcOffset()
{
    var date = new Date();
    var hours = -date.getTimezoneOffset()/60;
    return (hours>=0?'+':'')+hours+':00';
}


function formatFloatTwoDecimalDigits(_value)
{
    return parseFloat(Math.round(_value*100)/100).toFixed(2);
    //return _value;
}


jQuery.fn.selectText = function() {
   var doc = document;
   var element = this[0];
   if (doc.body.createTextRange) {
       var range = document.body.createTextRange();
       range.moveToElementText(element);
       range.select();
   } else if (window.getSelection) {
       var selection = window.getSelection();        
       var range = document.createRange();
       range.selectNodeContents(element);
       selection.removeAllRanges();
       selection.addRange(range);
   }
};


function escapeHtml(text) {
    var map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
    };
    if(text === null || text ===false){
        return '';
    }
    if(text.length){
        return text.replace(/[&<>"']/g, function(m) { return map[m]; });
    }else{
        return text;
    }
}

function bind_blueimp(params) {
    $(function () {
        var links = document.getElementById(params.containerId).getElementsByClassName(params.linkClass);
        blueimp.Gallery(
            links, {
                container: '#'+params.containerId+' .'+params.blueimpClass,
                carousel: true,
                slideshowInterval: parseInt(params.slideTime) * 1000,
                stretchImages: params.imgType,
                onslide: function () {
                    var $caption = $('#'+params.containerId+' .'+params.blueimpClass + ' .caption');
                    $caption.animate({'bottom': '-' + $caption.outerHeight() + 'px'}, function () {
                    });
                    $caption.find('.icons .icon').hide('slow');
                },
                onslideend: function (index, slide) {
                    var $frame = $('#'+params.containerId + ' .frames .frame:eq(' + index + ')');
                    var $href = $frame.attr('data-href');
                    var $caption = $('#'+params.containerId+' .'+params.blueimpClass + ' .caption');
                    var $title = $frame.find('.title').html();
                    if ($title) {
                        if ($href == undefined || $href == '') {
                            $caption.find('.title-normal').html($title);
                            $caption.find('.title-short').html($frame.find('.title-short').html());
                        } else {
                            $caption.find('.title-normal').html('<a href="' + $href + '" target="_blank">' + $title + '</a>');
                            $caption.find('.title-short').html('<a href="' + $href + '" target="_blank">' + $frame.find('.title-short').html() + '</a>');
                        }
                        $caption.find('.description').html($frame.find('.description').html());
                        if ($frame.attr('data-photo') == '1') $caption.find('.icons .icon-photo').attr('href', $href + '#photos').show('slow');
                        if ($frame.attr('data-video') == '1') $caption.find('.icons .icon-video').attr('href', $href + '#videos').show('slow');
                        $caption.animate({'bottom': 0});
                    }
                }
            }
        );
    });
}
