PageRenderTime 40ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/sys/lib/pkg.php

https://gitlab.com/VxMxPx/mysli
PHP | 171 lines | 129 code | 22 blank | 20 comment | 14 complexity | 11fffed8c934b8295b9c2c73d6b24b07 MD5 | raw file
  1. <?php namespace sys;
  2. use \sys\arr;
  3. use \sys\fs\{dir,file};
  4. class pkg
  5. {
  6. static private $list;
  7. static private $list_enabled;
  8. const LIST_WRITE = true;
  9. const LIST_ENABLED = true;
  10. # reload packages list
  11. static function reload() {
  12. self::$list = [];
  13. self::$list_enabled = [];
  14. # grab all packages
  15. $packages = scandir(pkgpath());
  16. foreach ($packages as $id) {
  17. if (!file_exists(pkgpath($id, 'pkg.ini'))) { continue; }
  18. $meta = self::load_meta($id);
  19. $meta['enabled'] = false;
  20. self::$list[$id] = new \sys\package($meta);
  21. }
  22. # grab enabled packages list
  23. $list = datpath('etc/packages');
  24. if (!file_exists($list)) { err('packages_file_missing', $list); }
  25. else { $list = file($list); }
  26. foreach ($list as $line) {
  27. $line = trim($line);
  28. if (substr($line, 0, 1) === '#') { continue; }
  29. if (!$line || strpos($line, ';') < 1) { continue; }
  30. list($id, $version, $date) = explode(';', $line);
  31. $meta = [
  32. 'id' => $id,
  33. 'version' => $version,
  34. 'date' => $date,
  35. 'enabled' => true
  36. ];
  37. if (!isset(self::$list[$id])) err('package_enabled_but_not_found_in_filesystem', $id);
  38. $pkg = self::$list[$id];
  39. $pkg->update_meta($meta);
  40. self::$list_enabled[] = $pkg;
  41. self::$list[$id] = $pkg;
  42. }
  43. }
  44. # get ordered list of enabled packages
  45. static function enabled(): array {
  46. if (!self::$list_enabled) self::reload();
  47. return self::$list_enabled;
  48. }
  49. # get list of all package in no particular order
  50. static function list(): array {
  51. if (!self::$list) self::reload();
  52. return self::$list;
  53. }
  54. # filter all packages
  55. static function filter($callback, bool $enabled = false): array {
  56. $packages = $enabled ? self::enabled() : self::list();
  57. $list = array_filter($packages, $callback, ARRAY_FILTER_USE_BOTH);
  58. return $list;
  59. }
  60. # call a function for each package
  61. # $callback ($pkg)
  62. # $enabled map only enabled packages
  63. # return [ return_value, return_value ]
  64. static function map($callback, bool $enabled = false): array {
  65. $list = $enabled ? self::enabled() : self::list();
  66. $results = [];
  67. foreach($list as $pkg) $results[] = $callback($pkg);
  68. return $results;
  69. }
  70. # check if package exists
  71. static function exists(string $id): bool {
  72. return !! self::get($id);
  73. }
  74. # does package exists and is enabled
  75. static function is_enabled(string $id): bool {
  76. $pkg = self::get($id);
  77. return $pkg && $pkg->enabled;
  78. }
  79. # get package by ID, null if not found
  80. static function get(string $id): \sys\package {
  81. $list = self::list();
  82. return isset($list[$id]) ? $list[$id] : null;
  83. }
  84. # get package by namespace, i.e. sys.pkg => sys
  85. static function by_namespace(string $namespace): \sys\package {
  86. $id = ltrim(str_replace('\\', '.', $namespace), '.');
  87. if (substr($id, 0, 4) === 'dat.') return self::get('dat');
  88. else if (substr_count($id, '.') === 0) return self::get($id);
  89. else return self::get(substr($id, 0, strpos($id, '.')));
  90. }
  91. # read package's metadata
  92. static function load_meta(string $id): array {
  93. $f = pkgpath($id, 'pkg.ini');
  94. if (!file::exists($f)) err('no_metadata_file_for_package', $id);
  95. return ini::decode_file($f);
  96. }
  97. # match a version with a pattern
  98. # $required version number (ie 1.1) will match 1.1-inf.*
  99. static function version_match(string $required, string $actual): bool {
  100. $resolve = function($ver) {
  101. $ver = explode('.', $ver);
  102. $breaking = isset($ver[0]) ? (int) $ver[0] : 0;
  103. $feature = isset($ver[1]) ? (int) $ver[1] : 0;
  104. $bugfix = isset($ver[2]) ? (int) $ver[2] : 0;
  105. return [ $breaking, $feature, $bugfix ];
  106. };
  107. $required = $resolve($required);
  108. $actual = $resolve($actual);
  109. return
  110. $required[0] === $actual[0] &&
  111. $required[1] <= $actual[1] &&
  112. $required[2] <= $actual[2];
  113. }
  114. # physically remove package's data files from file system
  115. static function delete(string $id): bool {
  116. $dir = pkgpath($id);
  117. if (dir::exists($dir)) {
  118. return dir::remove($dir);
  119. }
  120. }
  121. # add package to the list of enabled packages
  122. static function list_add(string $id, bool $write = false): bool {
  123. if (!self::$list_enabled) self::init();
  124. self::$list_enabled[] = self::get($id);
  125. return $write ? self::list_write() : true;
  126. }
  127. # remove package from the list of enabled packages
  128. static function list_remove(string $id, bool $write = false): bool {
  129. foreach(self::$list_enabled as $index => $pkg) {
  130. if ($pkg->id === $id) {
  131. array_splice(self::$list_enabled, $index, 1);
  132. return $write ? self::list_write() : true;
  133. }
  134. }
  135. return false;
  136. }
  137. # write list of enabled packages
  138. static function list_write(): bool {
  139. $list = "# package;version;date\n";
  140. $packages = self::enabled();
  141. $nowdata = gmdate('c');
  142. foreach ($packages as $pkg) {
  143. $date = $pkg->date ? $pkg->date : $nowdata;
  144. $list .= "{$pkg->id};{$pkg->version};{$date}\n";
  145. }
  146. return !! file::write(datpath('etc/packages'), $list);
  147. }
  148. }