PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/kirby/toolkit/lib/media.php

https://gitlab.com/RikaPM/vrindi
PHP | 639 lines | 256 code | 88 blank | 295 comment | 34 complexity | fc9f3afe85ec22aed4df4cfefce39e4f MD5 | raw file
  1. <?php
  2. /**
  3. * Media
  4. *
  5. * @package Kirby Toolkit
  6. * @author Bastian Allgeier <bastian@getkirby.com>
  7. * @link http://getkirby.com
  8. * @copyright Bastian Allgeier
  9. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  10. */
  11. class Media {
  12. // optional url where the file is reachable
  13. public $url = null;
  14. // the full path for the file
  15. protected $root = null;
  16. // the filename including the extension
  17. protected $filename = null;
  18. // the name excluding the extension
  19. protected $name = null;
  20. // the extension of the file
  21. protected $extension = null;
  22. // the content of the file
  23. protected $content = null;
  24. // cache for various data
  25. protected $cache = array();
  26. /**
  27. * Constructor
  28. *
  29. * @param string $root
  30. */
  31. public function __construct($root, $url = null) {
  32. $this->url = $url;
  33. $this->root = $root === null ? $root : realpath($root);
  34. $this->filename = basename($root);
  35. $this->name = pathinfo($root, PATHINFO_FILENAME);
  36. $this->extension = strtolower(pathinfo($root, PATHINFO_EXTENSION));
  37. }
  38. /**
  39. * Resets the internal cache
  40. */
  41. public function reset() {
  42. $this->cache = array();
  43. }
  44. /**
  45. * Returns the full root of the asset
  46. *
  47. * @return string
  48. */
  49. public function root() {
  50. return $this->root;
  51. }
  52. /**
  53. * Returns the url
  54. *
  55. * @return string
  56. */
  57. public function url() {
  58. return $this->url;
  59. }
  60. /**
  61. * Returns a md5 hash of the root
  62. */
  63. public function hash() {
  64. return md5($this->root);
  65. }
  66. /**
  67. * Returns the parent directory path
  68. *
  69. * @return string
  70. */
  71. public function dir() {
  72. return dirname($this->root);
  73. }
  74. /**
  75. * Returns the filename of the file
  76. * i.e. somefile.jpg
  77. *
  78. * @return string
  79. */
  80. public function filename() {
  81. return $this->filename;
  82. }
  83. /**
  84. * Returns the name of the file without extension
  85. *
  86. * @return string
  87. */
  88. public function name() {
  89. return $this->name;
  90. }
  91. /**
  92. * Returns the filename as safe name
  93. *
  94. * @return string
  95. */
  96. public function safeName() {
  97. return f::safeName($this->filename());
  98. }
  99. /**
  100. * Returns the extension of the file
  101. * i.e. jpg
  102. *
  103. * @return string
  104. */
  105. public function extension() {
  106. // return the current extension
  107. return $this->extension;
  108. }
  109. /**
  110. * Reads the file content and parses it
  111. *
  112. * @param string $format
  113. * @return mixed
  114. */
  115. public function read($format = null) {
  116. return str::parse($this->content(), $format);
  117. }
  118. /**
  119. * Setter and getter for the file content
  120. *
  121. * @param string $content
  122. * @return string
  123. */
  124. public function content($content = null, $format = null) {
  125. if(!is_null($content)) {
  126. if(is_array($content)) {
  127. switch($format) {
  128. case 'json':
  129. $content = json_encode($content);
  130. break;
  131. case 'yaml':
  132. $content = yaml::encode($content);
  133. break;
  134. default:
  135. $content = serialize($content);
  136. break;
  137. }
  138. } else if(is_object($content)) {
  139. $content = serialize($content);
  140. }
  141. return $this->content = $content;
  142. }
  143. if(is_null($this->content)) {
  144. $this->content = file_get_contents($this->root);
  145. }
  146. return $this->content;
  147. }
  148. /**
  149. * Saves the file
  150. *
  151. * @param string $content
  152. * @return boolean
  153. */
  154. public function save($content = null, $format = null) {
  155. $content = $this->content($content, $format);
  156. return f::write($this->root, $content);
  157. }
  158. /**
  159. * Alternative for save
  160. *
  161. * @param string $content
  162. * @return boolean
  163. */
  164. public function write($content = null, $format = null) {
  165. return $this->save($content, $format);
  166. }
  167. /**
  168. * Change the file's modification date to now
  169. * and create it with an empty content if it is not there yet
  170. *
  171. * @return boolean
  172. */
  173. public function touch() {
  174. return touch($this->root);
  175. }
  176. /**
  177. * Appends the content and saves the file
  178. *
  179. * @param string $content
  180. * @return boolean
  181. */
  182. public function append($content) {
  183. $this->content = $this->content() . $content;
  184. return $this->save();
  185. }
  186. /**
  187. * Deletes the file
  188. *
  189. * @return boolean
  190. */
  191. public function delete() {
  192. return f::remove($this->root);
  193. }
  194. /**
  195. * Alternative for delete
  196. *
  197. * @return boolean
  198. */
  199. public function remove() {
  200. return f::remove($this->root);
  201. }
  202. /**
  203. * Moves the file to a new location
  204. *
  205. * @param string $to
  206. * @return boolean
  207. */
  208. public function move($to) {
  209. if(!f::move($this->root, $to)) {
  210. return false;
  211. } else {
  212. $this->root = $to;
  213. return true;
  214. }
  215. }
  216. /**
  217. * Copies the file to a new location
  218. *
  219. * @param string $to
  220. * @return boolean
  221. */
  222. public function copy($to) {
  223. return f::copy($this->root, $to);
  224. }
  225. /**
  226. * Returns the file size as integer
  227. *
  228. * @return int
  229. */
  230. public function size() {
  231. return f::size($this->root);
  232. }
  233. /**
  234. * Returns the human readable version of the file size
  235. *
  236. * @return string
  237. */
  238. public function niceSize() {
  239. return f::niceSize($this->size());
  240. }
  241. /**
  242. * Get the file's last modification time.
  243. *
  244. * @return int
  245. */
  246. public function modified($format = null, $handler = 'date') {
  247. return f::modified($this->root, $format, $handler);
  248. }
  249. /**
  250. * Returns the mime type of a file
  251. *
  252. * @return string
  253. */
  254. public function mime() {
  255. return f::mime($this->root);
  256. }
  257. /**
  258. * Categorize the file
  259. *
  260. * @return string
  261. */
  262. public function type() {
  263. return f::type($this->root);
  264. }
  265. /**
  266. * Checks if a file is of a certain type
  267. *
  268. * @param string $value An extension or mime type
  269. * @return boolean
  270. */
  271. public function is($value) {
  272. return f::is($this->root, $value);
  273. }
  274. /**
  275. * Returns the file content as base64 encoded string
  276. *
  277. * @return string
  278. */
  279. public function base64() {
  280. return base64_encode($this->content());
  281. }
  282. /**
  283. * Returns the file as data uri
  284. *
  285. * @return string
  286. */
  287. public function dataUri() {
  288. return 'data:' . $this->mime() . ';base64,' . $this->base64();
  289. }
  290. /**
  291. * Checks if the file exists
  292. *
  293. * @return boolean
  294. */
  295. public function exists() {
  296. return file_exists($this->root);
  297. }
  298. /**
  299. * Checks if the file is writable
  300. *
  301. * @return boolean
  302. */
  303. public function isWritable() {
  304. return is_writable($this->root);
  305. }
  306. /**
  307. * Checks if the file is readable
  308. *
  309. * @return boolean
  310. */
  311. public function isReadable() {
  312. return is_readable($this->root);
  313. }
  314. /**
  315. * Checks if the file is executable
  316. *
  317. * @return boolean
  318. */
  319. public function isExecutable() {
  320. return is_executable($this->root);
  321. }
  322. /**
  323. * Sends an appropriate header for the asset
  324. *
  325. * @param boolean $send
  326. * @return mixed
  327. */
  328. public function header($send = true) {
  329. return header::type($this->mime(), false, $send);
  330. }
  331. /**
  332. * Safely requires a file if it exists
  333. *
  334. * @param array $data Optional variables, which will be made available to the file
  335. */
  336. public function load($data = array()) {
  337. return f::load($this->root, $data);
  338. }
  339. /**
  340. * Read and send the file with the correct headers
  341. */
  342. public function show() {
  343. f::show($this->root);
  344. }
  345. /*
  346. * Automatically sends all needed headers for the file to be downloaded
  347. * and echos the file's content
  348. *
  349. * @param string $filename Optional filename for the download
  350. */
  351. public function download($filename = null) {
  352. f::download($this->root, $filename);
  353. }
  354. /**
  355. * Returns the exif object for this file (if image)
  356. *
  357. * @return Exif
  358. */
  359. public function exif() {
  360. if(isset($this->cache['exif'])) return $this->cache['exif'];
  361. return $this->cache['exif'] = new Exif($this);
  362. }
  363. /**
  364. * Returns the PHP imagesize array
  365. *
  366. * @return array
  367. */
  368. public function imagesize() {
  369. return (array)getimagesize($this->root);
  370. }
  371. /**
  372. * Returns the dimensions of the file if possible
  373. *
  374. * @return Dimensions
  375. */
  376. public function dimensions() {
  377. if(isset($this->cache['dimensions'])) return $this->cache['dimensions'];
  378. if(in_array($this->mime(), array('image/jpeg', 'image/png', 'image/gif'))) {
  379. $size = (array)getimagesize($this->root);
  380. $width = a::get($size, 0, 0);
  381. $height = a::get($size, 1, 0);
  382. } else if($this->extension() == 'svg') {
  383. $content = $this->read();
  384. $xml = simplexml_load_string($content);
  385. $attr = $xml->attributes();
  386. $width = floatval($attr->width);
  387. $height = floatval($attr->height);
  388. if($width == 0 or $height == 0 and !empty($attr->viewBox)) {
  389. $box = str::split($attr->viewBox, ' ');
  390. $width = floatval(a::get($box, 2, 0));
  391. $height = floatval(a::get($box, 3, 0));
  392. }
  393. } else {
  394. $width = 0;
  395. $height = 0;
  396. }
  397. return $this->cache['dimensions'] = new Dimensions($width, $height);
  398. }
  399. /**
  400. * Returns the width of the asset
  401. *
  402. * @return int
  403. */
  404. public function width() {
  405. return $this->dimensions()->width();
  406. }
  407. /**
  408. * Returns the height of the asset
  409. *
  410. * @return int
  411. */
  412. public function height() {
  413. return $this->dimensions()->height();
  414. }
  415. /**
  416. * Returns the ratio of the asset
  417. *
  418. * @return int
  419. */
  420. public function ratio() {
  421. return $this->dimensions()->ratio();
  422. }
  423. /**
  424. * Checks if the dimensions of the asset are portrait
  425. *
  426. * @return boolean
  427. */
  428. public function isPortrait() {
  429. return $this->dimensions()->portrait();
  430. }
  431. /**
  432. * Checks if the dimensions of the asset are landscape
  433. *
  434. * @return boolean
  435. */
  436. public function isLandscape() {
  437. return $this->dimensions()->landscape();
  438. }
  439. /**
  440. * Checks if the dimensions of the asset are square
  441. *
  442. * @return boolean
  443. */
  444. public function isSquare() {
  445. return $this->dimensions()->square();
  446. }
  447. /**
  448. * Returns the orientation as string
  449. * landscape | portrait | square
  450. *
  451. * @return string
  452. */
  453. public function orientation() {
  454. return $this->dimensions()->orientation();
  455. }
  456. /**
  457. * @param array $attr
  458. * @return string
  459. */
  460. public function html($attr = array()) {
  461. if($this->type() != 'image') return false;
  462. $img = new Brick('img');
  463. $img->attr('src', $this->url());
  464. $img->attr('alt', ' ');
  465. if(is_string($attr) || (is_object($attr) && method_exists($attr, '__toString'))) {
  466. $img->attr('alt', (string)$attr);
  467. } else if(is_array($attr)) {
  468. $img->attr($attr);
  469. }
  470. return $img;
  471. }
  472. /**
  473. * Scales the image if possible
  474. *
  475. * @param int $width
  476. * @param mixed $height
  477. * @param mixed $quality
  478. * @return Media
  479. */
  480. public function resize($width, $height = null, $quality = null) {
  481. if($this->type() != 'image') return $this;
  482. $params = array('width' => $width);
  483. if($height) $params['height'] = $height;
  484. if($quality) $params['quality'] = $quality;
  485. return new Thumb($this, $params);
  486. }
  487. /**
  488. * Scales and crops the image if possible
  489. *
  490. * @param int $width
  491. * @param mixed $height
  492. * @param mixed $quality
  493. * @return Media
  494. */
  495. public function crop($width, $height = null, $quality = null) {
  496. if($this->type() != 'image') return $this;
  497. $params = array('width' => $width, 'crop' => true);
  498. if($height) $params['height'] = $height;
  499. if($quality) $params['quality'] = $quality;
  500. return new Thumb($this, $params);
  501. }
  502. /**
  503. * Converts the media object to a
  504. * plain PHP array
  505. *
  506. * @param closure $callback
  507. * @return array
  508. */
  509. public function toArray($callback = null) {
  510. $data = array(
  511. 'root' => $this->root(),
  512. 'url' => $this->url(),
  513. 'hash' => $this->hash(),
  514. 'dir' => $this->dir(),
  515. 'filename' => $this->filename(),
  516. 'name' => $this->name(),
  517. 'safeName' => $this->safeName(),
  518. 'extension' => $this->extension(),
  519. 'size' => $this->size(),
  520. 'niceSize' => $this->niceSize(),
  521. 'modified' => $this->modified(),
  522. 'mime' => $this->mime(),
  523. 'type' => $this->type(),
  524. 'dimensions' => $this->dimensions()->toArray()
  525. );
  526. if(is_null($callback)) {
  527. return $data;
  528. } else {
  529. return array_map($callback, $data);
  530. }
  531. }
  532. /**
  533. * Converts the entire file array into
  534. * a json string
  535. *
  536. * @param closure $callback Filter callback
  537. * @return string
  538. */
  539. public function toJson($callback = null) {
  540. return json_encode($this->toArray($callback));
  541. }
  542. /**
  543. * Returns a full link to this file
  544. * Perfect for debugging in connection with echo
  545. *
  546. * @return string
  547. */
  548. public function __toString() {
  549. return $this->root;
  550. }
  551. }