Milestones 0, 1, 2
Some checks are pending
CI / build_and_test (push) Waiting to run

This commit is contained in:
Funky Waddle 2026-09-09 18:58:20 -05:00
parent 1d37af7282
commit c3ec2b86d9
15 changed files with 2328 additions and 16 deletions

23
.forgejo/workflows/ci.yml Normal file
View file

@ -0,0 +1,23 @@
name: CI
on:
push:
branches: [master]
pull_request_target:
branches: [master]
jobs:
build_and_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: mbstring, pdo_mysql, json
coverage: none
- name: Install dependencies
run: composer install --no-progress --prefer-dist
- name: Run tests
run: vendor/bin/codecept run

View file

@ -1,7 +1,7 @@
milestones: milestones:
# Milestone 0: Project Foundation & Setup # Milestone 0: Project Foundation & Setup
milestone_0_project_foundation: milestone_0_project_foundation:
status: TODO status: COMPLETE
description: >- description: >-
Set up the project structure, Composer dependencies, autoloading, Set up the project structure, Composer dependencies, autoloading,
and basic bootstrap files. This establishes the base for all subsequent and basic bootstrap files. This establishes the base for all subsequent
@ -32,7 +32,7 @@ milestones:
# Milestone 1: Configuration & Environment Management # Milestone 1: Configuration & Environment Management
milestone_1_configuration: milestone_1_configuration:
status: TODO status: COMPLETE
description: >- description: >-
Implement environment configuration loading, Infisical integration, Implement environment configuration loading, Infisical integration,
and .env handling. This provides secure runtime secrets and and .env handling. This provides secure runtime secrets and

2
_bootstrap.php Normal file
View file

@ -0,0 +1,2 @@
<?php
require __DIR__ . '/vendor/autoload.php';

17
codeception.yml Normal file
View file

@ -0,0 +1,17 @@
actor: Tester
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
bootstrap: _bootstrap.php
settings:
colors: true
suites:
unit:
actor: UnitTester
path: unit
class_name: UnitSuite
modules:
enabled:
- Asserts

View file

