[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/infrastructure/storage/lisk/ -> PhabricatorLiskDAO.php (source)

   1  <?php
   2  
   3  /**
   4   * @task config Configuring Storage
   5   */
   6  abstract class PhabricatorLiskDAO extends LiskDAO {
   7  
   8    private static $namespaceStack = array();
   9  
  10    const ATTACHABLE = '<attachable>';
  11    const CONFIG_APPLICATION_SERIALIZERS = 'phabricator/serializers';
  12  
  13  /* -(  Configuring Storage  )------------------------------------------------ */
  14  
  15    /**
  16     * @task config
  17     */
  18    public static function pushStorageNamespace($namespace) {
  19      self::$namespaceStack[] = $namespace;
  20    }
  21  
  22    /**
  23     * @task config
  24     */
  25    public static function popStorageNamespace() {
  26      array_pop(self::$namespaceStack);
  27    }
  28  
  29    /**
  30     * @task config
  31     */
  32    public static function getDefaultStorageNamespace() {
  33      return PhabricatorEnv::getEnvConfig('storage.default-namespace');
  34    }
  35  
  36    /**
  37     * @task config
  38     */
  39    public static function getStorageNamespace() {
  40      $namespace = end(self::$namespaceStack);
  41      if (!strlen($namespace)) {
  42        $namespace = self::getDefaultStorageNamespace();
  43      }
  44      if (!strlen($namespace)) {
  45        throw new Exception('No storage namespace configured!');
  46      }
  47      return $namespace;
  48    }
  49  
  50    /**
  51     * @task config
  52     */
  53    public function establishLiveConnection($mode) {
  54      $namespace = self::getStorageNamespace();
  55  
  56      $conf = PhabricatorEnv::newObjectFromConfig(
  57        'mysql.configuration-provider',
  58        array($this, $mode, $namespace));
  59  
  60      return PhabricatorEnv::newObjectFromConfig(
  61        'mysql.implementation',
  62        array(
  63          array(
  64            'user'      => $conf->getUser(),
  65            'pass'      => $conf->getPassword(),
  66            'host'      => $conf->getHost(),
  67            'port'      => $conf->getPort(),
  68            'database'  => $conf->getDatabase(),
  69            'retries'   => 3,
  70          ),
  71        ));
  72    }
  73  
  74    /**
  75     * @task config
  76     */
  77    public function getTableName() {
  78      $str = 'phabricator';
  79      $len = strlen($str);
  80  
  81      $class = strtolower(get_class($this));
  82      if (!strncmp($class, $str, $len)) {
  83        $class = substr($class, $len);
  84      }
  85      $app = $this->getApplicationName();
  86      if (!strncmp($class, $app, strlen($app))) {
  87        $class = substr($class, strlen($app));
  88      }
  89  
  90      if (strlen($class)) {
  91        return $app.'_'.$class;
  92      } else {
  93        return $app;
  94      }
  95    }
  96  
  97    /**
  98     * @task config
  99     */
 100    abstract public function getApplicationName();
 101  
 102    protected function getConnectionNamespace() {
 103      return self::getStorageNamespace().'_'.$this->getApplicationName();
 104    }
 105  
 106  
 107    /**
 108     * Break a list of escaped SQL statement fragments (e.g., VALUES lists for
 109     * INSERT, previously built with @{function:qsprintf}) into chunks which will
 110     * fit under the MySQL 'max_allowed_packet' limit.
 111     *
 112     * Chunks are glued together with `$glue`, by default ", ".
 113     *
 114     * If a statement is too large to fit within the limit, it is broken into
 115     * its own chunk (but might fail when the query executes).
 116     */
 117    public static function chunkSQL(
 118      array $fragments,
 119      $glue = ', ',
 120      $limit = null) {
 121  
 122      if ($limit === null) {
 123        // NOTE: Hard-code this at 1MB for now, minus a 10% safety buffer.
 124        // Eventually we could query MySQL or let the user configure it.
 125        $limit = (int)((1024 * 1024) * 0.90);
 126      }
 127  
 128      $result = array();
 129  
 130      $chunk = array();
 131      $len = 0;
 132      $glue_len = strlen($glue);
 133      foreach ($fragments as $fragment) {
 134        $this_len = strlen($fragment);
 135  
 136        if ($chunk) {
 137          // Chunks after the first also imply glue.
 138          $this_len += $glue_len;
 139        }
 140  
 141        if ($len + $this_len <= $limit) {
 142          $len += $this_len;
 143          $chunk[] = $fragment;
 144        } else {
 145          if ($chunk) {
 146            $result[] = $chunk;
 147          }
 148          $len = strlen($fragment);
 149          $chunk = array($fragment);
 150        }
 151      }
 152  
 153      if ($chunk) {
 154        $result[] = $chunk;
 155      }
 156  
 157      foreach ($result as $key => $fragment_list) {
 158        $result[$key] = implode($glue, $fragment_list);
 159      }
 160  
 161      return $result;
 162    }
 163  
 164    protected function assertAttached($property) {
 165      if ($property === self::ATTACHABLE) {
 166        throw new PhabricatorDataNotAttachedException($this);
 167      }
 168      return $property;
 169    }
 170  
 171    protected function assertAttachedKey($value, $key) {
 172      $this->assertAttached($value);
 173      if (!array_key_exists($key, $value)) {
 174        throw new PhabricatorDataNotAttachedException($this);
 175      }
 176      return $value[$key];
 177    }
 178  
 179    protected function detectEncodingForStorage($string) {
 180      return phutil_is_utf8($string) ? 'utf8' : null;
 181    }
 182  
 183    protected function getUTF8StringFromStorage($string, $encoding) {
 184      if ($encoding == 'utf8') {
 185        return $string;
 186      }
 187  
 188      if (function_exists('mb_detect_encoding')) {
 189        if (strlen($encoding)) {
 190          $try_encodings = array(
 191            $encoding,
 192          );
 193        } else {
 194          // TODO: This is pretty much a guess, and probably needs to be
 195          // configurable in the long run.
 196          $try_encodings = array(
 197            'JIS',
 198            'EUC-JP',
 199            'SJIS',
 200            'ISO-8859-1',
 201          );
 202        }
 203  
 204        $guess = mb_detect_encoding($string, $try_encodings);
 205        if ($guess) {
 206          return mb_convert_encoding($string, 'UTF-8', $guess);
 207        }
 208      }
 209  
 210      return phutil_utf8ize($string);
 211    }
 212  
 213    protected function willReadData(array &$data) {
 214      parent::willReadData($data);
 215  
 216      static $custom;
 217      if ($custom === null) {
 218        $custom = $this->getConfigOption(self::CONFIG_APPLICATION_SERIALIZERS);
 219      }
 220  
 221      if ($custom) {
 222        foreach ($custom as $key => $serializer) {
 223          $data[$key] = $serializer->willReadValue($data[$key]);
 224        }
 225      }
 226    }
 227  
 228    protected function willWriteData(array &$data) {
 229      static $custom;
 230      if ($custom === null) {
 231        $custom = $this->getConfigOption(self::CONFIG_APPLICATION_SERIALIZERS);
 232      }
 233  
 234      if ($custom) {
 235        foreach ($custom as $key => $serializer) {
 236          $data[$key] = $serializer->willWriteValue($data[$key]);
 237        }
 238      }
 239  
 240      parent::willWriteData($data);
 241    }
 242  
 243  
 244  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1