Files
vivespos-landing/modules/system/classes/asset/PackageJson.php
avives 1f72193a64
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run
feat: VivesPOS landing on Winter CMS 1.2 — theme + plugin + Dockerfile
- Base: wintercms/winter branch 1.2 (full framework)
- Theme vivespos: Canvas 7 + Bootstrap 5 CDN, custom CSS
- Layout: deferred GTM/GA4 tracking, JSON-LD SoftwareApplication
- Partials: hero (offline-first), features, modes (offline/nube toggle),
  screenshots, pricing (3 planes), comparison, FAQ, CTA
- Plugin VivesPOS.Site with ContactForm
- Dockerfile: PHP 8.2 Apache, port 80, healthcheck
- Added winter/wn-pages, blog, sitemap, seo plugins
- Active theme set to vivespos
2026-08-21 19:29:00 -06:00

279 lines
8.2 KiB
PHP

<?php
namespace System\Classes\Asset;
use InvalidArgumentException;
use RuntimeException;
use Winter\Storm\Support\Facades\File;
/**
* PHP based interface for interacting with package.json files. This allows for modification of deps, devDeps, package
* name and workspaces.
*
* @package winter\wn-system-module
* @author Jack Wilkinson <me@jackwilky.com>
* @author Winter CMS
*/
class PackageJson
{
/**
* The contents of the package.json being modified
*/
protected array $data = [];
/**
* Create a new instance with optional path, loads file if file already exists
* @throws \JsonException
*/
public function __construct(
protected ?string $path = null
) {
if (File::exists($this->path)) {
// Test the json to insure it's valid
$json = json_decode(File::get($this->path), JSON_OBJECT_AS_ARRAY);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \JsonException('The contents of the file "' . $this->path . '" is not valid json.');
}
$this->data = $json;
}
}
/**
* Returns the package name if set
*/
public function getName(): ?string
{
return $this->data['name'] ?? null;
}
/**
* Sets the package name, throws `InvalidArgumentException` on invalid name
*/
public function setName(?string $name): static
{
if (is_null($name)) {
unset($this->data['name']);
return $this;
}
if ($name !== strtolower($name)) {
throw new InvalidArgumentException('Package names must be lower case');
}
if (preg_match('/^([._])/', $name)) {
throw new InvalidArgumentException('Package names must not start with . or _');
}
if (preg_match('/[~\'\"!()*]/', $name)) {
throw new InvalidArgumentException('Package names must not include special characters');
}
if (strlen($name) > 214) {
throw new InvalidArgumentException('Package names must not be longer than 214 characters');
}
if ($name !== trim($name)) {
throw new InvalidArgumentException('Package names must not include whitespace');
}
$this->data['name'] = $name;
return $this;
}
/**
* Checks if workspace package is set
*/
public function hasWorkspace(string $path): bool
{
return in_array($path, $this->data['workspaces']['packages'] ?? []);
}
/**
* Adds a new workspace, removes from ignored workspaces if present
*/
public function addWorkspace(string $path): static
{
if (!in_array($path, $this->data['workspaces']['packages'] ?? [])) {
$this->data['workspaces']['packages'][] = $path;
}
if (($key = array_search($path, $this->data['workspaces']['ignoredPackages'] ?? [])) !== false) {
// remove the package from ignored workspaces
unset($this->data['workspaces']['ignoredPackages'][$key]);
// reset keys
$this->data['workspaces']['ignoredPackages'] = array_values($this->data['workspaces']['ignoredPackages']);
}
// Sort the packages
asort($this->data['workspaces']['packages']);
$this->data['workspaces']['packages'] = array_values($this->data['workspaces']['packages']);
return $this;
}
/**
* Removes a workspace
*/
public function removeWorkspace(string $path): static
{
if (($key = array_search($path, $this->data['workspaces']['packages'] ?? [])) !== false) {
// remove the package from workspace packages
unset($this->data['workspaces']['packages'][$key]);
// reset keys
$this->data['workspaces']['packages'] = array_values($this->data['workspaces']['packages']);
}
return $this;
}
/**
* Check if package is ignored
*/
public function hasIgnoredPackage(string $path): bool
{
return in_array($path, $this->data['workspaces']['ignoredPackages'] ?? []);
}
/**
* Adds an ignored package, removes from workspaces if present
*/
public function addIgnoredPackage(string $path): static
{
if (!in_array($path, $this->data['workspaces']['ignoredPackages'] ?? [])) {
$this->data['workspaces']['ignoredPackages'][] = $path;
}
if (($key = array_search($path, $this->data['workspaces']['packages'] ?? [])) !== false) {
// remove the package from ignored workspaces
unset($this->data['workspaces']['packages'][$key]);
// reset keys
$this->data['workspaces']['packages'] = array_values($this->data['workspaces']['packages']);
}
// Sort the packages
asort($this->data['workspaces']['ignoredPackages']);
$this->data['workspaces']['ignoredPackages'] = array_values($this->data['workspaces']['ignoredPackages'] ?? []);
return $this;
}
/**
* Removes an ignored package
*/
public function removeIgnoredPackage(string $path): static
{
if (($key = array_search($path, $this->data['workspaces']['ignoredPackages'] ?? [])) !== false) {
// remove the package from workspace packages
unset($this->data['workspaces']['ignoredPackages'][$key]);
// reset keys
$this->data['workspaces']['ignoredPackages'] = array_values($this->data['workspaces']['ignoredPackages']);
}
return $this;
}
/**
* Checks if package.json has a dependency
*/
public function hasDependency(string $package): bool
{
return isset($this->data['dependencies'][$package]) || isset($this->data['devDependencies'][$package]);
}
/**
* Adds a dependency, supports adding to `dependencies` or `devDependencies` based on `$dev` and allows moving if
* `$overwrite` is set
*/
public function addDependency(string $package, string $version, bool $dev = false, bool $overwrite = false): static
{
// If the dep is defined already, but we are not overwriting, then exit
if (
(isset($this->data['dependencies'][$package]) || isset($this->data['devDependencies'][$package]))
&& !$overwrite
) {
return $this;
}
// Clear any existing settings because we are overwriting
$this->removeDependency($package);
// Define the dep
$this->data[$dev ? 'devDependencies' : 'dependencies'][$package] = $version;
return $this;
}
/**
* Removes a package from both `dependencies` and `devDependencies`
*/
public function removeDependency(string $package): static
{
unset($this->data['dependencies'][$package], $this->data['devDependencies'][$package]);
return $this;
}
/**
* Returns if a script exists
*/
public function hasScript(string $name): bool
{
return isset($this->data['scripts'][$name]);
}
/**
* Returns the value of a script by name
*/
public function getScript(string $name): ?string
{
return $this->data['scripts'][$name] ?? null;
}
/**
* Adds a script
*/
public function addScript(string $name, string $script): static
{
$this->data['scripts'][$name] = $script;
return $this;
}
/**
* Removes a script by name
*/
public function removeScript(string $name): static
{
unset($this->data['scripts'][$name]);
return $this;
}
/**
* Returns the package.json contents as an array
*/
public function getContents(): array
{
return $this->data;
}
/**
* Returns the path of the package.json if set
*/
public function getPath(): ?string
{
return $this->path;
}
/**
* Saves the contents to a file, if the object was init'ed with a path it will save to the path, or can be
* overwritten with `$path`.
*/
public function save(?string $path = null): int
{
return File::put(
$path ?? $this->path ?? throw new RuntimeException('Unable to save, no path given'),
json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
);
}
}