PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/webapp/_lib/model/class.ExportMySQLDAO.php

http://github.com/ginatrapani/ThinkUp
PHP | 359 lines | 286 code | 30 blank | 43 comment | 33 complexity | f2a0a90e55e511c5016f4d744c862481 MD5 | raw file
Possible License(s): Apache-2.0, GPL-2.0, GPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. *
  4. * ThinkUp/webapp/_lib/model/class.ExportMySQLDAO.php
  5. *
  6. * Copyright (c) 2011-2012 Gina Trapani
  7. *
  8. * LICENSE:
  9. *
  10. * This file is part of ThinkUp (http://thinkupapp.com).
  11. *
  12. * ThinkUp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
  13. * License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any
  14. * later version.
  15. *
  16. * ThinkUp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  17. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  18. * details.
  19. *
  20. * You should have received a copy of the GNU General Public License along with ThinkUp. If not, see
  21. * <http://www.gnu.org/licenses/>.
  22. *
  23. * Export MySQL Data Access Object
  24. *
  25. * @license http://www.gnu.org/licenses/gpl.html
  26. * @copyright 2011-2012 Gina Trapani
  27. * @author Gina Trapani <ginatrapani[at]gmail[dot]com>
  28. */
  29. class ExportMySQLDAO extends PDODAO implements ExportDAO {
  30. /**
  31. * Name of the temporary posts export table.
  32. * @var str
  33. */
  34. static $exported_posts_table_name = 'posts_tmp';
  35. /**
  36. * Name of the temporary follows export table.
  37. * @var str
  38. */
  39. static $exported_follows_table_name = 'follows_tmp';
  40. public function createExportedPostsTable() {
  41. $q = "CREATE TABLE #prefix#".self::$exported_posts_table_name." LIKE #prefix#posts;";
  42. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  43. $stmt = $this->execute($q);
  44. $q = "ALTER TABLE #prefix#".self::$exported_posts_table_name." DROP id";
  45. $stmt = $this->execute($q);
  46. return $this->doesExportedPostsTableExist();
  47. }
  48. public function doesExportedPostsTableExist() {
  49. $q = "SHOW TABLES LIKE '#prefix#" . self::$exported_posts_table_name . "'";
  50. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  51. $stmt = $this->execute($q);
  52. $tables = $this->getDataRowAsArray($stmt);
  53. return !empty($tables);
  54. }
  55. public function dropExportedPostsTable() {
  56. if ( self::doesExportedPostsTableExist() ) {
  57. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  58. $q = "DROP TABLE #prefix#".self::$exported_posts_table_name;
  59. $stmt = $this->execute($q);
  60. }
  61. return !$this->doesExportedPostsTableExist();
  62. }
  63. public function createExportedFollowsTable() {
  64. $q = "CREATE TABLE #prefix#".self::$exported_follows_table_name." LIKE #prefix#follows;";
  65. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  66. $stmt = $this->execute($q);
  67. return $this->doesExportedFollowsTableExist();
  68. }
  69. public function doesExportedFollowsTableExist() {
  70. $q = "SHOW TABLES LIKE '#prefix#" . self::$exported_follows_table_name . "'";
  71. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  72. $stmt = $this->execute($q);
  73. $tables = $this->getDataRowAsArray($stmt);
  74. return !empty($tables);
  75. }
  76. public function dropExportedFollowsTable() {
  77. if ( self::doesExportedFollowsTableExist() ) {
  78. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  79. $q = "DROP TABLE #prefix#".self::$exported_follows_table_name;
  80. $stmt = $this->execute($q);
  81. }
  82. return !$this->doesExportedFollowsTableExist();
  83. }
  84. public function exportPostsByServiceUser($username, $service) {
  85. if ( !self::doesExportedPostsTableExist() ) {
  86. self::createExportedPostsTable();
  87. }
  88. //select all-but-id into posts_to_export from posts where service user is the author
  89. $q = "INSERT IGNORE INTO #prefix#".self::$exported_posts_table_name." SELECT ";
  90. $q .= self::getExportFields('posts') . " ";
  91. $q .= "FROM #prefix#posts WHERE ";
  92. $q .= "author_username = :author_username AND network = :network";
  93. $vars = array(
  94. ':author_username'=>$username,
  95. ':network'=>$service
  96. );
  97. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  98. $stmt = $this->execute($q, $vars);
  99. return $this->getUpdateCount($stmt);
  100. }
  101. public function exportRepliesRetweetsOfPosts($posts_to_process) {
  102. if ( !self::doesExportedPostsTableExist() ) {
  103. self::createExportedPostsTable();
  104. }
  105. $total_posts_exported = 0;
  106. foreach ($posts_to_process as $post) {
  107. $q = "INSERT IGNORE INTO #prefix#".self::$exported_posts_table_name." SELECT ";
  108. $q .= self::getExportFields('posts'). " ";
  109. $q .= "FROM #prefix#posts WHERE ";
  110. $q .= "in_reply_to_post_id = :post_id AND network=:network;";
  111. $vars = array("post_id"=>$post->post_id, "network"=>$post->network);
  112. $stmt = $this->execute($q, $vars);
  113. $total_posts_exported = $total_posts_exported + $this->getUpdateCount($stmt);
  114. $q = "INSERT IGNORE INTO #prefix#".self::$exported_posts_table_name." SELECT ";
  115. $q .= self::getExportFields('posts'). " ";
  116. $q .= "FROM #prefix#posts WHERE ";
  117. $q .= "in_retweet_of_post_id = :post_id AND network=:network;";
  118. $vars = array("post_id"=>$post->post_id, "network"=>$post->network);
  119. $stmt = $this->execute($q, $vars);
  120. $total_posts_exported = $total_posts_exported + $this->getUpdateCount($stmt);
  121. }
  122. return $total_posts_exported;
  123. }
  124. public function exportMentionsOfServiceUser($username, $service) {
  125. if ( !self::doesExportedPostsTableExist() ) {
  126. self::createExportedPostsTable();
  127. }
  128. $author_username = '@'.$username;
  129. //select all-but-id into posts_to_export from posts where service username is mentioned
  130. $q = "INSERT IGNORE INTO #prefix#".self::$exported_posts_table_name." SELECT ";
  131. $q .= self::getExportFields('posts') . " ";
  132. $q .= "FROM #prefix#posts WHERE ";
  133. $q .= "network = :network AND ";
  134. if ( strlen($username) > PostMySQLDAO::FULLTEXT_CHAR_MINIMUM ) {
  135. $q .= "MATCH (`post_text`) AGAINST(:author_username IN BOOLEAN MODE) ";
  136. } else {
  137. $author_username = '%'.$author_username .'%';
  138. $q .= "post_text LIKE :author_username ";
  139. }
  140. $vars = array(
  141. ':author_username'=>$author_username,
  142. ':network'=>$service
  143. );
  144. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  145. $stmt = $this->execute($q, $vars);
  146. return $this->getUpdateCount($stmt);
  147. }
  148. public function exportPostsServiceUserRepliedTo($username, $service) {
  149. if ( !self::doesExportedPostsTableExist() ) {
  150. self::createExportedPostsTable();
  151. }
  152. $page = 1;
  153. $page_size = 500;
  154. $total_posts_inserted = 0;
  155. $posts_to_insert = self::getRepliedToPostIDs($username, $service, $page, $page_size);
  156. while (count($posts_to_insert) > 0 ) {
  157. foreach ($posts_to_insert as $post) {
  158. $q = "INSERT IGNORE INTO #prefix#".self::$exported_posts_table_name." SELECT ";
  159. $q .= self::getExportFields('posts') . " ";
  160. $q .= "FROM #prefix#posts WHERE ";
  161. $q .= "network = :network AND post_id=:post_id;";
  162. $vars = array(
  163. ':post_id'=>$post['post_id'],
  164. ':network'=>$service
  165. );
  166. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  167. $stmt = $this->execute($q, $vars);
  168. $total_posts_inserted = $total_posts_inserted + $this->getUpdateCount($stmt);
  169. }
  170. $page = $page+1;
  171. $posts_to_insert = self::getRepliedToPostIDs($username, $service, $page, $page_size);
  172. }
  173. return $total_posts_inserted;
  174. }
  175. private function getRepliedToPostIDs($username, $network, $page, $page_size) {
  176. $page = $page - 1;
  177. $start_on = $page * $page_size;
  178. $q = "SELECT in_reply_to_post_id as post_id FROM #prefix#posts WHERE ";
  179. $q .= "author_username = :author_username AND network=:network AND in_reply_to_post_id IS NOT null ";
  180. $q .= "LIMIT ".$start_on.", ".$page_size;
  181. $vars = array(
  182. ':author_username'=>$username,
  183. ':network'=>$network
  184. );
  185. if ($this->profiler_enabled) Profiler::setDAOMethod(__METHOD__);
  186. $stmt = $this->execute($q, $vars);
  187. return $this->getDataRowsAsArrays($stmt);
  188. }
  189. public function exportFavoritesOfServiceUser($user_id, $service, $favorites_file) {
  190. if ( !self::doesExportedPostsTableExist() ) {
  191. self::createExportedPostsTable();
  192. }
  193. $q = "SELECT * INTO OUTFILE '$favorites_file' FROM #prefix#favorites WHERE fav_of_user_id = :user_id ".
  194. "AND network = :network;";
  195. $vars = array(
  196. ':user_id'=>$user_id,
  197. ':network'=>$service
  198. );
  199. $stmt = $this->execute($q, $vars);
  200. $q = "SELECT post_id FROM #prefix#favorites WHERE fav_of_user_id = :user_id AND network = :network;";
  201. $stmt = $this->execute($q, $vars);
  202. $fav_ids = $this->getDataRowsAsArrays($stmt);
  203. $total_favs_exported = 0;
  204. foreach ($fav_ids as $post) {
  205. $q = "INSERT IGNORE INTO #prefix#".self::$exported_posts_table_name." SELECT ";
  206. $q .= self::getExportFields('posts'). " ";
  207. $q .= "FROM #prefix#posts WHERE ";
  208. $q .= "post_id = :post_id AND network = :network";
  209. $vars = array(
  210. ':post_id'=>$post['post_id'],
  211. ':network'=>$service
  212. );
  213. $stmt = $this->execute($q, $vars);
  214. $total_favs_exported = $total_favs_exported + $this->getUpdateCount($stmt);
  215. }
  216. return $total_favs_exported;
  217. }
  218. public function exportPostsLinksUsersToFile($posts_file, $links_file, $users_file) {
  219. if (file_exists($posts_file)) {
  220. unlink($posts_file);
  221. }
  222. if (file_exists($links_file)) {
  223. unlink($links_file);
  224. }
  225. if (file_exists($users_file)) {
  226. unlink($users_file);
  227. }
  228. if ( !self::doesExportedPostsTableExist() ) {
  229. self::createExportedPostsTable();
  230. }
  231. $q = "SELECT * INTO OUTFILE '$posts_file' FROM #prefix#".self::$exported_posts_table_name;
  232. $stmt = $this->execute($q);
  233. $q = "SELECT ".$this->getExportFields('links', 'l')." INTO OUTFILE '$links_file' FROM #prefix#links l ";
  234. $q .= "INNER JOIN #prefix#posts p ON l.post_key = p.id;";
  235. $stmt = $this->execute($q);
  236. $q = "SELECT DISTINCT ".$this->getExportFields('users', 'u')." INTO OUTFILE '$users_file' ";
  237. $q .= "FROM #prefix#users u INNER JOIN #prefix#".self::$exported_posts_table_name.
  238. " p ON p.author_user_id = u.user_id AND p.network = u.network;";
  239. $stmt = $this->execute($q);
  240. }
  241. public function exportFollowsUsersToFile($user_id, $network, $follows_file, $users_followers_file,
  242. $users_followees_file) {
  243. if (file_exists($follows_file)) {
  244. unlink($follows_file);
  245. }
  246. if (file_exists($users_followers_file)) {
  247. unlink($users_followers_file);
  248. }
  249. if (file_exists($users_followees_file)) {
  250. unlink($users_followees_file);
  251. }
  252. self::createExportedFollowsTable();
  253. //export follows to temp table
  254. $q = "INSERT IGNORE INTO #prefix#".self::$exported_follows_table_name." SELECT * FROM #prefix#follows ";
  255. $q .= "WHERE network=:network AND user_id = :user_id;";
  256. $vars = array(
  257. ':user_id'=>$user_id,
  258. ':network'=>$network
  259. );
  260. $stmt = $this->execute($q, $vars);
  261. //export followees to temp table
  262. $q = "INSERT IGNORE INTO #prefix#".self::$exported_follows_table_name." SELECT * FROM #prefix#follows ";
  263. $q .= "WHERE network=:network AND follower_id = :user_id;";
  264. $vars = array(
  265. ':user_id'=>$user_id,
  266. ':network'=>$network
  267. );
  268. $stmt = $this->execute($q, $vars);
  269. //export temp table to file
  270. $q = "SELECT * INTO OUTFILE '$follows_file' FROM #prefix#".self::$exported_follows_table_name." ";
  271. $stmt = $this->execute($q, $vars);
  272. //export users join on temp table followers
  273. $q = "SELECT DISTINCT ".$this->getExportFields('users', 'u'). " FROM #prefix#users u ";
  274. $q .= "INNER JOIN #prefix#".self::$exported_follows_table_name.
  275. " f ON f.network = u.network AND f.follower_id = u.user_id ";
  276. $q .= "INTO OUTFILE '$users_followees_file' ";
  277. $vars = array(
  278. ':user_id'=>$user_id,
  279. ':network'=>$network
  280. );
  281. $stmt = $this->execute($q, $vars);
  282. //export users join on temp table followers
  283. $q = "SELECT DISTINCT ".$this->getExportFields('users', 'u'). " FROM #prefix#users u ";
  284. $q .= "INNER JOIN #prefix#".self::$exported_follows_table_name.
  285. " f ON f.network = u.network AND f.user_id = u.user_id ";
  286. $q .= "INTO OUTFILE '$users_followers_file' ";
  287. $vars = array(
  288. ':user_id'=>$user_id,
  289. ':network'=>$network
  290. );
  291. $stmt = $this->execute($q, $vars);
  292. //drop temp table
  293. self::dropExportedFollowsTable();
  294. }
  295. public function exportFollowerCountToFile($user_id, $network, $file) {
  296. if (file_exists($file)) {
  297. unlink($file);
  298. }
  299. $q = "SELECT * INTO OUTFILE '$file' FROM #prefix#follower_count WHERE ";
  300. $q .= "network=:network AND network_user_id=:user_id GROUP by date;";
  301. $vars = array(
  302. ':user_id'=>$user_id,
  303. ':network'=>$network
  304. );
  305. $stmt = $this->execute($q, $vars);
  306. }
  307. public function exportGeoToFile($file) {
  308. if (file_exists($file)) {
  309. unlink($file);
  310. }
  311. $q = "SELECT * INTO OUTFILE '$file' FROM #prefix#encoded_locations;";
  312. $stmt = $this->execute($q);
  313. }
  314. public function getExportFields($table_name, $prefix='') {
  315. $q = "DESCRIBE #prefix#".$table_name.";";
  316. $stmt = $this->execute($q);
  317. $fields = $this->getDataRowsAsArrays($stmt);
  318. $fields_string = '';
  319. foreach ($fields as $field) {
  320. if ($fields_string != '') {
  321. $fields_string .= ", ";
  322. }
  323. if ($field['Field'] != 'id') {
  324. $fields_string .= $prefix.(($prefix!='')?".":"").$field['Field'];
  325. }
  326. }
  327. return $fields_string;
  328. }
  329. }