Update for PHP 8.2
This commit is contained in:
parent
40616f8346
commit
91976bbc02
@ -4,6 +4,10 @@ Stand-alone script designed to run via cron or systemd to back-up EC2 volumes on
|
|||||||
|
|
||||||
All volumes associated with the EC2 instance are backed up.
|
All volumes associated with the EC2 instance are backed up.
|
||||||
|
|
||||||
|
This script does not freeze the volume or a database or wait for inactivity. It just creates snapshots. High traffic
|
||||||
|
servers should not use this as their only means of backup since there is a chance the database could be mid-write
|
||||||
|
during the snapshot start which will break the database.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
After the required configuration settings are set up in the `.env` file, simply executing `php backup.php` will
|
After the required configuration settings are set up in the `.env` file, simply executing `php backup.php` will
|
||||||
perform the backup. The script has additional options such as `--no-prune` to prevent the script from removing old
|
perform the backup. The script has additional options such as `--no-prune` to prevent the script from removing old
|
||||||
@ -89,4 +93,5 @@ WantedBy=timers.target
|
|||||||
```
|
```
|
||||||
|
|
||||||
To activate the schedule, execute the command (noting the sudo use)
|
To activate the schedule, execute the command (noting the sudo use)
|
||||||
|
|
||||||
`sudo systemctl start ec2-backup.timer`
|
`sudo systemctl start ec2-backup.timer`
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Date Helper
|
* Dates.php
|
||||||
*
|
*
|
||||||
* @package Fairbanks\Kizarian\Utilities
|
* @copyright 2023 Fairbanks Publishing LLC
|
||||||
* @copyright (c) 2018, Fairbanks Publishing
|
|
||||||
* @license Proprietary
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace App;
|
namespace App;
|
||||||
@ -26,19 +24,19 @@ class Dates {
|
|||||||
*
|
*
|
||||||
* @return Carbon
|
* @return Carbon
|
||||||
*/
|
*/
|
||||||
public static function makeCarbon($date, Carbon $default=null)
|
public static function makeCarbon(mixed $date, Carbon $default=null): Carbon
|
||||||
{
|
{
|
||||||
if(is_object($date) && $date instanceof Carbon) {
|
if ($date instanceof Carbon) {
|
||||||
return $date;
|
return $date;
|
||||||
} elseif(is_object($date) && $date instanceof \DateTime) {
|
} elseif ($date instanceof \DateTime) {
|
||||||
return Carbon::instance($date);
|
return Carbon::instance($date);
|
||||||
} elseif(is_object($date)) {
|
} elseif (is_object($date)) {
|
||||||
return Carbon::parse($date->date, $date->timezone);
|
return Carbon::parse($date->date, $date->timezone);
|
||||||
} elseif(is_array($date)) {
|
} elseif (is_array($date)) {
|
||||||
return Carbon::parse($date['date'], $date['timezone']);
|
return Carbon::parse($date['date'], $date['timezone']);
|
||||||
} elseif(is_numeric($date)) {
|
} elseif (is_numeric($date)) {
|
||||||
return Carbon::createFromTimestamp($date);
|
return Carbon::createFromTimestamp($date);
|
||||||
} elseif(is_string($date)) {
|
} elseif (is_string($date)) {
|
||||||
return Carbon::parse($date);
|
return Carbon::parse($date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* (file name)
|
* Ec2Backup.php
|
||||||
*
|
*
|
||||||
* @copyright (c) 2019, Fairbanks Publishing
|
* @copyright 2023 Fairbanks Publishing LLC
|
||||||
* @license Proprietary
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace App;
|
namespace App;
|
||||||
@ -21,19 +20,19 @@ class Ec2Backup
|
|||||||
/**
|
/**
|
||||||
* @var Ec2Client
|
* @var Ec2Client
|
||||||
*/
|
*/
|
||||||
private $ec2Client;
|
private Ec2Client $ec2Client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var boolean
|
* @var boolean
|
||||||
*/
|
*/
|
||||||
private $enable = true;
|
private bool $enable = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of completed backups to keep
|
* Number of completed backups to keep
|
||||||
* This is the number BEFORE a backup is started
|
* This is the number BEFORE a backup is started
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $maxBackupCount = 4;
|
private int $maxBackupCount = 4;
|
||||||
|
|
||||||
public function __construct(Ec2Client $ec2Client) {
|
public function __construct(Ec2Client $ec2Client) {
|
||||||
$this->ec2Client = $ec2Client;
|
$this->ec2Client = $ec2Client;
|
||||||
@ -45,11 +44,11 @@ class Ec2Backup
|
|||||||
$this->maxBackupCount = 4;
|
$this->maxBackupCount = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(array $options=[])
|
public function create(array $options=[]): void
|
||||||
{
|
{
|
||||||
$options = array_merge(['noPrune' => false, 'force' => false], $options);
|
$options = array_merge(['noPrune' => false, 'force' => false], $options);
|
||||||
|
|
||||||
if($this->enable == false && $options['force'] != true) {
|
if (!$this->enable && !$options['force']) {
|
||||||
app_echo('EC2 Backup is disabled in environment');
|
app_echo('EC2 Backup is disabled in environment');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -69,7 +68,7 @@ class Ec2Backup
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($machine['type'] != 'ec2') {
|
if ($machine['type'] != 'ec2') {
|
||||||
app_echo('Instance type is wrong to do an EC2 backup', $machine);
|
app_echo('Instance type is wrong to do an EC2 backup', $machine);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -77,8 +76,8 @@ class Ec2Backup
|
|||||||
$volumes = $this->getVolumes($machine['instanceId']);
|
$volumes = $this->getVolumes($machine['instanceId']);
|
||||||
$tags = $this->getTags($machine['instanceId']);
|
$tags = $this->getTags($machine['instanceId']);
|
||||||
|
|
||||||
foreach($volumes as $volume) {
|
foreach ($volumes as $volume) {
|
||||||
if($options['noPrune'] == true) {
|
if ($options['noPrune']) {
|
||||||
$pruneWording = '(pruning disabled)';
|
$pruneWording = '(pruning disabled)';
|
||||||
} else {
|
} else {
|
||||||
$pruneCount = $this->pruneBackups($volume['volumeId']);
|
$pruneCount = $this->pruneBackups($volume['volumeId']);
|
||||||
@ -86,11 +85,10 @@ class Ec2Backup
|
|||||||
}
|
}
|
||||||
|
|
||||||
$name = (isset($tags['Name'])) ? $tags['Name'] : $machine['instanceId'];
|
$name = (isset($tags['Name'])) ? $tags['Name'] : $machine['instanceId'];
|
||||||
if(count($volumes) > 1)
|
if (count($volumes) > 1)
|
||||||
$name .= " ({$volume['device']})";
|
$name .= " ({$volume['device']})";
|
||||||
|
|
||||||
$r = $this->backup(['volumeId' => $volume['volumeId'], 'name' => $name]);
|
if ($this->backup(['volumeId' => $volume['volumeId'], 'name' => $name])) {
|
||||||
if($r == true) {
|
|
||||||
app_echo("Successfully started snapshot for {$volume['volumeId']} {$pruneWording}");
|
app_echo("Successfully started snapshot for {$volume['volumeId']} {$pruneWording}");
|
||||||
} else {
|
} else {
|
||||||
app_echo("Error starting snapshot for {$volume['volumeId']} {$pruneWording}");
|
app_echo("Error starting snapshot for {$volume['volumeId']} {$pruneWording}");
|
||||||
@ -98,7 +96,7 @@ class Ec2Backup
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVolumes($instanceId)
|
public function getVolumes($instanceId): array
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$result = $this->ec2Client->describeVolumes(
|
$result = $this->ec2Client->describeVolumes(
|
||||||
@ -118,7 +116,7 @@ class Ec2Backup
|
|||||||
}
|
}
|
||||||
|
|
||||||
$volumes = [];
|
$volumes = [];
|
||||||
foreach($result['Volumes'] as $volume) {
|
foreach ($result['Volumes'] as $volume) {
|
||||||
$volumes[$volume['VolumeId']] = [
|
$volumes[$volume['VolumeId']] = [
|
||||||
'device' => $volume['Attachments'][0]['Device'],
|
'device' => $volume['Attachments'][0]['Device'],
|
||||||
'volumeId' => $volume['VolumeId']
|
'volumeId' => $volume['VolumeId']
|
||||||
@ -128,7 +126,7 @@ class Ec2Backup
|
|||||||
return $volumes;
|
return $volumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTags($instanceId)
|
public function getTags($instanceId): array
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$result = $this->ec2Client->describeTags(
|
$result = $this->ec2Client->describeTags(
|
||||||
@ -148,14 +146,14 @@ class Ec2Backup
|
|||||||
}
|
}
|
||||||
|
|
||||||
$tags = [];
|
$tags = [];
|
||||||
foreach($result['Tags'] as $tag) {
|
foreach ($result['Tags'] as $tag) {
|
||||||
$tags[$tag['Key']] = $tag['Value'];
|
$tags[$tag['Key']] = $tag['Value'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $tags;
|
return $tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBackups($volumeId)
|
public function getBackups($volumeId): array
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$result = $this->ec2Client->describeSnapshots(
|
$result = $this->ec2Client->describeSnapshots(
|
||||||
@ -175,19 +173,19 @@ class Ec2Backup
|
|||||||
}
|
}
|
||||||
|
|
||||||
$snapshots = [];
|
$snapshots = [];
|
||||||
foreach($result['Snapshots'] as $snapshot) {
|
foreach ($result['Snapshots'] as $snapshot) {
|
||||||
if($snapshot['State'] != 'completed')
|
if ($snapshot['State'] != 'completed')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$snapshots[$snapshot['SnapshotId']] = [
|
$snapshots[$snapshot['SnapshotId']] = [
|
||||||
'started' => Dates::makeCarbon($snapshot['StartTime']),
|
'started' => Dates::makeCarbon($snapshot['StartTime']),
|
||||||
'description' => $snapshot['Description'],
|
'description' => $snapshot['Description'],
|
||||||
'snapshotId' => $snapshot['SnapshotId']
|
'snapshotId' => $snapshot['SnapshotId'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
uasort($snapshots, function($a, $b) {
|
uasort($snapshots, function($a, $b) {
|
||||||
if($a['started'] == $b['started']) {
|
if ($a['started'] == $b['started']) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return $a['started'] > $b['started'] ? 1 : 0;
|
return $a['started'] > $b['started'] ? 1 : 0;
|
||||||
@ -197,19 +195,21 @@ class Ec2Backup
|
|||||||
return $snapshots;
|
return $snapshots;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pruneBackups($volumeId)
|
public function pruneBackups($volumeId): int
|
||||||
{
|
{
|
||||||
$backups = $this->getBackups($volumeId);
|
$backups = $this->getBackups($volumeId);
|
||||||
|
|
||||||
if(count($backups) <= $this->maxBackupCount)
|
if (count($backups) <= $this->maxBackupCount) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
$prune = array_slice($backups, 0, count($backups) - $this->maxBackupCount);
|
$prune = array_slice($backups, 0, count($backups) - $this->maxBackupCount);
|
||||||
if(empty($prune))
|
if(empty($prune)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach($prune as $snapshotId => $snapshot) {
|
foreach ($prune as $snapshotId => $snapshot) {
|
||||||
try {
|
try {
|
||||||
$this->ec2Client->deleteSnapshot(
|
$this->ec2Client->deleteSnapshot(
|
||||||
[
|
[
|
||||||
@ -228,9 +228,9 @@ class Ec2Backup
|
|||||||
return $count;
|
return $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function backup(array $params)
|
public function backup(array $params): bool
|
||||||
{
|
{
|
||||||
if(!isset($params['volumeId'])) {
|
if (!isset($params['volumeId'])) {
|
||||||
app_echo('Volume ID is not set in backup parameters');
|
app_echo('Volume ID is not set in backup parameters');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -239,8 +239,8 @@ class Ec2Backup
|
|||||||
|
|
||||||
$tags = [['Key' => 'Name', 'Value' => $name]];
|
$tags = [['Key' => 'Name', 'Value' => $name]];
|
||||||
$snapTags = json_decode(config('TAGS', '[]'), true);
|
$snapTags = json_decode(config('TAGS', '[]'), true);
|
||||||
if(is_array($snapTags) && !empty($snapTags)) {
|
if (is_array($snapTags) && !empty($snapTags)) {
|
||||||
foreach($snapTags as $key => $value) {
|
foreach ($snapTags as $key => $value) {
|
||||||
$tags[] = ['Key' => $key, 'Value' => $value];
|
$tags[] = ['Key' => $key, 'Value' => $value];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Machine Details for Logging
|
* MachineDetails.php
|
||||||
*
|
*
|
||||||
* @copyright (c) 2017, Fairbanks Publishing
|
* @copyright 2023 Fairbanks Publishing LLC
|
||||||
* @license Proprietary
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace App;
|
namespace App;
|
||||||
@ -19,12 +18,12 @@ class MachineDetails
|
|||||||
/**
|
/**
|
||||||
* @var MachineDetails
|
* @var MachineDetails
|
||||||
*/
|
*/
|
||||||
protected static $instance;
|
protected static MachineDetails $instance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected static $details = [
|
protected static array $details = [
|
||||||
'type' => null,
|
'type' => null,
|
||||||
'id' => null,
|
'id' => null,
|
||||||
'machineId' => null,
|
'machineId' => null,
|
||||||
@ -36,14 +35,14 @@ class MachineDetails
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* PHP config setting for default_socket_timeout to reset to after doing file_get_contents()
|
* PHP config setting for default_socket_timeout to reset to after doing file_get_contents()
|
||||||
* @var int
|
* @var int|null
|
||||||
*/
|
*/
|
||||||
protected $socketTimeout = null;
|
protected ?int $socketTimeout = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return MachineDetails
|
* @return MachineDetails
|
||||||
*/
|
*/
|
||||||
public static function getInstance()
|
public static function getInstance(): MachineDetails
|
||||||
{
|
{
|
||||||
if (!isset(static::$instance)) {
|
if (!isset(static::$instance)) {
|
||||||
static::$instance = new static;
|
static::$instance = new static;
|
||||||
@ -55,7 +54,7 @@ class MachineDetails
|
|||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function getDetails()
|
public static function getDetails(): array
|
||||||
{
|
{
|
||||||
if(self::$instance === null)
|
if(self::$instance === null)
|
||||||
self::$instance = self::getInstance();
|
self::$instance = self::getInstance();
|
||||||
@ -66,7 +65,7 @@ class MachineDetails
|
|||||||
/**
|
/**
|
||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public static function id()
|
public static function id(): ?string
|
||||||
{
|
{
|
||||||
if(self::$instance === null)
|
if(self::$instance === null)
|
||||||
self::$instance = self::getInstance();
|
self::$instance = self::getInstance();
|
||||||
@ -77,7 +76,7 @@ class MachineDetails
|
|||||||
/**
|
/**
|
||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public static function machineId()
|
public static function machineId(): ?string
|
||||||
{
|
{
|
||||||
if(self::$instance === null)
|
if(self::$instance === null)
|
||||||
self::$instance = self::getInstance();
|
self::$instance = self::getInstance();
|
||||||
@ -88,7 +87,7 @@ class MachineDetails
|
|||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function fullMachineId()
|
public static function fullMachineId(): string
|
||||||
{
|
{
|
||||||
if(self::$instance === null)
|
if(self::$instance === null)
|
||||||
self::$instance = self::getInstance();
|
self::$instance = self::getInstance();
|
||||||
@ -105,7 +104,7 @@ class MachineDetails
|
|||||||
/**
|
/**
|
||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public static function region()
|
public static function region(): ?string
|
||||||
{
|
{
|
||||||
if(self::$instance === null)
|
if(self::$instance === null)
|
||||||
self::$instance = self::getInstance();
|
self::$instance = self::getInstance();
|
||||||
@ -116,19 +115,16 @@ class MachineDetails
|
|||||||
/**
|
/**
|
||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public static function publicIp()
|
public static function publicIp(): ?string
|
||||||
{
|
{
|
||||||
if(self::$instance === null)
|
if(self::$instance === null)
|
||||||
self::$instance = self::getInstance();
|
self::$instance = self::getInstance();
|
||||||
|
|
||||||
if(self::$details['publicIp'] === null) {
|
if(self::$details['publicIp'] === null) {
|
||||||
switch(self::$details['type']) {
|
self::$details['publicIp'] = match (self::$details['type']) {
|
||||||
case 'ec2' :
|
'ec2' => self::getEc2PublicIp(),
|
||||||
self::$details['publicIp'] = self::getEc2PublicIp();
|
default => self::getLocalPublicIp(),
|
||||||
break;
|
};
|
||||||
default :
|
|
||||||
self::$details['publicIp'] = self::getLocalPublicIp();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$details['privateIp'];
|
return self::$details['privateIp'];
|
||||||
@ -137,7 +133,7 @@ class MachineDetails
|
|||||||
/**
|
/**
|
||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public static function privateIp()
|
public static function privateIp(): ?string
|
||||||
{
|
{
|
||||||
if(self::$instance === null)
|
if(self::$instance === null)
|
||||||
self::$instance = self::getInstance();
|
self::$instance = self::getInstance();
|
||||||
@ -147,12 +143,12 @@ class MachineDetails
|
|||||||
|
|
||||||
/* Private methods */
|
/* Private methods */
|
||||||
|
|
||||||
private static function getLocalPublicIp()
|
private static function getLocalPublicIp(): string
|
||||||
{
|
{
|
||||||
return '127.0.0.1';
|
return '127.0.0.1';
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getEc2PublicIp()
|
private static function getEc2PublicIp(): false|string
|
||||||
{
|
{
|
||||||
if(self::$instance === null)
|
if(self::$instance === null)
|
||||||
self::$instance = self::getInstance();
|
self::$instance = self::getInstance();
|
||||||
@ -186,7 +182,7 @@ class MachineDetails
|
|||||||
*/
|
*/
|
||||||
private function __clone() {}
|
private function __clone() {}
|
||||||
|
|
||||||
private function determineMachineType()
|
private function determineMachineType(): string
|
||||||
{
|
{
|
||||||
$this->shortenTimeout();
|
$this->shortenTimeout();
|
||||||
$hostname = @file_get_contents('http://169.254.169.254/latest/meta-data/hostname');
|
$hostname = @file_get_contents('http://169.254.169.254/latest/meta-data/hostname');
|
||||||
@ -199,7 +195,7 @@ class MachineDetails
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getLocalData()
|
private function getLocalData(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => 'dev',
|
'id' => 'dev',
|
||||||
@ -210,7 +206,7 @@ class MachineDetails
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getEc2Data()
|
private function getEc2Data(): array
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* curl "http://169.254.169.254/latest/dynamic/instance-identity/document"
|
* curl "http://169.254.169.254/latest/dynamic/instance-identity/document"
|
||||||
@ -253,7 +249,7 @@ class MachineDetails
|
|||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function shortenTimeout()
|
private function shortenTimeout(): void
|
||||||
{
|
{
|
||||||
if($this->socketTimeout === null) {
|
if($this->socketTimeout === null) {
|
||||||
$this->socketTimeout = ini_get('default_socket_timeout');
|
$this->socketTimeout = ini_get('default_socket_timeout');
|
||||||
@ -262,7 +258,7 @@ class MachineDetails
|
|||||||
ini_set('default_socket_timeout', 2);
|
ini_set('default_socket_timeout', 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resetTimeout()
|
private function resetTimeout(): void
|
||||||
{
|
{
|
||||||
if($this->socketTimeout !== null) {
|
if($this->socketTimeout !== null) {
|
||||||
ini_set('default_socket_timeout', $this->socketTimeout);
|
ini_set('default_socket_timeout', $this->socketTimeout);
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
* Global helper functions
|
* Global helper functions
|
||||||
*
|
*
|
||||||
* @copyright (c) 2018, Fairbanks Publishing
|
* @copyright (c) 2018, Fairbanks Publishing
|
||||||
* @license Proprietary
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(!function_exists('array_combine_safe')) {
|
if(!function_exists('array_combine_safe')) {
|
||||||
@ -16,15 +15,15 @@ if(!function_exists('array_combine_safe')) {
|
|||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function array_combine_safe(array $keys = [], array $values = [], $default = null)
|
function array_combine_safe(array $keys = [], array $values = [], $default = null): array
|
||||||
{
|
{
|
||||||
if(empty($keys)) {
|
if (empty($keys)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$out = [];
|
$out = [];
|
||||||
|
|
||||||
foreach($keys as $index => $key) {
|
foreach ($keys as $index => $key) {
|
||||||
$out[$key] = (isset($values[$index])) ? $values[$index] : $default;
|
$out[$key] = (isset($values[$index])) ? $values[$index] : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ if(!function_exists('array_limit_keys')) {
|
|||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function array_limit_keys(array $keys = [], array $input = [])
|
function array_limit_keys(array $keys = [], array $input = []): array
|
||||||
{
|
{
|
||||||
if(empty($keys)) {
|
if(empty($keys)) {
|
||||||
return [];
|
return [];
|
||||||
@ -54,8 +53,8 @@ if(!function_exists('array_limit_keys')) {
|
|||||||
//}, ARRAY_FILTER_USE_KEY);
|
//}, ARRAY_FILTER_USE_KEY);
|
||||||
|
|
||||||
$out = [];
|
$out = [];
|
||||||
foreach($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
if(array_key_exists($key, $input)) {
|
if (array_key_exists($key, $input)) {
|
||||||
$out[$key] = $input[$key];
|
$out[$key] = $input[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,28 +98,22 @@ if(!function_exists('boolean')) {
|
|||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
function boolean($var)
|
function boolean(bool|int|string|null $var): bool
|
||||||
{
|
{
|
||||||
if(is_bool($var)) {
|
if (is_bool($var)) {
|
||||||
return ($var == true);
|
return ($var == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_string($var)) {
|
if (is_string($var)) {
|
||||||
$var = strtolower($var);
|
$var = strtolower($var);
|
||||||
|
|
||||||
switch($var) {
|
return match ($var) {
|
||||||
case 'true' :
|
'true', 'on', 'yes', 'y', '1' => true,
|
||||||
case 'on' :
|
default => false,
|
||||||
case 'yes' :
|
};
|
||||||
case 'y' :
|
|
||||||
case '1' :
|
|
||||||
return true;
|
|
||||||
default :
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_numeric($var)) {
|
if (is_numeric($var)) {
|
||||||
return ($var == 1);
|
return ($var == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,12 +124,12 @@ if(!function_exists('boolean')) {
|
|||||||
if(!function_exists('config')) {
|
if(!function_exists('config')) {
|
||||||
/**
|
/**
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param scalar $default
|
* @param float|bool|int|string|null $default
|
||||||
* @return scalar
|
* @return float|bool|int|string|null
|
||||||
*/
|
*/
|
||||||
function config($key, $default = null)
|
function config(string $key, float|bool|int|string $default = null): float|bool|int|string|null
|
||||||
{
|
{
|
||||||
if(array_key_exists($key, $_ENV)) {
|
if (array_key_exists($key, $_ENV)) {
|
||||||
return $_ENV[$key];
|
return $_ENV[$key];
|
||||||
} else {
|
} else {
|
||||||
return $default;
|
return $default;
|
||||||
@ -149,9 +142,9 @@ if(!function_exists('app_echo')) {
|
|||||||
* @param string $message
|
* @param string $message
|
||||||
* @param array $context
|
* @param array $context
|
||||||
*/
|
*/
|
||||||
function app_echo($message, $context = [])
|
function app_echo(string $message, array $context = []): void
|
||||||
{
|
{
|
||||||
if(is_array($context) && !empty($context)) {
|
if (is_array($context) && !empty($context)) {
|
||||||
$message .= ' ' . json_encode($context);
|
$message .= ' ' . json_encode($context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
|
"php": "^8.2",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"aws/aws-sdk-php": "^3.173",
|
"aws/aws-sdk-php": "^3.209",
|
||||||
"nesbot/carbon": "^2.45",
|
"nesbot/carbon": "^2.68",
|
||||||
"vlucas/phpdotenv": "^5.3"
|
"vlucas/phpdotenv": "^5.5"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"optimize-autoloader": true,
|
"optimize-autoloader": true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user