PageRenderTime 36ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/core_modules/importExport/backend/helpers/ImportExportHelper.php

https://bitbucket.org/btokman/unibot
PHP | 271 lines | 161 code | 31 blank | 79 comment | 25 complexity | 003b8578908d5dc84bd4133932bfa8ba MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: art
  5. * Date: 03.05.2017
  6. * Time: 10:54
  7. */
  8. namespace backend\modules\importExport\helpers;
  9. use backend\modules\importExport\models\ImportExportMessage;
  10. use metalguardian\fileProcessor\helpers\FPM;
  11. use yii\base\Exception;
  12. use yii\helpers\Inflector;
  13. use yii\web\UploadedFile;
  14. /**
  15. * Class DbimportHelper
  16. * @package backend\modules\importExport\helpers
  17. */
  18. class ImportExportHelper
  19. {
  20. const EXCEL_FORMAT_XML = 'Excel2003XML';
  21. const EXCEL_FORMAT_BIN = null;
  22. /**
  23. * Upload file and get path
  24. * @param $model
  25. * @param $attribute
  26. * @return bool|string
  27. */
  28. public static function uploadAndGetPath($model, $attribute)
  29. {
  30. if (count(UploadedFile::getInstances($model, $attribute)) == 0) {
  31. return false;
  32. }
  33. $file = UploadedFile::getInstances($model, $attribute)[0];
  34. $fileNameArray = explode('.', $file->name);
  35. $file->name = Inflector::slug(Inflector::transliterate($fileNameArray[0])) . '.' . $fileNameArray[1];
  36. $file->name = str_replace('-', '_', $file->name);
  37. $fileId = FPM::transfer()->saveUploadedFile($file);
  38. return \Yii::getAlias('@webroot') . FPM::getOriginalDirectoryUrl($fileId) . $fileId . '-' . $file->name;
  39. }
  40. /**
  41. * Get excel format
  42. * @param $filePath
  43. * @return string
  44. */
  45. public static function getExcelFormat($filePath)
  46. {
  47. //check is xml format
  48. $signature = [
  49. '<?xml version="1.0"'
  50. ];
  51. $isXml = self::validSignature($filePath, $signature);
  52. if ($isXml) {
  53. //check is valid xml
  54. $xmlValid = simplexml_load_file($filePath);
  55. //fix it if not valid
  56. if (!$xmlValid) {
  57. $data = file_get_contents($filePath);
  58. $data = self::stripInvalidXml($data);
  59. file_put_contents($filePath, $data);
  60. }
  61. //check if Excel2003XML for PHPExcel
  62. $signature = [
  63. '<?mso-application progid="Excel.Sheet"?>'
  64. ];
  65. $isExcelXml = self::validSignature($filePath, $signature);
  66. //if wrong format for PHPExcel - add signature tag
  67. if (!$isExcelXml) {
  68. $data = file_get_contents($filePath);
  69. $data = preg_replace('/' . preg_quote('?>', '/') . '/', '?>
  70. <?mso-application progid="Excel.Sheet"?>', $data, 1);
  71. file_put_contents($filePath, $data);
  72. }
  73. return self::EXCEL_FORMAT_XML;
  74. } else {
  75. return self::EXCEL_FORMAT_BIN;
  76. }
  77. }
  78. /**
  79. * fix excel data in preview, sometimes get something like this:
  80. * 69.6 (in excel cell) show as 69.59999999999999 (in preview) - don't know why
  81. * @param $dataArray
  82. * @return string[]
  83. */
  84. public static function fixExcelPreview($dataArray)
  85. {
  86. for ($i = 0; $i < count($dataArray); $i++) {
  87. foreach ($dataArray[$i] as $label => $value) {
  88. if (is_numeric($value)) {
  89. $numArray = explode('.', $value);
  90. if (isset($numArray[1]) && (strlen($numArray[1] > 2))) {
  91. $dataArray[$i][$label] = number_format($value, 2, '.', '');
  92. }
  93. }
  94. }
  95. }
  96. return $dataArray;
  97. }
  98. /**
  99. * format string for Excel preview
  100. * @param $columnValue
  101. * @return string
  102. */
  103. public static function formatForPreview($columnValue)
  104. {
  105. $cleanValue = strip_tags($columnValue);
  106. if (mb_strlen($cleanValue) > 50) {
  107. $cleanValue = mb_substr($cleanValue, 0, 50);
  108. $cleanValue .= '...';
  109. }
  110. return $cleanValue;
  111. }
  112. /**
  113. * check file signature
  114. * @param $filePath
  115. * @param $signature
  116. * @return bool
  117. */
  118. private static function validSignature($filePath, $signature)
  119. {
  120. // Open file
  121. $fileHandle = self::openFile($filePath, 'r');
  122. // Read sample data (first 2 KB will do)
  123. $data = fread($fileHandle, 2048);
  124. fclose($fileHandle);
  125. $valid = true;
  126. foreach ($signature as $match) {
  127. // every part of the signature must be present
  128. if (strpos($data, $match) === false) {
  129. $valid = false;
  130. break;
  131. }
  132. }
  133. return $valid;
  134. }
  135. /**
  136. * open file
  137. * @param $filePath
  138. * @param $type
  139. * @return mixed
  140. * @throws Exception
  141. */
  142. private static function openFile($filePath, $type)
  143. {
  144. // Check if file exists
  145. if (!file_exists($filePath) || !is_readable($filePath)) {
  146. throw new Exception('Could not open ' . $filePath . ' for reading! File does not exist.');
  147. }
  148. // Open file
  149. $fileHandle = fopen($filePath, $type);
  150. if ($fileHandle === false) {
  151. throw new Exception('Could not open file ' . $filePath . ' for reading.');
  152. }
  153. return $fileHandle;
  154. }
  155. /**
  156. * fix invalid XML
  157. * @param $value
  158. * @return string
  159. */
  160. private static function stripInvalidXml($value)
  161. {
  162. $ret = '';
  163. $current = null;
  164. if (empty($value)) {
  165. return $ret;
  166. }
  167. $length = strlen($value);
  168. for ($i = 0; $i < $length; $i++) {
  169. $current = ord($value{$i});
  170. if (($current == 0x9) ||
  171. ($current == 0xA) ||
  172. ($current == 0xD) ||
  173. (($current >= 0x20) && ($current <= 0xD7FF)) ||
  174. (($current >= 0xE000) && ($current <= 0xFFFD)) ||
  175. (($current >= 0x10000) && ($current <= 0x10FFFF))
  176. ) {
  177. $ret .= chr($current);
  178. } else {
  179. $ret .= ' ';
  180. }
  181. }
  182. return $ret;
  183. }
  184. /**
  185. * add message with data import result
  186. * @param $type
  187. * @param $handler
  188. * @param $message
  189. * @param int $isShow
  190. */
  191. public static function addImportExportMessage($type, $handler, $message, $isShow = 1)
  192. {
  193. $newMessage = new ImportExportMessage();
  194. $newMessage->type = $type;
  195. $newMessage->handler = $handler;
  196. $newMessage->message = $message;
  197. $newMessage->is_show = $isShow;
  198. $newMessage->is_shown = 0;
  199. $newMessage->save(false);
  200. }
  201. /**
  202. * add message with data import result
  203. * @param $type
  204. * @param $handler
  205. * @param $messageGlobal
  206. * @param $massageLog
  207. */
  208. public static function addDoubleImportExportMessage($type, $handler, $messageGlobal, $massageLog)
  209. {
  210. //add global message
  211. $newMessage = new ImportExportMessage();
  212. $newMessage->type = $type;
  213. $newMessage->handler = $handler;
  214. $newMessage->message = $messageGlobal;
  215. $newMessage->is_show = 1;
  216. $newMessage->is_shown = 0;
  217. $newMessage->save(false);
  218. //add log message
  219. $newMessage = new ImportExportMessage();
  220. $newMessage->type = $type;
  221. $newMessage->handler = $handler;
  222. $newMessage->message = $massageLog;
  223. $newMessage->is_show = 0;
  224. $newMessage->is_shown = 0;
  225. $newMessage->save(false);
  226. }
  227. /**
  228. * @param $massage
  229. */
  230. public static function addExportErrorMessage($massage)
  231. {
  232. $messageGlobal = \Yii::t('back/import-export', 'Export error. View log for details');
  233. self::addDoubleImportExportMessage(
  234. ImportExportMessage::MESSAGE_TYPE_ERROR,
  235. ImportExportMessage::MESSAGE_HANDLER_EXPORT,
  236. $messageGlobal,
  237. $massage
  238. );
  239. }
  240. }