migrate.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <?php
  2. /**
  3. * Tidypics file plugin migration
  4. *
  5. * Supports moving photos from the files plugin to Tidypics. All of a users
  6. * photos end up in a single album.
  7. *
  8. * Not supported
  9. */
  10. // need access to ElggDiskFilestore::make_file_matrix(), which is protected.
  11. // this is a PITA.
  12. class tempFilestore extends ElggDiskFilestore {
  13. public function make_file_matrix($filename) {
  14. return parent::make_file_matrix($filename);
  15. }
  16. }
  17. $filestore = new tempFilestore();
  18. /**
  19. * Migrates all pics from files to tidypics.
  20. *
  21. */
  22. function tidypics_migrate_pics() {
  23. $limit = 100;
  24. $r = true;
  25. // migrate
  26. // @todo: should this return false since there was no error?
  27. if (!$users = tidypics_get_user_guids_with_pics_in_files(0, $limit)) {
  28. return $r;
  29. }
  30. //echo "Grabbed " . count($users) . " users\n";
  31. while (is_array($users) AND count($users) > 0) {
  32. foreach ($users as $user_guid) {
  33. // reset the query cache.
  34. $DB_QUERY_CACHE = array();
  35. if (!$user = get_entity($user_guid)) {
  36. continue;
  37. }
  38. $r = tidypics_migrate_user_pics($user);
  39. }
  40. //echo "Trying to grab $limit more users...\n";
  41. $offset = $offset + $limit;
  42. $users = tidypics_get_user_guids_with_pics_in_files($offset, $limit);
  43. }
  44. return $r;
  45. }
  46. /**
  47. * Migrates all pictures owned by a user regardless of
  48. * if they're group or user files.
  49. *
  50. * @param ElggUser $user User to migrate.
  51. * @return bool on success
  52. */
  53. function tidypics_migrate_user_pics(ElggUser $user) {
  54. global $CONFIG, $filestore;
  55. $user_guid = $user->getGUID();
  56. // update all entity subtypes in a single go at the end.
  57. $updated_guids = array();
  58. if (!$pics = tidypics_get_user_pics_from_files($user_guid) OR count($pics) < 1) {
  59. return false;
  60. }
  61. //echo "{$user->name} ({$user->getGUID()}) has " . count($pics) . " pics.\n";
  62. // get an album to migrate into if it already exists.
  63. // will create later on if it doesn't.
  64. $user_album_entities = elgg_get_entities_from_metadata(array('metadata_name' => 'migrated_from_files',
  65. 'metadata_value' => true,
  66. 'type' => 'object',
  67. 'subtype' => 'album',
  68. 'owner_guid' => $user->getGUID(),
  69. 'limit' => 1));
  70. $user_album_guid = isset($album_entities[0]) ? $album_entities[0]->getGUID() : false;
  71. // a list of albums to randomly select a cover for on newly created albums.
  72. $new_album_guids = array();
  73. foreach ($pics as $pic) {
  74. // check that it's not already in tidy pics
  75. if (false !== strpos($pic->filename, 'image/')) {
  76. //echo "{$pic->filename} ({$pic->getGUID()}) looks like it's already in tidy pics. Ignoring.\n";
  77. continue;
  78. }
  79. // blank some vars
  80. $group_pic = $group_album_guid = $group_guid = false;
  81. // see if we're doing a group file migration.
  82. if ($pic->container_guid != $user->getGUID()
  83. AND $group = get_entity($pic->container_guid)
  84. AND $group instanceof ElggGroup
  85. ) {
  86. //echo "{$pic->getGUID()} is in a group!\n";
  87. $group_pic = true;
  88. $group_guid = $group->getGUID();
  89. // yes, this is how you get entities by container_guid.
  90. // yes, it's wrong, wrong, wrong for this function to work this way.
  91. $group_album_entities = elgg_get_entities(array('type' => 'object', 'subtype' => 'album', 'owner_guid' => $group_guid));
  92. // get_entities_from_metadata doesn't support container_guid (or owner_guid meaning container_guid)
  93. // do it the hard way.
  94. if (is_array($group_album_entities)) {
  95. foreach ($group_album_entities as $group_album) {
  96. if ($group_album->migrated_from_files == true) {
  97. $group_album_guid = $group_album->getGUID();
  98. break;
  99. }
  100. }
  101. }
  102. $album_guid = $group_album_guid;
  103. $group_album_guids[] = $group_album_guid;
  104. } else {
  105. $album_guid = $user_album_guid;
  106. }
  107. //echo "album_guid is $album_guid and group_pic is: $group_pic\n";
  108. // create an album if we need to.
  109. if (!$album_guid) {
  110. //echo "Creating new album...\n";
  111. $album = new ElggObject();
  112. $album->subtype = 'album';
  113. $album->new_album = TP_NEW_ALBUM;
  114. if ($group_pic) {
  115. $album->container_guid = $group_guid;
  116. $album->owner_guid = $group->owner_guid;
  117. $album->access_id = $group->group_acl;
  118. $album->title = $group->name;
  119. } else {
  120. $album->container_guid = $user_guid;
  121. $album->owner_guid = $user->getGUID();
  122. $album->access_id = ACCESS_DEFAULT;
  123. $album->title = $user->name;
  124. }
  125. if (!$album->save()) {
  126. //echo "Couldn't migrate pics for {$user->name} ($user_guid)!\n";
  127. return false;
  128. }
  129. $album->migrated_from_files = true;
  130. $album_guid = $album->getGUID();
  131. $new_album_guids[] = $album_guid;
  132. // save the album guid as the users
  133. if (!$group_pic) {
  134. $user_album_guid = $album_guid;
  135. }
  136. }
  137. if (!tidypics_migrate_pic_from_files($pic, $album_guid)) {
  138. //echo "{$pic->filename} ({$pic->getGUID()}) Couldn't be migrated. Ignoring.\n";
  139. continue;
  140. }
  141. }
  142. // randomly pic an image to be the cover for the user gallery
  143. //$album->cover = $pic_guids[array_rand($pic_guids)];
  144. foreach ($new_album_guids as $guid) {
  145. tidypics_set_random_cover_pic($guid);
  146. }
  147. return true;
  148. }
  149. /**
  150. * Randomly pics an image from an album to be the cover.
  151. * @return bool on success
  152. */
  153. function tidypics_set_random_cover_pic($album_guid) {
  154. global $CONFIG;
  155. if ($album = get_entity($album_guid) AND $album instanceof TidypicsAlbum) {
  156. $q = "SELECT guid FROM {$CONFIG->dbprefix}entities WHERE container_guid = $album_guid ORDER BY RAND() limit 1";
  157. $pic = get_data($q);
  158. return $album->cover = $pic[0]->guid;
  159. }
  160. return false;
  161. }
  162. /**
  163. * Migrates a single pic from the file repo.
  164. * @return bool on succes.
  165. */
  166. function tidypics_migrate_pic_from_files($pic, $album_guid) {
  167. global $CONFIG, $filestore;
  168. // get the subtype id.
  169. $image_subtype_id = get_subtype_id('object', 'image');
  170. // hold which metadata on the files need to be changes
  171. // also holds the images we need to move
  172. $file_md_fields = array('filename', 'thumbnail', 'smallthumb', 'largethumb');
  173. if (!$user = get_entity($pic->owner_guid)) {
  174. return false;
  175. }
  176. // figure out where to move the files.
  177. $matrix = $filestore->make_file_matrix($user->username);
  178. $user_fs_path = $CONFIG->dataroot . $matrix;
  179. $album_fs_path = $CONFIG->dataroot . $matrix . "image/$album_guid/";
  180. if (!is_dir($album_fs_path)) {
  181. if (!mkdir($album_fs_path, 0700, true)) {
  182. return false;
  183. }
  184. }
  185. // change all the 'file/'s to 'image/'s in certain metadata
  186. // these are also the files we need to move.
  187. foreach ($file_md_fields as $md_name) {
  188. // $pic->$md_name = str_replace('file/', 'image/', $pic->$md_name);
  189. $old_file = $pic->$md_name;
  190. $new_file = str_replace('file/', "image/$album_guid", $old_file);
  191. if (!($old_fp = fopen($user_fs_path . $old_file, 'r')
  192. AND $new_fp = fopen($user_fs_path . $new_file, 'w'))) {
  193. //echo "Could not move {$user_fs_path}{$old_file} to {$user_fs_path}{$new_file}\n";
  194. continue;
  195. }
  196. while (!feof($old_fp)) {
  197. if (!fputs($new_fp, fread($old_fp, 8192))) {
  198. //echo "Could not move {$user_fs_path}{$old_file} to {$user_fs_path}{$new_file} (Error writing.)\n";
  199. break;
  200. }
  201. }
  202. $pic->$md_name = $new_file;
  203. }
  204. // update container.
  205. // this doesn't work...?
  206. //$pic->container_guid = $album_guid;
  207. // delete old one.
  208. unlink($user_fs_path . $old_file);
  209. $q = "UPDATE {$CONFIG->dbprefix}entities SET subtype = $image_subtype_id, container_guid = $album_guid WHERE guid = {$pic->getGUID()}";
  210. //echo "Finished moving {$user_fs_path}{$old_file} to {$user_fs_path}{$new_file}\n";
  211. return update_data($q);
  212. }
  213. /**
  214. * Grabs all user IDs with images in the files repo.
  215. * return mixed. False on fail, array of GUIDs on success.
  216. */
  217. function tidypics_get_user_guids_with_pics_in_files($offset, $limit) {
  218. global $CONFIG;
  219. //$simpletype_ms_id = add_metastring('simple_type');
  220. //$image_ms_id = add_metastring('image');
  221. $q = "SELECT DISTINCT e.owner_guid
  222. FROM
  223. {$CONFIG->dbprefix}entities as e,
  224. {$CONFIG->dbprefix}entity_subtypes as st
  225. WHERE st.subtype = 'file'
  226. AND e.subtype = st.id
  227. LIMIT $offset, $limit";
  228. if (!$data = get_data($q)) {
  229. return false;
  230. }
  231. // return an array of IDs
  232. $r = array();
  233. foreach ($data as $row) {
  234. $r[] = $row->owner_guid;
  235. }
  236. return $r;
  237. }
  238. /**
  239. * Gets a list of images for a single user.
  240. * @return array of GUIDs, false on fail.
  241. */
  242. function tidypics_get_user_pics_from_files($user_guid) {
  243. if (!$user = get_entity($user_guid) AND $user instanceof ElggUser) {
  244. return false;
  245. }
  246. // @todo Might have to cycle this through with standard while + foreach.
  247. return elgg_get_entities_from_metadata(array('metadata_name' => 'simpletype',
  248. 'metadata_value' => 'image',
  249. 'type' => 'object',
  250. 'subtype' => 'file',
  251. 'owner_guid' => $user_guid,
  252. 'limit' => 5000));
  253. }