/lib/Controller/convertFileController.php

https://github.com/matecat/MateCat · PHP · 274 lines · 193 code · 65 blank · 16 comment · 23 complexity · 095392eb3b30d35c4bc7ee47c6e372d4 MD5 · raw file

  1. <?php
  2. use FilesStorage\AbstractFilesStorage;
  3. use FilesStorage\FilesStorageFactory;
  4. set_time_limit( 0 );
  5. class convertFileController extends ajaxController {
  6. protected $file_name;
  7. protected $source_lang;
  8. protected $target_lang;
  9. protected $segmentation_rule;
  10. protected $cache_days = 10;
  11. protected $intDir;
  12. protected $errDir;
  13. protected $cookieDir;
  14. //this will prevent recursion loop when ConvertFileWrapper will call the doAction()
  15. protected $convertZipFile = true;
  16. protected $lang_handler;
  17. /**
  18. * @var AbstractFilesStorage
  19. */
  20. protected $files_storage;
  21. public function __construct() {
  22. parent::__construct();
  23. $filterArgs = [
  24. 'file_name' => [
  25. 'filter' => FILTER_SANITIZE_STRING,
  26. 'flags' => FILTER_FLAG_STRIP_LOW // | FILTER_FLAG_STRIP_HIGH
  27. ],
  28. 'source_lang' => [
  29. 'filter' => FILTER_SANITIZE_STRING,
  30. 'flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH
  31. ],
  32. 'target_lang' => [
  33. 'filter' => FILTER_SANITIZE_STRING,
  34. 'flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH
  35. ],
  36. 'segmentation_rule' => [
  37. 'filter' => FILTER_SANITIZE_STRING,
  38. 'flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH
  39. ]
  40. ];
  41. $postInput = filter_input_array( INPUT_POST, $filterArgs );
  42. $this->file_name = $postInput[ 'file_name' ];
  43. $this->source_lang = $postInput[ "source_lang" ];
  44. $this->target_lang = $postInput[ "target_lang" ];
  45. $this->segmentation_rule = $postInput[ "segmentation_rule" ];
  46. if ( $this->segmentation_rule == "" ) {
  47. $this->segmentation_rule = null;
  48. }
  49. $this->cookieDir = $_COOKIE[ 'upload_session' ];
  50. $this->intDir = INIT::$UPLOAD_REPOSITORY . DIRECTORY_SEPARATOR . $this->cookieDir;
  51. $this->errDir = INIT::$STORAGE_DIR . DIRECTORY_SEPARATOR . 'conversion_errors' . DIRECTORY_SEPARATOR . $this->cookieDir;
  52. $this->readLoginInfo();
  53. $this->files_storage = FilesStorageFactory::create();
  54. }
  55. public function doAction() {
  56. $this->result[ 'code' ] = 0; // No Good, Default
  57. $this->lang_handler = Langs_Languages::getInstance();
  58. $this->validateSourceLang();
  59. $this->validateTargetLangs();
  60. if ( !Utils::isTokenValid( $this->cookieDir ) ) {
  61. $this->result[ 'code' ] = -19; // No Good, Default
  62. $this->result[ 'errors' ][] = [ "code" => -19, "message" => "Invalid Upload Token." ];
  63. return false;
  64. }
  65. if ( !Utils::isValidFileName( $this->file_name ) || empty( $this->file_name ) ) {
  66. $this->result[ 'code' ] = -1; // No Good, Default
  67. $this->result[ 'errors' ][] = [ "code" => -1, "message" => "Invalid File." ];
  68. return false;
  69. }
  70. if ( !empty( $this->result[ 'errors' ] ) ) {
  71. return false;
  72. }
  73. if ( $this->isLoggedIn() ) {
  74. $this->featureSet->loadFromUserEmail( $this->user->email );
  75. }
  76. $ext = AbstractFilesStorage::pathinfo_fix( $this->file_name, PATHINFO_EXTENSION );
  77. $conversionHandler = new ConversionHandler();
  78. $conversionHandler->setFileName( $this->file_name );
  79. $conversionHandler->setSourceLang( $this->source_lang );
  80. $conversionHandler->setTargetLang( $this->target_lang );
  81. $conversionHandler->setSegmentationRule( $this->segmentation_rule );
  82. $conversionHandler->setCookieDir( $this->cookieDir );
  83. $conversionHandler->setIntDir( $this->intDir );
  84. $conversionHandler->setErrDir( $this->errDir );
  85. $conversionHandler->setFeatures( $this->featureSet );
  86. $conversionHandler->setUserIsLogged( $this->userIsLogged );
  87. if ( $ext == "zip" ) {
  88. if ( $this->convertZipFile ) {
  89. $this->handleZip( $conversionHandler );
  90. } else {
  91. $this->result[ 'errors' ][] = [
  92. "code" => -2,
  93. "message" => "Nested zip files are not allowed"
  94. ];
  95. return false;
  96. }
  97. } else {
  98. $conversionHandler->doAction();
  99. $this->result = $conversionHandler->getResult();
  100. }
  101. ( isset( $this->result[ 'errors' ] ) ) ? null : $this->result[ 'errors' ] = [];
  102. if ( count( $this->result[ 'errors' ] ) == 0 ) {
  103. $this->result[ 'code' ] = 1;
  104. } else {
  105. $this->result[ 'errors' ] = array_values( $this->result[ 'errors' ] );
  106. }
  107. }
  108. private function validateSourceLang() {
  109. try {
  110. $this->lang_handler->validateLanguage( $this->source_lang );
  111. } catch ( Exception $e ) {
  112. $this->result[ 'errors' ][] = [ "code" => -3, "message" => $e->getMessage() ];
  113. }
  114. }
  115. private function validateTargetLangs() {
  116. $targets = explode( ',', $this->target_lang );
  117. $targets = array_map( 'trim', $targets );
  118. $targets = array_unique( $targets );
  119. if ( empty( $targets ) ) {
  120. $this->result[ 'errors' ][] = [ "code" => -4, "message" => "Missing target language." ];
  121. }
  122. try {
  123. foreach ( $targets as $target ) {
  124. $this->lang_handler->validateLanguage( $target );
  125. }
  126. } catch ( Exception $e ) {
  127. $this->result[ 'errors' ][] = [ "code" => -4, "message" => $e->getMessage() ];
  128. }
  129. $this->target_lang = implode( ',', $targets );
  130. }
  131. private function handleZip( ConversionHandler $conversionHandler ) {
  132. // this makes the conversionhandler accumulate eventual errors on files and continue
  133. $conversionHandler->setStopOnFileException( false );
  134. $internalZipFileNames = $conversionHandler->extractZipFile();
  135. //call convertFileWrapper and start conversions for each file
  136. if ( $conversionHandler->uploadError ) {
  137. $fileErrors = $conversionHandler->getUploadedFiles();
  138. foreach ( $fileErrors as $fileError ) {
  139. if ( count( $fileError->error ) == 0 ) {
  140. continue;
  141. }
  142. $brokenFileName = ZipArchiveExtended::getFileName( $fileError->name );
  143. /*
  144. * TODO
  145. * return error code is 2 because
  146. * <=0 is for errors
  147. * 1 is OK
  148. *
  149. * In this case, we raise warnings, hence the return code must be a new code
  150. */
  151. $this->result[ 'code' ] = 2;
  152. $this->result[ 'errors' ][ $brokenFileName ] = [
  153. 'code' => $fileError->error[ 'code' ],
  154. 'message' => $fileError->error[ 'message' ],
  155. 'debug' => $brokenFileName
  156. ];
  157. }
  158. }
  159. $realFileNames = array_map(
  160. [ 'ZipArchiveExtended', 'getFileName' ],
  161. $internalZipFileNames
  162. );
  163. foreach ( $realFileNames as $i => &$fileObject ) {
  164. $fileObject = [
  165. 'name' => $fileObject,
  166. 'size' => filesize( $this->intDir . DIRECTORY_SEPARATOR . $internalZipFileNames[ $i ] )
  167. ];
  168. }
  169. $this->result[ 'data' ][ 'zipFiles' ] = json_encode( $realFileNames );
  170. $stdFileObjects = [];
  171. if ( $internalZipFileNames !== null ) {
  172. foreach ( $internalZipFileNames as $fName ) {
  173. $newStdFile = new stdClass();
  174. $newStdFile->name = $fName;
  175. $stdFileObjects[] = $newStdFile;
  176. }
  177. } else {
  178. $errors = $conversionHandler->getResult();
  179. $errors = array_map( [ 'Upload', 'formatExceptionMessage' ], $errors[ 'errors' ] );
  180. $this->result[ 'errors' ] = array_merge( $this->result[ 'errors' ], $errors );
  181. return false;
  182. }
  183. /* Do conversions here */
  184. $converter = new ConvertFileWrapper( $stdFileObjects, false );
  185. $converter->intDir = $this->intDir;
  186. $converter->errDir = $this->errDir;
  187. $converter->cookieDir = $this->cookieDir;
  188. $converter->source_lang = $this->source_lang;
  189. $converter->target_lang = $this->target_lang;
  190. $converter->featureSet = $this->featureSet;
  191. $converter->doAction();
  192. $errors = $converter->checkResult();
  193. foreach ( $errors as $__err ) {
  194. // this is an array which identified not converted files such as xliff files
  195. $notConvertedFile = ["code" => 0, "message" => "OK"];
  196. if( $__err !== $notConvertedFile ){
  197. $this->result[ 'code' ] = 2;
  198. $brokenFileName = ZipArchiveExtended::getFileName( $__err[ 'debug' ] );
  199. if ( !isset( $this->result[ 'errors' ][ $brokenFileName ] ) ) {
  200. $this->result[ 'errors' ][ $brokenFileName ] = [
  201. 'code' => $__err[ 'code' ],
  202. 'message' => $__err[ 'message' ],
  203. 'debug' => $brokenFileName
  204. ];
  205. }
  206. }
  207. }
  208. }
  209. }