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

/modules/Beets/CliHandler.php

https://gitlab.com/x33n/ampache
PHP | 200 lines | 86 code | 21 blank | 93 comment | 7 complexity | 668c9bcd72ac427e4c6a78391678cddb MD5 | raw file
  1. <?php
  2. /* vim:set softtabstop=4 shiftwidth=4 expandtab: */
  3. /**
  4. *
  5. * LICENSE: GNU General Public License, version 2 (GPLv2)
  6. * Copyright 2001 - 2015 Ampache.org
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License v2
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. *
  21. */
  22. namespace Beets;
  23. /**
  24. * Start commands in CLI and dispatch them
  25. *
  26. * @author raziel
  27. */
  28. class CliHandler extends Handler
  29. {
  30. /**
  31. *
  32. * @var Catalog
  33. */
  34. protected $handler;
  35. /**
  36. * string handler command to do whatever we need
  37. * @var
  38. */
  39. protected $handlerCommand;
  40. /**
  41. * Field seperator for beets field format
  42. * @var string
  43. */
  44. protected $seperator = '###';
  45. /**
  46. * Custom limiter of beets song because we may have multi line output
  47. * @var string
  48. */
  49. protected $itemEnd = '//EOS';
  50. /**
  51. * Format string for the '-f' argument from 'beet ls'
  52. * @var string
  53. */
  54. protected $fieldFormat;
  55. /**
  56. * Choose whether the -f argument from beets is applied. May be needed to use other commands than 'beet ls'
  57. * @var boolean
  58. */
  59. protected $useCustomFields = true;
  60. /**
  61. * All stored beets fields
  62. * @var array
  63. */
  64. protected $fields = array();
  65. /**
  66. * Beets command
  67. * @var string
  68. */
  69. protected $beetsCommand = 'beet';
  70. /**
  71. * Seperator between command and arguments
  72. * @var string
  73. */
  74. protected $commandSeperator = ' ';
  75. /**
  76. * Defines the differences between beets and ampache fields
  77. * @var array Defines the differences between beets and ampache fields
  78. */
  79. protected $fieldMapping = array(
  80. 'disc' => array('disk', '%d'),
  81. 'path' => array('file', '%s'),
  82. 'length' => array('time', '%d'),
  83. 'comments' => array('comment', '%s'),
  84. 'bitrate' => array('bitrate', '%d')
  85. );
  86. /**
  87. * Starts a command
  88. * @param string $command
  89. */
  90. public function start($command)
  91. {
  92. $handle = popen($this->assembleCommand($command), 'r');
  93. if ($handle) {
  94. $this->iterateItems($handle);
  95. }
  96. }
  97. public function iterateItems($handle)
  98. {
  99. $item = '';
  100. while (!feof($handle)) {
  101. $item .= fgets($handle);
  102. if ($this->itemIsComlete($item)) {
  103. $song = $this->parse($item);
  104. $this->dispatch($song);
  105. $item = '';
  106. }
  107. }
  108. }
  109. /**
  110. * Assemble the command for CLI
  111. * @param string $command beets command (e.g. 'ls myArtist')
  112. * @param boolean $disableCostomFields disables the -f switch for this time
  113. * @return type
  114. */
  115. protected function assembleCommand($command, $disableCostomFields = false)
  116. {
  117. $commandParts = array(
  118. escapeshellcmd($this->beetsCommand),
  119. ' -l ' . escapeshellarg($this->handler->getBeetsDb()),
  120. escapeshellcmd($command)
  121. );
  122. if ($this->useCustomFields && !$disableCostomFields) {
  123. $commandParts[] = ' -f ' . escapeshellarg($this->getFieldFormat());
  124. }
  125. return implode(' ', $commandParts);
  126. }
  127. /**
  128. *
  129. * @param string $item
  130. * @return boolean
  131. */
  132. protected function itemIsComlete($item)
  133. {
  134. return strrpos($item, $this->itemEnd, strlen($this->itemEnd)) !== false;
  135. }
  136. /**
  137. * Parse the output string from beets into a song
  138. * @param string $item
  139. * @return array
  140. */
  141. protected function parse($item)
  142. {
  143. $item = str_replace($this->itemEnd, '', $item);
  144. $values = explode($this->seperator, $item);
  145. $song = array_combine($this->fields, $values);
  146. $mappedSong = $this->mapFields($song);
  147. $mappedSong['size'] = filesize($mappedSong['file']);
  148. return $mappedSong;
  149. }
  150. /**
  151. * Create the format string for beet ls -f
  152. * @return string
  153. */
  154. protected function getFieldFormat()
  155. {
  156. if (!isset($this->fieldFormat)) {
  157. $this->fields = $this->getFields();
  158. $this->fieldFormat = '$' . implode($this->seperator . '$', $this->fields) . $this->itemEnd;
  159. }
  160. return $this->fieldFormat;
  161. }
  162. /**
  163. *
  164. * @return array
  165. */
  166. protected function getFields()
  167. {
  168. $fields = null;
  169. $processedFields = array();
  170. exec($this->assembleCommand('fields', true), $fields);
  171. foreach ((array) $fields as $field) {
  172. $matches = array();
  173. if (preg_match('/^[\s]+([\w]+)$/', $field, $matches)) {
  174. $processedFields[] = $matches[1];
  175. }
  176. }
  177. return $processedFields;
  178. }
  179. }