@ -12,7 +12,8 @@
"phpmailer/phpmailer": "^7.1", "phpmailer/phpmailer": "^7.1",
"guzzlehttp/guzzle": "^7.8", "guzzlehttp/guzzle": "^7.8",
"symfony/http-foundation": "^6.3", "symfony/http-foundation": "^6.3",
"infisical/php-sdk": "^0.0.2" "infisical/php-sdk": "^0.0.2",
"ext-dom": "*"
}, },
"require-dev": { "require-dev": {
"codeception/codeception": "^5.3", "codeception/codeception": "^5.3",
@ -27,12 +28,17 @@
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"SiteWeaver\\": "src/Site/", "SiteWeaver\\": "src/Site/",
"Intervention\\": "src/Intervention/", "SiteWeaver\\Plugins\\": "site/plugins/",
"Tests\\": "tests/" "SiteWeaver\\Themes\\": "site/themes/",
"SiteWeaver\\AdminThemes\\": "site/admin_themes/",
"Intervention\\": "src/Intervention/"
}, },
"classmap": [ "classmap": []
"src/Intervention/Image/ImageManager.php" },
] "autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}, },
"scripts": { "scripts": {
"migrate:up": "php vendor/bin/phinx:migrations:up", "migrate:up": "php vendor/bin/phinx:migrations:up",

17
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "1976fa1898ee5b599738fe40055ea1be", "content-hash": "f9abfc5b9d7ebdcca8c6410cf861c505",
"packages": [ "packages": [
{ {
"name": "aws/aws-crt-php", "name": "aws/aws-crt-php",
@ -62,16 +62,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.394.10", "version": "3.394.11",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "3b7cbf17b8ba568f77546d1e5edd3f2071861c8f" "reference": "0a16c43453b30b5ec4025293f33028e299cf448e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3b7cbf17b8ba568f77546d1e5edd3f2071861c8f", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0a16c43453b30b5ec4025293f33028e299cf448e",
"reference": "3b7cbf17b8ba568f77546d1e5edd3f2071861c8f", "reference": "0a16c43453b30b5ec4025293f33028e299cf448e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -153,9 +153,9 @@
"support": { "support": {
"forum": "https://github.com/aws/aws-sdk-php/discussions", "forum": "https://github.com/aws/aws-sdk-php/discussions",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.394.10" "source": "https://github.com/aws/aws-sdk-php/tree/3.394.11"
}, },
"time": "2026-09-08T18:07:43+00:00" "time": "2026-09-09T18:06:19+00:00"
}, },
{ {
"name": "ezyang/htmlpurifier", "name": "ezyang/htmlpurifier",
@ -10534,7 +10534,8 @@
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": "^8.4" "php": "^8.4",
"ext-dom": "*"
}, },
"platform-dev": {}, "platform-dev": {},
"plugin-api-version": "2.9.0" "plugin-api-version": "2.9.0"

13
config/.env.example Normal file
View file

@ -0,0 +1,13 @@
# Example .env file for SiteWeaverCMS
#
# Required Infisical integration variables (set by your Nginx config or deployment environment)
INFISICAL_URL="https://your.infisical.instance"
INFISICAL_ENV="dev"
INFISICAL_PROJECT_ID="YOUR_PROJECT_ID"
# Optional client credentials for machine authentication
INFISICAL_CLIENT_ID="YOUR_CLIENT_ID"
INFISICAL_CLIENT_SECRET="YOUR_CLIENT_SECRET"
# Other application-specific environment variables can be added below
# e.g., DATABASE_URL, APP_ENV, etc.

18
config/bootstrap.php Normal file
View file

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->safeLoad();
$mergedEnv = $_ENV + $_SERVER;
use League\Container\Container;
use SiteWeaver\Core\Config;
$container = new Container();
$container->add('config', function () use ($mergedEnv) {
return new Config($mergedEnv);
});
return $container;

7
public/index.php Normal file
View file

@ -0,0 +1,7 @@
<?php
declare(strict_types=1);
$container = require __DIR__ . '/../config/bootstrap.php';
// Placeholder: output a simple message.
echo "SiteWeaverCMS running.";

77
src/Site/Core/Config.php Normal file
View file

@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
namespace SiteWeaver\Core;
use Infisical\SDK\InfisicalSDK;
use Infisical\SDK\Services\UniversalAuthService;
use Infisical\SDK\Models\MachineIdentityCredential;
/**
* Configuration service that loads environment variables and optionally fetches secrets from Infisical.
*/
class Config
{
/** @var array<string, mixed> */
private array $values = [];
public function __construct(array $env = null)
{
// Use provided env array or fallback to $_ENV
$this->values = $env ?? $_ENV;
// If Infisical integration variables are present, attempt to fetch secrets
if ($this->hasInfisicalConfig()) {
try {
$sdk = new InfisicalSDK($this->get('INFISICAL_URL'));
// Optional authentication using client credentials
$clientId = $this->get('INFISICAL_CLIENT_ID');
$clientSecret = $this->get('INFISICAL_CLIENT_SECRET');
if ($clientId !== null && $clientSecret !== null) {
/** @var UniversalAuthService $auth */
$auth = $sdk->auth()->universalAuth();
/** @var MachineIdentityCredential $credential */
$credential = $auth->login($clientId, $clientSecret);
// The SDK will internally set the auth token via callback
}
// Fetch secrets and merge into values if not already defined
foreach ($sdk->secrets()->list() as $secret) {
$key = $secret->secretKey ?? null;
$value = $secret->secretValue ?? null;
if ($key !== null && $value !== null && !array_key_exists($key, $this->values)) {
$this->values[$key] = $value;
}
}
} catch (\Throwable $e) {
// If Infisical integration fails, rethrow as runtime exception
throw new \RuntimeException('Failed to fetch secrets from Infisical: ' . $e->getMessage(), 0, $e);
}
}
}
/**
* Check if required Infisical config variables are present.
*/
private function hasInfisicalConfig(): bool
{
return !empty($this->values['INFISICAL_URL']) &&
!empty($this->values['INFISICAL_ENV']) &&
!empty($this->values['INFISICAL_PROJECT_ID']);
}
public function get(string $key, mixed $default = null): mixed
{
return $this->values[$key] ?? $default;
}
/**
* Return all configuration values.
*/
public function all(): array
{
return $this->values;
}
}
?>

2
tests/_bootstrap.php Normal file
View file

@ -0,0 +1,2 @@
<?php
require __DIR__ . '/../vendor/autoload.php';

View file

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
/**
* Inherited Methods
* @method void wantTo($text)
* @method void wantToTest($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method void pause($vars = [])
*
* @SuppressWarnings(PHPMD)
*/
class UnitTester extends \Codeception\Actor
{
use _generated\UnitTesterActions;
/**
* Define custom actions here
*/
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace Tests\unit\Core;
use SiteWeaver\Core\Config;
use PHPUnit\Framework\TestCase;
final class ConfigTest extends TestCase
{
public function testLoadsEnvironmentVariables(): void
{
$env = [
'APP_ENV' => 'testing',
'DB_HOST' => 'localhost',
'DEBUG' => true,
];
$config = new Config($env);
$this->assertSame('testing', $config->get('APP_ENV'));
$this->assertSame('localhost', $config->get('DB_HOST'));
$this->assertTrue($config->get('DEBUG'));
// unknown key returns null
$this->assertNull($config->get('NON_EXISTENT_KEY'));
}
public function testAllReturnsMergedArray(): void
{
$env = [
'FOO' => 'bar',
'BAZ' => 123,
];
$config = new Config($env);
$this->assertSame($env, $config->all());
}
}

View file

@ -0,0 +1,7 @@
<?php
namespace Tests\unit;
class UnitTester extends \Codeception\Actor {
use \Codeception\AssertThrows;
}