PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/elgg_language_packs.php

https://bitbucket.org/moodsdesign-ondemand/elgg_language_packs
PHP | 423 lines | 318 code | 23 blank | 82 comment | 113 complexity | b63fb74615954c1dc4932d52d97f06e4 MD5 | raw file
  1. <?php
  2. /*
  3. * This file contains common methods for both the
  4. * Elgg Language Packs plugin and the
  5. * GlotPress Elgg hack for ElggTranslate.com
  6. */
  7. define('ELGGLP_VERSION', '1.0.0');
  8. define('ELGGLP_OK', -1);
  9. define('ELGGLP_ERR_STRUCTURE', 1);
  10. define('ELGGLP_ERR_VERSION', 2);
  11. function elgglp_create_languagepack_meta($meta, $filters) {
  12. // copy filter options used here into local variables
  13. $dstdir = $filters['dst_dir'];
  14. // if there no meta info yet, create an empty array
  15. if ( !is_array($meta) ) $meta = array();
  16. // add Elgg version to metadata
  17. $meta['elgg_version'] = $filters['elgg_release'];
  18. // add plugin version to metadata
  19. $meta['languagepack_version'] = ELGGLP_VERSION;
  20. // json-encode the meta info
  21. $contents = json_encode($meta);
  22. // write to language pack meta file
  23. file_put_contents("$dstdir/languagepack.meta", $contents);
  24. }
  25. function elgglp_create_languagemod_meta($meta, $filters) {
  26. // work out the destination folder
  27. $dstdir = $filters['dst_dir'];
  28. if ( $meta['unique'] == 'install' ) {
  29. $dstdir = "$dstdir/install";
  30. } else if ( $meta['unique'] != 'core' ) {
  31. $dstdir = "$dstdir/mod/$meta[unique]";
  32. }
  33. // create directory if necessary
  34. @mkdir("$dstdir/languages", 0777, true);
  35. // json-encode the meta info
  36. $contents = json_encode($meta);
  37. // write to language mod meta file
  38. file_put_contents("$dstdir/languages/languagemod.meta", $contents);
  39. }
  40. function elgglp_check_language_pack($dir, &$elgg_version, &$languagepack_version, $check_meta = true) {
  41. // if anything goes wrong, we return false for both out params
  42. $elgg_version = false;
  43. $languagepack_version = false;
  44. // install directory exists and has languages/ directory?
  45. $install = file_exists("$dir/install/languages") && is_dir("$dir/install/languages");
  46. // root directory has languages/ directory?
  47. $core = file_exists("$dir/languages") && is_dir("$dir/languages");
  48. // mod directory exists?
  49. $mod = file_exists("$dir/mod") && is_dir("$dir/mod");
  50. // need to check for language pack meta?
  51. if ( $check_meta ) {
  52. // we are looking at a language pack proper
  53. $meta = file_exists("$dir/languagepack.meta") && is_file("$dir/languagepack.meta");
  54. if ( $meta ) {
  55. $meta = json_decode(file_get_contents("$dir/languagepack.meta"), true);
  56. $elgg_version = $meta['elgg_version'];
  57. $languagepack_version = $meta['languagepack_version'];
  58. }
  59. } else {
  60. // we must be looking at an Ellg product folder
  61. $meta = file_exists("$dir/version.php") && is_file("$dir/version.php");
  62. if ( $meta ) {
  63. include "$dir/version.php";
  64. $elgg_version = $release;
  65. $languagepack_version = ELGGLP_VERSION;
  66. }
  67. }
  68. // return result
  69. return $install && $core && $mod && $meta;
  70. }
  71. function elgglp_read_languagemod_meta($src_dir) {
  72. $meta_name = "$src_dir/languages/languagemod.meta";
  73. if ( !file_exists($meta_name) ) return false;
  74. $meta_contents = file_get_contents($meta_name);
  75. $info = json_decode($meta_contents, true);
  76. $slug = basename($src_dir);
  77. if ( $info['unique'] == $slug ) {
  78. return $info;
  79. } else {
  80. return false;
  81. }
  82. }
  83. function elgglp_read_plugin_manifest($src_dir) {
  84. if ( !file_exists("$src_dir/languages") ) return false;
  85. $manifest_name = "$src_dir/manifest.xml";
  86. if ( !file_exists($manifest_name) ) return false;
  87. $manifest_contents = file_get_contents($manifest_name);
  88. try {
  89. $manifest = new SimpleXMLElement($manifest_contents);
  90. } catch ( Exception $e ) {
  91. error_log("elgglp_read_manifest: $manifest_name not valid");
  92. return false;
  93. }
  94. $slug = basename($src_dir);
  95. $info = array(
  96. 'name' => (string)$manifest->name,
  97. 'version' => (string)$manifest->version,
  98. 'description' => (string)$manifest->description,
  99. 'unique' => $slug,
  100. );
  101. return $info;
  102. }
  103. /**
  104. * Creates a directory with a unique directory name.
  105. *
  106. * @param string|boolean $dir The directory under which the new directory should be created. If empty, the system temporary folder will be used
  107. * @param string $prefix A prefix to prepended to the generated directory name. If empty, no prefix will be added
  108. * @return string|boolean The name of the newly created directory, of false if a directory could not be created
  109. */
  110. function elgglp_tempdir($dir = false, $prefix = '') {
  111. if ( !$dir ) $dir = sys_get_temp_dir();
  112. if ( ($tempfile = tempnam($dir, $prefix)) ) {
  113. unlink($tempfile);
  114. if ( mkdir($tempfile) ) {
  115. return $tempfile;
  116. }
  117. }
  118. return false;
  119. }
  120. function elgglp_copy_languagemod($meta, $srcdir, $filters) {
  121. if ( @elgglp_copy_languages($meta, $srcdir, $filters) ) {
  122. if ( $filters['needs_manifest'] ) {
  123. @elgglp_create_languagemod_meta($meta, $filters);
  124. }
  125. }
  126. }
  127. function elgglp_copy_languages($meta, $srcdir, $filters) {
  128. return elgglp_recurse_languages($meta, $srcdir, $filters, 'elgglp_copy_file');
  129. }
  130. function elgglp_delete_file($meta, $file, $lang, $filters) {
  131. return unlink($file);
  132. }
  133. function elgglp_delete_languages($meta, $srcdir, $filters) {
  134. return elgglp_recurse_languages($meta, $srcdir, $filters, 'elgglp_delete_file');
  135. }
  136. function elgglp_recurse_languages($meta, $srcdir, $filters, $callback) {
  137. // copy filter options used here into local variables
  138. $langs = @$filters['langs'];
  139. $ignore_en = (bool)@$filters['ignore_en'];
  140. $return = $filters['return_array'];
  141. if ( $return || !$callback ) {
  142. // initialise the array for the list of detected languages
  143. $found = array();
  144. } else {
  145. // keep track of whether any file was copied from this folder
  146. $found = false;
  147. }
  148. // get all the files that match an Elgg language file and iterate
  149. $all_files = array_merge(glob("$srcdir/languages/??.php"), glob("$srcdir/languages/??[-_]??.php"));
  150. foreach ( $all_files as $file ) {
  151. // basic name of the file is the locale name
  152. $lang = basename($file, '.php');
  153. // should the current locale be filtered out?
  154. if ( $langs && !in_array($lang, $langs) ) {
  155. continue;
  156. }
  157. // should we ignore this if it is the original English file?
  158. if ( $ignore_en && $lang == 'en' ) {
  159. continue;
  160. }
  161. if ( $return || !$callback ) {
  162. $found[$lang] = $file;
  163. } else {
  164. if ( @call_user_func($callback, $meta, $file, $lang, $filters) ) {
  165. $found = true;
  166. }
  167. }
  168. }
  169. // all done in this folder
  170. return $found;
  171. }
  172. function elgglp_copy_file($meta, $file, $lang, $filters) {
  173. // copy filter options used here into local variables
  174. $dstdir = $filters['dst_dir'];
  175. $needs_meta = $filters['$needs_meta'];
  176. // work out the destination folder
  177. if ( $meta['unique'] == 'install' ) {
  178. $dstdir = "$dstdir/install";
  179. } else if ( $meta['unique'] != 'core' ) {
  180. $dstdir = "$dstdir/mod/$meta[unique]";
  181. }
  182. // if plugin directory is not there, skip this if importing
  183. if ( $needs_meta && !file_exists($dstdir) ) {
  184. return false;
  185. }
  186. // if there is not a JavaScript file for this language, create it if importing
  187. $jsfile = "$dstdir/views/default/js/languages/$lang.php";
  188. if ( $needs_meta && !file_exists($jsfile) ) {
  189. //@mkdir("$dstdir/views/default/js/languages", 0777, true);
  190. $jscode = "<?php
  191. echo elgg_view('js/languages', array('language' => '$lang'));
  192. ";
  193. file_put_contents($jsfile, $jscode);
  194. }
  195. // copy filter options used here into local variables
  196. $overwrite = (bool)@$filters['overwrite'];
  197. // the destination file we should write to
  198. $to_file = "$dstdir/languages/" . basename($file);
  199. // if it exists already, can we overwrite it?
  200. if ( !$overwrite && file_exists($to_file) ) {
  201. return false;
  202. }
  203. // create the folder if it does not exist
  204. if ( !file_exists("$dstdir/languages") ) {
  205. @mkdir("$dstdir/languages", 0777, true);
  206. }
  207. // copy the file
  208. if ( @copy($file, $to_file) ) {
  209. // signal at least one file was copied
  210. return true;
  211. }
  212. }
  213. /**
  214. * Zip an entire folder into a given file
  215. *
  216. * @param type $source the folder to zip up
  217. * @param type $destination the filename of the zip file to create
  218. * @return boolean true if the zip file was successfully create, false otherwise
  219. */
  220. function elgglp_zip_folder($source, $destination) {
  221. $zip = new ZipArchive();
  222. if ( !$zip->open($destination, ZIPARCHIVE::CREATE) ) {
  223. return false;
  224. }
  225. $source = str_replace('\\', '/', realpath($source));
  226. if ( is_dir($source) === true )
  227. {
  228. $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
  229. foreach ( $files as $file )
  230. {
  231. $file = str_replace('\\', '/', $file);
  232. // Ignore all hidden files and folders
  233. if ( $file[0] == '.' )
  234. continue;
  235. $file = realpath($file);
  236. if ( is_dir($file) === true )
  237. {
  238. $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
  239. }
  240. else if (is_file($file) === true)
  241. {
  242. $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
  243. }
  244. }
  245. }
  246. else if (is_file($source) === true)
  247. {
  248. $zip->addFromString(basename($source), file_get_contents($source));
  249. }
  250. return $zip->close();
  251. }
  252. /**
  253. * Completely and recursively delete a directory
  254. *
  255. * @param type $dirname the directory to remove
  256. * @return boolean true if the directory was removed successfully, false otherwise
  257. */
  258. function elgglp_deltree($dirname) {
  259. // Sanity check
  260. if ( !file_exists($dirname) ) { return false; }
  261. // Simple delete if it is an ordinary file or link
  262. if ( is_file($dirname) || is_link($dirname) ) {
  263. return unlink($dirname);
  264. }
  265. // Loop through each entry in the folder
  266. $dir = dir($dirname);
  267. while ( false !== ($entry = $dir->read()) ) {
  268. // Skip special pointers
  269. if ( $entry == '.' || $entry == '..' ) {
  270. continue;
  271. }
  272. // Recurse - if $entry is a file, this method will delete it and return
  273. elgglp_deltree("$dirname/$entry");
  274. }
  275. // Clean up
  276. $dir->close();
  277. return rmdir($dirname);
  278. }
  279. function elgglp_recurse_language_pack($srcdir, $filters, $callback) {
  280. // remove possible trailing slash from source directory
  281. $srcdir = rtrim($srcdir, '/');
  282. // remove possible trailing slash from target directory if it exists
  283. if ( $filters['dst_dir'] ) {
  284. $filters['dst_dir'] = rtrim($filters['dst_dir'], '/');
  285. }
  286. // copy filter options used here into local variables
  287. $projs = $filters['projs'];
  288. $needs_meta = $filters['needs_meta'];
  289. $needs_manifest = $filters['needs_manifest'];
  290. $return = $filters['return_array'];
  291. $releases = (array)$filters['elgg_release'];
  292. // check whether it is a valid Elgg Language Pack
  293. $elgg_version = null;
  294. $languagepack_version = null;
  295. if ( !elgglp_check_language_pack($srcdir, $elgg_version, $languagepack_version, $needs_meta) ) {
  296. return ELGGLP_ERR_STRUCTURE;
  297. }
  298. // is the language pack for the right Language Pack or Elgg version?
  299. if ( !in_array($elgg_version, $releases) || ELGGLP_VERSION != $languagepack_version ) {
  300. return ELGGLP_ERR_VERSION;
  301. }
  302. // set the detected version into the filters data
  303. $filters['elgg_release'] = $elgg_version;
  304. // should return list of language mods?
  305. if ( $return ) {
  306. $allmods = array();
  307. }
  308. // unless filtered, process the core language files
  309. if ( empty($projs) || in_array('core', $projs) ) {
  310. $meta = array(
  311. 'version' => $elgg_version,
  312. 'name' => 'Elgg Core',
  313. 'description' => 'The core elements of the social networking engine',
  314. 'unique' => 'core',
  315. );
  316. if ( $return ) {
  317. if ( ($alllangs = elgglp_recurse_languages($meta, $srcdir, $filters, null)) ) {
  318. $meta['langs'] = $alllangs;
  319. $allmods[] = $meta;
  320. }
  321. } else if ( $callback ) {
  322. @call_user_func($callback, $meta, $srcdir, $filters);
  323. }
  324. }
  325. // unless filtered, process the install language files
  326. if ( empty($projs) || in_array('install', $projs) ) {
  327. $meta = array(
  328. 'version' => $elgg_version,
  329. 'name' => 'Elgg Install',
  330. 'description' => 'Install wizard for setting up and configuring a new Elgg instance, or upgrading an existing one',
  331. 'unique' => 'install',
  332. );
  333. if ( $return ) {
  334. if ( ($alllangs = elgglp_recurse_languages($meta, "$srcdir/install", $filters, null)) ) {
  335. $meta['langs'] = $alllangs;
  336. $allmods[] = $meta;
  337. }
  338. } else if ( $callback ) {
  339. @call_user_func($callback, $meta, "$srcdir/install", $filters);
  340. }
  341. }
  342. // loop through all directories in mod/ looking for language mods
  343. $dir = dir("$srcdir/mod");
  344. while ( false !== ($entry = $dir->read()) ) {
  345. $curdir = "$srcdir/mod/$entry";
  346. if ( $entry[0] != '.' && is_dir($curdir) ) {
  347. // skip if filtered out by user
  348. if ( !empty($projs) && !in_array($entry, $projs) ) continue;
  349. // check whether at least one of meta and manifest files exist
  350. $meta_file = "$curdir/languages/languagemod.meta";
  351. $manifest_file = "$curdir/manifest.xml";
  352. $meta_exists = file_exists($meta_file);
  353. $manifest_exists = file_exists($manifest_file);
  354. if ( !$meta_exists && !$manifest_exists ) continue;
  355. // try and create meta data from either
  356. if ( (!$needs_meta || $meta_exists) && (!$needs_manifest || $manifest_exists) ) {
  357. if ( !$meta_exists || !is_array($meta = elgglp_read_languagemod_meta($curdir)) ) {
  358. if ( !$manifest_exists || !is_array($meta = elgglp_read_plugin_manifest($curdir)) ) {
  359. continue;
  360. }
  361. }
  362. if ( $return ) {
  363. if ( ($alllangs = elgglp_recurse_languages($meta, "$srcdir/mod/$entry", $filters, null)) ) {
  364. $meta['langs'] = $alllangs;
  365. $allmods[] = $meta;
  366. }
  367. } else if ( $callback ) {
  368. @call_user_func($callback, $meta, "$srcdir/mod/$entry", $filters);
  369. }
  370. }
  371. }
  372. }
  373. $dir->close();
  374. if ( $return ) {
  375. return $allmods;
  376. } else {
  377. return ELGGLP_OK;
  378. }
  379. }
  380. function elgglp_core_plugins($version = null) {
  381. static $cores = null;
  382. if ( !$cores ) {
  383. $cores = array(
  384. '1.8.8' => array(
  385. 'core', 'install', // these ones are not real Elgg plugins
  386. 'blog', 'bookmarks', 'categories', 'custom_index', 'dashboard', 'developers', 'diagnostics', 'embed',
  387. 'externalpages', 'file', 'garbagecollector', 'groups', 'invitefriends', 'likes', 'logbrowser', 'logrotate',
  388. 'members', 'messageboard', 'messages', 'notifications', 'oauth_api', 'pages', 'profile', 'reportedcontent',
  389. 'search', 'tagcloud', 'thewire', 'tinymce', 'twitter', 'twitter_api', 'uservalidationbyemail', 'zaudio'
  390. )
  391. );
  392. }
  393. if ( $version ) {
  394. return $cores[$version];
  395. } else {
  396. return $cores;
  397. }
  398. }