PageRenderTime 54ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/cp/expressionengine/third_party/assets/upd.assets.php

https://bitbucket.org/sbeuken/artelux
PHP | 866 lines | 621 code | 121 blank | 124 comment | 64 complexity | 97677de31d0be9cbb28f43f54769d182 MD5 | raw file
  1. <?php if (! defined('BASEPATH')) exit('No direct script access allowed');
  2. // load dependencies
  3. if (! defined('PATH_THIRD')) define('PATH_THIRD', EE_APPPATH.'third_party/');
  4. require_once PATH_THIRD.'assets/config.php';
  5. /**
  6. * Assets Update
  7. *
  8. * @package Assets
  9. * @author Brandon Kelly <brandon@pixelandtonic.com>
  10. * @copyright Copyright (c) 2011 Pixel & Tonic, Inc
  11. */
  12. class Assets_upd
  13. {
  14. var $version = ASSETS_VER;
  15. /**
  16. * Constructor
  17. */
  18. function __construct($switch = TRUE)
  19. {
  20. // -------------------------------------------
  21. // Make a local reference to the EE super object
  22. // -------------------------------------------
  23. $this->EE =& get_instance();
  24. }
  25. /**
  26. * Install
  27. */
  28. function install()
  29. {
  30. $this->EE->load->dbforge();
  31. // -------------------------------------------
  32. // Add row to exp_modules
  33. // -------------------------------------------
  34. $this->EE->db->insert('modules', array(
  35. 'module_name' => ASSETS_NAME,
  36. 'module_version' => ASSETS_VER,
  37. 'has_cp_backend' => 'y',
  38. 'has_publish_fields' => 'n'
  39. ));
  40. // -------------------------------------------
  41. // Add rows to exp_actions
  42. // -------------------------------------------
  43. // file manager actions
  44. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'upload_file'));
  45. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_files_view_by_folders'));
  46. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_props'));
  47. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'save_props'));
  48. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_ordered_files_view'));
  49. // Indexing actions
  50. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_session_id'));
  51. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'start_index'));
  52. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'perform_index'));
  53. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'finish_index'));
  54. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_s3_buckets'));
  55. // folder/file CRUD actions
  56. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'move_folder'));
  57. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'rename_folder'));
  58. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'create_folder'));
  59. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'delete_folder'));
  60. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'view_file'));
  61. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'move_file'));
  62. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'delete_file'));
  63. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'view_thumbnail'));
  64. // field actions
  65. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'build_sheet'));
  66. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_selected_files'));
  67. // -------------------------------------------
  68. // Create the exp_assets table
  69. // -------------------------------------------
  70. $fields = array(
  71. 'file_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE, 'auto_increment' => TRUE),
  72. 'folder_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE, 'null' => FALSE),
  73. 'source_type' => array('type' => 'varchar', 'constraint' => 2, 'null' => FALSE, 'default' => 'ee'),
  74. 'source_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  75. 'filedir_id' => array('type' => 'int', 'constraint' => 4, 'unsigned' => TRUE),
  76. 'file_name' => array('type' => 'varchar', 'constraint' => 255, 'null' => FALSE),
  77. 'title' => array('type' => 'varchar', 'constraint' => 100),
  78. 'date' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  79. 'alt_text' => array('type' => 'tinytext'),
  80. 'caption' => array('type' => 'tinytext'),
  81. 'author' => array('type' => 'tinytext'),
  82. '`desc`' => array('type' => 'text'),
  83. 'location' => array('type' => 'tinytext'),
  84. 'keywords' => array('type' => 'text'),
  85. 'date_modified' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  86. 'kind' => array('type' => 'varchar', 'constraint' => 5),
  87. 'width' => array('type' => 'int', 'constraint' => 2),
  88. 'height' => array('type' => 'int', 'constraint' => 2),
  89. 'size' => array('type' => 'int', 'constraint' => 3),
  90. 'search_keywords' => array('type' => 'text')
  91. );
  92. $this->EE->dbforge->add_field($fields);
  93. $this->EE->dbforge->add_key('file_id', TRUE);
  94. $this->EE->dbforge->create_table('assets_files');
  95. $this->EE->db->query('ALTER TABLE exp_assets_files ADD UNIQUE unq_folder_id__file_name (folder_id, file_name)');
  96. // -------------------------------------------
  97. // Create the exp_assets_selections table
  98. // -------------------------------------------
  99. $fields = array(
  100. 'file_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  101. 'entry_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  102. 'field_id' => array('type' => 'int', 'constraint' => 6, 'unsigned' => TRUE),
  103. 'col_id' => array('type' => 'int', 'constraint' => 6, 'unsigned' => TRUE),
  104. 'row_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  105. 'var_id' => array('type' => 'int', 'constraint' => 6, 'unsigned' => TRUE),
  106. 'sort_order' => array('type' => 'int', 'constraint' => 4, 'unsigned' => TRUE),
  107. 'is_draft' => array('type' => 'TINYINT', 'constraint' => '1', 'unsigned' => TRUE, 'default' => 0)
  108. );
  109. $this->EE->dbforge->add_field($fields);
  110. $this->EE->dbforge->add_key('file_id');
  111. $this->EE->dbforge->add_key('entry_id');
  112. $this->EE->dbforge->add_key('field_id');
  113. $this->EE->dbforge->add_key('col_id');
  114. $this->EE->dbforge->add_key('row_id');
  115. $this->EE->dbforge->add_key('var_id');
  116. $this->EE->dbforge->create_table('assets_selections');
  117. // folder structure
  118. $fields = array(
  119. 'folder_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE, 'auto_increment' => TRUE),
  120. 'source_type' => array('type' => 'varchar', 'constraint' => 2, 'null' => FALSE, 'default' => 'ee'),
  121. 'folder_name' => array('type' => 'varchar', 'constraint' => 255, 'null' => FALSE),
  122. 'full_path' => array('type' => 'varchar', 'constraint' => 255),
  123. 'parent_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE, 'null' => TRUE),
  124. 'source_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  125. 'filedir_id' => array('type' => 'int', 'constraint' => 4, 'unsigned' => TRUE),
  126. );
  127. $this->EE->dbforge->add_field($fields);
  128. $this->EE->dbforge->add_key('folder_id', true);
  129. $this->EE->dbforge->create_table('assets_folders');
  130. $this->EE->db->query('ALTER TABLE exp_assets_folders ADD UNIQUE unq_source_type__source_id__filedir_id__parent_id__folder_name (`source_type`, `source_id`, `filedir_id`, `parent_id`, `folder_name`)');
  131. $this->EE->db->query('ALTER TABLE exp_assets_folders ADD UNIQUE unq_source_type__source_id__filedir_id__full_path (`source_type`, `source_id`, `filedir_id`, `full_path`)');
  132. // source information
  133. $fields = array(
  134. 'source_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE, 'auto_increment' => TRUE),
  135. 'source_type' => array('type' => 'varchar', 'constraint' => 2, 'null' => FALSE, 'default' => 's3'),
  136. 'name' => array('type' => 'varchar', 'constraint' => 255, 'null' => FALSE, 'default' => ''),
  137. 'settings' => array('type' => 'text', 'null' => FALSE)
  138. );
  139. $this->EE->dbforge->add_field($fields);
  140. $this->EE->dbforge->add_key('source_id', true);
  141. $this->EE->dbforge->create_table('assets_sources');
  142. $this->EE->db->query('ALTER TABLE exp_assets_sources ADD UNIQUE unq_source_type__source_id (`source_type`, `source_id`)');
  143. // table for temporary data during indexing
  144. $fields = array(
  145. 'session_id' => array('type' => 'char', 'constraint' => 36),
  146. 'source_type' => array('type' => 'varchar', 'constraint' => 2, 'null' => FALSE, 'default' => 'ee'),
  147. 'source_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  148. 'offset' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  149. 'uri' => array('type' => 'varchar', 'constraint' => 255),
  150. 'filesize' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  151. 'type' => array('type' => 'enum', 'constraint' => "'file','folder'"),
  152. 'record_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE)
  153. );
  154. $this->EE->dbforge->add_field($fields);
  155. $this->EE->dbforge->create_table('assets_index_data');
  156. $this->EE->db->query('ALTER TABLE `exp_assets_index_data` ADD UNIQUE unq__session_id__source_type__source_id__offset (`session_id`, `source_type`, `source_id`, `offset`)');
  157. return TRUE;
  158. }
  159. /**
  160. * Update
  161. */
  162. function update($current = '')
  163. {
  164. if ($current == $this->version)
  165. {
  166. return FALSE;
  167. }
  168. // -------------------------------------------
  169. // Require Assets 1.x => 2.x to take place from the module unless DevDemon Updater is running the show
  170. // -------------------------------------------
  171. if (version_compare($current, '2.0b2', '<'))
  172. {
  173. // Prevent the EE update wizard from running this
  174. if (get_class($this->EE) == 'Wizard')
  175. {
  176. return FALSE;
  177. }
  178. // is this DevDemon Updater?
  179. if (
  180. $this->EE->input->get('C') == 'addons_modules' &&
  181. $this->EE->input->get('M') == 'show_module_cp' &&
  182. $this->EE->input->get('module') == 'updater' &&
  183. $this->EE->input->get('method') == 'ajax_router' &&
  184. $this->EE->input->get('task') == 'addon_install'
  185. )
  186. {
  187. // make sure they're running Updater 3.1.6 or later, which checks database_backup_required()
  188. $version = $this->EE->db->select('module_version')->where('module_name', 'Updater')->get('modules')->row('module_version');
  189. if (version_compare($version, '3.1.6', '<'))
  190. {
  191. $this->EE->lang->loadfile('assets');
  192. exit(lang('updater_316_required'));
  193. }
  194. }
  195. else
  196. {
  197. // is this an MCP index request?
  198. $mcp_index = (
  199. $this->EE->input->get('C') == 'addons_modules' &&
  200. $this->EE->input->get('M') == 'show_module_cp' &&
  201. $this->EE->input->get('module') == 'assets' &&
  202. (($method = $this->EE->input->get('method')) === FALSE || $method == 'index')
  203. );
  204. if (!$mcp_index || $this->EE->input->get('goforth') != 'y')
  205. {
  206. if ($mcp_index)
  207. {
  208. // let the MCP know to display the DB backup message
  209. $this->EE->session->cache['assets']['show_dbbackup'] = TRUE;
  210. }
  211. else
  212. {
  213. // redirect to the MCP index
  214. $this->EE->functions->redirect(BASE.AMP.'C=addons_modules'.AMP.'M=show_module_cp'.AMP.'module=assets');
  215. }
  216. // cancel the update
  217. return FALSE;
  218. }
  219. }
  220. }
  221. // -------------------------------------------
  222. // Schema changes
  223. // -------------------------------------------
  224. if (version_compare($current, '0.2', '<'))
  225. {
  226. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_subfolders'));
  227. }
  228. if (version_compare($current, '0.3', '<'))
  229. {
  230. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'upload_file'));
  231. }
  232. if (version_compare($current, '0.4', '<'))
  233. {
  234. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'move_folder'));
  235. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'create_folder'));
  236. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'delete_folder'));
  237. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'move_file'));
  238. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'delete_file'));
  239. }
  240. if (version_compare($current, '0.5', '<'))
  241. {
  242. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'view_file'));
  243. }
  244. if (version_compare($current, '0.6', '<'))
  245. {
  246. // {filedir_x}/filename => {filedir_x}filename
  247. $this->EE->db->query('UPDATE exp_assets SET file_path = REPLACE(file_path, "}/", "}")');
  248. }
  249. if (version_compare($current, '0.7', '<'))
  250. {
  251. $this->EE->load->dbforge();
  252. // delete unused exp_assets columns
  253. $this->EE->dbforge->drop_column('assets', 'asset_kind');
  254. $this->EE->dbforge->drop_column('assets', 'file_dir');
  255. $this->EE->dbforge->drop_column('assets', 'file_name');
  256. $this->EE->dbforge->drop_column('assets', 'file_size');
  257. $this->EE->dbforge->drop_column('assets', 'sha1_hash');
  258. $this->EE->dbforge->drop_column('assets', 'img_width');
  259. $this->EE->dbforge->drop_column('assets', 'img_height');
  260. $this->EE->dbforge->drop_column('assets', 'date_added');
  261. $this->EE->dbforge->drop_column('assets', 'edit_date');
  262. // rename 'asset_date' to 'date', and move it after title
  263. $this->EE->db->query('ALTER TABLE exp_assets
  264. CHANGE COLUMN `asset_date` `date` INT(10) UNSIGNED NULL DEFAULT NULL AFTER `title`');
  265. }
  266. if (version_compare($current, '0.8', '<'))
  267. {
  268. // build_file_manager => build_sheet
  269. $this->EE->db->where('method', 'build_file_manager')
  270. ->update('actions', array('method' => 'build_sheet'));
  271. }
  272. if (version_compare($current, '1.0.1', '<'))
  273. {
  274. // tell EE about the fieldtype's global settings
  275. $this->EE->db->where('name', 'assets')
  276. ->update('fieldtypes', array('has_global_settings' => 'y'));
  277. }
  278. if (version_compare($current, '1.1.5', '<'))
  279. {
  280. $this->EE->load->dbforge();
  281. // do we need to add the var_id column to exp_assets_entries?
  282. // - the 1.1 update might have added this but then failed on another step, so the version wouldn't be updated
  283. $query = $this->EE->db->query('SHOW COLUMNS FROM `'.$this->EE->db->dbprefix.'assets_entries` LIKE "var_id"');
  284. if (! $query->num_rows())
  285. {
  286. $this->EE->db->query('ALTER TABLE exp_assets_entries ADD var_id INT(6) UNSIGNED AFTER row_id, ADD INDEX (var_id)');
  287. }
  288. else
  289. {
  290. // do we need to add its index?
  291. $query = $this->EE->db->query('SHOW INDEX FROM exp_assets_entries WHERE Key_name = "var_id"');
  292. if (! $query->num_rows())
  293. {
  294. $this->EE->db->query('ALTER TABLE exp_assets_entries ADD INDEX (var_id)');
  295. }
  296. }
  297. // do we need to add the unq_file_path index to exp_assets?
  298. // - the 1.1 update used to attempt to add this, but it would fail if there was a duplicate file_path
  299. $query = $this->EE->db->query('SHOW INDEX FROM exp_assets WHERE Key_name = "unq_file_path"');
  300. if (! $query->num_rows())
  301. {
  302. // are there any duplicate file_path's?
  303. $query = $this->EE->db->query('
  304. SELECT a.asset_id, a.file_path FROM exp_assets a
  305. INNER JOIN (
  306. SELECT file_path FROM exp_assets
  307. GROUP BY file_path HAVING count(asset_id) > 1
  308. ) dup ON a.file_path = dup.file_path');
  309. if ($query->num_rows())
  310. {
  311. $duplicates = array();
  312. foreach ($query->result() as $asset)
  313. {
  314. $duplicates[$asset->file_path][] = $asset->asset_id;
  315. }
  316. foreach ($duplicates as $file_path => $asset_ids)
  317. {
  318. $first_asset_id = array_shift($asset_ids);
  319. // point any entries that were using the duplicate IDs over to the first one
  320. $this->EE->db->where_in('asset_id', $asset_ids)
  321. ->update('assets_entries', array('asset_id' => $first_asset_id));
  322. // delete the duplicates in exp_assets
  323. $this->EE->db->where_in('asset_id', $asset_ids)
  324. ->delete('assets');
  325. }
  326. }
  327. // now that there are no more unique file_path's, add the unique index,
  328. // and drop the old file_path index, since that would be redundant
  329. $this->EE->db->query('ALTER TABLE exp_assets ADD UNIQUE unq_file_path (file_path), DROP INDEX file_path');
  330. }
  331. }
  332. if (version_compare($current, '2.0b1', '<'))
  333. {
  334. $this->EE->load->dbforge();
  335. // Set file_path to NOT NULL
  336. $this->EE->db->query('ALTER TABLE exp_assets MODIFY COLUMN file_path VARCHAR(255) NOT NULL');
  337. // on a clean 1.2.1 install, this index might not exist
  338. $query = $this->EE->db->query('SHOW INDEX FROM exp_assets WHERE Key_name = "unq_file_path"');
  339. if ($query->num_rows())
  340. {
  341. // Drop the unq_file_path index
  342. $this->EE->db->query('ALTER TABLE exp_assets DROP INDEX unq_file_path');
  343. }
  344. // Add all the fields to make exp_assets a functional index table
  345. $fields = array(
  346. 'source_type' => array('type' => 'varchar', 'constraint' => 2, 'null' => FALSE, 'default' => 'ee'),
  347. 'source_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  348. 'filedir_id' => array('type' => 'int', 'constraint' => 4, 'unsigned' => TRUE, 'null' => TRUE),
  349. 'folder_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  350. 'date_modified' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  351. 'kind' => array('type' => 'varchar', 'constraint' => 5),
  352. 'width' => array('type' => 'int', 'constraint' => 2),
  353. 'height' => array('type' => 'int', 'constraint' => 2),
  354. 'size' => array('type' => 'int', 'constraint' => 3),
  355. 'search_keywords' => array('type' => 'text')
  356. );
  357. $this->EE->dbforge->add_column('assets', $fields);
  358. $this->EE->db->query('ALTER TABLE exp_assets CHANGE `file_path` `file_name` VARCHAR (255) NOT NULL');
  359. // table for storing folder structure
  360. $fields = array(
  361. 'folder_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE, 'auto_increment' => TRUE),
  362. 'source_type' => array('type' => 'varchar', 'constraint' => 2, 'null' => FALSE, 'default' => 'ee'),
  363. 'folder_name' => array('type' => 'varchar', 'constraint' => 255, 'null' => FALSE),
  364. 'full_path' => array('type' => 'varchar', 'constraint' => 255),
  365. 'parent_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE, 'null' => TRUE),
  366. 'source_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  367. 'filedir_id' => array('type' => 'int', 'constraint' => 4, 'unsigned' => TRUE),
  368. );
  369. $this->EE->dbforge->add_field($fields);
  370. $this->EE->dbforge->add_key('folder_id', true);
  371. $this->EE->dbforge->create_table('assets_folders');
  372. // source information
  373. $fields = array(
  374. 'source_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE, 'auto_increment' => TRUE),
  375. 'source_type' => array('type' => 'varchar', 'constraint' => 2, 'null' => FALSE, 'default' => 's3'),
  376. 'name' => array('type' => 'varchar', 'constraint' => 255),
  377. 'settings' => array('type' => 'text', 'null' => FALSE)
  378. );
  379. $this->EE->dbforge->add_field($fields);
  380. $this->EE->dbforge->add_key('source_id', TRUE);
  381. $this->EE->dbforge->create_table('assets_sources');
  382. // Add new actions
  383. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'rename_folder'));
  384. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'view_thumbnail'));
  385. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_session_id'));
  386. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'start_index'));
  387. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'perform_index'));
  388. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'finish_index'));
  389. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_s3_buckets'));
  390. // some more table structure changes
  391. $this->EE->db->query("ALTER TABLE exp_assets RENAME TO exp_assets_files");
  392. $this->EE->db->query("ALTER TABLE exp_assets_files CHANGE `asset_id` `file_id` INT(10) NOT NULL AUTO_INCREMENT");
  393. $this->EE->db->query("ALTER TABLE exp_assets_entries RENAME TO exp_assets_selections");
  394. $this->EE->db->query("ALTER TABLE exp_assets_selections CHANGE `asset_order` `sort_order` INT(4) UNSIGNED");
  395. $this->EE->db->query("ALTER TABLE exp_assets_selections CHANGE `asset_id` `file_id` INT(10)");
  396. // migrate the existing data
  397. $this->_migrate_data('<2 -> 2.0');
  398. // Add the unique indexes
  399. $this->EE->db->query('ALTER TABLE exp_assets_files ADD UNIQUE unq_folder_id__file_name (folder_id, file_name)');
  400. $this->EE->db->query('ALTER TABLE exp_assets_folders ADD UNIQUE unq_source_type__source_id__parent_id__folder_name (`source_type`, `source_id`, `parent_id`, `folder_name`)');
  401. $this->EE->db->query('ALTER TABLE exp_assets_folders ADD UNIQUE unq_source_type__source_id__full_path (`source_type`, `source_id`, `full_path`)');
  402. $this->EE->db->query('ALTER TABLE exp_assets_sources ADD UNIQUE unq_source_type__source_id (`source_type`, `source_id`)');
  403. // table for temporary data during indexing
  404. $fields = array(
  405. 'session_id' => array('type' => 'char', 'constraint' => 36),
  406. 'source_type' => array('type' => 'varchar', 'constraint' => 2),
  407. 'source_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  408. 'offset' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  409. 'uri' => array('type' => 'varchar', 'constraint' => 255),
  410. 'filesize' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE),
  411. 'type' => array('type' => 'enum', 'constraint' => "'file','folder'"),
  412. 'record_id' => array('type' => 'int', 'constraint' => 10, 'unsigned' => TRUE)
  413. );
  414. $this->EE->dbforge->add_field($fields);
  415. $this->EE->dbforge->create_table('assets_index_data');
  416. $this->EE->db->query('ALTER TABLE `exp_assets_index_data` ADD UNIQUE unq__session_id__source_type__source_id__offset (`session_id`, `source_type`, `source_id`, `offset`)');
  417. }
  418. elseif (version_compare($current, '2.0b2', '<'))
  419. {
  420. // add the new actions
  421. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_session_id'));
  422. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'start_index'));
  423. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'perform_index'));
  424. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'finish_index'));
  425. $this->EE->db->insert('actions', array('class' => 'Assets_mcp', 'method' => 'get_s3_buckets'));
  426. // files
  427. $this->EE->db->query("ALTER TABLE exp_assets_files CHANGE COLUMN `connector` `source_type` VARCHAR(2) NOT NULL DEFAULT 'ee'");
  428. $this->EE->db->query("ALTER TABLE exp_assets_files ADD COLUMN `source_id` INT(10) UNSIGNED NULL AFTER `source_type`");
  429. $this->EE->db->query("ALTER TABLE exp_assets_files ADD COLUMN `filedir_id` INT(4) UNSIGNED NULL AFTER `source_id`");
  430. $this->EE->db->query("ALTER TABLE exp_assets_files CHANGE COLUMN `folder_id` `folder_id` INT(10) UNSIGNED NULL");
  431. // folders
  432. $this->EE->db->query("ALTER TABLE exp_assets_folders CHANGE COLUMN `connector` `source_type` VARCHAR(2) NOT NULL DEFAULT 'ee'");
  433. $this->EE->db->query("ALTER TABLE exp_assets_folders CHANGE COLUMN `pref_id` `source_id` INT(10) UNSIGNED NULL");
  434. $this->EE->db->query("ALTER TABLE exp_assets_folders ADD COLUMN `filedir_id` INT(4) UNSIGNED NULL AFTER `source_id`");
  435. $this->EE->db->query('ALTER TABLE exp_assets_folders DROP INDEX unq_connector__parent_id__folder_name');
  436. $this->EE->db->query('ALTER TABLE exp_assets_folders DROP INDEX unq_connector__pref_id__full_path');
  437. $this->EE->db->query('ALTER TABLE exp_assets_folders ADD UNIQUE unq_source_type__source_id__filedir_id__parent_id__folder_name (`source_type`, `source_id`, `filedir_id`, `parent_id`, `folder_name`)');
  438. $this->EE->db->query('ALTER TABLE exp_assets_folders ADD UNIQUE unq_source_type__source_id__filedir_id__full_path (`source_type`, `source_id`, `filedir_id`, `full_path`)');
  439. // index_data
  440. $this->EE->db->query("ALTER TABLE exp_assets_sync_data RENAME TO exp_assets_index_data");
  441. $this->EE->db->query("ALTER TABLE exp_assets_index_data CHANGE COLUMN `sync_session` `session_id` CHAR(36) NULL");
  442. $this->EE->db->query("ALTER TABLE exp_assets_index_data ADD COLUMN `source_type` VARCHAR(2) AFTER `session_id`");
  443. $this->EE->db->query("ALTER TABLE exp_assets_index_data CHANGE COLUMN `folder_id` `source_id` INT(10) UNSIGNED NULL");
  444. $this->EE->db->query('ALTER TABLE exp_assets_index_data DROP INDEX `sync_index`');
  445. $this->EE->db->query('ALTER TABLE exp_assets_index_data ADD UNIQUE unq__session_id__source_type__source_id__offset (`session_id`, `source_type`, `source_id`, `offset`)');
  446. // sources
  447. $this->EE->db->query("ALTER TABLE exp_assets_folder_prefs RENAME TO exp_assets_sources");
  448. $this->EE->db->query("ALTER TABLE exp_assets_sources CHANGE COLUMN `pref_id` `source_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY");
  449. $this->EE->db->query("ALTER TABLE exp_assets_sources CHANGE COLUMN `connector` `source_type` VARCHAR(2) NOT NULL DEFAULT 's3'");
  450. $this->EE->db->query("ALTER TABLE exp_assets_sources ADD COLUMN `name` VARCHAR(255) DEFAULT '' AFTER `source_type`");
  451. $this->EE->db->query("ALTER TABLE exp_assets_sources CHANGE COLUMN `data` `settings` TEXT NOT NULL DEFAULT ''");
  452. $this->_migrate_data('2.0b1 -> 2.0b2');
  453. }
  454. if (version_compare($current, '2.0b4', '<')){
  455. $this->EE->load->dbforge();
  456. $fields = array(
  457. 'is_draft' => array('type' => 'TINYINT', 'constraint' => '1', 'unsigned' => TRUE, 'default' => 0)
  458. );
  459. $this->EE->dbforge->add_column('assets_selections', $fields);
  460. $this->EE->db->query("ALTER TABLE exp_assets_files MODIFY COLUMN `folder_id` INT(10) NOT NULL AFTER `file_id`");
  461. $this->EE->db->query("ALTER TABLE exp_assets_files MODIFY COLUMN `source_type` VARCHAR(2) NOT NULL DEFAULT 'ee' AFTER `folder_id`");
  462. $this->EE->db->query("ALTER TABLE exp_assets_files MODIFY COLUMN `source_id` INT(10) UNSIGNED NULL AFTER `source_type`");
  463. $this->EE->db->query("ALTER TABLE exp_assets_files MODIFY COLUMN `filedir_id` INT(4) UNSIGNED NULL AFTER `source_id`");
  464. $this->EE->db->query('UPDATE exp_modules SET module_version = "2.0" WHERE module_name = "Assets"');
  465. return FALSE;
  466. }
  467. // -------------------------------------------
  468. // Update version number in exp_fieldtypes and exp_extensions
  469. // -------------------------------------------
  470. $this->EE->db->where('name', 'assets')
  471. ->update('fieldtypes', array('version' => ASSETS_VER));
  472. $this->EE->db->where('class', 'Assets_ext')
  473. ->update('extensions', array('version' => ASSETS_VER));
  474. return TRUE;
  475. }
  476. /**
  477. * Uninstall
  478. */
  479. function uninstall()
  480. {
  481. $this->EE->load->dbforge();
  482. // routine EE table cleanup
  483. $this->EE->db->select('module_id');
  484. $module_id = $this->EE->db->get_where('modules', array('module_name' => 'Assets'))->row('module_id');
  485. $this->EE->db->where('module_id', $module_id);
  486. $this->EE->db->delete('module_member_groups');
  487. $this->EE->db->where('module_name', 'Assets');
  488. $this->EE->db->delete('modules');
  489. $this->EE->db->where('class', 'Assets');
  490. $this->EE->db->delete('actions');
  491. $this->EE->db->where('class', 'Assets_mcp');
  492. $this->EE->db->delete('actions');
  493. // drop Assets tables
  494. $this->EE->dbforge->drop_table('assets_files');
  495. $this->EE->dbforge->drop_table('assets_selections');
  496. $this->EE->dbforge->drop_table('assets_sources');
  497. $this->EE->dbforge->drop_table('assets_folders');
  498. $this->EE->dbforge->drop_table('assets_index_data');
  499. $cache_path = $this->EE->config->item('cache_path');
  500. if (empty($cache_path))
  501. {
  502. $cache_path = APPPATH.'cache/';
  503. }
  504. $this->_delete_recursively($cache_path . 'assets');
  505. return TRUE;
  506. }
  507. /**
  508. * Delete folder recursively
  509. * @param $folder
  510. */
  511. private function _delete_recursively($folder)
  512. {
  513. foreach(glob($folder . '/*') as $file)
  514. {
  515. if(is_dir($file))
  516. {
  517. $this->_delete_recursively($file);
  518. }
  519. else
  520. {
  521. @unlink($file);
  522. }
  523. }
  524. @rmdir($folder);
  525. }
  526. /**
  527. * Migrate data according to a scenario
  528. * @param $scenario
  529. */
  530. private function _migrate_data($scenario)
  531. {
  532. $this->EE = get_instance();
  533. $db = $this->EE->db;
  534. $this->EE->load->library('assets_lib');
  535. clearstatcache();
  536. switch ($scenario)
  537. {
  538. case '<2 -> 2.0':
  539. require_once(PATH_THIRD . 'assets/sources/ee/source.ee.php');
  540. $filedirs = array();
  541. $folder_list = array();
  542. // load upload preferences and store them in table for Assets
  543. $rows = $db->get('upload_prefs')->result();
  544. foreach ($rows as $filedir)
  545. {
  546. $filedirs[$filedir->id] = Assets_ee_source::apply_filedir_overrides($filedir);
  547. }
  548. // load physical folder structure
  549. foreach ($filedirs as $id => $filedir)
  550. {
  551. $filedir->server_path = Assets_ee_source::resolve_server_path($filedir->server_path);
  552. $folder_list[$id][] = $filedir->server_path;
  553. $this->_load_folder_structure($filedir->server_path, $folder_list[$id]);
  554. }
  555. // store the folder structure in database
  556. $subfolders = array();
  557. foreach ($folder_list as $filedir_id => $folders)
  558. {
  559. $filedir = $filedirs[$filedir_id];
  560. foreach ($folders as $folder)
  561. {
  562. $subpath = substr($folder, strlen($filedir->server_path));
  563. if (empty($subpath))
  564. {
  565. $folder_name = $filedir->name;
  566. $parent_id = NULL;
  567. }
  568. else
  569. {
  570. $path_parts = explode('/', $subpath);
  571. $folder_name = array_pop($path_parts);
  572. $parent_key = $filedir_id . ':' . rtrim(join('/', $path_parts), '/');
  573. $parent_id = isset($subfolders[$parent_key]) ? $subfolders[$parent_key] : 0;
  574. }
  575. // in case false was returned earlier
  576. $subpath = $subpath ? rtrim($subpath, '/') . '/' : '';
  577. $folder_entry = array(
  578. 'source_type' => 'ee',
  579. 'filedir_id' => $filedir_id,
  580. 'folder_name' => $folder_name,
  581. 'full_path' => $subpath
  582. );
  583. if ( ! is_null($parent_id))
  584. {
  585. $folder_entry['parent_id'] = $parent_id;
  586. }
  587. $this->EE->db->insert('assets_folders', $folder_entry);
  588. $subfolders[$filedir_id . ':' . rtrim($subpath, '/')] = $this->EE->db->insert_id();
  589. }
  590. }
  591. // bring up the list of existing assets and update the entries
  592. $rows = $db->get('assets_files')->result();
  593. $pattern = '/\{filedir_(?P<filedir_id>[0-9]+)\}(?P<path>.*)/';
  594. foreach ($rows as $asset)
  595. {
  596. $asset->connector = 'ee';
  597. if (preg_match($pattern, $asset->file_name, $matches))
  598. {
  599. if (isset($filedirs[$matches['filedir_id']]))
  600. {
  601. $filedir = $filedirs[$matches['filedir_id']];
  602. $full_path = str_replace('{filedir_' . $filedir->id . '}', $filedir->server_path, $asset->file_name);
  603. $subpath = substr($full_path, strlen($filedir->server_path));
  604. $path_parts = explode('/', $subpath);
  605. $file = array_pop($path_parts);
  606. $subpath = join('/', $path_parts);
  607. $folder_key = $matches['filedir_id'] . ':' . $subpath;
  608. if (isset($subfolders[$folder_key]))
  609. {
  610. $folder_id = $subfolders[$folder_key];
  611. $kind = Assets_helper::get_kind($full_path);
  612. $data = array(
  613. 'source_type' => 'ee',
  614. 'filedir_id' => $filedir->id,
  615. 'folder_id' => $folder_id,
  616. 'file_name' => $file,
  617. 'kind' => $kind,
  618. );
  619. if (file_exists($full_path))
  620. {
  621. $data['size'] = filesize($full_path);
  622. $data['date_modified'] = filemtime($full_path);
  623. if ($kind == 'image')
  624. {
  625. list ($width, $height) = getimagesize($full_path);
  626. $data['width'] = $width;
  627. $data['height'] = $height;
  628. }
  629. }
  630. $this->EE->db->update('assets_files', $data, array('file_id' => $asset->file_id));
  631. $this->EE->assets_lib->update_file_search_keywords($asset->file_id);
  632. }
  633. }
  634. }
  635. }
  636. // celebrate
  637. break;
  638. case '2.0b1 -> 2.0b2':
  639. // get S3 credentials if any
  640. $query = $this->EE->db->select('settings')
  641. ->where('name', 'assets')
  642. ->get('fieldtypes');
  643. $settings = unserialize(base64_decode($query->row('settings')));
  644. $settings = array_merge(array('license_key' => '', 's3_access_key_id' => '', 's3_secret_access_key' => ''), $settings);
  645. //if we have s3 settings, let's convert the "folder_prefs" way to "sources" way
  646. if (!empty($settings['s3_access_key_id']) && !empty($settings['s3_secret_access_key']))
  647. {
  648. $old_sources = $this->EE->db->get('assets_sources')->result();
  649. foreach ($old_sources as $source)
  650. {
  651. $previous_settings = json_decode($source->settings);
  652. $new_settings = (object) array(
  653. 'access_key_id' => $settings['s3_access_key_id'],
  654. 'secret_access_key' => $settings['s3_secret_access_key'],
  655. 'bucket' => $previous_settings->name,
  656. 'url_prefix' => $previous_settings->url_prefix,
  657. 'location' => $previous_settings->location
  658. );
  659. $data = array(
  660. 'name' => $previous_settings->name,
  661. 'settings' => json_encode($new_settings)
  662. );
  663. $this->EE->db->update('assets_sources', $data, array('source_id' => $source->source_id));
  664. }
  665. }
  666. // modify folder data and also keep a list of who's who
  667. $folders = $this->EE->db->get('assets_folders')->result();
  668. $folder_sources = array();
  669. foreach ($folders as $row)
  670. {
  671. if ($row->source_type == 'ee')
  672. {
  673. $row->filedir_id = $row->source_id;
  674. $row->source_id = NULL;
  675. $this->EE->db->update('assets_folders', $row, array('folder_id' => $row->folder_id));
  676. $folder_sources[$row->folder_id] = $row->filedir_id;
  677. }
  678. else
  679. {
  680. $folder_sources[$row->folder_id] = $row->source_id;
  681. }
  682. }
  683. // add some data for file entries and we're done!
  684. $files = $this->EE->db->get('assets_files')->result();
  685. foreach ($files as $row)
  686. {
  687. if ($row->source_type == 'ee' && isset($folder_sources[$row->folder_id]))
  688. {
  689. $row->source_id = NULL;
  690. $row->filedir_id = $folder_sources[$row->folder_id];
  691. $this->EE->db->update('assets_files', $row, array('file_id' => $row->file_id));
  692. }
  693. else if (isset($folder_sources[$row->folder_id]))
  694. {
  695. $row->source_id = $folder_sources[$row->folder_id];
  696. $row->filedir_id = NULL;
  697. $this->EE->db->update('assets_files', $row, array('file_id' => $row->file_id));
  698. }
  699. }
  700. // party!
  701. break;
  702. }
  703. }
  704. /**
  705. * Load the folder structure for data migration
  706. *
  707. * @param $path
  708. * @param $folder_structure
  709. */
  710. private function _load_folder_structure($path, &$folder_structure)
  711. {
  712. // starting with underscore or dot gets ignored
  713. $list = glob($path . '[!_.]*', GLOB_MARK);
  714. if (is_array($list) && count($list) > 0)
  715. {
  716. foreach ($list as $item)
  717. {
  718. // parse folders and add files
  719. $item = Assets_helper::normalize_path($item);
  720. if (substr($item, -1) == '/')
  721. {
  722. // add with dropped slash and parse
  723. $folder_structure[] = substr($item, 0, -1);
  724. $this->_load_folder_structure($item, $folder_structure);
  725. }
  726. }
  727. }
  728. }
  729. /**
  730. * Return true if updating from the $current version requires a DB backup
  731. * @param $current
  732. * @return bool
  733. */
  734. public function database_backup_required($current)
  735. {
  736. if (version_compare($current, '2.0', '<'))
  737. {
  738. return TRUE;
  739. }
  740. else
  741. {
  742. return FALSE;
  743. }
  744. }
  745. }