BxDolEmbed.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaCore UNA Core
  7. * @{
  8. */
  9. /**
  10. * Embed provider.
  11. *
  12. * Create an embed from a link.
  13. *
  14. * @section embed_provider_create Creating the Editor object:
  15. *
  16. *
  17. * Add record to 'sys_objects_embeds' table:
  18. *
  19. * - object: name of the embed object, in the format: vendor prefix, underscore, module prefix, underscore, internal identifier or nothing
  20. * - title: title of the embed provider, dmay be isplayed in the Studio.
  21. * - override_class_name: user defined class name which is derived from one of base embed provider classes.
  22. * - override_class_file: the location of the user defined class, leave it empty if class is located in system folders.
  23. *
  24. *
  25. * @section example Example of usage
  26. *
  27. * Generate HTML for a link which will be converted to an embed later:
  28. *
  29. * @code
  30. * $oEmbed = BxDolEmbed::getObjectInstance(); // get default embed object instance
  31. * if ($oEmbed) // check if embed provider is available for using
  32. * echo $oEmbed->getLinkHTML ('https://una.io', 'UNA.IO'); // output HTML which will be automatically converted into embed upon page load
  33. * else
  34. * echo '<a href="https://una.io">UNA.IO</a>';
  35. * @endcode
  36. *
  37. */
  38. class BxDolEmbed extends BxDolFactoryObject
  39. {
  40. protected $_bAsync = false;
  41. protected $_sSocketName = 'sys_embed';
  42. protected $_sTableData = '';
  43. protected $_iLifetime;
  44. protected $_bCssJsAdded = false;
  45. public function __construct ($aObject, $oTemplate = null)
  46. {
  47. parent::__construct($aObject, $oTemplate, 'BxDolEmbedQuery');
  48. $this->_oDb->setParams([
  49. 'table_data' => $this->_sTableData
  50. ]);
  51. $this->_iLifetime = 86400 * (int)getParam('sys_embed_lifetime');
  52. }
  53. /**
  54. * Get embed provider object instance by object name
  55. * @param $sObject object name
  56. * @return object instance or false on error
  57. */
  58. static public function getObjectInstance($sObject = false, $oTemplate = false)
  59. {
  60. if (!$sObject)
  61. $sObject = getParam('sys_embed_default');
  62. return parent::getObjectInstanceByClassNames($sObject, $oTemplate, 'BxDolEmbed', 'BxDolEmbedQuery');
  63. }
  64. /**
  65. * Print HTML which will be automatically converted into embed upon page load
  66. * @param $sLink - link
  67. * @param $sTitle - title or use link for the title if omitted
  68. * @param $sMaxWidth - try to restrict max width of embed (works in supported embed providers only)
  69. */
  70. public function getLinkHTML ($sLink, $sTitle = '', $sMaxWidth = '')
  71. {
  72. // override this function in particular embed provider class
  73. }
  74. /**
  75. * Execute an initialization JS code
  76. */
  77. public function addProcessLinkMethod ()
  78. {
  79. // override this function in particular embed provider class
  80. return '';
  81. }
  82. /**
  83. * Add css/js files which are needed for embed display and functionality.
  84. */
  85. public function addJsCss ()
  86. {
  87. // override this function in particular embed provider class
  88. }
  89. public function getData ($sUrl, $sTheme, $bForcedly = false)
  90. {
  91. $sUrl = $this->cleanYoutubeUrl($sUrl);
  92. if($this->_sTableData) {
  93. $aLocal = $this->_oDb->getLocalInfo($sUrl, $sTheme);
  94. $bRevalidate = false;
  95. if($this->_iLifetime && ($iAdded = (int)($aLocal['added'] ?? 0)) && $iAdded + $this->_iLifetime < time()) {
  96. $this->_oDb->deleteLocal([
  97. 'url' => $sUrl,
  98. 'theme' => $sTheme
  99. ]);
  100. $bRevalidate = true;
  101. }
  102. $sData = false;
  103. if($bRevalidate || (($sKey = 'data') && !($sData = $aLocal[$sKey] ?? false)))
  104. $sData = $this->{'_getData' . ($sData !== false ? 'Empty' : ($this->_bAsync && !$bForcedly ? 'Async' : ''))}($sUrl, $sTheme);
  105. }
  106. else
  107. $sData = $this->_getData($sUrl, $sTheme);
  108. return json_decode($sData, true);
  109. }
  110. public function getDataFromApi ($sUrl, $sTheme)
  111. {
  112. // override this function in particular embed provider class
  113. }
  114. public function onGetDataFromApi ($iId)
  115. {
  116. // override this function in particular embed provider class
  117. }
  118. public function process ()
  119. {
  120. $aEmbeds = $this->_oDb->getLocalUnprocessed();
  121. if(empty($aEmbeds) || !is_array($aEmbeds))
  122. return;
  123. $oSockets = BxDolSockets::getInstance();
  124. $bSockets = $oSockets->isEnabled();
  125. foreach($aEmbeds as $aEmbed)
  126. if(($sData = $this->getDataFromApi($aEmbed['url'], $aEmbed['theme']))) {
  127. $this->_oDb->updateLocal(['data' => $sData], ['id' => $aEmbed['id']]);
  128. $this->onGetDataFromApi($aEmbed['id']);
  129. if($bSockets)
  130. $oSockets->sendEvent($this->_sSocketName, $aEmbed['id'], 'processed', $sData);
  131. }
  132. }
  133. public function cleanYoutubeUrl($url)
  134. {
  135. $parsedUrl = parse_url($url);
  136. if (isset($parsedUrl['host']) && $parsedUrl['host'] === 'youtu.be') {
  137. if (isset($parsedUrl['query'])) {
  138. parse_str($parsedUrl['query'], $queryParams);
  139. if (isset($queryParams['si'])) {
  140. unset($queryParams['si']);
  141. }
  142. $queryString = http_build_query($queryParams);
  143. $cleanUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . $parsedUrl['path'];
  144. if (!empty($queryString)) {
  145. $cleanUrl .= '?' . $queryString;
  146. }
  147. return $cleanUrl;
  148. }
  149. return $url;
  150. }
  151. return $url;
  152. }
  153. protected function _getData($sUrl, $sTheme)
  154. {
  155. $sData = $this->getDataFromApi($sUrl, $sTheme);
  156. if($sData) {
  157. $iId = $this->_oDb->insertLocal($sUrl, $sTheme, $sData);
  158. $this->onGetDataFromApi($iId);
  159. }
  160. return $sData;
  161. }
  162. protected function _getDataAsync($sUrl, $sTheme)
  163. {
  164. $iId = $this->_oDb->insertLocal($sUrl, $sTheme);
  165. if(($sName = 'bx_embed_processing') && ($oCronQuery = BxDolCronQuery::getInstance()) && !$oCronQuery->isTransientJobService($sName))
  166. $oCronQuery->addTransientJobService($sName, ['system', 'process_embed', [], 'TemplServices']);
  167. return $this->_getDataEmpty($sUrl, $sTheme, [
  168. 'id' => $iId,
  169. 'processing' => true
  170. ]);
  171. }
  172. protected function _getDataEmpty($sUrl, $sTheme, $aAddons = [])
  173. {
  174. return json_encode(array_merge([
  175. 'url' => $sUrl,
  176. 'domain' => parse_url($sUrl, PHP_URL_HOST),
  177. ], $aAddons));
  178. }
  179. }
  180. /** @} */