PageRenderTime 30ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/afisha-cinema-kinohod2/import.php

https://github.com/66ru/gpor-contrib
PHP | 399 lines | 331 code | 45 blank | 23 comment | 67 complexity | 0201833ee18e9dee6bdea2b6444ef295 MD5 | raw file
  1. <?php
  2. define('DS', '/');
  3. ini_set('memory_limit', '-1');
  4. mb_internal_encoding("UTF-8");
  5. date_default_timezone_set('Asia/Yekaterinburg');
  6. include_once ('../_lib/xmlrpc-3.0.0.beta/xmlrpc.inc');
  7. class afishaCinemaKinohodParser
  8. {
  9. private $params = array(
  10. 'apiUrl' => '',
  11. 'apiKey' => '',
  12. 'kApiUrl' => '',
  13. 'kApiKey' => '',
  14. 'kPurchaseUrl' => '',
  15. 'kPurchaseUrlMobile' => '',
  16. 'kClientApiKey' => '',
  17. 'debug' => true
  18. );
  19. private $places = array();
  20. private $movies = array();
  21. private $seances = array();
  22. private function loadParams()
  23. {
  24. if (!is_file('config.php')) {
  25. echo "missing config.php";
  26. die;
  27. }
  28. $this->params = array_merge($this->params, include 'config.php');
  29. foreach ($this->params as $key => $param) {
  30. if (!isset($param)) {
  31. echo 'missing ' . $key . 'param in config file';
  32. die;
  33. }
  34. }
  35. }
  36. /**
  37. * Загружает список объектов с кинохода
  38. * @param string $type Доступны значения 'cinemas', 'movies'
  39. * @return array
  40. */
  41. public function loadList($type)
  42. {
  43. if (!$this->params['kCityId']) {
  44. return array();
  45. }
  46. $url = $this->params['kApiUrl'] . $this->params['kApiKey'] . '/' . $type . '.json';
  47. $headers = get_headers($url);
  48. if (substr($headers[0], 9, 3) != '200') {
  49. return false;
  50. }
  51. $content = false;
  52. $result = @file_get_contents($url);
  53. if ($result) {
  54. if ($this->saveData($type.'.json.gz', $result))
  55. $content = $this->readData($type.'.json.gz');
  56. }
  57. return $content;
  58. }
  59. /**
  60. * Загрузка расписаний кинотеатра
  61. * @param int placeId
  62. * @param string $dateString
  63. */
  64. public function loadSchedules()
  65. {
  66. $res = array();
  67. $urls = array();
  68. $urls[] = $this->params['kApiUrl'] . $this->params['kApiKey'] . '/city/' . $this->params['kCityId'] . '/seances/week.json';
  69. $urls[] = $this->params['kApiUrl'] . $this->params['kApiKey'] . '/city/' . $this->params['kCityId'] . '/seances/week/+1.json';
  70. $i = 1;
  71. foreach ($urls as $url) {
  72. $headers = get_headers($url);
  73. if (substr($headers[0], 9, 3) != '200')
  74. return false;
  75. $content = false;
  76. $result = @file_get_contents($url);
  77. if ($result) {
  78. if ($this->saveData('seances' . $i . '.json.gz', $result))
  79. $content = $this->readData('seances' . $i . '.json.gz');
  80. }
  81. $i++;
  82. if ($content)
  83. $res = array_merge($content, $res);
  84. }
  85. return $res;
  86. }
  87. public function run()
  88. {
  89. $this->loadParams();
  90. $this->places = $this->loadList('cinemas'); // список кинотеатров города
  91. $existingPlaces = $this->sendData("afisha.listPlaces");
  92. // Формируем массив кинотеатров, которые нужно будет создать на gpor
  93. $placesToSend = array();
  94. foreach ($this->places as $key => $place) {
  95. if (isset($this->params['disabledPlaces'][$place->title])) {
  96. if ($this->params['debug'])
  97. echo 'Place "' . $place->title . '" disabled.' . PHP_EOL;
  98. continue;
  99. }
  100. if ($place->cityId != $this->params['kCityId']) {
  101. //if ($this->params['debug'])
  102. // echo 'Place "' . $place->title . '" different city.' . PHP_EOL;
  103. continue;
  104. }
  105. $found = false;
  106. foreach($existingPlaces as $eKey => $ePlace) {
  107. if ($found)
  108. break;
  109. if ($this->matchName($place->title, $ePlace['name']) || $this->matchName($place->shortTitle, $ePlace['name'])) {
  110. $this->places[$key]->ePlaceId = $ePlace['id'];
  111. unset($existingPlaces[$eKey]);
  112. $found = true;
  113. break;
  114. }
  115. if ($ePlace['synonym']) {
  116. foreach (unserialize($ePlace['synonym']) as $syn) {
  117. if ($this->matchName($place->title, $syn) || $this->matchName($place->shortTitle, $syn)) {
  118. $this->places[$key]->ePlaceId = $ePlace['id'];
  119. unset($existingPlaces[$eKey]);
  120. $found = true;
  121. break;
  122. }
  123. }
  124. }
  125. }
  126. if (!$found) {
  127. $placesToSend[] = array('name' => $place->title);
  128. }
  129. else {
  130. if ($this->params['debug'])
  131. echo 'Place "' . $place->title . '" found.' . PHP_EOL;
  132. }
  133. }
  134. // Отправляем новые кинотеатры на gpor
  135. if (!empty($placesToSend)) {
  136. if ($this->params['debug'])
  137. echo 'Send new places to gpor.' . PHP_EOL;
  138. $sendedPlaces = $this->sendData('afisha.postPlace', $placesToSend);
  139. // Проставляем созданным кинотеатрам корректные внешние идентификаторы
  140. foreach ($sendedPlaces as $ePlace) {
  141. foreach ($this->places as $key => $place) {
  142. if ($this->matchName($place->title, $ePlace['name'])) {
  143. $this->places[$key]->ePlaceId = $ePlace['id'];
  144. }
  145. }
  146. }
  147. }
  148. // Формируем массив фильмов для загрузки на gpor
  149. $this->movies = $this->loadList('city/'. $this->params['kCityId'] .'/running/week');
  150. $existingMovies = $this->sendData('afisha.listMovies');
  151. $movieIdsArray = array(); // Массив соответствий индентификаторов фильма (kinohod => gpor)
  152. $moviesToSend = array();
  153. foreach ($this->movies as $key => $movie) {
  154. $found = false;
  155. foreach ($existingMovies as $eKey => $eMovie) {
  156. if ($found)
  157. break;
  158. if ($this->matchName($movie->title, $eMovie['title']) || $this->matchName($movie->originalTitle, $eMovie['originalTitle'])) {
  159. $movieIdsArray[$movie->id] = $eMovie['id'];
  160. unset($existingMovies[$eKey]);
  161. $found = true;
  162. break;
  163. }
  164. if ($eMovie['synonym']) {
  165. foreach (unserialize($eMovie['synonym']) as $syn) {
  166. if ($this->matchName($movie->title, $syn) || $this->matchName($movie->originalTitle, $syn)) {
  167. $movieIdsArray[$movie->id] = $eMovie['id'];
  168. unset($existingMovies[$eKey]);
  169. $found = true;
  170. break;
  171. }
  172. }
  173. }
  174. }
  175. if (!$found) {
  176. $moviesToSend[] = array(
  177. 'name' => $movie->title,
  178. 'text' => $movie->annotationFull,
  179. 'genre' => implode(', ', self::ObjToList($movie->genres)),
  180. 'year' => $movie->productionYear,
  181. 'ageRestriction' => $movie->ageRestriction,
  182. 'director' => implode(', ', self::ObjToList($movie->directors)),
  183. 'starring' => implode(', ', self::ObjToList($movie->actors)),
  184. 'country' => implode(', ', self::ObjToList($movie->countries)),
  185. 'duration' => $movie->duration
  186. );
  187. }
  188. }
  189. // Отправляем новые фильмы на gpor
  190. if (!empty($moviesToSend)) {
  191. if ($this->params['debug'])
  192. echo 'Send new movies to gpor.' . PHP_EOL;
  193. $sendedMovies = $this->sendData('afisha.postMovie', $moviesToSend);
  194. // Проставляем в массив соответсивий идентификаторов загруженные значения
  195. foreach ($sendedMovies as $eMovie) {
  196. foreach ($this->movies as $key => $movie) {
  197. if ($this->matchName($movie->title, $eMovie['title'])) {
  198. $movieIdsArray[$movie->id] = $eMovie['id'];
  199. }
  200. }
  201. }
  202. }
  203. // Формируем массивы сеансов
  204. $schedulesToSend = array();
  205. $dataList = $this->loadSchedules();
  206. foreach ($this->places as $place) {
  207. // пропускаем кинотеатр, если его по каким-то причинам нет на гпоре
  208. $placeId = isset($place->ePlaceId) ? $place->ePlaceId : false;
  209. if (!$placeId)
  210. continue;
  211. foreach($dataList as $data) {
  212. // Пропускаем сеанс, если такого фильма на гпоре нет
  213. $movieId = isset($movieIdsArray[$data->movieId]) ? $movieIdsArray[$data->movieId] : false;
  214. $placeId = false;
  215. if (!$movieId)
  216. continue;
  217. foreach ($this->places as $place) {
  218. if ($place->id == $data->cinemaId && $place->ePlaceId) {
  219. $placeId = $place->ePlaceId;
  220. break;
  221. }
  222. }
  223. if (!$placeId)
  224. continue;
  225. $newSeance = array();
  226. $startTime = strtotime($data->startTime);
  227. $newSeance['is3d'] = in_array('3d', $data->formats) ? 1 : 0;
  228. $newSeance['isImax'] = in_array('imax', $data->formats) ? 1 : 0;
  229. $newSeance['seanceTime'] = $startTime;
  230. $newSeance['placeId'] = $placeId;
  231. $newSeance['movieId'] = $movieId;
  232. $newSeance['minPrice'] = $data->minPrice;
  233. $newSeance['maxPrice'] = $data->maxPrice;
  234. if ($data->isSaleAllowed) {
  235. $newSeance['purchaseLink'] = $this->params['kPurchaseUrl'] . $data->id . '?apikey=' . $this->params['kClientApiKey'];
  236. $newSeance['purchaseLinkMobile'] = $this->params['kPurchaseUrlMobile'] . $data->id . '?apiKey=' . $this->params['kClientApiKey'];
  237. } else {
  238. $newSeance['purchaseLink'] = '';
  239. $newSeance['purchaseLinkMobile'] = '';
  240. }
  241. $schedulesToSend[] = $newSeance;
  242. }
  243. }
  244. // Отправка сеансов
  245. if (sizeof($schedulesToSend)) {
  246. for ($i = 0; $i < sizeof($schedulesToSend); $i += 250) {
  247. if ($this->params['debug'])
  248. echo "afisha.postSeances " .$i . " - " . min(sizeof($schedulesToSend),($i+250)) . " of total " . sizeof($schedulesToSend) ."\n";
  249. $this->sendData('afisha.postSeances', array_slice($schedulesToSend, $i, 250));
  250. }
  251. }
  252. }
  253. public function sendData($name, $params = array())
  254. {
  255. $client = new xmlrpc_client($this->params['apiUrl']);
  256. $client->request_charset_encoding = 'UTF-8';
  257. $client->return_type = 'phpvals';
  258. $client->debug = 0;
  259. $msg = new xmlrpcmsg($name);
  260. $p1 = new xmlrpcval($this->params['apiKey'], 'string');
  261. $msg->addparam($p1);
  262. if ($params) {
  263. $p2 = php_xmlrpc_encode($params);
  264. $msg->addparam($p2);
  265. }
  266. $client->accepted_compression = 'deflate';
  267. $res = $client->send($msg, 60 * 5, 'http11');
  268. if ($res->faultcode()) {
  269. print "An error occurred: ";
  270. print " Code: " . htmlspecialchars($res->faultCode());
  271. print " Reason: '" . htmlspecialchars($res->faultString()) . "' \n";
  272. die;
  273. } else
  274. return $res->val;
  275. }
  276. private function matchName($a, $b)
  277. {
  278. $a = mb_strtolower($a);
  279. $b = mb_strtolower($b);
  280. $a = preg_replace('|[^\p{L}\p{Nd}]|u', '', $a);
  281. $b = preg_replace('|[^\p{L}\p{Nd}]|u', '', $b);
  282. if (($a == $b) && ($a!=''))
  283. return true;
  284. return false;
  285. }
  286. public static function ObjToList($data)
  287. {
  288. $res = array();
  289. if (is_array($data)) {
  290. foreach ($data as $row) {
  291. $res[] = $row->name;
  292. }
  293. }
  294. return $res;
  295. }
  296. public function saveData($filename, $data)
  297. {
  298. $path = $this->params['filePath'] . '/' . $filename;
  299. $pathinfo = pathinfo($path);
  300. $tmp = explode(DS, $pathinfo['dirname']);
  301. $tmpPath = '';
  302. foreach ($tmp as $part) {
  303. if (empty($part)) {
  304. $tmpPath = DS;
  305. continue;
  306. }
  307. $tmpPath .= $part . DS;
  308. if (!is_dir($tmpPath)) {
  309. echo $tmpPath;
  310. if (!mkdir($tmpPath, 0755))
  311. die('Can\'t create dir '.$tmpPath);
  312. chmod($tmpPath, 0755);
  313. }
  314. }
  315. $tmpFile = $path.'.tmp';
  316. if (!$handle = fopen($tmpFile, 'w+'))
  317. die('Can\'t create file '.$filename);
  318. fwrite($handle, $data);
  319. fclose($handle);
  320. if (file_exists($tmpFile)) {
  321. if (file_exists($path))
  322. unlink($path);
  323. copy($tmpFile, $path);
  324. }
  325. unlink($tmpFile);
  326. return true;
  327. }
  328. public function readData($filename)
  329. {
  330. $fileName = $this->params['filePath'] . '/' . $filename;
  331. if (!file_exists($fileName))
  332. return null;
  333. $content = '';
  334. var_dump($filename);
  335. $handle = gzopen($filename, "r");
  336. if ($handle) {
  337. while (($line = fgets($handle)) !== false) {
  338. $content .= $line;
  339. }
  340. fclose($handle);
  341. } else {
  342. die('error reading ' . $filename);
  343. }
  344. //$content = @file_get_contents($fileName);
  345. if (!$content)
  346. return null;
  347. $content = json_decode($content);
  348. if (!$content)
  349. return null;
  350. return $content;
  351. }
  352. }
  353. $p = new afishaCinemaKinohodParser();
  354. $p->run();