{"id":31830639,"url":"https://github.com/wp-spaghetti/wp-env","last_synced_at":"2026-01-20T17:35:05.241Z","repository":{"id":312433962,"uuid":"1047392808","full_name":"wp-spaghetti/wp-env","owner":"wp-spaghetti","description":"A comprehensive WordPress environment management utility with typed getters, system detection and secure configuration handling","archived":false,"fork":false,"pushed_at":"2025-09-14T17:47:16.000Z","size":124,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-14T19:30:16.998Z","etag":null,"topics":["environment","wordpress","wordpress-development"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wp-spaghetti.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":".github/SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["frugan-dev"],"buy_me_a_coffee":"frugan"}},"created_at":"2025-08-30T10:13:51.000Z","updated_at":"2025-09-14T17:30:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"a2e98cf3-062c-4633-aa67-75fdb13d28c2","html_url":"https://github.com/wp-spaghetti/wp-env","commit_stats":null,"previous_names":["wp-spaghetti/wp-env"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/wp-spaghetti/wp-env","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wp-spaghetti%2Fwp-env","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wp-spaghetti%2Fwp-env/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wp-spaghetti%2Fwp-env/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wp-spaghetti%2Fwp-env/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wp-spaghetti","download_url":"https://codeload.github.com/wp-spaghetti/wp-env/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wp-spaghetti%2Fwp-env/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279008830,"owners_count":26084516,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["environment","wordpress","wordpress-development"],"created_at":"2025-10-11T21:20:57.535Z","updated_at":"2025-10-11T21:20:59.795Z","avatar_url":"https://github.com/wp-spaghetti.png","language":"PHP","funding_links":["https://github.com/sponsors/frugan-dev","https://buymeacoffee.com/frugan"],"categories":[],"sub_categories":[],"readme":"![PHP Version](https://img.shields.io/packagist/php-v/wp-spaghetti/wp-env)\n![Packagist Downloads](https://img.shields.io/packagist/dt/wp-spaghetti/wp-env)\n![Packagist Stars](https://img.shields.io/packagist/stars/wp-spaghetti/wp-env)\n![GitHub Actions Workflow Status](https://github.com/wp-spaghetti/wp-env/actions/workflows/main.yml/badge.svg)\n![Coverage Status](https://img.shields.io/codecov/c/github/wp-spaghetti/wp-env)\n![Known Vulnerabilities](https://snyk.io/test/github/wp-spaghetti/wp-env/badge.svg)\n![GitHub Issues](https://img.shields.io/github/issues/wp-spaghetti/wp-env)\n\n![GitHub Release](https://img.shields.io/github/v/release/wp-spaghetti/wp-env)\n![License](https://img.shields.io/github/license/wp-spaghetti/wp-env)\n\u003c!--\nQlty @see https://github.com/badges/shields/issues/11192\n![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/wp-spaghetti/wp-env/total)\n![Code Climate](https://img.shields.io/codeclimate/maintainability/wp-spaghetti/wp-env)\n![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)\n--\u003e\n\n# WP Env\n\nA comprehensive WordPress environment management utility with typed getters, system detection and secure configuration handling.\n\n## Features\n\n- **Multi-Source Configuration**: WordPress constants, .env files, and getenv() with intelligent priority\n- **Typed Getters**: Type-safe methods for bool, int, float, and array values\n- **Environment Detection**: Automatic development, staging, and production environment detection\n- **Container Detection**: Docker, Kubernetes, Podman, and other containerization detection\n- **Performance Caching**: Smart caching system with sensitive data protection\n- **Security-Focused**: Built-in protection for sensitive configuration values\n- **WordPress Integration**: Native WordPress hooks and filters for customization\n- **Zero Dependencies**: Works with or without external environment libraries\n- **Bedrock Compatible**: Seamless integration with modern WordPress setups\n\n## Installation\n\nInstall via Composer:\n\n```bash\ncomposer require wp-spaghetti/wp-env\n```\n\n## Quick Start\n\n### 1. Basic Usage\n\n```php\n\u003c?php\nuse WpSpaghetti\\WpEnv\\Environment;\n\n// Get environment variables with fallbacks\n$dbHost = Environment::get('DB_HOST', 'localhost');\n$debug = Environment::getBool('WP_DEBUG', false);\n$maxUploads = Environment::getInt('MAX_UPLOADS', 10);\n$allowedTypes = Environment::getArray('ALLOWED_TYPES', ['jpg', 'png']);\n\n// Check environment type\nif (Environment::isDevelopment()) {\n    // Development-specific code\n    error_reporting(E_ALL);\n}\n\n// Check containerization\nif (Environment::isDocker()) {\n    // Docker-specific configuration\n    $redisHost = 'redis'; // Use container name\n}\n```\n\n### 2. Configuration Priority\n\nWP Env uses the following priority order:\n\n1. **WordPress Constants** (`define()` in wp-config.php)\n2. **.env files** (via oscarotero/env if available)\n3. **System environment** (`getenv()`)\n4. **Default values**\n\n```php\n\u003c?php\n// wp-config.php\ndefine('API_TIMEOUT', 30);\n\n// .env file\nAPI_TIMEOUT=60\n\n// System environment\nexport API_TIMEOUT=90\n\n// Result: 30 (WordPress constant wins)\n$timeout = Environment::getInt('API_TIMEOUT', 10);\n```\n\n### 3. WordPress Integration\n\n```php\n\u003c?php\n// In your plugin or theme\nuse WpSpaghetti\\WpEnv\\Environment;\n\nclass MyPlugin \n{\n    public function __construct() \n    {\n        // Validate required configuration\n        Environment::validateRequired([\n            'MY_PLUGIN_API_KEY',\n            'MY_PLUGIN_SECRET'\n        ]);\n        \n        add_action('init', [$this, 'init']);\n    }\n    \n    public function init(): void \n    {\n        $config = Environment::load([\n            'MY_PLUGIN_API_KEY',\n            'MY_PLUGIN_TIMEOUT' =\u003e 30,\n            'MY_PLUGIN_RETRIES' =\u003e 3,\n            'MY_PLUGIN_ENABLED' =\u003e true\n        ]);\n        \n        // Environment-specific behavior\n        if (Environment::isProduction()) {\n            $this-\u003eenableCaching();\n        }\n        \n        if (Environment::isDebug()) {\n            $this-\u003eenableDetailedLogging();\n        }\n    }\n}\n```\n\n## API Reference\n\n### Core Methods\n\n#### `Environment::get(string $key, mixed $default = null): mixed`\nGet environment variable with fallback to default value.\n\n#### `Environment::getBool(string $key, bool $default = false): bool`\nGet environment variable as boolean. Recognizes: `1`, `true`, `on`, `yes`, `enabled`.\n\n#### `Environment::getInt(string $key, int $default = 0): int`\nGet environment variable as integer with type conversion.\n\n#### `Environment::getFloat(string $key, float $default = 0.0): float`\nGet environment variable as float with type conversion.\n\n#### `Environment::getArray(string $key, array $default = []): array`\nGet environment variable as array (comma-separated values).\n\n#### `Environment::getRequired(string $key): mixed`\nGet required environment variable (throws exception if missing).\n\n### Validation Methods\n\n#### `Environment::validateRequired(array $keys): void`\nValidate that all required environment variables are set.\n\n```php\nEnvironment::validateRequired([\n    'DB_HOST',\n    'DB_NAME', \n    'API_KEY'\n]);\n```\n\n#### `Environment::load(array $keys): array`\nLoad multiple environment variables at once.\n\n```php\n// Simple array\n$vars = Environment::load(['KEY1', 'KEY2', 'KEY3']);\n\n// With defaults\n$vars = Environment::load([\n    'API_URL' =\u003e 'https://api.example.com',\n    'TIMEOUT' =\u003e 30,\n    'ENABLED' =\u003e true\n]);\n```\n\n### Environment Detection\n\n#### `Environment::getEnvironment(): string`\nGet current environment type: `development`, `staging`, or `production`.\n\n#### `Environment::isDevelopment(): bool`\nCheck if running in development environment.\n\n#### `Environment::isStaging(): bool`\nCheck if running in staging environment.\n\n#### `Environment::isProduction(): bool`\nCheck if running in production environment.\n\n### Container Detection\n\n#### `Environment::isDocker(): bool`\nCheck if running inside a Docker container.\n\n#### `Environment::isContainer(): bool`\nCheck if running in any containerized environment (Docker, Podman, etc.).\n\n### WordPress-Specific Methods\n\n#### `Environment::isDebug(): bool`\nCheck if WordPress debug mode is enabled (`WP_DEBUG`).\n\n#### `Environment::isMultisite(): bool`\nCheck if WordPress is running in multisite mode.\n\n#### `Environment::isCli(): bool`\nCheck if running via CLI (WP-CLI or PHP CLI).\n\n#### `Environment::isWeb(): bool`\nCheck if running via web request.\n\n### System Information\n\n#### `Environment::getServerSoftware(): string`\nGet server software (nginx, apache, litespeed, iis).\n\n#### `Environment::getPhpSapi(): string`\nGet PHP SAPI information.\n\n### Utility Methods\n\n#### `Environment::getDebugInfo(): array`\nGet comprehensive environment information for debugging.\n\n#### `Environment::clearCache(): void`\nClear internal caches (useful for testing).\n\n#### `Environment::addSensitiveKey(string $key): void`\nAdd key to sensitive list (prevents caching/logging).\n\n## Configuration Examples\n\n### WordPress Constants (wp-config.php)\n\n```php\n\u003c?php\n// Basic WordPress configuration\ndefine('WP_DEBUG', true);\ndefine('WP_ENVIRONMENT_TYPE', 'development');\n\n// Custom application settings\ndefine('API_BASE_URL', 'https://api.example.com');\ndefine('CACHE_ENABLED', true);\ndefine('MAX_UPLOAD_SIZE', 50);\ndefine('ALLOWED_EXTENSIONS', 'jpg,png,gif,pdf');\n\n// Container-specific settings\ndefine('REDIS_HOST', 'redis');\ndefine('ELASTICSEARCH_URL', 'http://elasticsearch:9200');\n```\n\n### Environment File (.env)\n\n```env\n# Environment identification\nWP_ENVIRONMENT_TYPE=development\nWP_DEBUG=true\n\n# Database configuration\nDB_HOST=db\nDB_NAME=wordpress\nDB_USER=wp_user\nDB_PASSWORD=secure_password\n\n# Application settings\nAPI_BASE_URL=https://api.staging.example.com\nCACHE_TTL=3600\nMAX_RETRIES=5\nFEATURE_FLAGS=feature1,feature2,feature3\n\n# Container settings\nREDIS_HOST=redis\nREDIS_PORT=6379\nELASTICSEARCH_URL=http://elasticsearch:9200\n```\n\n### Docker Compose Integration\n\n```yaml\nservices:\n  wordpress:\n    image: wordpress:latest\n    environment:\n      - WP_ENVIRONMENT_TYPE=development\n      - WP_DEBUG=true\n      - DB_HOST=db\n      - REDIS_HOST=redis\n      - API_TIMEOUT=60\n      - DOCKER_CONTAINER=true\n    volumes:\n      - .:/var/www/html\n    depends_on:\n      - db\n      - redis\n      \n  db:\n    image: mysql:8.0\n    environment:\n      - MYSQL_DATABASE=wordpress\n      - MYSQL_USER=wp_user\n      - MYSQL_PASSWORD=secure_password\n      \n  redis:\n    image: redis:alpine\n```\n\n## Hook System\n\nWP Env provides several WordPress hooks for customization:\n\n### Filter Environment Values\n\n```php\n// Modify any environment value\nadd_filter('wp_env_get_value', function($value, $key, $default) {\n    // Force debug mode for specific users\n    if ($key === 'WP_DEBUG' \u0026\u0026 current_user_can('administrator')) {\n        return true;\n    }\n    \n    return $value;\n}, 10, 3);\n```\n\n### Custom Environment Detection\n\n```php\n// Override environment detection\nadd_filter('wp_env_get_environment', function($environment, $originalEnv) {\n    // Custom logic for environment detection\n    if (str_contains($_SERVER['HTTP_HOST'] ?? '', 'beta.')) {\n        return 'staging';\n    }\n    \n    return $environment;\n}, 10, 2);\n```\n\n### Container Detection Override\n\n```php\n// Override Docker detection\nadd_filter('wp_env_is_docker', function($isDocker) {\n    // Custom Docker detection logic\n    return file_exists('/app/.dockerenv');\n});\n```\n\n### Sensitive Key Protection\n\n```php\n// Add custom sensitive keys\nadd_filter('wp_env_is_sensitive_key', function($isSensitive, $key) {\n    $customSensitive = [\n        'STRIPE_SECRET_KEY',\n        'MAILCHIMP_API_KEY',\n        'GOOGLE_ANALYTICS_SECRET'\n    ];\n    \n    return $isSensitive || in_array($key, $customSensitive);\n}, 10, 2);\n```\n\n### Cache Events\n\n```php\n// React to cache clearing\nadd_action('wp_env_cache_cleared', function() {\n    // Your custom cache clearing logic\n    wp_cache_flush();\n});\n```\n\n## Advanced Usage Examples\n\n### Plugin Configuration Management\n\n```php\n\u003c?php\nuse WpSpaghetti\\WpEnv\\Environment;\n\nclass PluginConfigManager \n{\n    private array $config;\n    \n    public function __construct() \n    {\n        $this-\u003eloadConfiguration();\n    }\n    \n    private function loadConfiguration(): void \n    {\n        // Load all plugin settings at once\n        $this-\u003econfig = Environment::load([\n            'MYPLUGIN_API_URL' =\u003e 'https://api.example.com',\n            'MYPLUGIN_TIMEOUT' =\u003e 30,\n            'MYPLUGIN_RETRIES' =\u003e 3,\n            'MYPLUGIN_CACHE_TTL' =\u003e 3600,\n            'MYPLUGIN_FEATURES' =\u003e [],\n            'MYPLUGIN_DEBUG' =\u003e false\n        ]);\n        \n        // Environment-specific overrides\n        if (Environment::isDevelopment()) {\n            $this-\u003econfig['MYPLUGIN_DEBUG'] = true;\n            $this-\u003econfig['MYPLUGIN_TIMEOUT'] = 5; // Shorter timeout for dev\n        }\n        \n        if (Environment::isDocker()) {\n            $this-\u003econfig['MYPLUGIN_API_URL'] = 'http://api:8080'; // Container URL\n        }\n        \n        // Validate critical configuration\n        if (Environment::isProduction()) {\n            Environment::validateRequired([\n                'MYPLUGIN_API_KEY',\n                'MYPLUGIN_SECRET_KEY'\n            ]);\n        }\n    }\n    \n    public function get(string $key, $default = null) \n    {\n        return $this-\u003econfig[$key] ?? $default;\n    }\n}\n```\n\n### Environment-Specific Service Registration\n\n```php\n\u003c?php\nuse WpSpaghetti\\WpEnv\\Environment;\n\nclass ServiceProvider \n{\n    public function register(): void \n    {\n        switch (Environment::getEnvironment()) {\n            case Environment::ENV_DEVELOPMENT:\n                $this-\u003eregisterDevelopmentServices();\n                break;\n                \n            case Environment::ENV_STAGING:\n                $this-\u003eregisterStagingServices();\n                break;\n                \n            case Environment::ENV_PRODUCTION:\n                $this-\u003eregisterProductionServices();\n                break;\n        }\n        \n        // Container-specific services\n        if (Environment::isContainer()) {\n            $this-\u003eregisterContainerServices();\n        }\n    }\n    \n    private function registerDevelopmentServices(): void \n    {\n        // Development-only services\n        add_action('wp_footer', [$this, 'addDebugInfo']);\n        \n        // Use different API endpoints\n        $apiUrl = 'http://localhost:3000/api';\n    }\n    \n    private function registerProductionServices(): void \n    {\n        // Production optimizations\n        add_action('init', [$this, 'enableCaching']);\n        \n        // Production API endpoints\n        $apiUrl = Environment::get('PROD_API_URL', 'https://api.example.com');\n    }\n    \n    private function registerContainerServices(): void \n    {\n        // Container-specific networking\n        $redisHost = Environment::get('REDIS_HOST', 'redis');\n        $dbHost = Environment::get('DB_HOST', 'db');\n    }\n}\n```\n\n### Multi-Environment Configuration\n\n```php\n\u003c?php\nuse WpSpaghetti\\WpEnv\\Environment;\n\nclass MultiEnvironmentConfig \n{\n    private array $environments = [\n        Environment::ENV_DEVELOPMENT =\u003e [\n            'debug' =\u003e true,\n            'cache_ttl' =\u003e 0,\n            'api_url' =\u003e 'http://localhost:3000',\n            'log_level' =\u003e 'debug'\n        ],\n        Environment::ENV_STAGING =\u003e [\n            'debug' =\u003e true,\n            'cache_ttl' =\u003e 300,\n            'api_url' =\u003e 'https://staging-api.example.com',\n            'log_level' =\u003e 'info'\n        ],\n        Environment::ENV_PRODUCTION =\u003e [\n            'debug' =\u003e false,\n            'cache_ttl' =\u003e 3600,\n            'api_url' =\u003e 'https://api.example.com',\n            'log_level' =\u003e 'error'\n        ]\n    ];\n    \n    public function get(string $key, $default = null) \n    {\n        $currentEnv = Environment::getEnvironment();\n        $envConfig = $this-\u003eenvironments[$currentEnv] ?? [];\n        \n        // Try environment-specific config first\n        if (isset($envConfig[$key])) {\n            return $envConfig[$key];\n        }\n        \n        // Fall back to environment variable\n        return Environment::get(strtoupper($key), $default);\n    }\n    \n    public function getApiUrl(): string \n    {\n        return $this-\u003eget('api_url');\n    }\n    \n    public function getCacheTtl(): int \n    {\n        return (int) $this-\u003eget('cache_ttl');\n    }\n    \n    public function shouldEnableDebug(): bool \n    {\n        return (bool) $this-\u003eget('debug');\n    }\n}\n```\n\n## Troubleshooting\n\n### Debug Information\n\n```php\n// Get comprehensive environment info\n$info = Environment::getDebugInfo();\nprint_r($info);\n\n// Check specific values\necho \"Environment: \" . Environment::getEnvironment() . \"\\n\";\necho \"Is Docker: \" . (Environment::isDocker() ? 'yes' : 'no') . \"\\n\";\necho \"Debug Mode: \" . (Environment::isDebug() ? 'enabled' : 'disabled') . \"\\n\";\n```\n\n### Common Issues\n\n**Environment not detected correctly:**\n- Set `WP_ENVIRONMENT_TYPE` constant in wp-config.php\n- Use `.env` file with `WP_ENV=development`\n- Check domain-based detection logic\n\n**Values not loading:**\n- Verify constant names (WordPress constants take priority)\n- Check if oscarotero/env is installed for .env support\n- Clear cache with `Environment::clearCache()`\n\n**Container detection issues:**\n- Ensure Docker environment variables are set\n- Check if `.dockerenv` file exists\n- Use custom detection with hooks\n\n## Requirements\n\n- PHP 8.0 or higher\n- WordPress 5.0 or higher (for WordPress-specific features)\n- Optional: [oscarotero/env](https://packagist.org/packages/oscarotero/env) for .env file support\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for a detailed list of changes for each release.\n\nWe follow [Semantic Versioning](https://semver.org/) and use [Conventional Commits](https://www.conventionalcommits.org/) to automatically generate our changelog.\n\n### Release Process\n\n- **Major versions** (1.0.0 → 2.0.0): Breaking changes\n- **Minor versions** (1.0.0 → 1.1.0): New features, backward compatible\n- **Patch versions** (1.0.0 → 1.0.1): Bug fixes, backward compatible\n\nAll releases are automatically created when changes are pushed to the `main` branch, based on commit message conventions.\n\n## Contributing\n\nFor your contributions please use:\n\n- [Conventional Commits](https://www.conventionalcommits.org)\n- [git-flow workflow](https://danielkummer.github.io/git-flow-cheatsheet/)\n- [Pull request workflow](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project)\n\nSee [CONTRIBUTING](.github/CONTRIBUTING.md) for detailed guidelines.\n\n## Sponsor\n\n[\u003cimg src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" width=\"200\" alt=\"Buy Me A Coffee\"\u003e](https://buymeacoff.ee/frugan)\n\n## License\n\n(ɔ) Copyleft 2025 [Frugan](https://frugan.it).  \n[GNU GPLv3](https://choosealicense.com/licenses/gpl-3.0/), see [LICENSE](LICENSE) file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwp-spaghetti%2Fwp-env","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwp-spaghetti%2Fwp-env","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwp-spaghetti%2Fwp-env/lists"}