PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/application/protected/extensions/widgets/audioplayer/AiiPublishRegisterBehavior.php

https://bitbucket.org/dinhtrung/yiicorecms/
PHP | 539 lines | 223 code | 41 blank | 275 comment | 27 complexity | f3afba173e892ce4fd7baa0a44c332a2 MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause, CC0-1.0, BSD-2-Clause, GPL-2.0, LGPL-2.1, LGPL-3.0
  1. <?php
  2. /**
  3. * This behavior implements logic supporting publishing
  4. * and then registering JS and CSS owner assets,
  5. * but may be used for publishing other filetypes as well.
  6. * Design of this behavior is focused on supporting widgets
  7. * with publishing own JS and CSS assets, which usually
  8. * are located under widget subdirectory.
  9. * This subdirectory needs to be know to this behavior
  10. * and it can be passed to behavior using {@link basePath} property value.
  11. * Later, this subdirectory is avaliable also as {basePath} placeholder.
  12. * Usually you need to set it during behaviors initialization following
  13. * <code>
  14. * $this->attachBehavior( 'pubRegManager',
  15. * array(
  16. * 'class' => 'AiiPublishRegisterBehavior',
  17. * 'cssPath' => false,
  18. * 'jsToRegister' => array( 'audio-player.js' ),
  19. * 'basePath' => __FILE__,
  20. * 'toPublish' => array( 'mp3Folder' => $this->mp3Folder ),
  21. * ) );
  22. * </code>
  23. * If you need to publish assets from directory which is not owner subdirectory
  24. * you should can do thi with this behavior as well.
  25. *
  26. * Note that you can use also other placeholders when specifying paths to publish
  27. * e.g. {assets} which points to {@link assetsPath}
  28. * {js} which points to {@link jsPath}
  29. * {css} which points to {@link cssPath}
  30. *
  31. * By default behavior initializes all path properties with following value
  32. * referencing to some aforementioned placeholders
  33. * - {@link assetsPath} is initialized with <code>{basePath}/assets</code>
  34. * - {@link jsPath} is initialized with <code>{assets}/js</code>
  35. * - {@link cssPath} is initialized with <code>{assets}/css</code>
  36. *
  37. * Hint: you can use {/} as alias for DIRECTORY_SEPARATOR
  38. *
  39. * Note that {@link otherResToPublish} are not set by default.
  40. * You can use this e.g. to publish such resorces as audio files, archieves, etc.
  41. *
  42. * If you need to register published CSS and JS files
  43. * they need to be listed using properties
  44. * (please refer them to see how to specify this files):
  45. * - {@link cssToRegister}
  46. * - {@link jsToRegister}
  47. *
  48. * You can also register Yii core scripts it owner need them by setting
  49. * {@link coreScriptsToRegister}.
  50. *
  51. * Note that by default all JS scripts are registered in head. You can change
  52. * this beaavior by setting {@link jsDefaultPos} to one of constant
  53. * defined in {@link CClientScript}
  54. *
  55. * All CSS files registered uses media type all. You can change this behavior by
  56. * setting {@link defaultMedia} to other value, e.g. screen.
  57. *
  58. * Note that {@link cssToRegister} and {@link jsToRegister} allows to specify
  59. * media type and position of registered JS script for each file separatelly.
  60. *
  61. * If you need this behavior just for registering or paths passed to
  62. * {@link assetsPath} {@link jsPath} {@link cssPath} are mixture of published
  63. * and unpublished path, you can inform this behavior about this by setting
  64. * {@link publishingStatus} to proper value. Setted value will inform behavior which
  65. * path points is published/unpublished.
  66. * For example, value 6 means that ot via {@link cssPath} and {@link jsPath}
  67. * are passed published paths.
  68. * Set 1 {@link NOT_PUBLISHED} to inform that nothing is published yet
  69. * Add 2 {@link JS_PUBLISHED} to inform that {@link jsPath} is published
  70. * Add 4 {@link CSS_PUBLISHED} to inform that {@link cssPath} is published
  71. * Add 8 {@link ASSETS_PUBLISHED} to inform that {@link assetsPath} is published
  72. * Add 16 {@link OTHERS_PUBLISHED} to inform that all resources from {@link otherResToPublish} are published
  73. *
  74. * You can also update status by calling method {@link updateStatus} but we awared
  75. * that this method do not check if particular resource is really published.
  76. * Note also that calling this method twice for the same resource
  77. * will result with unproper {@link publishingStatus} property value.
  78. * To be sure that you are not changing status for second time, use method {@link checkIsPublished}
  79. *
  80. *
  81. * @author Tomasz Suchanek <tomasz.suchanek@gmail.com>
  82. * @copyright Copyright &copy; 2010 Tomasz "Aztech" Suchanek
  83. * @link http://code.google.com/p/aii-extensions
  84. * @license http://www.yiiframework.com/license/
  85. * @package aii.extensions
  86. * @version 0.1.0
  87. **/
  88. class AiiPublishRegisterBehavior extends CBehavior
  89. {
  90. /**
  91. * @var message category
  92. */
  93. const NOT_PUBLISHED = 1;
  94. const JS_PUBLISHED = 2;
  95. const CSS_PUBLISHED = 4;
  96. const ASSETS_PUBLISHED = 8;
  97. const OTHERS_PUBLISHED = 16;
  98. /**
  99. * @var string equals to initial value of {@link jsPath}
  100. * if {assets} reference were found in {@link jsPath} definition
  101. */
  102. private $_jsPathTemplate;
  103. /**
  104. * @var string equals to initial value of {@link cssPath}
  105. * if {assets} reference were used in {@link cssPath}
  106. */
  107. private $_cssPathTemplate;
  108. /**
  109. * Stores all files or directories which were published.
  110. */
  111. private $_published = array( );
  112. /**
  113. *
  114. * @var array stores ll generated paths
  115. */
  116. private $_paths = array( );
  117. /**
  118. * @var boolean determines if paths and placeholders are generated
  119. */
  120. private $_pathsGenerated = false;
  121. /**
  122. * @var integer
  123. * {@link assetsPath}, {@link cssPath} and {@link jsPath}
  124. * are already published paths. This is mainly used when we know
  125. * published paths and we want just to register CSS and JS files.
  126. * If false, each path will be published
  127. * This value don't affects files passed into {@link toPublish} property
  128. */
  129. public $publishingStatus = self::NOT_PUBLISHED;
  130. /**
  131. * Array of pairs <id>-<file name>.
  132. * Setting id is not mandatory. Please use them in case you will
  133. * need to know where file or directory were published.
  134. * You can do this by passing <id> into {@link getPublished}
  135. * @var other resources that need to be published
  136. */
  137. public $otherResToPublish = array( );
  138. /**
  139. * @var string base path directory, usually set to directory where owner of behaviour is found
  140. */
  141. public $basePath;
  142. /**
  143. * @var string folder path to assets
  144. * You can use here {basePath} placeholder
  145. * Set false if content shouldn't be published
  146. * Default to null, meaning path '{basePath}{/}assets' will be used
  147. * Note that {basePath} is detrmined basing on {@link basePath} value
  148. */
  149. public $assetsPath = null;
  150. /**
  151. * @var string folder path to css
  152. * You can use here {assets} and {basePath} placeholders
  153. * Set false if no css should be published
  154. * Default to null, meaning path '{assets}{/}css' will be used
  155. */
  156. public $cssPath = null;
  157. /**
  158. * @var string folder path to js
  159. * You can use here {assets} and {basePath} placeholders
  160. * Set false if no JS should be published
  161. * Default to null, meaning path '{assets}{/}js' will be used
  162. */
  163. public $jsPath = null;
  164. /**
  165. * @var array css files under {@link cssPath} to register
  166. * Array may consist only <cssFile> or pairs <media>-<cssFile>
  167. * or its mixture, e.g
  168. * <code>
  169. * array(
  170. * 'print' => 'print.css',
  171. * 'screen, projection' => 'main.css',
  172. * 'ie.css',
  173. * );
  174. * </code>
  175. * Leaving media empty, will set published css as media 'all'
  176. */
  177. public $cssToRegister = array( );
  178. /**
  179. * @var array js files under {@link jsPath} to register
  180. * Array may consist only <jsFile> or pairs <jsFile>-<position>
  181. * or its mixture, e.g.
  182. * <code>
  183. * array(
  184. * 'some.js' => '2',
  185. * 'load.js' => CClientScript::POS_LOAD,
  186. * 'head.js'
  187. * );
  188. * </code>
  189. * If position is not specified, by default position from
  190. * {@link jsDefaultPos} is used
  191. */
  192. public $jsToRegister = array( );
  193. /**
  194. * @var array core scripts to register
  195. * Array consisting core names scipts to register, e.g.
  196. * <code>
  197. * array ( 'jquery' , 'yiiactiveform' );
  198. * </code>
  199. */
  200. public $coreScriptsToRegister = array( );
  201. /**
  202. * @var integer, the position of the JavaScript code.
  203. * Not that this value differs from Yii default, first is 1 (meaning HEAD) later is 4.
  204. */
  205. public $jsDefaultPos = CClientScript::POS_HEAD;
  206. /**
  207. *
  208. * @var string default media type, defualt empty meaning all media types
  209. */
  210. public $defaultMedia = '';
  211. /**
  212. * @var boolean, set to true if assets should be shared among other extensions
  213. */
  214. public $share = false;
  215. /**
  216. * used internally to initialize bahavior
  217. */
  218. private function initBehavior( )
  219. {
  220. $this->buildPaths( );
  221. }
  222. /**
  223. *
  224. * @param string $key key taken from array {@link otherResToPublish}
  225. * Other avaliable keys are {basePath} {assets} {css} {js}
  226. * @return string to published resource or false if published file not found
  227. */
  228. public function getPublished( $key )
  229. {
  230. return isset( $this->_published[$key] ) ? $this->_published[$key] : false;
  231. }
  232. /**
  233. * Used internal, build paths, by replacing placeholders {@link assetsPath}, {@link cssPath} and {@link jsPath}
  234. */
  235. protected function buildPaths( )
  236. {
  237. if ( $this->_pathsGenerated === false )
  238. {
  239. #set defualts value if needed
  240. if ( $this->assetsPath === null )
  241. $this->assetsPath = '{basePath}{/}assets';
  242. if ( $this->cssPath === null )
  243. $this->cssPath = '{assets}{/}css';
  244. if ( $this->jsPath === null )
  245. $this->jsPath = '{assets}{/}js';
  246. #create real paths when placeholders used
  247. $this->_paths['assets'] = strtr( $this->assetsPath, $this->getTr( ) );
  248. $this->_cssPathTemplate = ( substr_count( $this->cssPath , '{assets}' ) > 0 ) ? $this->cssPath : null;
  249. $this->_paths['css'] = strtr( $this->cssPath , $this->getTr( ) );
  250. $this->_jsPathTemplate = ( substr_count( $this->jsPath , '{assets}' ) > 0 ) ? $this->jsPath : null;
  251. $this->_paths['js'] = strtr( $this->jsPath , $this->getTr( ) );
  252. $this->_pathsGenerated = true;
  253. }
  254. }
  255. /**
  256. * publish Yii core scripts
  257. */
  258. public function registerCoreScripts( )
  259. {
  260. if ( empty( $this->coreScriptsToRegister ) )
  261. Yii::trace( Yii::t( 'aii-publish-register-behavior' , 'No core scripts to register' ) );
  262. else
  263. {
  264. foreach ( $this->coreScriptsToRegister as $coreScript )
  265. {
  266. Yii::app()->clientScript->registerCoreScript( $coreScript );
  267. Yii::trace( Yii::t( 'aii-publish-register-behavior' , 'Core script "{script}" registered.' , array( '{script}' => $coreScript ) ) );
  268. }
  269. }
  270. }
  271. /**
  272. * Register JS scripts, CSS files and core scripts
  273. * If needed files are not published, implicit publishing is done
  274. */
  275. public function registerAll( )
  276. {
  277. $this->registerCoreScripts( );
  278. $this->registerCssFiles( );
  279. $this->registerJsFiles( );
  280. }
  281. /**
  282. * All css files form {@link cssToRegister} are registered
  283. * If {@link cssPath} is not published it is published here
  284. * If {@link cssPath} is a subfolder of {@link assetsPath} the later is published
  285. * @return boolean, false if there is nothing to register
  286. */
  287. public function registerCssFiles( )
  288. {
  289. if ( !empty( $this->cssToRegister ) && $this->publishCssFiles( ) )
  290. {
  291. #register all CSS files
  292. foreach ( $this->cssToRegister as $cssFile )
  293. {
  294. #css file name
  295. $cssFileName = is_string( $cssFile ) ? $cssFile : $cssFile['name'];
  296. #position where it should ne registered
  297. $media = is_array( $cssFile ) && isset( $cssFile['media'] ) ? $cssFile['media'] : $this->defaultMedia;
  298. #published resource
  299. $cssPubFile = $this->_published['{css}'].'/'.$cssFileName;
  300. if ( !Yii::app()->clientScript->isCssFileRegistered( $cssPubFile , $media ) )
  301. {
  302. Yii::app()->clientScript->registerCssFile( $cssPubFile , $media );
  303. Yii::trace(
  304. Yii::t( 'aii-publish-register-behavior' ,
  305. 'Css file "{css}" was registered as {registered}.' ,
  306. array( '{css}' => $cssFileName , '{registered}' => $cssPubFile,
  307. ) ) );
  308. }
  309. }
  310. return true;
  311. }
  312. else
  313. return false;
  314. }
  315. /**
  316. * All js files form {@link jsToRegister} are registered
  317. * If {@link jsPath} is not published it is published here
  318. * If {@link jsPath} is a subfolder of {@link assetsPath} the later is published
  319. * @return boolean, false if nothing were registered
  320. */
  321. public function registerJsFiles( )
  322. {
  323. if ( !empty( $this->jsToRegister ) && $this->publishJsFiles( ) )
  324. {
  325. #register all JS files
  326. foreach ( $this->jsToRegister as $jsFile => $pos )
  327. {
  328. #js file name
  329. $jsFileName = empty( $pos ) || is_integer( $jsFile ) ? $pos : $jsFile;
  330. #position where it should ne registered
  331. $jsPos = empty( $pos ) || is_integer( $jsFile ) ? $this->jsDefaultPos : $pos;
  332. #published resource
  333. $jsPubFile = $this->_published['{js}'].'/'.$jsFileName;
  334. if ( !Yii::app()->clientScript->isScriptRegistered( $jsPubFile , $jsPos ) )
  335. {
  336. Yii::app()->getClientScript( )->registerScriptFile( $jsPubFile , $jsPos );
  337. Yii::trace(
  338. Yii::t( 'aii-publish-register-behavior' ,
  339. 'JS file "{js}" was registered as {registered}.' ,
  340. array( '{js}' => $jsFileName , '{registered}' => $jsPubFile,
  341. ) ) );
  342. }
  343. }
  344. return true;
  345. }
  346. return false;
  347. }
  348. /**
  349. * Publish all files in from directory specified in {@link assetsPath}
  350. * Published resource is available via placeholder {assets}
  351. * @return string published path
  352. */
  353. public function publishAssets( )
  354. {
  355. if ( $this->checkIsPublished( self::ASSETS_PUBLISHED ) === false )
  356. {
  357. $tr = $this->getTr( );
  358. $this->updateStatus( self::ASSETS_PUBLISHED );
  359. $this->_published['{assets}'] = CHtml::asset( strtr( $this->assetsPath , $tr ), $this->share );
  360. }
  361. return isset( $this->_published['{assets}'] ) ? $this->_published['{assets}'] : false;
  362. }
  363. /**
  364. * Publish CSS fiels path. In case CSS file path is in reference to {@link assetsPath}
  365. * this methiod publish them if they are not published yet.
  366. * Note that assets reference is recognized by {assets} placeholder
  367. * @return string or false; published CSS files path or false if nothing to publish
  368. */
  369. public function publishCssFiles( )
  370. {
  371. $this->initBehavior( );
  372. #if css files path was not set, do nothing
  373. if ( $this->cssPath === false )
  374. return false;
  375. if ( !$this->checkIsPublished( self::CSS_PUBLISHED ) )
  376. {
  377. #if cssPath has {assets} placeholder publish all assets
  378. if ( $this->_cssPathTemplate )
  379. {
  380. $this->publishAssets( );
  381. $this->_published['{css}'] = strtr( $this->_cssPathTemplate , $this->getTr( ) );
  382. }
  383. #publish "traditional" way
  384. else
  385. $this->_published['{css}'] = CHtml::asset( $this->cssPath , $this->share );
  386. }
  387. #check if user sets already published css files path
  388. elseif ( !isset ( $this->_published['{css}'] ) )
  389. $this->_published['{css}'] = $this->cssPath;
  390. $this->updateStatus( self::CSS_PUBLISHED );
  391. return $this->_published['{css}'];
  392. }
  393. /**
  394. * Publish JS files path. In case JS file path is in reference to {@link assetsPath}
  395. * this methiod publish them if they are not published yet.
  396. * Note that assets reference is recognized by {assets} placeholder
  397. * @return string or false; published JS files path or false if nothing to publish
  398. */
  399. public function publishJsFiles( )
  400. {
  401. $this->initBehavior( );
  402. #if js files path was not set, do nothing
  403. if ( $this->jsPath === false )
  404. return false;
  405. if ( !$this->checkIsPublished( self::JS_PUBLISHED ) )
  406. {
  407. #if jsPath has {assets} placeholder publish all assets
  408. if ( $this->_jsPathTemplate )
  409. {
  410. $this->publishAssets( );
  411. $this->_published['{js}'] = strtr( $this->_jsPathTemplate , $this->getTr( ) );
  412. }
  413. #publish "traditional" way
  414. else
  415. $this->_published['{js}'] = CHtml::asset( $this->jsPath , $this->share );
  416. }
  417. #check if user sets already published js files path
  418. elseif ( !isset ( $this->_published['{js}'] ) )
  419. $this->_published['{js}'] = $this->jsPath;
  420. $this->updateStatus( self::JS_PUBLISHED );
  421. return $this->_published['{js}'];
  422. }
  423. /**
  424. * Publish resources from {@link otherResToPublish}
  425. * @return boolean false if nothing was published
  426. */
  427. public function publishResources( )
  428. {
  429. $this->initBehavior( );
  430. #start only if resources was not published
  431. if ( !$this->checkIsPublished( self::OTHERS_PUBLISHED ) )
  432. {
  433. if ( empty ( $this->otherResToPublish ) )
  434. {
  435. Yii::trace( Yii::t( 'aii-publish-register-behavior', 'There are no resources to publish.' ) );
  436. return false;
  437. }
  438. else
  439. {
  440. foreach ( $this->otherResToPublish as $key => $res )
  441. {
  442. $this->_published[$key] = CHtml::asset( strtr( $res , $this->getTr( ) ) , $this->share );
  443. Yii::trace( Yii::t( 'aii-publish-register-behavior' , 'Resource "{res}" published as {published}.' , array( '{res}' => $res , '{published}' => $this->getPublished( $key ) ) ) );
  444. }
  445. $this->updateStatus( self::OTHERS_PUBLISHED );
  446. }
  447. }
  448. return true;
  449. }
  450. /**
  451. * This method publish files from all specified path (assets, css, js, resources)
  452. */
  453. public function publishAll( )
  454. {
  455. $this->publishResources( );
  456. $this->publishAssets( );
  457. $this->publishCssFiles( );
  458. $this->publishJsFiles( );
  459. }
  460. /**
  461. * Check if resource is published
  462. * @param integer $level resource level number
  463. * @return boolean, true if particular resource is published
  464. */
  465. public function checkIsPublished( $level = null )
  466. {
  467. if ( $level === null )
  468. return ( $this->publishingStatus === ( self::INITIAL + self::JS_PUBLISHED + self::CSS_PUBLISHED + self::ASSETS_PUBLISHED + self::OTHERS_PUBLISHED ) );
  469. elseif ( ( $level % 2 ) !== 0 )
  470. throw new CException( Yii::t( 'aii-publish-register-behavior' , 'Level need to be power of 2!' ) );
  471. return floor( $this->publishingStatus / $level ) % 2 === 1;
  472. }
  473. /**
  474. * updates publishing status
  475. * @param integer $level resource level number
  476. */
  477. public function updateStatus( $level )
  478. {
  479. $this->publishingStatus += $level;
  480. }
  481. /**
  482. * @return array array used in strtr function to replace placeholders with real values
  483. */
  484. private function getTr( )
  485. {
  486. $tr = array( );
  487. $tr['{/}'] = DIRECTORY_SEPARATOR;
  488. $tr['{basePath}'] = $this->basePath;
  489. if ( $this->checkIsPublished( self::JS_PUBLISHED ) )
  490. $tr['{js}'] = $this->_published['{js}'];
  491. if ( $this->checkIsPublished ( self::CSS_PUBLISHED ) )
  492. $tr['{css}'] = $this->_published['{css}'];
  493. if ( $this->checkIsPublished ( self::ASSETS_PUBLISHED ) )
  494. $tr['{assets}'] = $this->_published['{assets}'];
  495. return $tr;
  496. }
  497. }
  498. ?>