/lib/Model/LanguageStats/LanguageStatsDAO.php

https://github.com/matecat/MateCat · PHP · 349 lines · 209 code · 73 blank · 67 comment · 17 complexity · f56c10f4f242e1e0543f85107a36d954 MD5 · raw file

  1. <?php
  2. use DataAccess\ShapelessConcreteStruct;
  3. /**
  4. * Created by PhpStorm.
  5. * User: roberto
  6. * Date: 22/09/15
  7. * Time: 16.42
  8. */
  9. class LanguageStats_LanguageStatsDAO extends DataAccess_AbstractDao {
  10. const TABLE = "language_stats";
  11. const STRUCT_TYPE = "LanguageStats_LanguageStatsStruct";
  12. public function getLastDate() {
  13. $con = $this->database->getConnection();
  14. $stmt = $con->prepare( "select max( date ) as date from " . self::TABLE );
  15. $stmt->setFetchMode( PDO::FETCH_ASSOC );
  16. $stmt->execute();
  17. return @$stmt->fetch()[ 'date' ];
  18. }
  19. public function getLanguageStats( DateTime $filterDate = null ) {
  20. if ( !$filterDate ) {
  21. $con = $this->database->getConnection();
  22. $stmt = $con->prepare( "SELECT MAX( date ) as date FROM " . self::TABLE );
  23. $this->setCacheTTL( 24 * 60 * 60 );
  24. $filterDate = $this->_fetchObject( $stmt, new ShapelessConcreteStruct(), [] )[ 0 ][ 'date' ];
  25. } else {
  26. $filterDate = $filterDate->format( 'Y-m-d H:i:s' );
  27. }
  28. $query = "
  29. SELECT source, target, date, total_post_editing_effort, job_count, total_word_count, fuzzy_band
  30. FROM " . self::TABLE . "
  31. WHERE date = :filterDate
  32. AND job_count > 50
  33. ;
  34. ";
  35. $con = $this->database->getConnection();
  36. $stmt = $con->prepare( $query );
  37. return $this->_fetchObject( $stmt, new LanguageStats_LanguageStatsStruct(), [
  38. 'filterDate' => $filterDate
  39. ] );
  40. }
  41. public function getSnapshotDates() {
  42. $query = "
  43. SELECT distinct DATE_FORMAT( date,'%Y-%m-%d' ) AS date_format , date
  44. FROM " . self::TABLE;
  45. $con = $this->database->getConnection();
  46. $stmt = $con->prepare( $query );
  47. $stmt->setFetchMode( PDO::FETCH_ASSOC );
  48. $stmt->execute();
  49. return $stmt->fetchAll();
  50. }
  51. public function getGraphData( ShapelessConcreteStruct $filters ) {
  52. $query = "
  53. SELECT
  54. source,
  55. target,
  56. fuzzy_band,
  57. total_post_editing_effort,
  58. DATE_FORMAT( date, '%Y-%m' ) as date
  59. FROM " . self::TABLE . "
  60. WHERE
  61. date BETWEEN ? AND ?
  62. AND
  63. source IN( " . str_repeat( '?,', count( $filters->sources ) - 1 ) . '?' . " )
  64. AND
  65. target IN( " . str_repeat( '?,', count( $filters->targets ) - 1 ) . '?' . " )
  66. AND
  67. fuzzy_band IN( " . str_repeat( '?,', count( $filters->fuzzy_band ) - 1 ) . '?' . " )
  68. ORDER BY 5 ASC
  69. ;";
  70. $conn = Database::obtain()->getConnection();
  71. $stmt = $conn->prepare( $query );
  72. $values = array_merge(
  73. [
  74. $filters->date_start,
  75. $filters->date_end
  76. ],
  77. $filters->sources,
  78. $filters->targets,
  79. $filters->fuzzy_band
  80. );
  81. /**
  82. * @var $resultSet ShapelessConcreteStruct[]
  83. */
  84. $resultSet = $this->_fetchObject( $stmt, new ShapelessConcreteStruct(), $values );
  85. return $resultSet;
  86. }
  87. /**
  88. * @param DataAccess_IDaoStruct $obj
  89. *
  90. * @return LanguageStats_LanguageStatsStruct|null The inserted object on success, null otherwise
  91. * @throws Exception
  92. */
  93. public function create( DataAccess_IDaoStruct $obj ) {
  94. /**
  95. * @var $obj LanguageStats_LanguageStatsStruct
  96. */
  97. $obj = $this->sanitize( $obj );
  98. $this->_validateNotNullFields( $obj );
  99. $query = "INSERT INTO " . self::TABLE .
  100. " (date, source, target, fuzzy_band, total_word_count, total_post_editing_effort, total_time_to_edit, job_count)
  101. VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )
  102. ON DUPLICATE KEY UPDATE
  103. total_post_editing_effort = values( total_post_editing_effort ),
  104. total_time_to_edit = values( total_time_to_edit ),
  105. job_count = values( job_count )";
  106. $bind_values = [
  107. $obj->date,
  108. $obj->source,
  109. $obj->target,
  110. $obj->fuzzy_band,
  111. $obj->total_word_count,
  112. $obj->total_post_editing_effort,
  113. $obj->total_time_to_edit,
  114. (int)$obj->job_count
  115. ];
  116. $stmt = $this->getDatabaseHandler()->getConnection()->prepare( $query );
  117. $stmt->execute( $bind_values );
  118. //return the inserted object on success, null otherwise
  119. if ( $stmt->rowCount() > 0 ) {
  120. return $obj;
  121. }
  122. return null;
  123. }
  124. /**
  125. * @param DataAccess_IDaoStruct $obj
  126. *
  127. * @return array
  128. * @throws Exception
  129. */
  130. public function read( DataAccess_IDaoStruct $obj ) {
  131. /**
  132. * @var $obj LanguageStats_LanguageStatsStruct
  133. */
  134. $obj = $this->sanitize( $obj );
  135. $bind_values = [];
  136. $condition = [];
  137. $query = "SELECT date,
  138. source,
  139. target,
  140. total_word_count,
  141. total_post_editing_effort,
  142. total_time_to_edit,
  143. job_count
  144. FROM " . self::TABLE . " WHERE %s";
  145. if ( $obj->date !== null ) {
  146. $condition[] = "date = ?";
  147. $bind_values[] = $obj->date;
  148. }
  149. if ( $obj->source !== null ) {
  150. $condition [] = "source = ?";
  151. $bind_values[] = $obj->source;
  152. }
  153. if ( $obj->target !== null ) {
  154. $condition [] = "target = ?";
  155. $bind_values[] = $obj->target;
  156. }
  157. if ( $obj->fuzzy_band !== null ) {
  158. $condition [] = "fuzzy_band = ?";
  159. $bind_values[] = $obj->target;
  160. }
  161. if ( count( $condition ) ) {
  162. $where_string = implode( " AND ", $condition );
  163. } else {
  164. throw new Exception( "Where condition needed." );
  165. }
  166. $query = sprintf( $query, $where_string );
  167. $stmt = $this->database->getConnection()->prepare( $query );
  168. $stmt->execute( $bind_values );
  169. $stmt->setFetchMode( PDO::FETCH_CLASS, self::STRUCT_TYPE );
  170. return $stmt->fetchAll();
  171. }
  172. /**
  173. * @param $obj_arr LanguageStats_LanguageStatsStruct[] An array of LanguageStats_LanguageStatsStruct objects
  174. *
  175. * @return array|null The input array on success, null otherwise
  176. * @throws Exception
  177. */
  178. public function createList( Array $obj_arr ) {
  179. $obj_arr = $this->sanitizeArray( $obj_arr );
  180. $query = "INSERT INTO " . self::TABLE .
  181. " (date, source, target, fuzzy_band, total_word_count, total_post_editing_effort, total_time_to_edit, job_count)
  182. VALUES %s
  183. ON DUPLICATE KEY UPDATE
  184. total_post_editing_effort = values( total_post_editing_effort ),
  185. total_time_to_edit = values( total_time_to_edit ),
  186. job_count = values( job_count )";
  187. //chunk array using MAX_INSERT_NUMBER
  188. $objects = array_chunk( $obj_arr, 20 );
  189. $values = [];
  190. $tuple_list = [];
  191. $allInsertPerformed = true;
  192. //create an insert query for each chunk
  193. foreach ( $objects as $i => $chunk ) {
  194. foreach ( $chunk as $obj ) {
  195. $tuple_list[] = "( ?, ?, ?, ?, ?, ?, ?, ? )";
  196. //fill values array
  197. $values = array_merge( $values, [
  198. $obj->date,
  199. $obj->source,
  200. $obj->target,
  201. $obj->fuzzy_band,
  202. $obj->total_word_count,
  203. $obj->total_post_editing_effort,
  204. $obj->total_time_to_edit,
  205. (int)$obj->job_count
  206. ] );
  207. }
  208. $insert_query = sprintf( $query, implode( ", ", $tuple_list ) );
  209. $stmt = $this->database->getConnection()->prepare( $insert_query );
  210. $stmt->execute( $values );
  211. if ( $stmt->errorCode() > 0 ) {
  212. $allInsertPerformed = false;
  213. break;
  214. }
  215. $values = [];
  216. $tuple_list = [];
  217. }
  218. if ( $allInsertPerformed ) {
  219. return $obj_arr;
  220. }
  221. return null;
  222. }
  223. /**
  224. * See parent definition
  225. * @see DataAccess_AbstractDao::sanitize
  226. *
  227. * @param LanguageStats_LanguageStatsStruct $input
  228. *
  229. * @return DataAccess_IDaoStruct|LanguageStats_LanguageStatsStruct
  230. * @throws Exception
  231. */
  232. public function sanitize( $input ) {
  233. return parent::_sanitizeInput( $input, self::STRUCT_TYPE );
  234. }
  235. /**
  236. * See parent definition.
  237. * @see DataAccess_AbstractDao::sanitizeArray
  238. *
  239. * @param array $input
  240. *
  241. * @return array
  242. * @throws Exception
  243. */
  244. public static function sanitizeArray( $input ) {
  245. return parent::_sanitizeInputArray( $input, self::STRUCT_TYPE );
  246. }
  247. /**
  248. * See in DataAccess_AbstractDao::validateNotNullFields
  249. * @see DataAccess_AbstractDao::_validateNotNullFields
  250. *
  251. * @param DataAccess_IDaoStruct $obj
  252. *
  253. * @return void
  254. * @throws Exception
  255. */
  256. protected function _validateNotNullFields( DataAccess_IDaoStruct $obj ) {
  257. /**
  258. * @var $obj LanguageStats_LanguageStatsStruct
  259. */
  260. if ( is_null( $obj->total_post_editing_effort ) || empty( $obj->total_post_editing_effort ) ) {
  261. throw new Exception( "Total postediting effort cannot be null" );
  262. }
  263. if ( is_null( $obj->total_time_to_edit ) ) {
  264. throw new Exception( "Total time to edit cannot be null" );
  265. }
  266. if ( is_null( $obj->job_count ) ) {
  267. throw new Exception( "Job count cannot be null" );
  268. }
  269. if ( is_null( $obj->total_word_count ) ) {
  270. throw new Exception( "Total wordcount cannot be null" );
  271. }
  272. if ( is_null( $obj->fuzzy_band ) ) {
  273. throw new Exception( "Fuzzy band cannot be null" );
  274. }
  275. }
  276. }