Passed
Push — master ( d021a5...a13070 )
by Sam
03:47 queued 12s
created

RetrieveMediaWidget   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 244
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 7
dl 0
loc 244
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A renderWatchInBrowserButton() 0 13 1
A checkLinks() 0 7 3
A renderWatchButton() 0 11 1
A getLoggableLinkOptions() 0 6 1
A renderMissingFile() 0 4 1
A renderPlayOnBackendLink() 0 6 1
A renderForm() 0 34 4
A init() 0 3 1
A renderLinks() 0 26 4
A getStreamUrl() 0 9 5
A getDownloadName() 0 3 1
A run() 0 14 3
A getWatchButtonsOptions() 0 7 1
1
<?php
2
3
/**
4
 * Base class for rendering a watch button and links to media items
5
 *
6
 * @author Sam Stenvall <[email protected]>
7
 * @copyright Copyright &copy; Sam Stenvall 2013-
8
 * @license https://www.gnu.org/licenses/gpl.html The GNU General Public License v3.0
9
 */
10
abstract class RetrieveMediaWidget extends CWidget
11
{
12
13
	/**
14
	 * @var string the type of media that the links are for
15
	 */
16
	public $type;
17
18
	/**
19
	 * @var File the media file
20
	 */
21
	public $details;
22
	
23
	/**
24
	 * @var ItemLink[] the media links
25
	 */
26
	private $_links;
27
	
28
	/**
29
	 * @return string the category to use when logging download link clicks
30
	 */
31
	abstract protected function getLogMessage();
32
	
33
	/**
34
	 * @return array the action for retrieving an item's playlist (as a single 
35
	 * item array)
36
	 */
37
	abstract protected function getPlayListAction();
38
	
39
	/**
40
	 * Initializes the widget
41
	 */
42
	public function init()
43
	{
44
		$this->_links = $this->details->getItemLinks();
45
	}
46
47
	/**
48
	 * Runs the widget
49
	 */
50
	public function run()
51
	{
52
		// Don't render links for spectators
53
		if (Yii::app()->user->role === User::ROLE_SPECTATOR)
54
			return;
55
		
56
		if (!$this->checkLinks())
57
		{
58
			$this->renderMissingFile();
59
60
			return;
61
		}
62
		
63
		$this->renderForm();
64
	}
65
66
	/**
67
	 * Checks that all media links are valid
68
	 * @return boolean
69
	 */
70
	private function checkLinks()
71
	{
72
		foreach ($this->_links as $link)
73
			if (!$link->url)
74
				return false;
75
76
		return true;
77
	}
78
	
79
	/**
80
	 * @param string $link
81
	 * @return string the filename part of the full link to a file
82
	 */
83
	private function getDownloadName($link)
84
	{
85
		return urldecode(substr($link, strrpos($link, '%2f') + 3));
86
	}
87
88
	/**
89
	 * Returns the stream URL for the media. A direct link will be returned if 
90
	 * the user is on a mobile device or if the "singleFilePlaylist" setting 
91
	 * is enabled, otherwise the media playlist URL will be returned
92
	 * @return string the stream URL
93
	 */
94
	protected function getStreamUrl()
95
	{
96
		if (count($this->_links) === 1 && (Setting::getBoolean('singleFilePlaylist') 
97
				|| (Browser::isMobile() || Browser::isTablet())))
98
		{
99
			return $this->_links[0]->url;
100
		}
101
		else
102
			return $this->getPlayListAction();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getPlayListAction() returns the type array which is incompatible with the documented return type string.
Loading history...
103
	}
104
	
105
	/**
106
	 * @return array options for the watch buttons displayed
107
	 */
108
	private function getWatchButtonsOptions()
109
	{
110
		return array(
111
			'color'=>TbHtml::BUTTON_COLOR_SUCCESS,
112
			'size'=>TbHtml::BUTTON_SIZE_LARGE,
113
			'url'=>$this->getStreamUrl(),
114
			'class'=>'fa fa-file-movie-o');
115
	}
116
	
117
	/**
118
	 * Renders the form that contains the buttons and links to watch/download 
119
	 * and item
120
	 */
121
	private function renderForm()
122
	{
123
		// Render the form with all the retrieval options
124
		echo CHtml::beginForm($this->getPlayListAction(), 'get');
125
		echo CHtml::hiddenField('id', $this->details->getId());
126
		
127
		// Show the "Play in browser" button when applicable
128
		$helper = new MediaInfoHelper($this->details);
129
		
130
		if (!$helper->needsTranscoding() && count($this->_links) === 1)
131
		{
132
			?>
133
			<section>
134
				<?php $this->renderWatchInBrowserButton(); ?>
135
			</section>
136
			<?php
137
		}
138
		
139
		// Show the "Watch as playlist" button if the file is streamable, 
140
		// otherwise show an alert
141
		if ($helper->isStreamable())
142
		{
143
			?>
144
			<section>
145
				<?php $this->renderWatchButton(); ?>
146
			</section>
147
			<?php
148
		}
149
		else
150
			$this->renderMissingFile();
151
		
152
		// Render the download links and close the form
153
		$this->renderLinks();
154
		echo CHtml::endForm();
155
	}
156
157
	/**
158
	 * Renders the download links
159
	 */
160
	private function renderLinks()
161
	{
162
		echo CHtml::openTag('div', array('class'=>'item-links'));
163
164
		$numLinks = count($this->_links);
165
		$linkOptions = array_merge(array(
166
			'class'=>'fa fa-floppy-o loggable-link'), $this->getLoggableLinkOptions());
167
168
		foreach ($this->_links as $k=> $link)
169
		{
170
			if ($numLinks == 1)
171
				$label = Yii::t('RetrieveMediaWidget', 'Download');
172
			else
173
				$label = Yii::t('RetrieveMediaWidget', 'Download (part #{partNumber})', array('{partNumber}'=>++$k));
174
175
			// Add the "download" attribute
176
			$linkOptions['download'] = $this->getDownloadName($link->url);
177
			
178
			echo CHtml::tag('p', array(), CHtml::link($label, $link->url, $linkOptions));
179
		}
180
		
181
		// Show a "Play in XBMC" link to administrators
182
		if (Yii::app()->user->role === User::ROLE_ADMIN)
183
			$this->renderPlayOnBackendLink();
184
185
		echo CHtml::closeTag('div');
186
	}
187
	
188
	/**
189
	 * Renders a warning about a missing file
190
	 */
191
	private function renderMissingFile()
192
	{
193
		echo CHtml::tag('p', array('class'=>'missing-video-file'), TbHtml::icon(TBHtml::ICON_WARNING_SIGN).
194
					Yii::t('RetrieveMediaWidget', 'The file(s) for this item is not available'));
195
	}
196
	
197
	/**
198
	 * Renders the "Play in XBMC" link
199
	 */
200
	private function renderPlayOnBackendLink()
201
	{
202
		echo CHtml::tag('p', array(), CHtml::link(
203
				Yii::t('RetrieveMediaWidget', 'Play in XBMC'), 
204
				array('playOnBackend', 'file'=>$this->details->file), 
205
				array('class'=>'fa fa-desktop'))); 
206
	}
207
208
	/**
209
	 * Renders the "Watch as playlist" button
210
	 */
211
	private function renderWatchButton()
212
	{
213
		// Select the default playlist format by default
214
		$dropdownOptions = array(
215
			Setting::getString('playlistFormat')=>array('selected'=>'selected'));
216
217
		echo TbHtml::dropDownListControlGroup('playlistFormat', 'playlistFormat', PlaylistFactory::getTypes(), array(
218
			'label'=>Yii::t('Settings', 'Playlist format'),
219
			'options'=>$dropdownOptions));
220
221
		echo TbHtml::submitButton(Yii::t('RetrieveMediaWidget', 'Watch as playlist'), $this->getWatchButtonsOptions());
222
	}
223
	
224
	/**
225
	 * Renders the "Watch as in browser" button
226
	 */
227
	private function renderWatchInBrowserButton()
228
	{
229
		// Swap the button URL for the first item link
230
		$buttonOptions = $this->getWatchButtonsOptions();
231
		$buttonOptions['class'] = 'fa fa-play';
232
		$buttonOptions['color'] = TbHtml::BUTTON_COLOR_PRIMARY;
233
		$buttonOptions['url'] = array('watchInBrowser', 'url'=>$this->_links[0]->url);
234
		
235
		// Add logging
236
		TbHtml::addCssClass('loggable-link', $buttonOptions);
237
		$buttonOptions = array_merge($buttonOptions, $this->getLoggableLinkOptions());
238
		
239
		echo TbHtml::linkButton(Yii::t('RetrieveMediaWidget', 'Watch in browser'), $buttonOptions);
240
	}
241
	
242
	/**
243
	 * @return array HTML options for loggable links
244
	 */
245
	private function getLoggableLinkOptions()
246
	{
247
		return array(
248
			'data-log-category'=>get_class(Yii::app()->controller),
249
			'data-log-message'=>htmlentities($this->getLogMessage()),
250
			'data-log-url'=>Yii::app()->controller->createUrl('/log/logEvent'));
251
	}
252
253
}