content.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php
  2. /**
  3. * ownCloud
  4. *
  5. * @author Tom Needham
  6. * @copyright 2012 Tom Needham tom@owncloud.com
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  10. * License as published by the Free Software Foundation; either
  11. * version 3 of the License, or any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public
  19. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. /**
  23. * provides methods to add and access data from the migration
  24. */
  25. class OC_Migration_Content{
  26. private $zip=false;
  27. // Holds the MDB2 object
  28. private $db=null;
  29. // Holds an array of tmpfiles to delete after zip creation
  30. private $tmpfiles=false;
  31. /**
  32. * @brief sets up the
  33. * @param $zip ZipArchive object
  34. * @param optional $db a MDB2 database object (required for exporttype user)
  35. * @return bool
  36. */
  37. public function __construct( $zip, $db=null ){
  38. $this->zip = $zip;
  39. $this->db = $db;
  40. if( !is_null( $db ) ){
  41. // Get db path
  42. $db = $this->db->getDatabase();
  43. $this->tmpfiles[] = $db;
  44. }
  45. }
  46. // @brief prepares the db
  47. // @param $query the sql query to prepare
  48. public function prepare( $query ){
  49. // Optimize the query
  50. $query = $this->processQuery( $query );
  51. // Optimize the query
  52. $query = $this->db->prepare( $query );
  53. // Die if we have an error (error means: bad query, not 0 results!)
  54. if( PEAR::isError( $query ) ) {
  55. $entry = 'DB Error: "'.$result->getMessage().'"<br />';
  56. $entry .= 'Offending command was: '.$query.'<br />';
  57. OC_Log::write( 'migration', $entry, OC_Log::FATAL );
  58. return false;
  59. } else {
  60. return $query;
  61. }
  62. }
  63. /**
  64. * @brief processes the db query
  65. * @param $query the query to process
  66. * @return string of processed query
  67. */
  68. private function processQuery( $query ){
  69. $query = str_replace( '`', '\'', $query );
  70. $query = str_replace( 'NOW()', 'datetime(\'now\')', $query );
  71. $query = str_replace( 'now()', 'datetime(\'now\')', $query );
  72. // remove table prefixes
  73. $query = str_replace( '*PREFIX*', '', $query );
  74. return $query;
  75. }
  76. /**
  77. * @brief copys rows to migration.db from the main database
  78. * @param $options array of options.
  79. * @return bool
  80. */
  81. public function copyRows( $options ){
  82. if( !array_key_exists( 'table', $options ) ){
  83. return false;
  84. }
  85. $return = array();
  86. // Need to include 'where' in the query?
  87. if( array_key_exists( 'matchval', $options ) && array_key_exists( 'matchcol', $options ) ){
  88. // If only one matchval, create an array
  89. if(!is_array($options['matchval'])){
  90. $options['matchval'] = array( $options['matchval'] );
  91. }
  92. foreach( $options['matchval'] as $matchval ){
  93. // Run the query for this match value (where x = y value)
  94. $sql = "SELECT * FROM *PREFIX*" . $options['table'] . " WHERE " . $options['matchcol'] . " LIKE ?";
  95. $query = OC_DB::prepare( $sql );
  96. $results = $query->execute( array( $matchval ) );
  97. $newreturns = $this->insertData( $results, $options );
  98. $return = array_merge( $return, $newreturns );
  99. }
  100. } else {
  101. // Just get everything
  102. $sql = "SELECT * FROM *PREFIX*" . $options['table'];
  103. $query = OC_DB::prepare( $sql );
  104. $results = $query->execute();
  105. $return = $this->insertData( $results, $options );
  106. }
  107. return $return;
  108. }
  109. /**
  110. * @brief saves a sql data set into migration.db
  111. * @param $data a sql data set returned from self::prepare()->query()
  112. * @param $options array of copyRows options
  113. * @return void
  114. */
  115. private function insertData( $data, $options ){
  116. $return = array();
  117. // Foreach row of data to insert
  118. while( $row = $data->fetchRow() ){
  119. // Now save all this to the migration.db
  120. foreach($row as $field=>$value){
  121. $fields[] = $field;
  122. $values[] = $value;
  123. }
  124. // Generate some sql
  125. $sql = "INSERT INTO `" . $options['table'] . '` ( `';
  126. $fieldssql = implode( '`, `', $fields );
  127. $sql .= $fieldssql . "` ) VALUES( ";
  128. $valuessql = substr( str_repeat( '?, ', count( $fields ) ),0,-2 );
  129. $sql .= $valuessql . " )";
  130. // Make the query
  131. $query = $this->prepare( $sql );
  132. if( !$query ){
  133. OC_Log::write( 'migration', 'Invalid sql produced: '.$sql, OC_Log::FATAL );
  134. return false;
  135. exit();
  136. } else {
  137. $query->execute( $values );
  138. // Do we need to return some values?
  139. if( array_key_exists( 'idcol', $options ) ){
  140. // Yes we do
  141. $return[] = $row[$options['idcol']];
  142. } else {
  143. // Take a guess and return the first field :)
  144. $return[] = reset($row);
  145. }
  146. }
  147. $fields = '';
  148. $values = '';
  149. }
  150. return $return;
  151. }
  152. /**
  153. * @brief adds a directory to the zip object
  154. * @param $dir string path of the directory to add
  155. * @param $recursive bool
  156. * @param $internaldir string path of folder to add dir to in zip
  157. * @return bool
  158. */
  159. public function addDir( $dir, $recursive=true, $internaldir='' ) {
  160. $dirname = basename($dir);
  161. $this->zip->addEmptyDir($internaldir . $dirname);
  162. $internaldir.=$dirname.='/';
  163. if( !file_exists( $dir ) ){
  164. return false;
  165. }
  166. if ($dirhandle = opendir($dir)) {
  167. while (false !== ( $file = readdir($dirhandle))) {
  168. if (( $file != '.' ) && ( $file != '..' )) {
  169. if (is_dir($dir . '/' . $file) && $recursive) {
  170. $this->addDir($dir . '/' . $file, $recursive, $internaldir);
  171. } elseif (is_file($dir . '/' . $file)) {
  172. $this->zip->addFile($dir . '/' . $file, $internaldir . $file);
  173. }
  174. }
  175. }
  176. closedir($dirhandle);
  177. } else {
  178. OC_Log::write('admin_export',"Was not able to open directory: " . $dir,OC_Log::ERROR);
  179. return false;
  180. }
  181. return true;
  182. }
  183. /**
  184. * @brief adds a file to the zip from a given string
  185. * @param $data string of data to add
  186. * @param $path the relative path inside of the zip to save the file to
  187. * @return bool
  188. */
  189. public function addFromString( $data, $path ){
  190. // Create a temp file
  191. $file = tempnam( get_temp_dir(). '/', 'oc_export_tmp_' );
  192. $this->tmpfiles[] = $file;
  193. if( !file_put_contents( $file, $data ) ){
  194. OC_Log::write( 'migation', 'Failed to save data to a temporary file', OC_Log::ERROR );
  195. return false;
  196. }
  197. // Add file to the zip
  198. $this->zip->addFile( $file, $path );
  199. return true;
  200. }
  201. /**
  202. * @brief closes the zip, removes temp files
  203. * @return bool
  204. */
  205. public function finish(){
  206. if( !$this->zip->close() ){
  207. OC_Log::write( 'migration', 'Failed to write the zip file with error: '.$this->zip->getStatusString(), OC_Log::ERROR );
  208. return false;
  209. }
  210. $this->cleanup();
  211. return true;
  212. }
  213. /**
  214. * @brief cleans up after the zip
  215. */
  216. private function cleanup(){
  217. // Delete tmp files
  218. foreach($this->tmpfiles as $i){
  219. unlink( $i );
  220. }
  221. }
  222. }