Play images and video from Synology PhotoStation server

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. <?php
  2. require_once('smart_album.inc.php');
  3. require_once('albumutil.php');
  4. class SmartAlbumAPI extends WebAPI {
  5. function __construct() {
  6. parent::__construct(SZ_WEBAPI_API_DESCRIPTION_PATH);
  7. }
  8. protected function Process() {
  9. if (!strcasecmp($this->method, "list")) {
  10. session_write_close();
  11. $this->SmartAlbumList();
  12. } elseif (!strcasecmp($this->method, "getinfo")) {
  13. session_write_close();
  14. $this->GetInfo();
  15. } else {
  16. csSYNOPhotoMisc::CheckSessionTimeOut();
  17. if (!strcasecmp($this->method, "create")) {
  18. $this->Create();
  19. } elseif (!strcasecmp($this->method, "edit")) {
  20. $this->Edit();
  21. } elseif (!strcasecmp($this->method, "delete")) {
  22. $this->Delete();
  23. }
  24. }
  25. }
  26. private function ExtractAlbumToArray($data)
  27. {
  28. $params = array();
  29. $idArr = array();
  30. $items = explode(',', $data);
  31. foreach ($items as $item) {
  32. $arr = explode('_', $item);
  33. if (2 !== count($arr)) {
  34. return $idArr;
  35. }
  36. if ('album' !== $arr[0]) {
  37. return $idArr;
  38. }
  39. $sharename = trim($arr[1]);
  40. if ('' != $sharename) {
  41. $sharename = @pack('H*', $arr[1]);
  42. array_push($params, $sharename);
  43. }
  44. }
  45. $albums = Album::GetBySharename($params);
  46. foreach ($albums as $album) {
  47. $id = $album['shareid'];
  48. array_push($idArr, $id);
  49. }
  50. return $idArr;
  51. }
  52. private function ExtractTagStringToArray($tagString)
  53. {
  54. $tagArr = array();
  55. $arr = explode(',', $tagString);
  56. foreach ($arr as $tag) {
  57. $split = explode('tag_', $tag);
  58. if (2 !== count($split)) {
  59. return $tagArr;
  60. }
  61. array_push($tagArr, $split[1]);
  62. }
  63. return $tagArr;
  64. }
  65. private function ExtractExifStringToArray($exifString, $prefix = 'tag_')
  66. {
  67. $exifArr = array();
  68. $arr = explode(',', $exifString);
  69. foreach ($arr as $exif) {
  70. $split = explode($prefix, $exif);
  71. if (2 !== count($split)) {
  72. return false;
  73. }
  74. array_push($exifArr, $split[1]);
  75. }
  76. return $exifArr;
  77. }
  78. private function GetParams_List() {
  79. $params = array();
  80. if (!isset($_REQUEST['offset']) || !isset($_REQUEST['limit'])) {
  81. return false;
  82. }
  83. $params['offset'] = $_REQUEST['offset'];
  84. $params['limit'] = $_REQUEST['limit'];
  85. $params['sort_by'] = (isset($_REQUEST['sort_by'])) ? $_REQUEST['sort_by'] : 'title';
  86. if (!in_array($params['sort_by'], array('title'))) {
  87. return false;
  88. }
  89. $params['sort_direction'] = (isset($_REQUEST['sort_direction'])) ? $_REQUEST['sort_direction'] : 'asc';
  90. if (!in_array($params['sort_direction'], array('asc', 'desc'))) {
  91. return false;
  92. }
  93. // additional operator
  94. $params['additional'] = array();
  95. $params['additional'] = explode(',', $_REQUEST['additional']);
  96. return $params;
  97. }
  98. /**
  99. *
  100. * @return
  101. * params object - success
  102. * -1 - bad parameter
  103. * -2 - smart album not exist
  104. */
  105. private function GetParams_Info() {
  106. $params = array();
  107. if (!isset($_REQUEST['id'])) {
  108. return -1;
  109. }
  110. $arr = explode(',', $_REQUEST['id']);
  111. $params['id'] = array();
  112. foreach ($arr as $smartID) {
  113. if (!$this->CheckSmartAlbumExist($smartID)) {
  114. return -2;
  115. }
  116. $split = explode('smart_', $smartID);
  117. array_push($params['id'], $split[1]);
  118. }
  119. // additional operator
  120. $params['additional'] = array();
  121. $params['additional'] = explode(',', $_REQUEST['additional']);
  122. return $params;
  123. }
  124. /**
  125. *
  126. * @return
  127. * -1 - bad parameter
  128. * -2 - smart album not exist
  129. */
  130. private function GetPrams_Edit() {
  131. $params = array();
  132. if (!isset($_REQUEST['id'])) {
  133. return -1;
  134. }
  135. // check smart album exist
  136. if (!$this->CheckSmartAlbumExist($_REQUEST['id'])) {
  137. return -2;
  138. }
  139. $arr = explode('smart_', $_REQUEST['id']);
  140. if (2 !== count($arr)) {
  141. return -1;
  142. }
  143. $params['id'] = $arr[1];
  144. $smartName = @pack('H*', $arr[1]);
  145. $params['name'] = (isset($_REQUEST['name']) && '' !== $_REQUEST['name']) ? $_REQUEST['name'] : $smartName;
  146. $params['orig_name'] = $smartName;
  147. // get original smart album setting
  148. $smartAlbumCond = SmartAlbum::GetSmartAlbumInstance()->GetSmartCondition($smartName);
  149. // type
  150. if (isset($_REQUEST['type'])) {
  151. $params['type'] = $_REQUEST['type'];
  152. $arr = explode(',', $params['type']);
  153. $count = 0;
  154. foreach ($arr as $type) {
  155. if (!in_array($type, array('photo', 'video'))) {
  156. return -1;
  157. }
  158. $count++;
  159. }
  160. if (1 > $count) {
  161. return -1;
  162. }
  163. } else {
  164. $params['type'] = $smartAlbumCond['type'];
  165. }
  166. // albums
  167. if (isset($_REQUEST['albums'])) {
  168. if (empty($_REQUEST['albums'])) {
  169. $params['albums'] = null;
  170. } else {
  171. $params['albums'] = $this->ExtractAlbumToArray($_REQUEST['albums']);
  172. }
  173. } else {
  174. $arr = $this->ExtractAlbumToArray($smartAlbumCond['albums']);
  175. $params['albums'] = empty($arr) ? null : $arr;
  176. }
  177. // keyword
  178. if (isset($_REQUEST['keyword'])) {
  179. if ('' === $_REQUEST['keyword']) {
  180. $params['keyword'] = null;
  181. $params['keyword_op'] = null;
  182. } else {
  183. $params['keyword'] = $_REQUEST['keyword'];
  184. $default = isset($smartAlbumCond['keyword_op']) ? $smartAlbumCond['keyword_op'] : 'any';
  185. $params['keyword_op'] = (isset($_REQUEST['keyword_op'])) ? $_REQUEST['keyword_op'] : $default;
  186. if (isset($params['keyword_op']) && !in_array($params['keyword_op'], array('any', 'all', 'exact'))) {
  187. return -1;
  188. }
  189. }
  190. } else {
  191. $params['keyword'] = $smartAlbumCond['keyword'];
  192. $params['keyword_op'] = $smartAlbumCond['keyword_op'];
  193. }
  194. // date
  195. if (isset($_REQUEST['date'])) {
  196. if (empty($_REQUEST['date'])) {
  197. $params['date'] = null;
  198. $params['date_op'] = null;
  199. } else {
  200. $default = isset($smartAlbumCond['date_op']) ? $smartAlbumCond['date_op'] : 'taken';
  201. $params['date_op'] = (isset($_REQUEST['date_op'])) ? $_REQUEST['date_op'] : $default;
  202. if (in_array($params['date_op'], array('recently_add', 'recently_comment'))) {
  203. $params['date'] = $_REQUEST['date'];
  204. } else if (in_array($params['date_op'], array('taken', 'upload'))) {
  205. $dates = explode(',', $_REQUEST['date']);
  206. try {
  207. if ($dates[0]) {
  208. $date1 = new DateTime($dates[0]);
  209. }
  210. if ($dates[1]) {
  211. $date2 = new DateTime($dates[1]);
  212. }
  213. } catch (Exception $e) {
  214. return -1;
  215. }
  216. if (($date1 && $date2 && $date2 < $date1) || (!$date1 && !$date2)) {
  217. return -1;
  218. }
  219. $params['date'] = ($date1 ? $date1->format('Y-m-d') : "").",".($date2 ? $date2->format("Y-m-d") : "");
  220. } else {
  221. return -1;
  222. }
  223. }
  224. } else {
  225. $params['date'] = $smartAlbumCond['date'];
  226. $params['date_op'] = $smartAlbumCond['date_op'];
  227. }
  228. // peopel_tag
  229. if (isset($_REQUEST['people_tag'])) {
  230. if (empty($_REQUEST['people_tag'])) {
  231. $params['people_tag'] = null;
  232. $params['people_tag_op'] = null;
  233. } else {
  234. // get people_tag
  235. $params['people_tag'] = $this->ExtractTagStringToArray($_REQUEST['people_tag']);
  236. // get people_tag_op
  237. $default = isset($smartAlbumCond['people_tag_op']) ? $smartAlbumCond['people_tag_op'] : 'all';
  238. $params['people_tag_op'] = (isset($_REQUEST['people_tag_op'])) ? $_REQUEST['people_tag_op'] : $default;
  239. if (isset($params['people_tag_op']) && !in_array($params['people_tag_op'], array('all', 'any'))) {
  240. return -1;
  241. }
  242. }
  243. } else {
  244. $arr = $this->ExtractTagStringToArray($smartAlbumCond['people_tag']);
  245. $params['people_tag'] = empty($arr) ? null : $arr;
  246. $params['people_tag_op'] = $smartAlbumCond['people_tag_op'];
  247. }
  248. // geo_tag
  249. if (isset($_REQUEST['geo_tag'])) {
  250. if (empty($_REQUEST['geo_tag'])) {
  251. $params['geo_tag'] = null;
  252. $params['geo_tag_op'] = null;
  253. } else {
  254. // get geo_tag
  255. $params['geo_tag'] = $this->ExtractTagStringToArray($_REQUEST['geo_tag']);
  256. // get geo_tag_op
  257. $default = isset($smartAlbumCond['geo_tag_op']) ? $smartAlbumCond['geo_tag_op'] : 'all';
  258. $params['geo_tag_op'] = (isset($_REQUEST['geo_tag_op'])) ? $_REQUEST['geo_tag_op'] : $default;
  259. if (isset($params['geo_tag_op']) && !in_array($params['geo_tag_op'], array('all', 'any'))) {
  260. return -1;
  261. }
  262. }
  263. } else {
  264. $arr = $this->ExtractTagStringToArray($smartAlbumCond['geo_tag']);
  265. $params['geo_tag'] = empty($arr) ? null : $arr;
  266. $params['geo_tag_op'] = $smartAlbumCond['geo_tag_op'];
  267. }
  268. // desc_tag
  269. if (isset($_REQUEST['desc_tag'])) {
  270. if (empty($_REQUEST['desc_tag'])) {
  271. $params['desc_tag'] = null;
  272. $params['desc_tag_op'] = null;
  273. } else {
  274. // get desc_tag
  275. $params['desc_tag'] = $this->ExtractTagStringToArray($_REQUEST['desc_tag']);
  276. // get desc_tag_op
  277. $default = isset($smartAlbumCond['desc_tag_op']) ? $smartAlbumCond['desc_tag_op'] : 'all';
  278. $params['desc_tag_op'] = (isset($_REQUEST['desc_tag_op'])) ? $_REQUEST['desc_tag_op'] : $default;
  279. if (isset($params['desc_tag_op']) && !in_array($params['desc_tag_op'], array('all', 'any'))) {
  280. return -1;
  281. }
  282. }
  283. } else {
  284. $arr = $this->ExtractTagStringToArray($smartAlbumCond['desc_tag']);
  285. $params['desc_tag'] = empty($arr) ? null : $arr;
  286. $params['desc_tag_op'] = $smartAlbumCond['desc_tag_op'];
  287. }
  288. foreach(SmartAlbum::$exif2IdPrefix as $label => $prefix) {
  289. $exifParam = $this->GetExifParams_Edit($label, $prefix.'_');
  290. if (-1 === $exifParam['success']) {
  291. return -1;
  292. } else {
  293. $params[$label] = $exifParam['label'];
  294. $params[$label.'_op'] = $exifParam['op'];
  295. }
  296. }
  297. if ((null === $params['keyword'] || '' === $params['keyword']) && empty($params['date']) && empty($params['people_tag']) && empty($params['geo_tag'])
  298. && empty($params['desc_tag']) && empty($params['albums']) && empty($params['camera']) && empty($params['model']) && empty($params['exposure']) && empty($params['aperture'])
  299. && empty($params['iso']) && empty($params['focal']) && empty($params['lens']) && empty($params['flash'])) {
  300. return -1;
  301. }
  302. return $params;
  303. }
  304. private function GetExifParams_Edit($label, $prefix) {
  305. $ret['success'] = true;
  306. $op = $label."_op";
  307. if (isset($_REQUEST[$label])) {
  308. if (empty($_REQUEST[$label])) {
  309. $ret['label'] = null;
  310. $ret['op'] = null;
  311. } else {
  312. $ret['label'] = array();
  313. $ret['label'] = $this->ExtractExifStringToArray($_REQUEST[$label], $prefix);
  314. $defalt = isset($smartAlbumCond[$op]) ? $smartAlbumCond[$op] : 'any';
  315. $ret['op'] = (isset($_REQUEST[$op])) ? $_REQUEST[$op] : $default;
  316. if (isset($ret['op']) && 'any' !== $ret['op']) {
  317. $ret['success'] = false;
  318. }
  319. }
  320. } else {
  321. $arr = $this->ExtractExifStringToArray($smartAlbumCond[$lable]);
  322. $ret['label'] = empty($arr) ? null : $arr;
  323. $ret['op'] = $smartAlbumCond[$op];
  324. }
  325. return $ret;
  326. }
  327. private function GetParams_Create() {
  328. $params = array();
  329. if (!isset($_REQUEST['name']) || !isset($_REQUEST['type'])) {
  330. return false;
  331. }
  332. $params['name'] = $_REQUEST['name'];
  333. // type
  334. $params['type'] = $_REQUEST['type'];
  335. $arr = explode(',', $params['type']);
  336. $count = 0;
  337. foreach ($arr as $type) {
  338. if (!in_array($type, array('photo', 'video'))) {
  339. return false;
  340. }
  341. $count++;
  342. }
  343. if (1 > $count) {
  344. return false;
  345. }
  346. $albums = (isset($_REQUEST['albums'])) ? $_REQUEST['albums'] : null;
  347. if (!empty($_REQUEST['albums'])) {
  348. $params['albums'] = $this->ExtractAlbumToArray($albums);
  349. }
  350. $params['keyword'] = (isset($_REQUEST['keyword'])) ? $_REQUEST['keyword'] : null;
  351. if (!empty($_REQUEST['keyword']) || '0' === $_REQUEST['keyword']) {
  352. $default = 'all';
  353. $params['keyword_op'] = (isset($_REQUEST['keyword_op'])) ? $_REQUEST['keyword_op'] : $default;
  354. if (isset($params['keyword_op']) && !in_array($params['keyword_op'], array('any', 'all', 'exact'))) {
  355. return false;
  356. }
  357. }
  358. $params['date'] = (isset($_REQUEST['date'])) ? $_REQUEST['date'] : null;
  359. if (!empty($_REQUEST['date'])) {
  360. $default = 'taken';
  361. $params['date_op'] = (isset($_REQUEST['date_op'])) ? $_REQUEST['date_op'] : $default;
  362. if (isset($params['date_op']) && !in_array($params['date_op'], array('taken', 'upload', 'recently_add', 'recently_comment'))) {
  363. return false;
  364. }
  365. }
  366. $people_tags = (isset($_REQUEST['people_tag'])) ? $_REQUEST['people_tag'] : null;
  367. if (!empty($_REQUEST['people_tag'])) {
  368. // get people_tag
  369. $params['people_tag'] = array();
  370. $params['people_tag'] = $this->ExtractTagStringToArray($people_tags);
  371. // get people_tag_op
  372. $default = 'all';
  373. $params['people_tag_op'] = (isset($_REQUEST['people_tag_op'])) ? $_REQUEST['people_tag_op'] : $default;
  374. if (isset($params['people_tag_op']) && !in_array($params['people_tag_op'], array('all', 'any'))) {
  375. return false;
  376. }
  377. }
  378. $geo_tags = (isset($_REQUEST['geo_tag'])) ? $_REQUEST['geo_tag'] : null;
  379. if (!empty($_REQUEST['geo_tag'])) {
  380. // get geo_tag
  381. $params['geo_tag'] = array();
  382. $params['geo_tag'] = $this->ExtractTagStringToArray($geo_tags);
  383. // get geo_tag_op
  384. $default = 'all';
  385. $params['geo_tag_op'] = (isset($_REQUEST['geo_tag_op'])) ? $_REQUEST['geo_tag_op'] : $default;
  386. if (isset($params['geo_tag_op']) && !in_array($params['geo_tag_op'], array('all', 'any'))) {
  387. return false;
  388. }
  389. }
  390. $desc_tags = (isset($_REQUEST['desc_tag'])) ? $_REQUEST['desc_tag'] : null;
  391. if (!empty($_REQUEST['desc_tag'])) {
  392. // get desc_tag
  393. $params['desc_tag'] = array();
  394. $params['desc_tag'] = $this->ExtractTagStringToArray($desc_tags);
  395. // get desc_tag_op
  396. $default = 'all';
  397. $params['desc_tag_op'] = (isset($_REQUEST['desc_tag_op'])) ? $_REQUEST['desc_tag_op'] : $default;
  398. if (isset($params['desc_tag_op']) && !in_array($params['desc_tag_op'], array('all', 'any'))) {
  399. return false;
  400. }
  401. }
  402. foreach(SmartAlbum::$exif2IdPrefix as $label => $prefix) {
  403. $value = (isset($_REQUEST[$label])) ? $_REQUEST[$label] : null;
  404. $op = $label.'_op';
  405. if (!empty($_REQUEST[$label])) {
  406. $params[$label] = $this->ExtractExifStringToArray($value, $prefix.'_');
  407. $default = 'any';
  408. $params[$op] = (isset($_REQUEST[$op])) ? $_REQUEST[$op] : $default;
  409. if (isset($params[$op]) && 'any' !== $params[$op]) {
  410. return false;
  411. }
  412. }
  413. }
  414. if ((null === $params['keyword'] || '' === $params['keyword']) && empty($params['albums']) && empty($params['date']) && empty($params['people_tag'])
  415. && empty($params['geo_tag']) && empty($params['desc_tag']) && empty($params['camera']) && empty($params['model'])
  416. && empty($params['exposure']) && empty($params['aperture']) && empty($params['iso']) && empty($params['focal'])
  417. && empty($params['lens']) && empty($params['flash'])) {
  418. return false;
  419. }
  420. return $params;
  421. }
  422. /**
  423. *
  424. * @param
  425. * $tagIDs - array
  426. * $type - 0 means people tag
  427. * 1 means geo tag
  428. * 2 means desc tag
  429. */
  430. private function CheckTagExist($tagIDs, $type) {
  431. if (!is_array($tagIDs)) {
  432. return false;
  433. }
  434. foreach ($tagIDs as $id) {
  435. $query = "SELECT count(id) FROM photo_label WHERE id={$id} AND category={$type}";
  436. $db_result = PHOTO_DB_Query($query);
  437. $row = PHOTO_DB_FetchRow($db_result);
  438. if (1 !== (int)$row[0]) {
  439. return false;
  440. }
  441. }
  442. return true;
  443. }
  444. private function CheckExifExist($exifNames, $columnName) {
  445. if (!is_array($exifNames)) {
  446. return false;
  447. }
  448. foreach($exifNames as $exifName) {
  449. if ('flash_v2' == $columnName) {
  450. $exifName = str_replace('#', ',', $exifName);
  451. }
  452. $query = "SELECT count(". $columnName .") FROM photo_image WHERE ". $columnName ."=?";
  453. $db_result = PHOTO_DB_Query($query, array($exifName));
  454. $row = PHOTO_DB_FetchRow($db_result);
  455. if (1 > (int)$row[0]) {
  456. return false;
  457. }
  458. }
  459. return true;
  460. }
  461. /**
  462. *
  463. * @param
  464. * $smartID - ex: smart_id
  465. */
  466. private function CheckSmartAlbumExist($smartID) {
  467. $arr = explode('smart_', $smartID);
  468. if (2 !== count($arr)) {
  469. return false;
  470. }
  471. $smartName = @pack('H*', $arr[1]);
  472. $result = SmartAlbum::GetSmartAlbumInstance()->ReadSmartAlbumFile();
  473. if (!isset($result['smart_albums'][$smartName])) {
  474. return false;
  475. }
  476. return true;
  477. }
  478. private function ConvertToSmartExifCondition($data, $label, $op){
  479. $rule_set['field'] = $label;
  480. $rule_set['operator'] = $data[$op];
  481. $strings = implode(',', $data[$label]);
  482. $rule_set['value'] = $strings;
  483. return $rule_set;
  484. }
  485. private function ConvertToSmartCondition($data) {
  486. $rule_sets = array();
  487. $rule_sets[0] = array();
  488. $ret['orig_name'] = $data['orig_name'];
  489. $ret['name'] = $data['name'];
  490. $ret['desc'] = '';
  491. $ret['show_photo'] = strstr($data['type'], 'photo') ? true : false;
  492. $ret['show_video'] = strstr($data['type'], 'video') ? true : false;
  493. if (isset($data['albums'])) {
  494. $rule_set['field'] = 'albums';
  495. $rule_set['operator'] = 'any';
  496. $albumString = implode(',', $data['albums']);
  497. $rule_set['value'] = $albumString;
  498. array_push($rule_sets[0], $rule_set);
  499. }
  500. if (isset($data['keyword']) && isset($data['keyword_op'])) {
  501. $rule_set['field'] = 'keyword';
  502. $rule_set['operator'] = $data['keyword_op'];
  503. $rule_set['value'] = $data['keyword'];
  504. array_push($rule_sets[0], $rule_set);
  505. }
  506. if (isset($data['date']) && isset($data['date_op'])) {
  507. $rule_set['field'] = 'date';
  508. $rule_set['operator'] = $data['date_op'];
  509. $rule_set['value'] = $data['date'];
  510. array_push($rule_sets[0], $rule_set);
  511. }
  512. if (isset($data['people_tag']) && isset($data['people_tag_op'])) {
  513. $rule_set['field'] = 'people';
  514. $rule_set['operator'] = $data['people_tag_op'];
  515. $peopleString = implode(',', $data['people_tag']);
  516. $rule_set['value'] = $peopleString;
  517. array_push($rule_sets[0], $rule_set);
  518. }
  519. if (isset($data['geo_tag']) && isset($data['geo_tag_op'])) {
  520. $rule_set['field'] = 'geo';
  521. $rule_set['operator'] = $data['geo_tag_op'];
  522. $geoString = implode(',', $data['geo_tag']);
  523. $rule_set['value'] = $geoString;
  524. array_push($rule_sets[0], $rule_set);
  525. }
  526. if (isset($data['desc_tag']) && isset($data['desc_tag_op'])) {
  527. $rule_set['field'] = 'desc';
  528. $rule_set['operator'] = $data['desc_tag_op'];
  529. $descString = implode(',', $data['desc_tag']);
  530. $rule_set['value'] = $descString;
  531. array_push($rule_sets[0], $rule_set);
  532. }
  533. foreach(SmartAlbum::$exif2IdPrefix as $label => $prefix) {
  534. $op = $label.'_op';
  535. if (isset($data[$label]) && isset($data[$op])) {
  536. $rule_set = $this->ConvertToSmartExifCondition($data, $label, $op);
  537. array_push($rule_sets[0], $rule_set);
  538. }
  539. }
  540. $ret['rule_sets'] = $rule_sets;
  541. return json_encode($ret);
  542. }
  543. private function FormSmartAlbums($smartNames = false, $params = array()) {
  544. $smartAlbumList = SmartAlbum::GetSmartAlbumInstance()->ReadSmartAlbumFile();
  545. $smartAlbumArr = array();
  546. if (empty($smartAlbumList) || !is_array($smartAlbumList['smart_albums'])) {
  547. return $smartAlbumArr;
  548. }
  549. $smartAlbums = $smartAlbumList['smart_albums'];
  550. if (false != $smartNames) {
  551. foreach($smartNames as $name) {
  552. if ($smartAlbums[$name]) {
  553. $list[$name] = $smartAlbums[$name];
  554. }
  555. }
  556. } else {
  557. $list = $smartAlbums;
  558. }
  559. $needThumbSize = in_array('thumb_size', $params['additional']);
  560. foreach ($list as $key => $item) {
  561. $item['name'] = (string)$key;
  562. $smartAlbum = Decorator::SmartFormula($item, array(
  563. 'param'=> $params,
  564. 'needThumbSize' => $needThumbSize
  565. ));
  566. if (-1 === $smartAlbum) {
  567. continue;
  568. }
  569. $smartAlbumArr[] = $smartAlbum;
  570. }
  571. return $smartAlbumArr;
  572. }
  573. private function SortTitle_ASC($a, $b) {
  574. if (strtoupper($a['name']) == strtoupper($b['name'])) {
  575. return 0;
  576. }
  577. return (strtoupper($a['name']) < strtoupper($b['name'])) ? -1 : 1;
  578. }
  579. private function SortTitle_DESC($a, $b) {
  580. if (strtoupper($a['name']) == strtoupper($b['name'])) {
  581. return 0;
  582. }
  583. return (strtoupper($a['name']) > strtoupper($b['name'])) ? -1 : 1;
  584. }
  585. private function SortItem($smartAlbums, $sortBy, $sortDirection, $offset, $limit) {
  586. if ('title' ===$sortBy) {
  587. if ('asc' === $sortDirection) {
  588. usort($smartAlbums, 'self::SortTitle_ASC');
  589. } else {
  590. usort($smartAlbums, 'self::SortTitle_DESC');
  591. }
  592. }
  593. $cutItemSort = array();
  594. if (0 > (int)$limit) {
  595. // array_slice() will reorder and reset the numeric array indices by default.
  596. // Preserve_keys are set to TRUE to solve bug#2195.
  597. $cutItemsSort = array_slice($smartAlbums, $offset, NULL, true);
  598. } else {
  599. $cutItemsSort = array_slice($smartAlbums, $offset, $limit, true);
  600. }
  601. return $cutItemsSort;
  602. }
  603. private function SmartAlbumList() {
  604. // Get and check params
  605. $params = array();
  606. $params = $this->GetParams_List();
  607. if (!$params) {
  608. $this->SetError(WEBAPI_ERR_BAD_REQUEST);
  609. goto End;
  610. }
  611. $resp = array(
  612. 'total' => 0,
  613. 'offset' => 0,
  614. 'smart_albums'=> array()
  615. );
  616. $smartAlbumList = SmartAlbum::GetSmartAlbumInstance()->ReadSmartAlbumFile();
  617. if (empty($smartAlbumList) || !is_array($smartAlbumList['smart_albums'])) {
  618. goto End;
  619. }
  620. $smartAlbums = $smartAlbumList['smart_albums'];
  621. $selectedAlbums = array();
  622. if ('title' == $params['sort_by']) {
  623. if ('asc' === $params['sort_direction']) {
  624. ksort($smartAlbums);
  625. } else {
  626. krsort($smartAlbums);
  627. }
  628. if (0 > (int)$limit) {
  629. // array_slice() will reorder and reset the numeric array indices by default.
  630. // Preserve_keys are set to TRUE to solve bug#2195.
  631. $selectedAlbums = array_slice($smartAlbums, $params['offset'], NULL, true);
  632. } else {
  633. $selectedAlbums = array_slice($smartAlbums, $params['offset'], $params['limit'], true);
  634. }
  635. }
  636. if (count($selectedAlbums)) {
  637. $albumNames = array_keys($selectedAlbums);
  638. } else {
  639. $albumNames = false;
  640. }
  641. // Get and form to webapi format
  642. $smart_albums = array();
  643. $smart_albums = $this->FormSmartAlbums($albumNames, $params);
  644. $total = count($smart_albums);
  645. // sort and set offset, limit
  646. $smartSort = $smart_albums;
  647. $smartSort = $this->SortItem($smart_albums, $params['sort_by'], $params['sort_direction'], $params['offset'], $params['limit']);
  648. $resp['total'] = $total;
  649. $offset = (0 > $params['limit']) ? $resp['total'] : $params['offset'] + $params['limit'];
  650. $resp['offset'] = ($offset > $total) ? $total : $offset;
  651. $resp['smart_albums'] = $smartSort;
  652. End:
  653. $this->SetResponse($resp);
  654. return;
  655. }
  656. private function GetInfo() {
  657. // Get and check params
  658. $params = array();
  659. $params = $this->GetParams_Info();
  660. if (-1 === $params) {
  661. $this->SetError(WEBAPI_ERR_BAD_REQUEST);
  662. goto End;
  663. } elseif (-2 === $params) {
  664. $this->SetError(PHOTOSTATION_SMARTALBUM_NOT_EXIST);
  665. goto End;
  666. }
  667. // Get and form to webapi format
  668. $smartNames = array();
  669. foreach ($params['id'] as $id) {
  670. $smartName = @pack('H*', $id);
  671. array_push($smartNames, $smartName);
  672. }
  673. $smart_albums = $this->FormSmartAlbums($smartNames, $params);
  674. $resp['smart_albums'] = $smart_albums;
  675. $this->SetResponse($resp);
  676. End:
  677. return;
  678. }
  679. private function Create() {
  680. $isAdmin = isset($_SESSION[SYNOPHOTO_ADMIN_USER]['admin_syno_user']);
  681. if (false === $isAdmin) {
  682. $this->SetError(PHOTOSTATION_SMARTALBUM_ACCESS_DENY);
  683. goto End;
  684. }
  685. // check parameter
  686. if (false === ($params = $this->GetParams_Create())) {
  687. $this->SetError(WEBAPI_ERR_BAD_REQUEST);
  688. goto End;
  689. }
  690. // check tag_id exist
  691. if (is_array($params['people_tag']) && !$this->CheckTagExist($params['people_tag'], 0)) {
  692. $this->SetError(PHOTOSTATION_SMARTALBUM_TAG_NOT_EXIST);
  693. goto End;
  694. }
  695. if (is_array($params['geo_tag']) && !$this->CheckTagExist($params['geo_tag'], 1)) {
  696. $this->SetError(PHOTOSTATION_SMARTALBUM_TAG_NOT_EXIST);
  697. goto End;
  698. }
  699. if (is_array($params['desc_tag']) && !$this->CheckTagExist($params['desc_tag'], 2)) {
  700. $this->SetError(PHOTOSTATION_SMARTALBUM_TAG_NOT_EXIST);
  701. goto End;
  702. }
  703. foreach(SmartAlbum::$exif2Column as $label => $column) {
  704. if (is_array($params[$label]) && !$this->CheckExifExist($params[$label], $column)) {
  705. $this->SetError(PHOTOSTATION_SMARTALBUM_TAG_NOT_EXIST);
  706. goto End;
  707. }
  708. }
  709. // add smart album
  710. $jsonRuleData = $this->ConvertToSmartCondition($params);
  711. $jsonRet = SmartAlbum::GetSmartAlbumInstance()->AddSmartAlbum($jsonRuleData);
  712. $ret = json_decode($jsonRet, true);
  713. if (false === $ret['success']) {
  714. if ($ret["error"]["code"] == 103) {
  715. $this->SetError(PHOTOSTATION_SMARTALBUM_CREATE_FAIL_EXIST);
  716. } else {
  717. $this->SetError(PHOTOSTATION_SMARTALBUM_CREATE_FAIL);
  718. }
  719. goto End;
  720. }
  721. $resp['id'] = 'smart_'.bin2hex($params['name']);
  722. $this->SetResponse($resp);
  723. End:
  724. return;
  725. }
  726. private function Edit() {
  727. $isAdmin = isset($_SESSION[SYNOPHOTO_ADMIN_USER]['admin_syno_user']);
  728. if (false === $isAdmin) {
  729. $this->SetError(PHOTOSTATION_SMARTALBUM_ACCESS_DENY);
  730. goto End;
  731. }
  732. // get parameter
  733. $params = $this->GetPrams_Edit();
  734. if (-1 === $params) {
  735. $this->SetError(WEBAPI_ERR_BAD_REQUEST);
  736. goto End;
  737. } elseif (-2 === $params) {
  738. $this->SetError(PHOTOSTATION_SMARTALBUM_NOT_EXIST);
  739. goto End;
  740. }
  741. // check tag_id exist
  742. if (is_array($params['people_tag']) && !$this->CheckTagExist($params['people_tag'], 0)) {
  743. $this->SetError(PHOTOSTATION_SMARTALBUM_TAG_NOT_EXIST);
  744. goto End;
  745. }
  746. if (is_array($params['geo_tag']) && !$this->CheckTagExist($params['geo_tag'], 1)) {
  747. $this->SetError(PHOTOSTATION_SMARTALBUM_TAG_NOT_EXIST);
  748. goto End;
  749. }
  750. if (is_array($params['desc_tag']) && !$this->CheckTagExist($params['desc_tag'], 2)) {
  751. $this->SetError(PHOTOSTATION_SMARTALBUM_TAG_NOT_EXIST);
  752. goto End;
  753. }
  754. foreach(SmartAlbum::$exif2Column as $label => $column) {
  755. if (is_array($params[$label]) && !$this->CheckExifExist($params[$label], $column)) {
  756. $this->SetError(PHOTOSTATION_SMARTALBUM_TAG_NOT_EXIST);
  757. goto End;
  758. }
  759. }
  760. // edit smart album
  761. $jsonRuleData = $this->ConvertToSmartCondition($params);
  762. $jsonRet = SmartAlbum::GetSmartAlbumInstance()->EditSmartAlbum($jsonRuleData);
  763. $ret = json_decode($jsonRet, true);
  764. if (empty($ret) || false === $ret['success']) {
  765. $this->SetError(PHOTOSTATION_SMARTALBUM_EDIT_FAIL);
  766. goto End;
  767. }
  768. // category hook
  769. if ($params['name'] !== $params['orig_name']) {
  770. $newID = bin2hex($params['name']);
  771. $query = "UPDATE category_items SET smart_id='{$newID}' WHERE smart_id='{$params['id']}'";
  772. if (false === PHOTO_DB_Query($query)) {
  773. $this->SetError(PHOTOSTATION_SMARTALBUM_EDIT_FAIL);
  774. goto End;
  775. }
  776. }
  777. $resp['id'] = 'smart_'.bin2hex($params['name']);
  778. $this->SetResponse($resp);
  779. End:
  780. return;
  781. }
  782. private function Delete() {
  783. $isAdmin = isset($_SESSION[SYNOPHOTO_ADMIN_USER]['admin_syno_user']);
  784. if (false === $isAdmin) {
  785. $this->SetError(PHOTOSTATION_SMARTALBUM_ACCESS_DENY);
  786. goto End;
  787. }
  788. // Get and check params
  789. $params = $this->GetParams_Info();
  790. if (-1 === $params) {
  791. $this->SetError(WEBAPI_ERR_BAD_REQUEST);
  792. goto End;
  793. } elseif (-2 === $params) {
  794. $this->SetError(PHOTOSTATION_SMARTALBUM_NOT_EXIST);
  795. goto End;
  796. }
  797. // get smart album names
  798. $smartNames = array();
  799. foreach ($params['id'] as $id) {
  800. $smartName = @pack('H*', $id);
  801. array_push($smartNames, $smartName);
  802. }
  803. // delete
  804. foreach ($smartNames as $smartName) {
  805. $data['name'] = $smartName;
  806. $jsonData = json_encode($data);
  807. SmartAlbum::GetSmartAlbumInstance()->DeleteSmartAlbum($jsonData);
  808. // category hook
  809. $id = bin2hex($smartName);
  810. $query = "DELETE FROM category_items WHERE smart_id='{$id}'";
  811. PHOTO_DB_Query($query);
  812. }
  813. End:
  814. return;
  815. }
  816. }
  817. $api = new SmartAlbumAPI();
  818. $api->Run();
  819. ?>