/public/rotate.php

https://github.com/ciniki/images · PHP · 190 lines · 117 code · 13 blank · 60 comment · 30 complexity · 5ad4867690a9bf30fe1f1fa412662931 MD5 · raw file

  1. <?php
  2. //
  3. // Description
  4. // ===========
  5. // This method will rotate an image in the database.
  6. //
  7. // Arguments
  8. // ---------
  9. // api_key:
  10. // auth_token:
  11. // tnid: The ID of the tenant the image is attached to.
  12. // image_id: The ID of the image to be rotated.
  13. // direction: The direction to rotate the image.
  14. //
  15. // default - rotate the image clockwise
  16. // right - rotate the image clockwise
  17. // left - rotate the image counter clockwise
  18. //
  19. // Returns
  20. // -------
  21. // <rsp stat='ok' id='34' />
  22. //
  23. function ciniki_images_rotate(&$ciniki) {
  24. //
  25. // Find all the required and optional arguments
  26. // FIXME: Allow rotate to apply to only a certain version, currently applies to all versions
  27. //
  28. ciniki_core_loadMethod($ciniki, 'ciniki', 'core', 'private', 'prepareArgs');
  29. $rc = ciniki_core_prepareArgs($ciniki, 'no', array(
  30. 'tnid'=>array('required'=>'yes', 'blank'=>'no', 'name'=>'Tenant'),
  31. 'image_id'=>array('required'=>'yes', 'blank'=>'no', 'name'=>'Image'),
  32. 'direction'=>array('required'=>'no', 'default'=>'right', 'blank'=>'no', 'name'=>'Direction'),
  33. ));
  34. if( $rc['stat'] != 'ok' ) {
  35. return $rc;
  36. }
  37. $args = $rc['args'];
  38. //
  39. // Make sure this module is activated, and
  40. // check permission to run this function for this tenant
  41. //
  42. ciniki_core_loadMethod($ciniki, 'ciniki', 'images', 'private', 'checkAccess');
  43. $rc = ciniki_images_checkAccess($ciniki, $args['tnid'], 'ciniki.images.rotate');
  44. if( $rc['stat'] != 'ok' ) {
  45. return $rc;
  46. }
  47. //
  48. // Turn off autocommit
  49. //
  50. ciniki_core_loadMethod($ciniki, 'ciniki', 'core', 'private', 'dbTransactionStart');
  51. ciniki_core_loadMethod($ciniki, 'ciniki', 'core', 'private', 'dbTransactionRollback');
  52. ciniki_core_loadMethod($ciniki, 'ciniki', 'core', 'private', 'dbTransactionCommit');
  53. ciniki_core_loadMethod($ciniki, 'ciniki', 'core', 'private', 'dbQuote');
  54. ciniki_core_loadMethod($ciniki, 'ciniki', 'core', 'private', 'dbUpdate');
  55. ciniki_core_loadMethod($ciniki, 'ciniki', 'core', 'private', 'dbHashQuery');
  56. ciniki_core_loadMethod($ciniki, 'ciniki', 'core', 'private', 'dbAddModuleHistory');
  57. $rc = ciniki_core_dbTransactionStart($ciniki, 'ciniki.images');
  58. if( $rc['stat'] != 'ok' ) {
  59. return $rc;
  60. }
  61. //
  62. // Load the image
  63. //
  64. $strsql = "SELECT id, uuid, image "
  65. . "FROM ciniki_images "
  66. . "WHERE tnid = '" . ciniki_core_dbQuote($ciniki, $args['tnid']) . "' "
  67. . "AND id = '" . ciniki_core_dbQuote($ciniki, $args['image_id']) . "' "
  68. . "";
  69. $rc = ciniki_core_dbHashQuery($ciniki, $strsql, 'ciniki.images', 'image');
  70. if( $rc['stat'] != 'ok' ) {
  71. return $rc;
  72. }
  73. if( !isset($rc['image']) ) {
  74. return array('stat'=>'fail', 'err'=>array('code'=>'ciniki.images.138', 'msg'=>'Unable to find the image requested'));
  75. }
  76. $img = $rc['image'];
  77. //
  78. // Get the tenant storage directory
  79. //
  80. ciniki_core_loadMethod($ciniki, 'ciniki', 'tenants', 'hooks', 'storageDir');
  81. $rc = ciniki_tenants_hooks_storageDir($ciniki, $args['tnid'], array());
  82. if( $rc['stat'] != 'ok' ) {
  83. return $rc;
  84. }
  85. $tenant_storage_dir = $rc['storage_dir'];
  86. $storage_filename = $tenant_storage_dir . '/ciniki.images/'
  87. . $img['uuid'][0] . '/' . $img['uuid'];
  88. if( file_exists($storage_filename) ) {
  89. $image = new Imagick($storage_filename);
  90. } else {
  91. $image = new Imagick();
  92. $image->readImageBlob($img['image']);
  93. }
  94. //
  95. // Rotate the image
  96. //
  97. if( isset($args['direction']) && $args['direction'] == 'left' ) {
  98. $image->rotateImage(new ImagickPixel('none'), -90);
  99. } else {
  100. $image->rotateImage(new ImagickPixel('none'), 90);
  101. }
  102. //
  103. // Save the image
  104. //
  105. $h = fopen($storage_filename, 'w');
  106. if( $h ) {
  107. fwrite($h, $image->getImageBlob());
  108. fclose($h);
  109. } else {
  110. return array('stat'=>'fail', 'err'=>array('code'=>'ciniki.images.139', 'msg'=>'Unable to add image'));
  111. }
  112. //
  113. // Save the updated version
  114. //
  115. $strsql = "UPDATE ciniki_images "
  116. // . "SET image = '" . ciniki_core_dbQuote($ciniki, $image->getImageBlob()) . "' "
  117. . "SET last_updated = UTC_TIMESTAMP() "
  118. . "WHERE tnid = '" . ciniki_core_dbQuote($ciniki, $args['tnid']) . "' "
  119. . "AND id = '" . ciniki_core_dbQuote($ciniki, $args['image_id']) . "' "
  120. . "";
  121. $rc = ciniki_core_dbUpdate($ciniki, $strsql, 'ciniki.images');
  122. if( $rc['stat'] != 'ok' ) {
  123. return $rc;
  124. }
  125. $ciniki['syncqueue'][] = array('push'=>'ciniki.images.image',
  126. 'args'=>array('id'=>$args['image_id']));
  127. //
  128. // Update the crop parameters for each version
  129. //
  130. $strsql = "SELECT id, image_id, version, sequence, action, params "
  131. . "FROM ciniki_image_actions "
  132. . "WHERE image_id = '" . ciniki_core_dbQuote($ciniki, $args['image_id']) . "' "
  133. . "";
  134. $rc = ciniki_core_dbHashQuery($ciniki, $strsql, 'ciniki.images', 'actions');
  135. if( $rc['stat'] != 'ok' ) {
  136. return $rc;
  137. }
  138. if( isset($rc['rows']) ) {
  139. $actions = $rc['rows'];
  140. foreach($actions as $rnum => $action) {
  141. if( $action['action'] == 1 ) {
  142. // Crop
  143. $params = preg_split('/,/', $action['params']);
  144. $new_params = $params[1] . ',' . $params[0] . ',' . $params[3] . ',' . $params[2];
  145. $strsql = "UPDATE ciniki_image_actions "
  146. . "SET params = '" . ciniki_core_dbQuote($ciniki, $new_params) . "', "
  147. . "last_updated = UTC_TIMESTAMP() "
  148. . "WHERE image_id = '" . ciniki_core_dbQuote($ciniki, $action['image_id']) . "' "
  149. . "AND version = '" . ciniki_core_dbQuote($ciniki, $action['version']) . "' "
  150. . "AND sequence = '" . ciniki_core_dbQuote($ciniki, $action['sequence']) . "' "
  151. . "";
  152. $rc = ciniki_core_dbUpdate($ciniki, $strsql, 'ciniki.images');
  153. if( $rc['stat'] != 'ok' ) {
  154. return $rc;
  155. }
  156. // FIXME: Add history log for this action
  157. $ciniki['syncqueue'][] = array('push'=>'ciniki.images.action',
  158. 'args'=>array('id'=>$action['id']));
  159. }
  160. }
  161. }
  162. //
  163. // Commit the database changes
  164. //
  165. $rc = ciniki_core_dbTransactionCommit($ciniki, 'ciniki.images');
  166. if( $rc['stat'] != 'ok' ) {
  167. return $rc;
  168. }
  169. //
  170. // Update the last_change date in the tenant modules
  171. // Ignore the result, as we don't want to stop user updates if this fails.
  172. //
  173. ciniki_core_loadMethod($ciniki, 'ciniki', 'tenants', 'private', 'updateModuleChangeDate');
  174. ciniki_tenants_updateModuleChangeDate($ciniki, $args['tnid'], 'ciniki', 'images');
  175. return array('stat'=>'ok');
  176. }
  177. ?>