PageRenderTime 25ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/install/sync.php

https://gitlab.com/billyprice1/Addon-Frontend
PHP | 251 lines | 200 code | 20 blank | 31 comment | 86 complexity | 43c601264919aca5fb0157a672b50a7d MD5 | raw file
  1. <?php
  2. // protect script from unauthorized calls
  3. $basePath = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
  4. require_once($basePath . 'includes/configuration.php');
  5. require_once($basePath . 'includes/functions.php');
  6. checkAdminAccess();
  7. // ############## Include Files ################ //
  8. require_once($basePath . 'includes/db_connection.php');
  9. // ############## Finish Includes ############### //
  10. if (isset($configuration['repositories']) && is_array($configuration['repositories']) && count($configuration['repositories'])) {
  11. $consoleLog = array('Begin of import: ' . date('l jS \of F Y h:i:s A'));
  12. $error = FALSE;
  13. $checkDependencies = isset($configuration['dependencies']) && count($configuration['dependencies']) ? TRUE : FALSE;
  14. // cache existing addon-IDs
  15. $result = $db->get_results('SELECT id, version, deleted FROM addon');
  16. $addonCache = array(
  17. 'processed' => array(),
  18. 'existing' => array()
  19. );
  20. if ($result) {
  21. foreach ($result as $addon) {
  22. $addonCache['existing'][$addon->id] = $addon;
  23. }
  24. }
  25. // import addons from each repository
  26. foreach($configuration['repositories'] as $repositoryId => $repositoryConfiguration) {
  27. # Check the XML exists
  28. if (isset($repositoryConfiguration['xmlUrl']) && $repositoryConfiguration['xmlUrl']) {
  29. $repositoryXmlUrl = $repositoryConfiguration['xmlUrl'];
  30. } else {
  31. $repositoryXmlUrl = $repositoryConfiguration['dataUrl'] . 'addons.xml';
  32. }
  33. try {
  34. $xml = simplexml_load_file($repositoryXmlUrl);
  35. } catch(Exception $e) {}
  36. if (!$xml || !isset($xml->addon['id'])) {
  37. $error = TRUE;
  38. $consoleLog[] = 'Error while reading repository ' . $repositoryConfiguration['xmlUrl'];
  39. continue;
  40. }
  41. $counter = 0;
  42. $counterUpdated = 0;
  43. $counterNewlyAdded = 0;
  44. // Loop through each addon
  45. foreach ($xml->addon as $addon) {
  46. $counter++;
  47. $description = '';
  48. $name = removeKodiFormatting($addon['name']);
  49. $summary = '';
  50. $forum = '';
  51. $source = '';
  52. $website = '';
  53. $license = '';
  54. $author = '';
  55. $id = (string) $addon['id'];
  56. $broken = '';
  57. $extensionPoint = '';
  58. $contentTypes = array();
  59. $platforms = array();
  60. $languages = array();
  61. $meetsRequirements = TRUE;
  62. foreach ($addon->children() as $nodeName => $node) {
  63. // only import if requirements are met
  64. if ($checkDependencies && $nodeName == 'requires' && $node->children()) {
  65. foreach($node->children() as $childName => $childNode) {
  66. if ($childName == 'import') {
  67. $dependency = (string)$childNode['addon'];
  68. $version = (string)$childNode['version'];
  69. if (isset($configuration['dependencies'][$dependency])
  70. && version_compare($version, $configuration['dependencies'][$dependency], '>=') === FALSE)
  71. {
  72. $meetsRequirements = FALSE;
  73. break;
  74. }
  75. }
  76. }
  77. if (!$meetsRequirements) {
  78. break;
  79. }
  80. }
  81. if ($nodeName == 'extension') {
  82. // grab extension point and content types
  83. if ($node['point'] != 'xbmc.addon.metadata') {
  84. // don't overwrite primary/first extension point
  85. if ($extensionPoint == '') {
  86. $extensionPoint = $node['point'];
  87. }
  88. $type = $node['point'];
  89. if ($node->children()) {
  90. foreach($node->children() as $childName => $childNode) {
  91. if ($childName == 'provides') {
  92. $contentTypes = array_merge($contentTypes, explode(' ', trim((string) $childNode)));
  93. }
  94. }
  95. }
  96. // convert rarely used extensions points to common ones
  97. if ($extensionPoint == 'xbmc.addon.video') {
  98. $contentTypes[] = 'video';
  99. }
  100. if ($extensionPoint == 'xbmc.addon.audio') {
  101. $contentTypes[] = 'audio';
  102. }
  103. if ($extensionPoint == 'xbmc.addon.image') {
  104. $contentTypes[] = 'image';
  105. }
  106. // move scripts with no "provides" data to "executable"
  107. if ($extensionPoint == 'xbmc.python.script' && !count($contentTypes)) {
  108. if (strpos($id, 'script.game') !== FALSE) {
  109. $contentTypes[] = 'game';
  110. } else {
  111. $contentTypes[] = 'executable';
  112. }
  113. }
  114. // grab metadata
  115. } else if ($node['point'] == 'xbmc.addon.metadata' && $node->children()) {
  116. foreach ($node->children() as $subNodeName => $subNode) {
  117. // Check for the Forum XML Subnode
  118. if ($subNodeName == 'forum') {
  119. $forum = $subNode;
  120. }
  121. // Check for the Website XML Subnode
  122. if ($subNodeName == 'website') {
  123. $website = $subNode;
  124. }
  125. // Check for the Source XML Subnode
  126. if ($subNodeName == 'source') {
  127. $source = $subNode;
  128. }
  129. // Check for the License XML Subnode
  130. if ($subNodeName == 'license') {
  131. $license = $subNode;
  132. }
  133. // Check for broken status
  134. if ($subNodeName == 'broken') {
  135. $broken = $subNode;
  136. }
  137. // Check for the Description XML Subnode
  138. if ($subNodeName == 'description'
  139. && ($subNode['lang'] == 'en' || !isset($subNode['lang']) ) )
  140. {
  141. $description = removeKodiFormatting($subNode);
  142. }
  143. // Check for the Summary XML Subnode
  144. if ($subNodeName == 'summary'
  145. && ($subNode['lang'] == 'en' || !isset($subNode['lang']) ) )
  146. {
  147. $summary = removeKodiFormatting($subNode);
  148. }
  149. // Check for platform status
  150. if ($subNodeName == 'platform') {
  151. $platforms = array_unique(array_merge($platforms, explode(' ', trim((string) $subNode))));
  152. }
  153. // Check for languages
  154. if ($subNodeName == 'language') {
  155. $langs = explode(' ', trim(str_replace(',', ' ', (string) $subNode)));
  156. foreach ($langs as $k => $l) {
  157. if (strlen($l) != 2) {
  158. unset($langs[$k]);
  159. }
  160. }
  161. $languages = array_unique(array_merge($languages, $langs));
  162. }
  163. }
  164. // Merge the description and summary variables
  165. if ($description == '' && $summary) {
  166. $description = $summary;
  167. }
  168. }
  169. }
  170. }
  171. if (!$meetsRequirements) {
  172. continue;
  173. }
  174. // unify format of multiple authors
  175. $author = strtr(removeKodiFormatting($addon['provider-name']), array('|' => ',', ';' => ',', '&amp;' => ',', ', ' => ','));
  176. $contentTypes = array_unique($contentTypes);
  177. $cacheAddonData = FALSE;
  178. //Check here to see if the Item already exists
  179. $previousVersion = FALSE;
  180. if (isset($addonCache['existing'][$id])) {
  181. $previousVersion = $addonCache['existing'][$id];
  182. } else if (isset($addonCache['processed'][$id])) {
  183. $previousVersion = $addonCache['processed'][$id];
  184. }
  185. if ($previousVersion) {
  186. //Item exists
  187. //Check here to see if the addon needs to be updated
  188. $updateQuery = ' deleted = 0, name = "' . $db->escape($name) . '", provider_name = "' . $db->escape($author) . '", description = "' . $db->escape($description) . '", forum = "' . $db->escape($forum) . '", website = "' . $db->escape($website) . '", source = "' . $db->escape($source) . '", license = "' . $db->escape($license) . '", extension_point="' . $extensionPoint . '", content_types="' . implode(',', $contentTypes) . '", broken="' . $db->escape($broken) . '", repository_id="' . $db->escape($repositoryId) . '", platforms="' . implode(',', $platforms) . '", languages="' . implode(',', $languages) . '"';
  189. // only update timestamp on new version
  190. if (version_compare($addon['version'], $previousVersion->version, '>')) {
  191. $counterUpdated++;
  192. $updateQuery .= ', version = "' . $db->escape($addon['version']) . '", updated = NOW() ';
  193. deleteAddonCache($id);
  194. $cacheAddonData = TRUE;
  195. }
  196. $db->query('UPDATE addon SET ' . $updateQuery . ' WHERE id = "' . $db->escape($id) . '"');
  197. // Add a new add-on if it doesn't exist
  198. } else {
  199. $counterNewlyAdded++;
  200. $query = 'INSERT INTO addon (id, name, provider_name, version, description, created, updated, forum, website, source, license, extension_point, content_types, broken, deleted, repository_id, platforms, languages) ';
  201. $query .= 'VALUES ("' . $db->escape($id) . '", "' . $db->escape($name) . '", "' . $db->escape($author) . '", "' . $db->escape($addon['version']) . '", "' . $db->escape($description) . '", NOW(), NOW(), "' . $db->escape($forum) . '", "' . $db->escape($website) . '", "' . $db->escape($source) . '", "' . $db->escape($license) . '", "' . $extensionPoint . '", "' . implode(',', $contentTypes) . '", "' . $db->escape($broken) . '", 0, "' . $db->escape($repositoryId) . '", "' . implode(',', $platforms) . '", "' . implode(',', $languages) . '")';
  202. $db->query($query);
  203. $cacheAddonData = TRUE;
  204. }
  205. // only scrape artwork if required
  206. if ($cacheAddonData) {
  207. cacheAddonData($id, $repositoryId);
  208. }
  209. $addonCache['processed'][$id] = $addon;
  210. }
  211. $consoleLog[] = 'Repository: ' . $repositoryConfiguration['name'] . ' - Total ' . $counter . ', ' . $counterUpdated . ' Updated, ' . $counterNewlyAdded . ' New';
  212. }
  213. if (!$error) {
  214. // mark addons no longer part of repo xml as deleted
  215. $orphaned = array_diff(array_keys($addonCache['existing']), array_keys($addonCache['processed']));
  216. $removedAddons = array();
  217. foreach ($orphaned as $addonId) {
  218. if (isset($addonCache['existing'][$addonId]) && (bool) $addonCache['existing'][$addonId]->deleted == FALSE) {
  219. $removedAddons[] = $db->escape($addonId);
  220. }
  221. }
  222. if (count($removedAddons)) {
  223. $db->query('UPDATE addon SET deleted = 1 WHERE id IN ("' . implode('","', $removedAddons) . '")');
  224. }
  225. $consoleLog[] = 'Import finished: ' . date('l jS \of F Y h:i:s A') . ' - ' . count($removedAddons) . ' orphaned addons removed';
  226. } else {
  227. $consoleLog[] = 'Import abortet: ' . date('l jS \of F Y h:i:s A') . ' - an error occured during import';
  228. }
  229. echo implode(" | ", $consoleLog);
  230. }
  231. ?>