PageRenderTime 63ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/backend/class-node.php

https://github.com/jinzora/jinzora3
PHP | 1744 lines | 1186 code | 156 blank | 402 comment | 437 complexity | b73a24c1d3c98448504b8431b89d0679 MD5 | raw file
  1. <?php if (!defined(JZ_SECURE_ACCESS)) die ('Security breach detected.');
  2. /**
  3. * - JINZORA | Web-based Media Streamer -
  4. *
  5. * Jinzora is a Web-based media streamer, primarily desgined to stream MP3s
  6. * (but can be used for any media file that can stream from HTTP).
  7. * Jinzora can be integrated into a CMS site, run as a standalone application,
  8. * or integrated into any PHP website. It is released under the GNU GPL.
  9. *
  10. * - Resources -
  11. * - Jinzora Author: Ross Carlson <ross@jasbone.com>
  12. * - Web: http://www.jinzora.org
  13. * - Documentation: http://www.jinzora.org/docs
  14. * - Support: http://www.jinzora.org/forum
  15. * - Downloads: http://www.jinzora.org/downloads
  16. * - License: GNU GPL <http://www.gnu.org/copyleft/gpl.html>
  17. *
  18. * - Contributors -
  19. * Please see http://www.jinzora.org/modules.php?op=modload&name=jz_whois&file=index
  20. *
  21. * - Code Purpose -
  22. * These are the classes extended by the backend adaptors.
  23. *
  24. * @since 05.10.04
  25. * @author Ben Dodson <bdodson@seas.upenn.edu>
  26. */
  27. class jzMediaNodeClass extends jzMediaElement {
  28. var $natural_depth; // if the level before us is 'hidden'
  29. /**
  30. * Constructor for a jzMediaNodeClass
  31. *
  32. * @author Ben Dodson
  33. * @version 5/14/04
  34. * @since 5/14/04
  35. */
  36. function jzMediaNodeClass($par = array(),$mode = "path") {
  37. $this->_constructor($par,$mode);
  38. }
  39. function _constructor($par = array(),$mode) {
  40. $this->natural_depth = 1;
  41. parent::_constructor($par,$mode);
  42. }
  43. /**
  44. * Returns the type of the node.
  45. *
  46. * @author Ben Dodson
  47. * @version 10/31/04
  48. * @since 10/31/04
  49. */
  50. function getType() {
  51. return "jzMediaNode";
  52. }
  53. /**
  54. * Gets the 'natural depth' of this node.
  55. * This has no real purpose outside of the class.
  56. *
  57. * @author Ben Dodson
  58. * @version 5/21/04
  59. * @since 5/21/04
  60. */
  61. function getNaturalDepth() {
  62. return $this->natural_depth;
  63. }
  64. /**
  65. * Sets the natural depth (for searching, counting etc.) of this node.
  66. * Useful if the node is preceded by a hidden level.
  67. *
  68. * @author Ben Dodson
  69. * @version 5/14/04
  70. * @since 5/14/04
  71. */
  72. function setNaturalDepth($n) {
  73. $this->natural_depth = $n;
  74. }
  75. /**
  76. * Counts the number of subnodes $distance steps down of type $type.
  77. * $distance = -1 means do it recursively.
  78. *
  79. * @author Ben Dodson
  80. * @version 5/14/04
  81. * @since 5/14/04
  82. */
  83. function getSubNodeCount($type='both', $distance = false) {
  84. if ($distance === false) {
  85. $distance = $this->getNaturalDepth();
  86. }
  87. // alias:
  88. if ($type == "tracks") {
  89. $type = "leaves";
  90. }
  91. // EASY METHOD:
  92. return sizeof($this->getSubNodes($type,$distance,true,0)); // $random = true is faster than sorting.
  93. // POSSIBLE TODO 1) make another cache for counting.
  94. // POSSIBLE TODO 2) don't return the array; just count as you go.
  95. }
  96. /**
  97. * Returns the subnodes as an array. A $distance of -1 means do it recursively.
  98. *
  99. * @author Ben Dodson
  100. * @version 6/4/04
  101. * @since 6/4/04
  102. */
  103. function getSubNodes($type='nodes',$distance=false, $random=false, $limit=0, $hasArt = false, $offset=false) {
  104. if ($distance === false) {
  105. $distance = $this->getNaturalDepth();
  106. }
  107. // alias:
  108. if ($type == "tracks") {
  109. $type = "leaves";
  110. }
  111. // 2 cases:
  112. $search = array();
  113. $vals = array();
  114. // 1) recursive
  115. if ($distance <= 0) {
  116. $node = $this;
  117. $search[] = $node;
  118. while ($search != array()) {
  119. $node = array_pop($search);
  120. $cache = $node->readCache("nodes");
  121. if ($nodearray = $cache[7]) {
  122. foreach ($nodearray as $name) {
  123. $search[] = &new jzMediaNode($node->getPath("String") . "/" . $name);
  124. if ($type == "nodes" || $type == "both") {
  125. $me = new jzMediaNode($node->getPath("String") . "/" . $name);
  126. if ($hasArt) {
  127. if ($me->getMainArt() != "-" && $me->getMainArt() !== false)
  128. $vals[] = $me;
  129. } else {
  130. $vals[] = $me;
  131. }
  132. }
  133. }
  134. }
  135. if ($type == "leaves" || $type == "both") {
  136. if ($trackarray = $cache[8]) {
  137. foreach ($trackarray as $track) {
  138. $vals[] = &new jzMediaTrack($node->getPath("String") . "/" . $track);
  139. }
  140. }
  141. }
  142. }
  143. }
  144. // 2: not.
  145. else {
  146. $i = 1;
  147. $node = $this;
  148. $search[] = $node;
  149. while ($distance != $i) {
  150. $i++;
  151. $temp = array();
  152. while ($search != array()) {
  153. $node = array_pop($search);
  154. $cache = $node->readCache("nodes");
  155. if ($nodearray = $cache[7]) {
  156. foreach ($nodearray as $name) {
  157. $temp[] = &new jzMediaNode($node->getPath("String") . "/" . $name);
  158. }
  159. }
  160. }
  161. $search = $temp;
  162. }
  163. foreach ($search as $node) {
  164. $cache = $node->readCache("nodes");
  165. if ($type == "both" || $type == "nodes") {
  166. if ($nodearray = $cache[7]) {
  167. foreach ($nodearray as $name) {
  168. $me = new jzMediaNode($node->getPath("String") . "/" . $name);
  169. if ($hasArt) {
  170. if ($me->getMainArt() != "-" && $me->getMainArt() !== false) {
  171. $vals[] = $me;
  172. }
  173. } else {
  174. $vals[] = $me;
  175. }
  176. }
  177. }
  178. }
  179. if ($type == "both" || $type == "leaves") {
  180. if ($trackarray = $cache[8]) {
  181. foreach ($trackarray as $track) {
  182. $vals[] = &new jzMediaTrack($node->getPath("String") . "/" . $track);
  183. }
  184. }
  185. }
  186. }
  187. }
  188. if ($random === true) {
  189. srand((float)microtime() * 1000000);
  190. shuffle($vals);
  191. }
  192. else if ($random === false) {
  193. usort($vals, "compareNodes");
  194. }
  195. else {
  196. // do nothing.
  197. }
  198. if ($limit > 0 && $limit < sizeof($vals)) {
  199. $final = array();
  200. for ($i = 0; $i < $limit; $i++) {
  201. $final[] = $vals[$i];
  202. }
  203. return $final;
  204. }
  205. else {
  206. return $vals;
  207. }
  208. }
  209. /**
  210. * Returns the 'top' subnodes. $distance = -1 is recursive.
  211. *
  212. * $top_type is one of:
  213. * most-played, best-rated
  214. *
  215. * @author
  216. * @version
  217. * @since
  218. */
  219. function getTopSubNodes($type='nodes',$top_type='most-played', $distance=false, $limit=0) {
  220. if ($distance === false) {
  221. $distance = $this->getNaturalDepth();
  222. }
  223. // alias:
  224. if ($type == "tracks") {
  225. $type = "leaves";
  226. }
  227. }
  228. /**
  229. * Returns the subnode named $name.
  230. *
  231. * @author Ben Dodson
  232. * @version 5/16/04
  233. * @since 5/16/04
  234. */
  235. function getSubNode($name) {
  236. $p = $this->path;
  237. $p[] = $name;
  238. // TODO: check for jzMediaTrack or jzMediaNode?
  239. // I'm not sure how needed this function is anyways...
  240. return jzMediaElement($p);
  241. }
  242. /**
  243. * Completely handles a power search
  244. *
  245. * @author Ben Dodson
  246. * @since 4/6/05
  247. * @version 4/6/05
  248. *
  249. **/
  250. function powerSearch() {
  251. $roots = array();
  252. $roots[] = $this;
  253. // Exploit our hierarchical design.
  254. // A relational database should handle this search differently.
  255. if (isset($_POST['genre']) && $_POST['genre'] != "") {
  256. $roots = $this->search($_POST['genre'],"nodes",distanceTo("genre",$this));
  257. }
  258. if (isset($_POST['artist']) && $_POST['artist'] != "") {
  259. $new_roots = array();
  260. foreach ($roots as $r) {
  261. $new_roots = $new_roots + $r->search($_POST['artist'],"nodes",distanceTo("artist",$r));
  262. }
  263. $roots = $new_roots;
  264. }
  265. if (isset($_POST['album']) && $_POST['album'] != "") {
  266. $new_roots = array();
  267. foreach ($roots as $r) {
  268. $new_roots = $new_roots + $r->search($_POST['album'],"nodes",distanceTo("album",$r));
  269. }
  270. $roots = $new_roots;
  271. }
  272. // If nothing in their query is track-specifc, we are done.
  273. if (powerSearchType() != "tracks") {
  274. return $roots;
  275. }
  276. $results = array();
  277. $metasearch = getSearchMeta();
  278. foreach ($roots as $r) {
  279. $results = $results + $r->search($_POST['song_title'],"tracks",-1,0,$_POST['operator'],$metasearch);
  280. }
  281. return $results;
  282. }
  283. /**
  284. * Searches a specified level for elements.
  285. * The level is -1 for any level.
  286. * These parameters may change before the coding gets done.
  287. * The 'op' is one of: and|or|exact
  288. * If it is 'exact', the search term should be a string.
  289. *
  290. * @author Ben Dodson
  291. * @version 9/21/04
  292. * @since 9/20/04
  293. */
  294. function search($searchArray2, $type='both', $depth = -1, $limit = 0, $op = "and", $metasearch = array(), $exclude = array()) {
  295. // for now, no search by id:
  296. if ($type == "id") {
  297. return array();
  298. }
  299. // alias:
  300. if ($type == "tracks") {
  301. $type = "leaves";
  302. }
  303. if ($depth === false) {
  304. $depth = $this->getNaturalDepth();
  305. }
  306. // allow strings as well as arrays for searching:
  307. if (is_string($searchArray2) && $op != "exact") {
  308. if (stristr($searchArray2,"\"") === false) {
  309. if ($searchArray2 == "")
  310. $searchArray = array();
  311. else {
  312. $searchArray = explode(" ",$searchArray2);
  313. }
  314. }
  315. else { // gets nasty..
  316. $open_quote = false;
  317. $searchArray = array();
  318. $word = "";
  319. for ($i = 0; $i < strlen($searchArray2); $i++) {
  320. if ($searchArray2[$i] == ' ' && $open_quote == false) {
  321. $searchArray[] = $word;
  322. $word = "";
  323. }
  324. else if ($searchArray2[$i] == '"') {
  325. $open_quote = !$open_quote;
  326. }
  327. else {
  328. $word .= $searchArray2[$i];
  329. }
  330. }
  331. if ($word != "") {
  332. $searchArray[] = $word;
  333. }
  334. }
  335. } else {
  336. $searchArray = $searchArray2;
  337. }
  338. // Exclude array, too:
  339. if (is_string($exclude)) {
  340. if ($exclude == "") {
  341. $excludeArray = array();
  342. }
  343. else if (stristr($exclude,"\"") === false) {
  344. if ($exclude == "") {
  345. $excludeArray = array();
  346. } else {
  347. $excludeArray = explode(" ",$exclude);
  348. }
  349. }
  350. else { // gets nasty..
  351. $open_quote = false;
  352. $excludeArray = array();
  353. $word = "";
  354. for ($i = 0; $i < strlen($exclude); $i++) {
  355. if ($exclude[$i] == ' ' && $open_quote == false) {
  356. $excludeArray[] = $word;
  357. $word = "";
  358. }
  359. else if ($exclude[$i] == '"') {
  360. $open_quote = !$open_quote;
  361. }
  362. else {
  363. $word .= $exclude[$i];
  364. }
  365. }
  366. if ($word != "") {
  367. $excludeArray[] = $word;
  368. }
  369. }
  370. } else {
  371. $excludeArray = $exclude;
  372. }
  373. // Clean up:
  374. $tmp = array();
  375. if (is_array($searchArray)) {
  376. foreach ($searchArray as $term) {
  377. if (!($term == "" || $term == " ")) {
  378. $tmp[] = $term;
  379. }
  380. }
  381. $searchArray = $tmp;
  382. }
  383. $tmp = array();
  384. foreach ($excludeArray as $term) {
  385. if (!($term == "" || $term == " ")) {
  386. $tmp[] = $term;
  387. }
  388. }
  389. $excludeArray = $tmp;
  390. // LYRICS SEARCHING: different kind of search.
  391. if ($type == "lyrics") {
  392. $matches = array();
  393. $kids = $this->getSubNodes("tracks",$depth,"leave",0);
  394. foreach ($kids as $kid) {
  395. $meta = $kid->getMeta();
  396. $path = $kid->getPath("String");
  397. if ($op == "exact") {
  398. if (stristr($meta['lyrics'], $searchArray2) !== false) {
  399. $matches[] = $kid;
  400. }
  401. } else if ($op == "or") {
  402. $valid = true;
  403. if ($excludeArray != array()) {
  404. foreach($excludeArray as $word) {
  405. if (stristr($meta['lyrics'],$word) !== false) {
  406. $valid = false;
  407. }
  408. }
  409. }
  410. if ($valid) {
  411. if (sizeof($searchArray) == 0) {
  412. $matches[] = $kid;
  413. if ($limit > 0 && sizeof($matches) >= $limit) {
  414. return $matches;
  415. }
  416. }
  417. else {
  418. foreach($searchArray as $word) {
  419. if (stristr($meta['lyrics'],$word) !== false) {
  420. $matches[] = $kid;
  421. if ($limit > 0 && sizeof($matches) >= $limit) {
  422. return $matches;
  423. }
  424. }
  425. }
  426. }
  427. }
  428. } else { // $op == "and"
  429. $possible_match = false;
  430. $all_words = true;
  431. $valid = true;
  432. if ($excludeArray != array()) {
  433. foreach($excludeArray as $word) {
  434. if (stristr($meta['lyrics'],$word) !== false) {
  435. $valid = false;
  436. }
  437. }
  438. }
  439. if ($valid) {
  440. if (sizeof($searchArray) == 0) {
  441. $matches[] = $kid;
  442. if ($limit > 0 && sizeof($matches) >= $limit) {
  443. return $matches;
  444. }
  445. }
  446. else {
  447. foreach($searchArray as $word) {
  448. if (stristr($meta['lyrics'],$word) !== false) {
  449. $possible_match = true;
  450. }
  451. else if (stristr($path,$word) === false) {
  452. $all_words = false;
  453. }
  454. }
  455. }
  456. if ($possible_match && $all_words) {
  457. $matches[] = $kid;
  458. if ($limit > 0 && sizeof($matches) >= $limit) {
  459. return $matches;
  460. }
  461. }
  462. }
  463. }
  464. }
  465. return $matches;
  466. }
  467. $kids = $this->getSubNodes($type,$depth,"leave",0);
  468. // don't sort our nodes, because it takes time.
  469. // but don't randomize either.
  470. $matches = array();
  471. foreach ($kids as $kid) {
  472. $path = $kid->getPath("String");
  473. $pathArray = $kid->getPath();
  474. // NOTE: The 'name' of the child is taken from the filename,
  475. // NOT from the ID3 or any other metadata method.
  476. // This is currently (9/21/04) DIFFERENT than what $this->getName() returns
  477. // ..and it is MUCH faster!!
  478. $name = $pathArray[sizeof($pathArray)-1];
  479. // op == 'exact'
  480. if ($op == "exact") {
  481. if ($name == $searchArray2) {
  482. $matches[] = $kid;
  483. if ($limit > 0 && sizeof($matches) >= $limit) {
  484. return $matches;
  485. }
  486. }
  487. // op == 'or'
  488. } else if ($op == "or") {
  489. $valid = true;
  490. if ($excludeArray != array()) {
  491. foreach($excludeArray as $word) {
  492. if (stristr($name,$word) !== false) {
  493. $valid = false;
  494. }
  495. }
  496. }
  497. if ($valid) {
  498. if (sizeof($searchArray) == 0) {
  499. $matches[] = $kid;
  500. if ($limit > 0 && sizeof($matches) >= $limit) {
  501. return $matches;
  502. }
  503. }
  504. else {
  505. foreach($searchArray as $word) {
  506. if (stristr($name,$word) !== false) {
  507. $matches[] = $kid;
  508. if ($limit > 0 && sizeof($matches) >= $limit) {
  509. return $matches;
  510. }
  511. }
  512. }
  513. }
  514. }
  515. }
  516. else { // "and"
  517. $possible_match = false;
  518. $all_words = true;
  519. $valid = true;
  520. if ($excludeArray != array()) {
  521. foreach($excludeArray as $word) {
  522. if (stristr($name,$word) !== false) {
  523. $valid = false;
  524. }
  525. }
  526. }
  527. if ($valid) {
  528. if (sizeof($searchArray) == 0) {
  529. $matches[] = $kid;
  530. if ($limit > 0 && sizeof($matches) >= $limit) {
  531. return $matches;
  532. }
  533. }
  534. else {
  535. foreach($searchArray as $word) {
  536. if (stristr($name,$word) !== false) {
  537. $possible_match = true;
  538. }
  539. else if (stristr($path,$word) === false) {
  540. $all_words = false;
  541. }
  542. }
  543. }
  544. if ($possible_match && $all_words) {
  545. $matches[] = $kid;
  546. if ($limit > 0 && sizeof($matches) >= $limit) {
  547. return $matches;
  548. }
  549. }
  550. }
  551. }
  552. }
  553. if ($metasearch != array() && $type == "leaves") {
  554. $matches = filterSearchResults($matches,$metasearch);
  555. }
  556. return $matches;
  557. }
  558. /**
  559. * Updates the cache using this node as a base.
  560. *
  561. * @author Ben Dodson
  562. * @version 6/7/04
  563. * @since 5/17/04
  564. */
  565. function updateCache($recursive = true, $root = false, $showStatus = false, $readID3 = true) {
  566. /* Serialized array:
  567. * nodes/path---to---node:
  568. * (root is called jzroot)
  569. * See backend.php.
  570. */
  571. $this->updateCacheHelper($recursive, $this->getNaturalDepth()-1, $root, $showStatus, $readID3);
  572. $be = &new jzBackend();
  573. $be->setUpdated();
  574. }
  575. function updateCacheHelper($recursive, $levelsLeft, $root, $showStatus, $readID3) {
  576. global $audio_types, $video_types, $ext_graphic, $default_art, $backend,
  577. $track_num_seperator, $hierarchy, $protocols;
  578. if ($root !== false)
  579. $mediapath = $root;
  580. else
  581. $mediapath = $this->getFilePath();
  582. if ($mediapath == "-") { // let's find it..
  583. $parent = $this->getParent();
  584. $mediapath = $parent->getFilePath() . "/" . $this->getName();
  585. }
  586. $nodepath = $this->getPath("String");
  587. /* Echo out our current status, if they want it: */
  588. if ($showStatus === true) {
  589. showStatus($mediapath);
  590. } else if ($showStatus == "cli") {
  591. echo word("Scanning: ") . $mediapath . "\n";
  592. }
  593. // First add $this.
  594. // Was I already cached?
  595. $cache = $this->readCache();
  596. if ($cache[0] == "-") { $cache[0] = $nodepath; }
  597. if ($cache[13] == "-") { $cache[13] = $mediapath; }
  598. if ($cache[6] == "-") { $cache[6] = jz_filemtime($mediapath); }
  599. if ($cache[15] == "-") {
  600. $ptype = findPType($this);
  601. $cache[15] = $ptype;
  602. }
  603. $blankfilecache = blankCache("track");
  604. // Recurse and add $this's media files.
  605. if (!($handle = opendir($mediapath)))
  606. die("Could not access directory $mediapath");
  607. // scan for info while going through directory:
  608. $trackcount = 0;
  609. $new_nodes = $cache[7];
  610. $new_tracks = $cache[8];
  611. $bestImage = "";
  612. $bestDescription = "";
  613. while ($file = readdir($handle)) {
  614. $childpath = ($nodepath == "") ? $file : $nodepath . "/" . $file;
  615. $fullchildpath = $mediapath . "/" . $file;
  616. if ($file == "." || $file == "..") {
  617. continue;
  618. }
  619. else if (is_dir($fullchildpath)) {
  620. if ($recursive) {
  621. $next = &new jzMediaNode($childpath);
  622. $next->updateCacheHelper(true,$levelsLeft, $fullchildpath,$showStatus,$readID3);
  623. } else {
  624. if ($levelsLeft === false && $this->getNaturalDepth() > 1) {
  625. $next = &new jzMediaNode($childpath);
  626. $next->updateCacheHelper(false,$this->getNaturalDepth()-2,$fullchildpath,$showStatus,$readID3);
  627. } else if ($levelsLeft > 0) {
  628. $next = &new jzMediaNode($childpath);
  629. $next->updateCacheHelper(false,$levelsLeft-1,$fullchildpath,$showStatus,$readID3);
  630. }
  631. }
  632. if ($new_nodes != array()) {
  633. $key = array_search($file,$new_nodes);
  634. if (false === $key) {
  635. $new_nodes[] = $file;
  636. $next = &new jzMediaNode($childpath);
  637. }
  638. } else {
  639. $new_nodes[] = $file;
  640. $next = &new jzMediaNode($childpath);
  641. }
  642. }
  643. else {
  644. if (preg_match("/\.(txt)$/i", $file)) {
  645. // TODO: GET THE CORRECT DESCRIPTION IN $bestDescription
  646. // $bestDescription = $fullchildpath;
  647. }
  648. else if (preg_match("/\.($ext_graphic)$/i", $file) && !stristr($file,".thumb.")) {
  649. // An image
  650. if (@preg_match("/($default_art)/i",$file)) {
  651. $bestImage = $fullchildpath;
  652. }
  653. else if ($bestImage == "") {
  654. $bestImage = $fullchildpath;
  655. }
  656. }
  657. else if (preg_match("/\.($audio_types)$/i", $file)
  658. || preg_match("/\.($video_types)$/i", $file)) {
  659. //* * * A track * * * *//
  660. // Add it to the track list.
  661. if ($new_tracks != array()) {
  662. $key = array_search($file,$new_tracks);
  663. if (false === $key) {
  664. $new_tracks[] = $file;
  665. }
  666. } else {
  667. $new_tracks[] = $file;
  668. }
  669. // And at it's details..
  670. $childnode = &new jzMediaTrack($childpath);
  671. if (($cache[2] == "-" || $cache[2] < date("U",jz_filemtime($fullchildpath))) || !$childnode->readCache()) {
  672. // Add as a new/updated track.
  673. $filecache[$trackcount] = $childnode->readCache();
  674. if ($filecache[$trackcount][0] == "-") {
  675. $filecache[$trackcount][0] = $fullchildpath;
  676. $filecache[$trackcount][6] = jz_filemtime($fullchildpath);
  677. $filecache[$trackcount][2] = $file;
  678. }
  679. //////////
  680. // META //
  681. //////////
  682. $track = &new jzMediaTrack($childpath);
  683. $track->playpath = $fullchildpath;
  684. if ($readID3 === true) {
  685. $meta = $track->getMeta("file"); // read meta info from the file;
  686. } else {
  687. $meta = array();
  688. }
  689. $filecache[$trackcount][7] = $meta['title'];
  690. $filecache[$trackcount][8] = $meta['frequency'];
  691. $filecache[$trackcount][9] = $meta['comment'];
  692. $filecache[$trackcount][11] = $meta['year'];
  693. $filecache[$trackcount][13] = $meta['size'];
  694. $filecache[$trackcount][14] = $meta['length'];
  695. $filecache[$trackcount][15] = $meta['genre'];
  696. $filecache[$trackcount][16] = $meta['artist'];
  697. $filecache[$trackcount][17] = $meta['album'];
  698. $filecache[$trackcount][18] = $meta['type'];
  699. $filecache[$trackcount][19] = $meta['lyrics'];
  700. $filecache[$trackcount][20] = $meta['bitrate'];
  701. $filecache[$trackcount][21] = $meta['number'];
  702. // Now let's see if there is a description file...
  703. $desc_file = str_replace(".". $meta['type'],"",$fullchildpath). ".txt";
  704. $long_description = "";
  705. if (is_file($desc_file) and filesize($desc_file) <> 0){
  706. // Ok, let's read the description file
  707. $handle2 = fopen($desc_file, "rb");
  708. $filecache[$trackcount][10] = fread($handle2, filesize($desc_file));
  709. fclose($handle2);
  710. } else {
  711. $filecache[$trackcount][10] = "";
  712. }
  713. // Now let's see if there is a thumbnail for this track
  714. $filecache[$trackcount][1] = searchThumbnail($fullchildpath);
  715. } else {
  716. // slow but necessary..
  717. //$filecache[$trackcount] = $childnode->readCache();
  718. }
  719. $trackcount++;
  720. // Let's track this
  721. writeLogData('importer',"Importing track: ". $fullchildpath);
  722. $_SESSION['jz_import_full_progress']++;
  723. }
  724. }
  725. }
  726. if ($new_nodes != array()) {
  727. foreach ($new_nodes as $i => $my_path) {
  728. $me = &new jzMediaNode($nodepath . "/" . $my_path);
  729. if ($me->getFilePath() == "-") {
  730. $arr = explode("/",$my_path);
  731. $mfp = $this->getFilePath() . "/" . $arr[sizeof($arr)-1];
  732. } else {
  733. $mfp = $me->getFilePath();
  734. }
  735. if (!is_dir($mfp)) {
  736. // TODO: The commented out part should check to see if there are 'permanent' subnodes.
  737. // It is possible a directory was created to house links (and does not have
  738. // any data on the filesystem)
  739. $remove_me = true;
  740. $list = $me->getSubNodes("tracks",-1);
  741. foreach ($list as $el) {
  742. if (stristr($el->getFilePath(),"://")) {
  743. $remove_me = false;
  744. break;
  745. }
  746. }
  747. if ($remove_me) {
  748. $me->deleteCache();
  749. unset($new_nodes[$i]);
  750. }
  751. }
  752. }
  753. }
  754. if ($new_tracks != array()) {
  755. foreach ($new_nodes as $i => $my_path) {
  756. $me = &new jzMediaTrack($nodepath . "/" . $my_path);
  757. if (!is_file($fpath = $me->getFilePath())) {
  758. $valid = false;
  759. $parr = explode("|",$protocols);
  760. if (strlen($fpath) > 2) {
  761. foreach ($parr as $p) {
  762. if (stristr($fpath,$p) !== false) {
  763. $valid = true;
  764. }
  765. }
  766. }
  767. if (!$valid) {
  768. $me->deleteCache();
  769. unset($new_tracks[$i]);
  770. }
  771. }
  772. }
  773. }
  774. // Update $this
  775. if ($bestImage != "") {
  776. $cache[1] = $bestImage;
  777. }
  778. if ($bestDescription != "") {
  779. $cache[10] = file_get_contents($bestDescription);
  780. }
  781. $cache[2] = date("U");
  782. natcasesort($new_nodes);
  783. $cache[7] = array_values($new_nodes);
  784. natcasesort($new_tracks);
  785. $cache[8] = array_values($new_tracks);
  786. // * * * * * * * *
  787. // Write the cache.
  788. $this->writeCache($cache,"nodes");
  789. if ($filecache != array()) {
  790. $this->writeCache($filecache,"tracks");
  791. }
  792. }
  793. /**
  794. * Returns whether or not this is a leaf (which it isn't)
  795. *
  796. * @author Laurent Perrin
  797. * @version 5/10/04
  798. * @since 5/10/04
  799. */
  800. function isLeaf() { return false; }
  801. /**
  802. * Returns the nodes starting with the specified letter.
  803. * if $letter is "#" it returns nodes that don't start with a-z.
  804. * if $letter is "*" it returns all nodes.
  805. *
  806. * @author Ben Dodson <bdodson@seas.upenn.edu>
  807. * @version 6/4/04
  808. * @since 5/11/04
  809. */
  810. function getAlphabetical($letter, $type = "nodes", $depth = false) {
  811. if ($depth === false) {
  812. $depth = $this->getNaturalDepth();
  813. }
  814. if ($depth == 0) {
  815. $first = strtolower(substr($this->getName(),0,1));
  816. $letter = strtolower($letter);
  817. if ($letter == "#") {
  818. if (!('a' <= $first && $first <= 'z')) {
  819. return array($this);
  820. }
  821. } else if ($letter == "*") {
  822. return array($this);
  823. }
  824. else { // standard case
  825. if ($letter == $first) {
  826. return array($this);
  827. }
  828. }
  829. }
  830. else {
  831. $array = array();
  832. foreach ($this->getSubNodes() as $subnode) {
  833. if (!$subnode->isLeaf()) {
  834. if (($arr = $subnode->getAlphabetical($letter, $type,$depth - 1)) != array()) {
  835. foreach ($arr as $item) {
  836. $array[] = $item;
  837. }
  838. }
  839. }
  840. }
  841. usort($array,"compareNodes");
  842. return $array;
  843. }
  844. }
  845. /**
  846. * Marks this node as 'featured.'
  847. *
  848. * @author Ben Dodson
  849. * @version 6/8/04
  850. * @since 6/8/04
  851. */
  852. function addFeatured() {
  853. // Just 1 cache: from the root node.
  854. $root = &new jzMediaNode();
  855. $cache = $root->readCache("featured");
  856. $cache[] = $this->getPath("String");
  857. $root->writeCache($cache, "featured");
  858. }
  859. /**
  860. * Checks to see if this node is featured
  861. *
  862. * @author Ben Dodson
  863. * @version 6/8/04
  864. * @since 6/8/04
  865. */
  866. function isFeatured() {
  867. $root = &new jzMediaNode();
  868. $path = $this->getPath("String");
  869. $cache = $root->readCache("featured");
  870. for ($i = 0; $i < sizeof($cache); $i++) {
  871. if ($cache[$i] == $path) {
  872. return true;
  873. }
  874. }
  875. return false;
  876. }
  877. /**
  878. * Removes this node from the featured list.
  879. *
  880. * @author Ben Dodson
  881. * @version 6/8/04
  882. * @since 6/8/04
  883. */
  884. function removeFeatured() {
  885. $root = &new jzMediaNode();
  886. $path = $this->getPath("String");
  887. $cache = $root->readCache("featured");
  888. for ($i = 0; $i < sizeof($cache); $i++) {
  889. if ($cache[$i] == $path) {
  890. $cache[$i] = $cache[sizeof($cache)-1];
  891. unset($cache[sizeof($cache)-1]);
  892. $root->writeCache($cache, "featured");
  893. return true;
  894. }
  895. }
  896. return false;
  897. }
  898. /**
  899. * Returns featured nodes. Limit 0 means get them all.
  900. * Order is random.
  901. *
  902. * @author Ben Dodson
  903. * @version 6/8/04
  904. * @since 6/8/04
  905. */
  906. function getFeatured($distance = -1, $limit = 1) {
  907. $root = &new jzMediaNode();
  908. $cache = $root->readCache("featured");
  909. $path = $this->getPath("String");
  910. $level = $this->getLevel();
  911. $vals = array();
  912. $i = 0;
  913. if ($distance === false) {
  914. $distance = $this->getNaturalDepth();
  915. }
  916. if (sizeof($cache) == 0) { return false; }
  917. srand((float) microtime() * 10000000);
  918. $keys = array_rand($cache,sizeof($cache));
  919. if (!is_array($keys)) {
  920. // only 1 key:
  921. $keys = array($keys);
  922. }
  923. foreach ($keys as $key) {
  924. $temp = $cache[$key];
  925. if ($path == "" || (strpos($temp, $path) == 0 && strpos($temp, $path) !== false && $temp != $path)) {
  926. $temp2 = &new jzMediaNode($temp);
  927. if ($distance <= 0 || $temp2->getLevel() - $level == $distance) {
  928. $vals[$i] = $temp2;
  929. $i++;
  930. if ($i >= $limit) {
  931. return $vals;
  932. }
  933. }
  934. }
  935. }
  936. return $vals;
  937. }
  938. /**
  939. * Adds a request. $type is either 'request' or 'broken.'
  940. *
  941. *
  942. * @author Ben Dodson
  943. * @version 9/1/04
  944. * @since 9/1/04
  945. */
  946. function addRequest($entry, $comment, $user, $type = "request") {
  947. // Just 1 cache: from the root node.
  948. $root = &new jzMediaNode();
  949. $cache = $root->readCache("request");
  950. $new = array();
  951. $new['entry'] = $entry;
  952. $new['comment'] = $comment;
  953. $new['user'] = $user;
  954. $new['type'] = strtolower($type);
  955. $new['id'] = md5($entry . $comment . $user . $type);
  956. $new['path'] = $this->getPath("String");
  957. $cache[] = $new;
  958. $root->writeCache($cache, "request");
  959. }
  960. /**
  961. * Gets requests. Default is to do so recursively and return all types.
  962. * Returns results as an array with the following fields:
  963. * entry,comment,user,type,id,path
  964. *
  965. * Path is the parent path for the request.
  966. * Type is the type of the request, currently 'broken' or 'request'
  967. *
  968. * @author Ben Dodson
  969. * @version 9/1/04
  970. * @since 9/1/04
  971. */
  972. function getRequests($distance = -1, $type = "all") {
  973. $root = &new jzMediaNode();
  974. $cache = $root->readCache("request");
  975. $path = $this->getPath("String");
  976. $level = $this->getLevel();
  977. $results = array();
  978. if (sizeof($cache) == 0) { return false; }
  979. for ($i = 0; $i < sizeof($cache); $i++) {
  980. if (strtolower($type) == "all" || strtolower($type) == $cache[$i]['type']) {
  981. $temp = $cache[$i]['path'];
  982. $tnode = &new jzMediaNode($temp);
  983. if ($path == "" || (strpos($temp, $path) == 0 && strpos($temp, $path) !== false)) {
  984. if ($distance <= 0) {
  985. $results[] = $cache[$i];
  986. }
  987. else if ($tnode->getLevel() - $level == $distance) {
  988. $results[] = $cache[$i];
  989. }
  990. }
  991. }
  992. }
  993. return $results;
  994. }
  995. /**
  996. * Removes request with id $id. (from getRequests['id']).
  997. *
  998. *
  999. * @author Ben Dodson
  1000. * @version 9/1/04
  1001. * @since 9/1/04
  1002. */
  1003. function removeRequest($id) {
  1004. $root = &new jzMediaNode();
  1005. $cache = $root->readCache("request");
  1006. for ($i = 0; $i < sizeof($cache); $i++) {
  1007. if ($cache[$i]['id'] == $id) {
  1008. $cache[$i] = $cache[sizeof($cache)-1];
  1009. unset($cache[sizeof($cache)-1]);
  1010. $root->writeCache($cache, "request");
  1011. return true;
  1012. }
  1013. }
  1014. return false;
  1015. }
  1016. /**
  1017. * Adds link to the given node.
  1018. *
  1019. *
  1020. * @author Ben Dodson
  1021. * @version 9/18/04
  1022. * @since 9/18/04
  1023. */
  1024. function addLink ($node) {
  1025. $cache = $this->readCache();
  1026. $linkarray = $cache[14];
  1027. $count = sizeof($linkarray);
  1028. // let's not add it twice.
  1029. $path = $node->getPath("String");
  1030. $type = ($node->isLeaf()) ? 'leaf' : 'node';
  1031. for ($i = 0; $i < $count; $i++) {
  1032. if ($linkarray[$i]['path'] == $path && $linkarray[$i]['type'] == $type) {
  1033. return true;
  1034. }
  1035. }
  1036. $linkarray[$count]['path'] = $node->getPath("String");
  1037. if ($node->isLeaf()) {
  1038. $linkarray[$count]['type'] = 'leaf';
  1039. }
  1040. else {
  1041. $linkarray[$count]['type'] = 'node';
  1042. }
  1043. $cache[14] = $linkarray;
  1044. $this->writeCache($cache);
  1045. }
  1046. /**
  1047. * Removes the link to the given node.
  1048. *
  1049. *
  1050. * @author Ben Dodson
  1051. * @version 9/18/04
  1052. * @since 9/18/04
  1053. */
  1054. function removeLink ($node) {
  1055. $cache = $this->readCache();
  1056. $linkarray = $cache[14];
  1057. $newlinkarray = array();
  1058. $count = sizeof($linkarray);
  1059. $path = $node->getPath("String");
  1060. $type = ($node->isLeaf()) ? 'leaf' : 'node';
  1061. for ($i = 0; $i < $count; $i++) {
  1062. if (!($linkarray[$i]['path'] == $path && $linkarray[$i]['type'] == $type)) {
  1063. $newlinkarray[] = $linkarray[$i];
  1064. }
  1065. }
  1066. $cache[14] = $newlinkarray;
  1067. $this->writeCache($cache);
  1068. }
  1069. /**
  1070. * Gets the node's links.
  1071. *
  1072. *
  1073. * @author Ben Dodson
  1074. * @version 9/18/04
  1075. * @since 9/18/04
  1076. */
  1077. function getLinks($type = 'both') {
  1078. $cache = $this->readCache();
  1079. $linkarray = $cache[14];
  1080. $return = array();
  1081. // alias:
  1082. if ($type == "tracks") {
  1083. $type = "leaves";
  1084. }
  1085. for ($i = 0; $i < sizeof($linkarray); $i++) {
  1086. if ($linkarray[$i]['type'] == 'node') {
  1087. if ($type == 'both' || $type == 'nodes') {
  1088. $return[] = &new jzMediaNode($linkarray[$i]['path']);
  1089. }
  1090. }
  1091. if ($linkarray[$i]['type'] == 'leaf') {
  1092. if ($type == 'both' || $type == 'leaves') {
  1093. $return[] = &new jzMediaTrack($linkarray[$i]['path']);
  1094. }
  1095. }
  1096. }
  1097. return $return;
  1098. }
  1099. /**
  1100. * Injects a leaf or a node into $this.
  1101. * Updated parameters for Jinzora 3.0.
  1102. *
  1103. * $pathArray can set the following fields:
  1104. * genre, subgenre, artist, album, disk, track
  1105. * If anything is not set, this function will try and pull
  1106. * the information from $this.
  1107. *
  1108. * @author Ben Dodson
  1109. * @since version - Jul 28, 2006
  1110. */
  1111. function inject($pathArray, $filename, $meta = false) {
  1112. if (!isset($pathArray['genre']) && false !== ($info = getInformation($this, "genre"))) {
  1113. $pathArray['genre'] = $info;
  1114. }
  1115. if (!isset($pathArray['subgenre']) && false !== ($info = getInformation($this, "subgenre"))) {
  1116. $pathArray['subgenre'] = $info;
  1117. }
  1118. if (!isset($pathArray['artist']) && false !== ($info = getInformation($this, "artist"))) {
  1119. $pathArray['artist'] = $info;
  1120. }
  1121. if (!isset($pathArray['album']) && false !== ($info = getInformation($this, "album"))) {
  1122. $pathArray['album'] = $info;
  1123. }
  1124. if (!isset($pathArray['disk']) && false !== ($info = getInformation($this, "disk"))) {
  1125. $pathArray['disk'] = $info;
  1126. }
  1127. $mpath = buildPath($pathArray);
  1128. $root = new jzMediaNode();
  1129. $res = $root->oldInject($mpath, $filename);
  1130. if (is_object($res) and $res->isLeaf()) {
  1131. $be = new jzBackend();
  1132. $be->registerFile($filename, $mpath);
  1133. if (is_array($meta) && sizeof($meta) > 0) {
  1134. $res->setMeta($meta,"cache");
  1135. $res->playpath = $filename;
  1136. }
  1137. }
  1138. else if (is_array($meta) && sizeof($meta) > 0) {
  1139. // Update the meta data even if file is already in cache
  1140. $track = &new jzMediaTrack($mpath);
  1141. $track->playpath = $filename;
  1142. $track->setMeta($meta,"cache");
  1143. }
  1144. return $res;
  1145. }
  1146. /*
  1147. * Adds tracks in bulk to Jinzora.
  1148. *
  1149. * @author Ben Dodson
  1150. * @since 9/5/04
  1151. */
  1152. function bulkInject($paths,$filenames,$metas) {
  1153. $results = array();
  1154. for ($i = 0; $i < sizeof($paths); $i++) {
  1155. $results[] = $this->inject($paths[$i],$filenames[$i],$metas[$i]);
  1156. }
  1157. return $results;
  1158. }
  1159. /**
  1160. * Injects a leaf or a node into $this.
  1161. * If sizeof($path) > 1, does so 'recursively'
  1162. * If the element path is found, do nothing and return false.
  1163. *
  1164. * @author Ben Dodson
  1165. * @version 10/14/04
  1166. * @since 10/14/04
  1167. */
  1168. function oldInject($path, $filepath, $type = "leaf") {
  1169. global $hierarchy;
  1170. if (is_string($path)) {
  1171. // todo: be more flexible (be carefully of '://')
  1172. return false;
  1173. }
  1174. if ($type == "track") {
  1175. $type = "leaf";
  1176. }
  1177. // Handle $path[0].
  1178. if ($path == array()) {
  1179. return false;
  1180. }
  1181. else {
  1182. $rawhead = array_shift($path);
  1183. $head = pathize($rawhead);
  1184. $nextpath = $this->getPath();
  1185. $nextpath[] = $head;
  1186. $nexttrack = &new jzMediaTrack($nextpath);
  1187. $nexttrack->playpath = $filepath;
  1188. $nextnode = &new jzMediaNode($nextpath);
  1189. if (file_exists($filepath)) {
  1190. $date = jz_filemtime($filepath);
  1191. } else {
  1192. $date = 0;
  1193. }
  1194. // add $next to cache, add its child, and continue.
  1195. $cache = $this->readCache("nodes");
  1196. if ($cache[15] == "-") {
  1197. $ptype = findPType($this);
  1198. $cache[15] = $ptype;
  1199. }
  1200. if (sizeof($path) == 0 && $type == "leaf") {
  1201. $found = false;
  1202. foreach ($cache[8] as $el) {
  1203. if ($el == $rawhead) {
  1204. return false;
  1205. }
  1206. }
  1207. if (!$found) {
  1208. $cache[8][] = $rawhead;
  1209. }
  1210. natcasesort($cache[8]);
  1211. }
  1212. else {
  1213. $found = false;
  1214. if (!is_array($cache[7])) {
  1215. //print_r($this);
  1216. die();
  1217. }
  1218. foreach ($cache[7] as $el) {
  1219. if (strtolower($el) == strtolower($head)) {
  1220. $found = true;
  1221. }
  1222. }
  1223. if (!$found) {
  1224. $cache[7][] = $head;
  1225. }
  1226. natcasesort($cache[7]);
  1227. }
  1228. $this->writeCache($cache,"nodes");
  1229. if (sizeof($path) == 0) { // gets its own cache.
  1230. if ($type == "leaf") {
  1231. $cache = $nexttrack->readCache();
  1232. $cache[6] = $date;
  1233. $cache[0] = $filepath;
  1234. $cache[2] = $rawhead;
  1235. $nexttrack->playpath = $filepath;
  1236. $nexttrack->writeCache($cache);
  1237. return $nexttrack;
  1238. }
  1239. else {
  1240. $cache = $nextnode->readCache();
  1241. $cache[6] = ($cache[6] < $date) ? $date : $cache[6];
  1242. // Don't need filepath. Writing to filesystem in id3 mode is stupid-
  1243. // everything will go in the data_dir.
  1244. $nextnode->writeCache($cache);
  1245. return $nextnode;
  1246. }
  1247. }
  1248. else {
  1249. return $nextnode->oldInject($path,$filepath,$type);
  1250. }
  1251. }
  1252. }
  1253. /**
  1254. * Gets the ptype for this node.
  1255. *
  1256. * @author Ben Dodson
  1257. * @version 10/31/04
  1258. * @since 10/31/04
  1259. */
  1260. function getPType() {
  1261. if ($this->getLevel() == 0) return "root";
  1262. $cache = $this->readCache();
  1263. return $cache[15];
  1264. }
  1265. /**
  1266. * Sets the ptype for this node.
  1267. * @author Ben Dodson
  1268. * @version 10/31/04
  1269. * @since 10/31/04
  1270. */
  1271. function setPType($type) {
  1272. $cache = $this->readCache();
  1273. $cache[15] = $type;
  1274. $this->writeCache($cache);
  1275. }
  1276. /**
  1277. * Adds meta data to all subnodes
  1278. *
  1279. * @author Ben Dodson
  1280. * @version 1/21/05
  1281. * @since 1/21/05
  1282. *
  1283. **/
  1284. function bulkMetaUpdate($meta,$mode = false, $displayOutput = false) {
  1285. $tracks = $this->getSubNodes("tracks",-1);
  1286. foreach ($tracks as $track) {
  1287. $track->setMeta($meta,$mode,$displayOutput);
  1288. }
  1289. $display = new jzDisplay();
  1290. $display->purgeCachedPage($this);
  1291. }
  1292. /**
  1293. * Imports media in the specified format.
  1294. * @author Ben Dodson
  1295. * @version 10/31/04
  1296. * @since 10/31/04
  1297. */
  1298. function mediaImport($type, $file) {
  1299. switch ($type) {
  1300. case "jzLibrary":
  1301. echo "Importing media...<br>";
  1302. ob_flush();
  1303. if ($file == "URL") {
  1304. $contents = "";
  1305. $url = $_GET['query'];
  1306. $fp = fopen($url,'r');
  1307. while (!feof($fp)) {
  1308. $contents .= fread($fp, 2048);
  1309. }
  1310. $arr = unserialize($contents);
  1311. } else {
  1312. $arr = unserialize($file);
  1313. }
  1314. for ($i = 0; $i < sizeof($arr); $i++) {
  1315. $mpath = explode("/",$arr[$i]['path']);
  1316. if (sizeof($mpath) > 0) {
  1317. if ($child = $this->oldInject($mpath,$arr[$i]['filepath'])) {
  1318. $child->setMeta($arr[$i]['meta'],"cache");
  1319. }
  1320. }
  1321. }
  1322. echo "Import complete.";
  1323. break;
  1324. }
  1325. }
  1326. /**
  1327. * Gathers all of our statistics as an array with
  1328. * the following keys:
  1329. *
  1330. * avg_bitrate
  1331. * avg_length (seconds)
  1332. * avg_length_str (string version)
  1333. * total_length (seconds)
  1334. * total_length_str (string version)
  1335. * avg_size (megs)
  1336. * total_size (megs)
  1337. * total_size_str (string version)
  1338. * total_genres
  1339. * total_artists
  1340. * total_albums
  1341. * total_disks
  1342. * total_tracks
  1343. * avg_year
  1344. *
  1345. * @author Ben Dodson
  1346. * @version 11/16/04
  1347. * @since 11/16/04
  1348. */
  1349. function getStats($return = false) {
  1350. if (!$return){
  1351. $this->generateStats($return);
  1352. return $this->stats;
  1353. } else {
  1354. $data = $this->generateStats($return);
  1355. return $data[$return];
  1356. }
  1357. }
  1358. /**
  1359. * Creates all of our statistics.
  1360. *
  1361. * @author Ben Dodson
  1362. * @version 11/16/04
  1363. * @since 11/16/04
  1364. * @param $string specifically what to return, defaults to everything
  1365. */
  1366. function generateStats($return = false) {
  1367. $stats = array();
  1368. // have to do it...
  1369. $elements = $this->getSubNodes("tracks",-1);
  1370. $length = $size = $bitrate = $year = $yearc = $lengthc = $brc = $sizec = $tracks = 0;
  1371. foreach ($elements as $track) {
  1372. $tracks++;
  1373. $meta = $track->getMeta();
  1374. if ($meta['length'] != '-' && $meta['length'] > 0) {
  1375. $length += $meta['length'];
  1376. $lengthc++;
  1377. }
  1378. if ($meta['size'] != '-' && $meta['size'] > 0) {
  1379. $size += $meta['size'];
  1380. $sizec++;
  1381. }
  1382. if ($meta['year'] != '-' && $meta['year'] > 1000) {
  1383. $year += $meta['year'];
  1384. $yearc++;
  1385. }
  1386. if ($meta['bitrate'] != '-' && $meta['bitrate'] > 0) {
  1387. $bitrate += $meta['bitrate'];
  1388. $brc++;
  1389. }
  1390. }
  1391. if ($tracks == 0) return false;
  1392. $stats['total_size'] = $size;
  1393. $stats['total_length'] = $length;
  1394. $stats['total_tracks'] = $tracks;
  1395. $stats['avg_bitrate'] = @round($bitrate / $brc,2);
  1396. $stats['avg_length'] = @round($length / $lengthc,0);
  1397. $stats['avg_size'] = @round($size / $sizec,2);
  1398. $stats['avg_year'] = @round($year / $yearc,2);
  1399. $str = "";
  1400. // stringize stuff:
  1401. $stats['avg_length_str'] = stringize_time($stats['avg_length']);
  1402. $stats['total_length_str'] = stringize_time($stats['total_length']);
  1403. $stats['total_size_str'] = stringize_size($stats['total_size']);
  1404. // Now did we want to return something specific
  1405. if ($return){
  1406. return $stats[$return];
  1407. }
  1408. if (($d = distanceTo('genre',$this)) !== false)
  1409. $stats['total_genres'] = $this->getSubNodeCount('nodes',$d);
  1410. else
  1411. $stats['total_genres'] = 0;
  1412. if (($d = distanceTo('artist',$this)) !== false)
  1413. $stats['total_artists'] = $this->getSubNodeCount('nodes',$d);
  1414. else
  1415. $stats['total_artists'] = 0;
  1416. if (($d = distanceTo('album',$this)) !== false)
  1417. $stats['total_albums'] = $this->getSubNodeCount('nodes',$d);
  1418. else
  1419. $stats['total_albums'] = 0;
  1420. // nodes at track level are disks.
  1421. if (($d = distanceTo('track',$this)) !== false)
  1422. $stats['total_disks'] = $this->getSubNodeCount('nodes',$d);
  1423. else
  1424. $stats['total_disks'] = 0;
  1425. $this->stats = $stats;
  1426. }
  1427. /**
  1428. * Removes media from the cache.
  1429. *
  1430. * @author Ben Dodson
  1431. * @version 11/16/04
  1432. * @since 11/16/04
  1433. */
  1434. function removeMedia($element) {
  1435. $parent = $element->getParent();
  1436. if ($element->isLeaf()) {
  1437. // Delete parent references to $element:
  1438. $nodecache = $parent->readCache("nodes");
  1439. $tracklist = $nodecache[8];
  1440. $name = $element->getPath();
  1441. $name = $name[sizeof($name)-1];
  1442. removeFromArray($tracklist,$name);
  1443. $nodecache[8] = $tracklist;
  1444. $parent->writeCache($nodecache,"nodes");
  1445. $trackcache = $parent->readCache("tracks");
  1446. foreach ($trackcache as $id=>$arr) {
  1447. if ($arr[2] == $name) {
  1448. unset($trackcache[$id]);
  1449. }
  1450. }
  1451. $trackcache = array_values($trackcache);
  1452. $parent->writeCache($trackcache,"tracks");
  1453. } else {
  1454. // First wipe out the children:
  1455. $children = $element->getSubNodes("nodes",-1);
  1456. foreach ($children as $child) {
  1457. $this->removeMedia($child);
  1458. }
  1459. // Now clear $element from its parent:
  1460. $nodecache = $parent->readCache("nodes");
  1461. $nodelist = $nodecache[7];
  1462. $name = $element->getName();
  1463. removeFromArray($nodelist,$name);
  1464. $nodecache[7] = $nodelist;
  1465. $parent->writeCache($nodecache,"nodes");
  1466. // Now kill $element's caches:
  1467. $element->deleteCache();
  1468. }
  1469. // Now see if the parent should be removed:
  1470. $count = $parent->getSubNodeCount("both",1);
  1471. if ($count == 0 && $parent->getLevel() > 0) {
  1472. $this->removeMedia($parent);
  1473. }
  1474. }
  1475. /* Moves media from one location to another
  1476. * This function calls other backend functions
  1477. * to make it work for all backends.
  1478. * It is not meant to be the most efficient implementation.
  1479. *
  1480. * @author Ben Dodson
  1481. * @since 8/10/05
  1482. * @version 8/11/05
  1483. **/
  1484. function moveMedia($element, $newpath) {
  1485. $root = new jzMediaNode();
  1486. $be = new jzBackend();
  1487. $playpath = $element->getFilePath();
  1488. $type = ($element->isLeaf()) ? "leaf" : "node";
  1489. if (is_string($newpath)) {
  1490. $path = explode("/",$newpath);
  1491. } else if (is_array($newpath)) {
  1492. $path = $newpath;
  1493. } else {
  1494. return false;
  1495. }
  1496. if ($type == "node") { return false; }
  1497. $pc = $element->getPlayCount();
  1498. $dc = $element->getDownloadCount();
  1499. $vc = $element->getViewCount();
  1500. $desc = $element->getDescription();
  1501. $sdesc = $element->getShortDescription();
  1502. $art = $element->getMainArt();
  1503. $discussion = $element->getDiscussion();
  1504. $rating = $element->getRating();
  1505. $rating_count = $element->getRatingCount();
  1506. if ($be->hasFeature('setID')) {
  1507. $mid = $element->getID();
  1508. }
  1509. // TODO:
  1510. // This does not work correctly with nodes yet.
  1511. // You should pull the above data, then recursively move children,
  1512. // then remove me, and finally set the data as below.
  1513. // I did not do this yet (8/11/05) because I would not have been
  1514. // able to test it. (for things like collisions,
  1515. // and also how to handle the filesystem)
  1516. // If the backend has a lookup file, update it.
  1517. if ($element->isLeaf()) {
  1518. $media_path = getMediaDir($element);
  1519. $be = new jzBackend();
  1520. $rl_name = 'reverse_lookup-' . str_replace(':','',str_replace('\\','-',str_replace('/','-',$media_path)));
  1521. $LOOKUP = $be->loadData($rl_name);
  1522. if (is_array($LOOKUP)) {
  1523. if (isset($LOOKUP[$element->getFilename("host")])) {
  1524. $LOOKUP[$element->getFilename("host")] = implode('/',$path);
  1525. $be->storeData($rl_name,$LOOKUP);
  1526. }
  1527. }
  1528. }
  1529. $this->removeMedia($element);
  1530. if (false !== ($new = $root->inject($path,$playpath))) {
  1531. $new->setPlayCount($pc);
  1532. $new->setDownloadCount($dc);
  1533. $new->setViewCount($vc);
  1534. $new->addRating($rating,$rating_count);
  1535. if ($be->hasFeature('setID')) {
  1536. $new->setID($mid);
  1537. }
  1538. if (!isNothing($desc)) {
  1539. $new->addDescription($desc);
  1540. }
  1541. if (!isNothing($sdesc)) {
  1542. $new->addShortDescription($sdesc);
  1543. }
  1544. if (!isNothing($art)) {
  1545. $new->addMainArt($art);
  1546. }
  1547. if ($discussion != array() && !isNothing($discussion)) {
  1548. $new->addFullDiscussion($discussion);
  1549. }
  1550. return $new;
  1551. }
  1552. }
  1553. function getMostDownloaded($type = "nodes", $distance = false, $limit = 10) {
  1554. return array();
  1555. }
  1556. function getMostPlayed($type = "nodes", $distance = false, $limit = 10) {
  1557. return array();
  1558. }
  1559. function getMostViewed($type = "nodes", $distance = false, $limit = 10) {
  1560. return array();
  1561. }
  1562. function getRecentlyAdded($type = "nodes", $distance = false, $limit = 10) {
  1563. return array();
  1564. }
  1565. function getRecentlyPlayed($type = "nodes", $distance = false, $limit = 10) {
  1566. return array();
  1567. }
  1568. function getTopRated($type = "nodes", $distance = false, $limit = 10) {
  1569. return array();
  1570. }
  1571. }
  1572. ?>