Overview

Namespaces

  • Alchemy
    • core
      • query
      • schema
    • dialect
    • engine
    • orm
    • tests
    • util
      • promise
  • PHP

Classes

  • ANSICompiler
  • Compiler
  • MySQLCompiler
  • SQLiteCompiler
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: namespace Alchemy\dialect;
  4: 
  5: class Compiler {
  6: 
  7:     protected static $default_tag = 'sql.compile';
  8: 
  9:     private $config = array();
 10: 
 11:     protected $defaults = array();
 12: 
 13: 
 14:     public function __construct($config = array()) {
 15:         $this->pushConfig($config + $this->defaults);
 16:     }
 17: 
 18: 
 19:     /**
 20:      * Compile an Expression or array of Expressions into a string.
 21:      *
 22:      * @param  array|Expression $obj    object(s) to compile
 23:      * @param  array            $config temporary config overrides
 24:      * @return array|string             compiled result(s)
 25:      */
 26:     public function compile($obj = null, $config = null) {
 27:         $result = '';
 28: 
 29:         if ($config) {
 30:             $this->pushConfig($config);
 31:         }
 32: 
 33:         if (is_array($obj)) {
 34:             $result = $this->map('compile', $obj);
 35:         } elseif (is_object($obj)) {
 36:             $fn = $this->getFunction($obj, static::$default_tag, '', true);
 37:             $result = call_user_func($fn, $obj);
 38:         }
 39: 
 40:         if ($config) {
 41:             $this->popConfig();
 42:         }
 43: 
 44:         return $result;
 45:     }
 46: 
 47: 
 48:     /**
 49:      * Apply the special Compiler-format to an array of strings (recursive).
 50:      * Variardic formatting is done with %/<subformat>/<delimiter>/,
 51:      * which applies a format & implode to the remainder of the elements,
 52:      * if any (you may use any punctuation mark in place of '/').
 53:      * <subformat> may contain recursive tokens. It is your responsibility
 54:      * to make sure $format and $subject make sense to use together.
 55:      *
 56:      * Ex: "%s %s (%4/+%s/, /)" * [A, B, C, D, E] = "A B (D, E)"
 57:      * Ex: "%2$s (%2$1/+%s/, /)" * [[A, B, C], D] = "D (A, B, C)"
 58:      *
 59:      * @param  string $format
 60:      * @param  array  $subject
 61:      * @return string
 62:      */
 63:     public function format($format = '', $subject = '') {
 64:         if (!is_array($subject)) {
 65:             $subject = array($subject);
 66:         }
 67: 
 68:         while (preg_match("/.*?(%(?:(\d+).)?(\d+)?(\p{P})([^\g4]*?)\g4([^\g4]*?)\g4)/", $format, $matches)) {
 69:             list(,$token, $pos, $start, $p, $subfmt, $delim) = $matches;
 70:             $start = ((int) $start ?: 1) - 1;
 71:             $pos   = ((int) $pos   ?: 1) - 1;
 72:             $tail = array_slice($pos ? $subject[$pos] : $subject, $start);
 73: 
 74:             if ($subfmt) {
 75:                 foreach($tail as &$item) {
 76:                     $item = $this->format($subfmt ?: '%s', $item);
 77:                 }
 78:             }
 79: 
 80:             $subject[] = implode($delim, array_filter($tail));
 81:             $format = str_replace($token, '%'.count($subject).'$s', $format);
 82:         }
 83: 
 84:         return vsprintf($format, $subject);
 85:     }
 86: 
 87: 
 88:     public function getConfig($key) {
 89:         $end = end($this->config);
 90:         return isset($end[$key]) ? $end[$key] : null;
 91:     }
 92: 
 93: 
 94:     protected function getFunction($obj, $tag = '', $prefix = '', $strict = false) {
 95:         $type = $obj->getTag($tag ?: static::$default_tag);
 96: 
 97:         if (method_exists($this, "{$prefix}{$type}")) {
 98:             return array($this, "{$prefix}{$type}");
 99:         }
100: 
101:         if ($strict) {
102:             throw new \Exception("Compiler method not found with prefix '$prefix' for '$tag' = '$type'");
103:         }
104:     }
105: 
106: 
107:     public function popConfig() {
108:         array_pop($this->config);
109:     }
110: 
111: 
112:     public function pushConfig($config) {
113:         $end = end($this->config) ?: array();
114:         array_push($this->config, array_merge($end, $config));
115:     }
116: 
117: 
118:     protected function map($method, $objs) {
119:         return array_map(array($this, $method), $objs);
120:     }
121:  }
API documentation generated by ApiGen 2.8.0