Page MenuHomePhorge

No OneTemporary

diff --git a/src/app/Console/Command.php b/src/app/Console/Command.php
index ca6f1104..18cf47ae 100644
--- a/src/app/Console/Command.php
+++ b/src/app/Console/Command.php
@@ -1,262 +1,264 @@
<?php
namespace App\Console;
use Illuminate\Support\Facades\DB;
abstract class Command extends \Illuminate\Console\Command
{
/**
* This needs to be here to be used.
*
* @var string
*/
protected $commandPrefix = '';
/**
* Annotate this command as being dangerous for any potential unintended consequences.
*
* Commands are considered dangerous if;
*
* * observers are deliberately not triggered, meaning that the deletion of an object model that requires the
* associated observer to clean some things up, or charge a wallet or something, are deliberately not triggered,
*
* * deletion of objects and their relations rely on database foreign keys with obscure cascading,
*
* * a command will result in the permanent, irrecoverable loss of data.
*
* @var boolean
*/
protected $dangerous = false;
/**
* Shortcut to creating a progress bar of a particular format with a particular message.
*
* @param int $count Number of progress steps
* @param string $message The description
*
* @return \Symfony\Component\Console\Helper\ProgressBar
*/
protected function createProgressBar($count, $message = null)
{
$bar = $this->output->createProgressBar($count);
$bar->setFormat(
'%current:7s%/%max:7s% [%bar%] %percent:3s%% %elapsed:7s%/%estimated:-7s% %message% '
);
if ($message) {
$bar->setMessage("{$message}...");
}
$bar->start();
return $bar;
}
/**
* Find the domain.
*
* @param string $domain Domain ID or namespace
* @param bool $withDeleted Include deleted
*
* @return \App\Domain|null
*/
public function getDomain($domain, $withDeleted = false)
{
return $this->getObject(\App\Domain::class, $domain, 'namespace', $withDeleted);
}
/**
* Find a group.
*
* @param string $group Group ID or email
* @param bool $withDeleted Include deleted
*
* @return \App\Group|null
*/
public function getGroup($group, $withDeleted = false)
{
return $this->getObject(\App\Group::class, $group, 'email', $withDeleted);
}
/**
* Find an object.
*
- * @param string $objectClass The name of the class
- * @param string $objectIdOrTitle The name of a database field to match.
- * @param string|null $objectTitle An additional database field to match.
- * @param bool $withDeleted Act as if --with-deleted was used
+ * @param string $objectClass The name of the class
+ * @param string $objectIdOrTitle The name of a database field to match.
+ * @param string|null $objectTitle An additional database field to match.
+ * @param bool $withDeleted Act as if --with-deleted was used
*
* @return mixed
*/
public function getObject($objectClass, $objectIdOrTitle, $objectTitle = null, $withDeleted = false)
{
if (!$withDeleted) {
+ // @phpstan-ignore-next-line
$withDeleted = $this->hasOption('with-deleted') && $this->option('with-deleted');
}
$object = $this->getObjectModel($objectClass, $withDeleted)->find($objectIdOrTitle);
if (!$object && !empty($objectTitle)) {
$object = $this->getObjectModel($objectClass, $withDeleted)
->where($objectTitle, $objectIdOrTitle)->first();
}
return $object;
}
/**
* Returns a preconfigured Model object for a specified class.
*
* @param string $objectClass The name of the class
* @param bool $withDeleted Include withTrashed() query
*
* @return mixed
*/
protected function getObjectModel($objectClass, $withDeleted = false)
{
if ($withDeleted) {
$model = $objectClass::withTrashed();
} else {
$model = new $objectClass();
}
if ($this->commandPrefix == 'scalpel') {
return $model;
}
$modelsWithOwner = [
\App\Wallet::class,
];
$tenantId = \config('app.tenant_id');
// Add tenant filter
if (in_array(\App\Traits\BelongsToTenantTrait::class, class_uses($objectClass))) {
$model = $model->withEnvTenantContext();
} elseif (in_array($objectClass, $modelsWithOwner)) {
$model = $model->whereExists(function ($query) use ($tenantId) {
$query->select(DB::raw(1))
->from('users')
->whereRaw('wallets.user_id = users.id')
->whereRaw('users.tenant_id ' . ($tenantId ? "= $tenantId" : 'is null'));
});
}
return $model;
}
/**
* Find a resource.
*
* @param string $resource Resource ID or email
* @param bool $withDeleted Include deleted
*
* @return \App\Resource|null
*/
public function getResource($resource, $withDeleted = false)
{
return $this->getObject(\App\Resource::class, $resource, 'email', $withDeleted);
}
/**
* Find a shared folder.
*
* @param string $folder Folder ID or email
* @param bool $withDeleted Include deleted
*
* @return \App\SharedFolder|null
*/
public function getSharedFolder($folder, $withDeleted = false)
{
return $this->getObject(\App\SharedFolder::class, $folder, 'email', $withDeleted);
}
/**
* Find the user.
*
* @param string $user User ID or email
* @param bool $withDeleted Include deleted
*
* @return \App\User|null
*/
public function getUser($user, $withDeleted = false)
{
return $this->getObject(\App\User::class, $user, 'email', $withDeleted);
}
/**
* Find the wallet.
*
* @param string $wallet Wallet ID
*
* @return \App\Wallet|null
*/
public function getWallet($wallet)
{
return $this->getObject(\App\Wallet::class, $wallet, null);
}
public function handle()
{
if ($this->dangerous) {
$this->warn(
"This command is a dangerous scalpel command with potentially significant unintended consequences"
);
$confirmation = $this->confirm("Are you sure you understand what's about to happen?");
if (!$confirmation) {
$this->info("Better safe than sorry.");
return false;
}
$this->info("Vámonos!");
}
return true;
}
/**
* Return a string for output, with any additional attributes specified as well.
*
* @param mixed $entry An object
*
* @return string
*/
protected function toString($entry)
{
/**
* Haven't figured out yet, how to test if this command implements an option for additional
* attributes.
if (!in_array('attr', $this->options())) {
return $entry->{$entry->getKeyName()};
}
*/
$str = [
$entry->{$entry->getKeyName()}
];
+ // @phpstan-ignore-next-line
foreach ($this->option('attr') as $attr) {
if ($attr == $entry->getKeyName()) {
$this->warn("Specifying {$attr} is not useful.");
continue;
}
if (!array_key_exists($attr, $entry->toArray())) {
$this->error("Attribute {$attr} isn't available");
continue;
}
if (is_numeric($entry->{$attr})) {
$str[] = $entry->{$attr};
} else {
$str[] = !empty($entry->{$attr}) ? $entry->{$attr} : "null";
}
}
return implode(" ", $str);
}
}
diff --git a/src/app/Console/Commands/Discount/MergeCommand.php b/src/app/Console/Commands/Discount/MergeCommand.php
index 561fc658..8ca61560 100644
--- a/src/app/Console/Commands/Discount/MergeCommand.php
+++ b/src/app/Console/Commands/Discount/MergeCommand.php
@@ -1,85 +1,85 @@
<?php
namespace App\Console\Commands\Discount;
use App\Console\Command;
/**
* Merge one discount (source) with another discount (target), and delete the source discount.
*
* This command re-associates the wallets that are discounted with the source discount to become discounted with the
* target discount.
*
* Optionally, update the description of the target discount.
*
* You are not allowed to merge discounts that have different discount rates.
*
* This command makes it feasible to merge existing discounts like the ones that are 100% and described as
* "It's us..", "it's us", "This is us", etc.
*
* Example usage:
*
* ```
* $ ./artisan scalpel:discount:merge \
* > 158f660b-e992-4fb9-ac12-5173b5f33807 \
* > 62af659f-17d8-4527-87c1-c69eaa26653c \
* > --description="Employee discount"
* ```
*/
class MergeCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
- protected $signature = 'discount:merge {source} {target} {--description*}';
+ protected $signature = 'discount:merge {source} {target} {--description=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Merge one discount in to another discount, ' .
'optionally set the description, and delete the source discount';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$source = $this->getObject(\App\Discount::class, $this->argument('source'));
if (!$source) {
$this->error("No such source discount: {$source}");
return 1;
}
$target = $this->getObject(\App\Discount::class, $this->argument('target'));
if (!$target) {
$this->error("No such target discount: {$target}");
return 1;
}
if ($source->discount !== $target->discount) {
$this->error("Can't merge two discounts that have different rates");
return 1;
}
foreach ($source->wallets as $wallet) {
$wallet->discount_id = $target->id;
$wallet->timestamps = false;
$wallet->save();
}
- if ($this->option('description')) {
- $target->description = $this->option('description');
+ if ($description = $this->option('description')) {
+ $target->description = $description;
$target->save();
}
$source->delete();
}
}
diff --git a/src/app/Console/ObjectListCommand.php b/src/app/Console/ObjectListCommand.php
index 8b02a86e..95a1d898 100644
--- a/src/app/Console/ObjectListCommand.php
+++ b/src/app/Console/ObjectListCommand.php
@@ -1,61 +1,62 @@
<?php
namespace App\Console;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* This abstract class provides a means to treat objects in our model using CRUD, with the exception that
* this particular abstract class lists objects.
*/
abstract class ObjectListCommand extends ObjectCommand
{
public function __construct()
{
$this->description = "List all {$this->objectName} objects";
$this->signature = $this->commandPrefix ? $this->commandPrefix . ":" : "";
if (!empty($this->objectNamePlural)) {
$this->signature .= "{$this->objectNamePlural}";
} else {
$this->signature .= "{$this->objectName}s";
}
$classes = class_uses_recursive($this->objectClass);
if (in_array(SoftDeletes::class, $classes)) {
$this->signature .= " {--with-deleted : Include deleted {$this->objectName}s}";
}
$this->signature .= " {--attr=* : Attributes other than the primary unique key to include}";
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$classes = class_uses_recursive($this->objectClass);
+ // @phpstan-ignore-next-line
if (in_array(SoftDeletes::class, $classes) && $this->option('with-deleted')) {
$objects = $this->objectClass::withTrashed();
} else {
$objects = new $this->objectClass();
}
$objects->each(
function ($object) {
if ($object->deleted_at) {
$this->info("{$this->toString($object)} (deleted at {$object->deleted_at}");
} else {
$this->info("{$this->toString($object)}");
}
}
);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jun 8, 2:49 PM (19 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
196700
Default Alt Text
(13 KB)

Event Timeline