ElementParser.php 5.94 KB
<?php


class Q_Db_Adapter_Pdo_ElementParser
{

    /**
     * 设定Map元素
     *
     * @var Array
     */
    private $mapElementsConfig = array(
        'Insert',
        'Update',
        'Select',
        'Delete',
        'Command'
    );

    /**
     * 创建一个临时文件夹
     *
     * @var unknown_type
     */
    private $tmp = 'tmp';

    /**
     * map 文件
     *
     * @var String
     */
    private $_sqlMapXmlFile;

    private $_resourceFiles;

    /**
     * 替换列表
     *
     * @var Array
     */
    private $replaceMap = array();

    /**
     * 元素Map
     *
     * @var Array
     */
    private $elementMap = array();

    /**
     * Cache
     *
     * @var Q_Db_Cache
     */
    private $cache;

    private $sqlStr;

    /**
     * 替换参数验证
     *
     * @var String
     */
    private $replaceFilters = '/(?=select\s|insert\s|delete\s|update\s)/i';

    /**
     * 初始化
     *
     * @param String $dbname
     */
    public function __construct($sqlMapXmlFile)
    {
        if (!is_string($sqlMapXmlFile) || empty($sqlMapXmlFile)) {
            throw new Q_Db_Exception('ElementParser :SQL Map find');
        }
        $this->_sqlMapXmlFile = $sqlMapXmlFile;
        $this->parseResource();
    }

    /**
     * 获取元素
     *
     */
    public function element($sqlId)
    {
        return $this->elementMap[$sqlId];
    }

    /**
     * 分析元素
     *
     */
    private function parseResource()
    {
        $xmlFile = new Q_Utils_Io_File($this->_sqlMapXmlFile);
        if (!$xmlFile->exists()) {
            throw new Q_Db_Exception($this->_sqlMapXmlFile . ' not find');
        } else {
            $this->resourceFiles = "file://" . $xmlFile->absPath();
            $lastModified = $xmlFile->lastModified();
            /**
             * APC Cache
             */
            if (Q_Cache_Backend::isEnabled()) {
                $apcEntry = Q_Cache_Backend::load($this->resourceFiles);
                if ($apcEntry != null && $lastModified == $apcEntry['lastModified']) {
                    $this->elementMap = $apcEntry['elementMap'];
                    return;
                }
            } else {
                $cachePath = (defined('Q_CACHE_FILE_PATH') && Q_CACHE_FILE_PATH != '') ? Q_CACHE_FILE_PATH : $this->tmp;
                $tmpFile = new Q_Utils_Io_File($cachePath . DIRECTORY_SEPARATOR . md5($this->resourceFiles) . '.php');
                /**
                 * 文件Cache
                 */
                if ($tmpFile->exists() == true) {
                    $entry = json_decode($tmpFile->reader()->read(), true);
                    if (!empty($entry) && $lastModified == $entry['lastModified']) {
                        $this->elementMap = $entry['elementMap'];
                        return;
                    }
                }
            }
            $resourceDocument = new DOMDocument();
            $resourceDocument->load($xmlFile->absPath());
            $resourceNode = new Q_Utils_Xml_XmlNode();
            $resourceNode->loadDOM($resourceDocument);
            $sqlMapNodeList = $resourceNode->namedChildren("sqlMap");
            $sqlMapNode = $sqlMapNodeList[0];
            $namespace = trim($sqlMapNode->attr("namespace"));
            $queryNodeList = $sqlMapNode->children();
            foreach ($queryNodeList as $queryNode) {
                if ($queryNode->type() == XML_ELEMENT_NODE) {
                    $tagName = strToLower($queryNode->name());
                    $queryId = trim($queryNode->attr("id"));
                    if (in_array(ucwords($tagName), $this->mapElementsConfig) && $queryId != '' && $namespace != '') {
                        $this->elementMap[$namespace . '.' . $queryId] = $queryNode->value();
                    }
                }
            }
            /** 存入 Cache **/
            if (Q_Cache_Backend::isEnabled()) {
                $valArray = array(
                    'elementMap' => $this->elementMap,
                    'lastModified' => $lastModified
                );
                Q_Cache_Backend::load($this->resourceFiles, $valArray);
            } else {
                if ($tmpFile->exists() == true) {
                    $valArray = array(
                        'elementMap' => $this->elementMap,
                        'lastModified' => $lastModified
                    );
                    $tmpFile->writer()->write(json_encode($valArray));
                }
            }
        }
    }

    /**
     * 获取所有对象
     *
     * @return Array
     */
    public function elementMap()
    {
        return $this->elementMap;
    }

    /**
     * 设置替换列表
     *
     * @param array $replaceMap 替换列表(关联数组)
     */
    public function setReplaceMap(array $replaceMap)
    {
        if (is_array($replaceMap)) {
            $newMap = array();
            foreach ($replaceMap as $key => $value) {
                if (is_array($value)) {
                    throw new Q_Db_Exception(' replaceMap value Should not be array ');
                }
                if (preg_match($this->replaceFilters, $value) == 1) {
                    throw new Q_Db_Exception(' replaceMap should not contain select、insert、delete、update ');
                }
                $newMap["#" . $key . "#"] = $value;
            }
            $this->replaceMap = $newMap;
        }
    }

    /**
     * 获取Sql
     *
     * @return String
     */
    public function sql($sqlId)
    {
        if (stristr($sqlId, '.') === FALSE || empty($sqlId)) {
            throw new Q_Db_Exception(' sqlId Incorrect format ');
        }
        if (!is_array($this->replaceMap)) {
            throw new Q_Db_Exception(' replaceMap Incorrect format ');
        }
        $this->sqlStr = strtr($this->element($sqlId), $this->replaceMap);
        return $this->sqlStr;
    }

    /**
     * 获取map标签元素配置
     *
     * @return Array
     */
    public function getMapElementsConfig()
    {
        return $this->mapElementsConfig;
    }
}