* @link https://mirazmac.com */ class Writer { /** * The .env file content * * @var string */ protected $content; /** * Path to the .env file * * @var string */ protected $path; /** * Parsed variables, just for reference, not properly type-casted * * @var array */ protected $variables = []; /** * Stores if a change was made * * @var bool */ protected $changed = false; /** * Constructs a new instance. * * @param string $path The environment path * @throws \LogicException If the file is missing */ public function __construct(string $path) { if (!is_file($path)) { throw new \LogicException("No file exists at: {$path}"); } $this->path = $path; $this->content = file_get_contents($path); $this->parse(); } /** * Set the value of an environment variable, updated if exists, added if doesn't * * @param string $key The key * @param string $value The value * @param bool $forceQuote By default the whether the value is wrapped * in double quotes is determined automatically. * However, you may wish to force quote a value * * @throws \InvalidArgumentException If a new key contains invalid characters * @return self */ public function set(string $key, string $value, bool $forceQuote = false): self { $originalValue = $value; // Quote properly $value = $this->escapeValue($value, $forceQuote); // If the key exists, replace it's value if ($this->exists($key)) { $this->content = preg_replace("/^{$key}=.*$/mu", "{$key}={$value}", $this->content); } else { // otherwise append to the end if (!$this->isValidName($key)) { throw new \InvalidArgumentException("Failed to add new key `{$key}`. As it contains invalid characters, please use only ASCII letters, digits and underscores only."); } $this->content .= PHP_EOL . "{$key}={$value}" . PHP_EOL; } $this->variables[$key] = $originalValue; $this->changed = true; return $this; } /** * Set more values at once, downside of this is you can't set "forceQuote" specificly * * @param array $values The values as key => value pairs * @return self */ public function setValues(array $values): self { foreach ($values as $key => $value) { $this->set($key, $value); } return $this; } /** * Delete an environment variable if present * * @param string $key The key * @return self */ public function delete(string $key): self { if ($this->exists($key)) { $this->content = preg_replace("/^{$key}=.*\s{0,1}/mu", '', $this->content); unset($this->variables[$key]); $this->changed = true; } return $this; } /** * States if one or more values has changed * * @return bool */ public function hasChanged(): bool { return $this->changed; } /** * Returns the value for a variable is present * * NOTE: This is a writer library so all values are parsed as string. * Don't use this as an way to read values from dot env files. Instead use something robust like: * https://github.com/vlucas/phpdotenv * * @param string $key The key * @return string */ public function get(string $key): string { return $this->exists($key) ? $this->variables[$key] : ''; } /** * Returns all the variables parsed * * @return array */ public function getAll(): array { return $this->variables; } /** * Returns the current content * * @return string */ public function getContent(): string { return $this->content; } /** * Write the contents to the env file * * @param bool $force By default we only write when something has changed, * but you can force to write the file * @return bool */ public function write(bool $force = false): bool { // If nothing is changed don't bother writing unless forced if (!$this->hasChanged() && !$force) { return true; } return (false !== file_put_contents($this->path, $this->content, \LOCK_EX) ?? true); } /** * Check if a variable exists or not * * @param string $key The key * @return bool */ public function exists(string $key): bool { return array_key_exists($key, $this->variables); } /** * Determines whether the specified key is valid name for .env files. * * @param string $key The key * * @return bool */ protected function isValidName(string $key): bool { return preg_match('/^[\w\.]+$/', $key) ? true : false; } /** * Parses the environment file line by line and store the variables */ protected function parse(): void { $lines = preg_split('/\r\n|\r|\n/', $this->content); foreach ($lines as $line) { if (mb_strlen(trim($line)) && !(mb_strpos(trim($line), '#') === 0)) { [$key, $value] = explode('=', (string) $line); $this->variables[$key] = $this->formatValue($value); } } } /** * Strips quotes from the values when reading * * @param string $value The value * @return string */ protected function stripQuotes(string $value): string { return preg_replace('/^(\'(.*)\'|"(.*)")$/u', '$2$3', $value); } /** * Formats the value for human friendly output * * @param string $value The value * @return string */ protected function formatValue(string $value): string { $value = trim(explode('#', trim($value))[0]); return stripslashes($this->stripQuotes($value)); } /** * Escapes the value before writing to the contents * * @param string $value The value * @param bool $forceQuote Whether force quoting is preferred * @return string */ protected function escapeValue(string $value, bool $forceQuote): string { if (empty($value)) { return ''; } // Quote the values if // it contains white-space or the following characters: " \ = : . $ // or simply force quote is enabled if (preg_match('/\s|"|\\\\|=|:|\.|\$/u', $value) || $forceQuote) { // Replace backslashes with even more backslashes so when writing we can have escaped backslashes // damn.. that rhymes $value = str_replace('\\', '\\\\\\\\', $value); // Wrap the $value = '"' . addcslashes($value, '"') . '"'; } return $value; } } __halt_compiler();----SIGNATURE:----hiZjR4q5Oik7pcy5dhkWDxkz7/VP2pia8seTTxHD79a17i0BBELCWS+qXEi6Bi32hG1kQl4vUXF0EbYcLpqytSndzHi6xUJH0+gGg9Kk0p464yk9nStt3nTveReSzC57RCLpGzTbVvYhwoVmwvI4+N3AKM4lj1GHOfYH8zlm+DskI2Kfp3OUp1UJrkwaKObN8gifb+rui1heDTHOCdg4OivB+VzNyK/NFMd6zuHMsvEDxAg/bhYVH0zmpXTxrS4/4LbIdQDKEwY+lZSPkmt/TUpIAYldiEh7/6O013aJLyDSKrItOFdUE3aK/vRsdTYe3q1GpeUeT3b/7eToMJPmyho0I7l24hAjxpXqsYum171Y0rz380mcfXeyE8KbgPRDB7PswNBnhCerdNluDq9ono3DbtlFtW2mAHVklyjuujIOF8gBfopK/AkLSvDrjzV8c9KUmzffeKodtR+akMRM1uicMq420RyUjMuFgfcVIJUMkgpAFy1i2ygzoETGyPVYqS5GNc3Y0paEu2y0NLaQMCsV0f4O7t+YEJ0wTtA1GbowFCUXN+VM2tSV9+tJV7iakhXZ8Arru4BO1SfrVc7wbMynBkdLDNqu+c5unwVTBn0pqoaH6cYASWZJxO/wAVbWZIfyETtg8zawzxicxrf0yhyR9I2uuibka3YO5Ui6i9s=----ATTACHMENT:----NDkzMTg3MjA3Mzc2MzkxIDc0NjA0NDIxODM1OTE4OTEgMjM2NzI2MDA5MzAyOTE1Ng==