[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |