1: <?php
2: /**
3: * Magento
4: *
5: * NOTICE OF LICENSE
6: *
7: * This source file is subject to the Open Software License (OSL 3.0)
8: * that is bundled with this package in the file LICENSE.txt.
9: * It is also available through the world-wide-web at this URL:
10: * http://opensource.org/licenses/osl-3.0.php
11: * If you did not receive a copy of the license and are unable to
12: * obtain it through the world-wide-web, please send an email
13: * to license@magentocommerce.com so we can send you a copy immediately.
14: *
15: * DISCLAIMER
16: *
17: * Do not edit or add to this file if you wish to upgrade Magento to newer
18: * versions in the future. If you wish to customize Magento for your
19: * needs please refer to http://www.magentocommerce.com for more information.
20: *
21: * @category Mage
22: * @package Mage_Core
23: * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
24: * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
25: */
26:
27: /**
28: * Abstract resource helper class
29: *
30: * @category Mage
31: * @package Mage_Core
32: * @author Magento Core Team <core@magentocommerce.com>
33: */
34: abstract class Mage_Core_Model_Resource_Helper_Abstract
35: {
36: /**
37: * Read adapter instance
38: *
39: * @var Varien_Db_Adapter_Interface
40: */
41: protected $_readAdapter;
42:
43: /**
44: * Write adapter instance
45: *
46: * @var Varien_Db_Adapter_Interface
47: */
48: protected $_writeAdapter;
49:
50: /**
51: * Resource helper module prefix
52: *
53: * @var string
54: */
55: protected $_modulePrefix;
56:
57: /**
58: * Initialize resource helper instance
59: *
60: * @param string $module
61: */
62: public function __construct($module)
63: {
64: $this->_modulePrefix = (string)$module;
65: }
66:
67: /**
68: * Retrieve connection for read data
69: *
70: * @return Varien_Db_Adapter_Interface
71: */
72: protected function _getReadAdapter()
73: {
74: if ($this->_readAdapter === null) {
75: $this->_readAdapter = $this->_getConnection('read');
76: }
77:
78: return $this->_readAdapter;
79: }
80:
81: /**
82: * Retrieve connection for write data
83: *
84: * @return Varien_Db_Adapter_Interface
85: */
86: protected function _getWriteAdapter()
87: {
88: if ($this->_writeAdapter === null) {
89: $this->_writeAdapter = $this->_getConnection('write');
90: }
91:
92: return $this->_writeAdapter;
93: }
94:
95: /**
96: * Retrieves connection to the resource
97: *
98: * @param string $name
99: * @return Varien_Db_Adapter_Interface
100: */
101: protected function _getConnection($name)
102: {
103: $connection = sprintf('%s_%s', $this->_modulePrefix, $name);
104: /** @var $resource Mage_Core_Model_Resource */
105: $resource = Mage::getSingleton('core/resource');
106:
107: return $resource->getConnection($connection);
108: }
109:
110: /**
111: * Escapes value, that participates in LIKE, with '\' symbol.
112: * Note: this func cannot be used on its own, because different RDMBS may use different default escape symbols,
113: * so you should either use addLikeEscape() to produce LIKE construction, or add escape symbol on your own.
114: *
115: * By default escapes '_', '%' and '\' symbols. If some masking symbols must not be escaped, then you can set
116: * appropriate options in $options.
117: *
118: * $options can contain following flags:
119: * - 'allow_symbol_mask' - the '_' symbol will not be escaped
120: * - 'allow_string_mask' - the '%' symbol will not be escaped
121: * - 'position' ('any', 'start', 'end') - expression will be formed so that $value will be found at position within string,
122: * by default when nothing set - string must be fully matched with $value
123: *
124: * @param string $value
125: * @param array $options
126: * @return string
127: */
128: public function escapeLikeValue($value, $options = array())
129: {
130: $value = str_replace('\\', '\\\\', $value);
131:
132: $from = array();
133: $to = array();
134: if (empty($options['allow_symbol_mask'])) {
135: $from[] = '_';
136: $to[] = '\_';
137: }
138: if (empty($options['allow_string_mask'])) {
139: $from[] = '%';
140: $to[] = '\%';
141: }
142: if ($from) {
143: $value = str_replace($from, $to, $value);
144: }
145:
146: if (isset($options['position'])) {
147: switch ($options['position']) {
148: case 'any':
149: $value = '%' . $value . '%';
150: break;
151: case 'start':
152: $value = $value . '%';
153: break;
154: case 'end':
155: $value = '%' . $value;
156: break;
157: }
158: }
159:
160: return $value;
161: }
162:
163: /**
164: * Escapes, quotes and adds escape symbol to LIKE expression.
165: * For options and escaping see escapeLikeValue().
166: *
167: * @param string $value
168: * @param array $options
169: * @return Zend_Db_Expr
170: *
171: * @see escapeLikeValue()
172: */
173: abstract public function addLikeEscape($value, $options = array());
174:
175: /**
176: * Returns case insensitive LIKE construction.
177: * For options and escaping see escapeLikeValue().
178: *
179: * @param string $field
180: * @param string $value
181: * @param array $options
182: * @return Zend_Db_Expr
183: *
184: * @see escapeLikeValue()
185: */
186: public function getCILike($field, $value, $options = array())
187: {
188: $quotedField = $this->_getReadAdapter()->quoteIdentifier($field);
189: return new Zend_Db_Expr($quotedField . ' LIKE ' . $this->addLikeEscape($value, $options));
190: }
191:
192: /**
193: * Converts old pre-MMDB column definition for MySQL to new cross-db column DDL definition.
194: * Used to convert data from 3rd party extensions that hasn't been updated to MMDB style yet.
195: *
196: * E.g. Converts type 'varchar(255)' to array('type' => Varien_Db_Ddl_Table::TYPE_TEXT, 'length' => 255)
197: *
198: * @param array $column
199: * @return array
200: */
201: public function convertOldColumnDefinition($column)
202: {
203: // Match type and size - e.g. varchar(100) or decimal(12,4) or int
204: $matches = array();
205: $definition = trim($column['type']);
206: if (!preg_match('/([^(]*)(\\((.*)\\))?/', $definition, $matches)) {
207: throw Mage::exception(
208: 'Mage_Core',
209: Mage::helper('core')->__("Wrong old style column type definition: {$definition}.")
210: );
211: }
212:
213: $length = null;
214: $proposedLength = (isset($matches[3]) && strlen($matches[3])) ? $matches[3] : null;
215: switch (strtolower($matches[1])) {
216: case 'bool':
217: $length = null;
218: $type = Varien_Db_Ddl_Table::TYPE_BOOLEAN;
219: break;
220: case 'char':
221: case 'varchar':
222: case 'tinytext':
223: $length = $proposedLength;
224: if (!$length) {
225: $length = 255;
226: }
227: $type = Varien_Db_Ddl_Table::TYPE_TEXT;
228: break;
229: case 'text':
230: $length = $proposedLength;
231: if (!$length) {
232: $length = '64k';
233: }
234: $type = Varien_Db_Ddl_Table::TYPE_TEXT;
235: break;
236: case 'mediumtext':
237: $length = $proposedLength;
238: if (!$length) {
239: $length = '16M';
240: }
241: $type = Varien_Db_Ddl_Table::TYPE_TEXT;
242: break;
243: case 'longtext':
244: $length = $proposedLength;
245: if (!$length) {
246: $length = '4G';
247: }
248: $type = Varien_Db_Ddl_Table::TYPE_TEXT;
249: break;
250: case 'blob':
251: $length = $proposedLength;
252: if (!$length) {
253: $length = '64k';
254: }
255: $type = Varien_Db_Ddl_Table::TYPE_BLOB;
256: break;
257: case 'mediumblob':
258: $length = $proposedLength;
259: if (!$length) {
260: $length = '16M';
261: }
262: $type = Varien_Db_Ddl_Table::TYPE_BLOB;
263: break;
264: case 'longblob':
265: $length = $proposedLength;
266: if (!$length) {
267: $length = '4G';
268: }
269: $type = Varien_Db_Ddl_Table::TYPE_BLOB;
270: break;
271: case 'tinyint':
272: case 'smallint':
273: $type = Varien_Db_Ddl_Table::TYPE_SMALLINT;
274: break;
275: case 'mediumint':
276: case 'int':
277: $type = Varien_Db_Ddl_Table::TYPE_INTEGER;
278: break;
279: case 'bigint':
280: $type = Varien_Db_Ddl_Table::TYPE_BIGINT;
281: break;
282: case 'float':
283: $type = Varien_Db_Ddl_Table::TYPE_FLOAT;
284: break;
285: case 'decimal':
286: case 'numeric':
287: $length = $proposedLength;
288: $type = Varien_Db_Ddl_Table::TYPE_DECIMAL;
289: break;
290: case 'datetime':
291: $type = Varien_Db_Ddl_Table::TYPE_DATETIME;
292: break;
293: case 'timestamp':
294: case 'time':
295: $type = Varien_Db_Ddl_Table::TYPE_TIMESTAMP;
296: break;
297: case 'date':
298: $type = Varien_Db_Ddl_Table::TYPE_DATE;
299: break;
300: default:
301: throw Mage::exception(
302: 'Mage_Core',
303: Mage::helper('core')->__("Unknown old style column type definition: {$definition}.")
304: );
305: }
306:
307: $result = array(
308: 'type' => $type,
309: 'length' => $length,
310: 'unsigned' => $column['unsigned'],
311: 'nullable' => $column['is_null'],
312: 'default' => $column['default'],
313: 'identity' => stripos($column['extra'], 'auto_increment') !== false
314: );
315:
316: /**
317: * Process the case when 'is_null' prohibits null value, and 'default' proposed to be null.
318: * It just means that default value not specified, and we must remove it from column definition.
319: */
320: if (false === $column['is_null'] && null === $column['default']) {
321: unset($result['default']);
322: }
323:
324: return $result;
325: }
326: }
327: