Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion _define.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@
'batch-propertieslist' => 'staff',
'removeProperty' => 'staff',
'removeProperties' => 'staff',
'doRemoveProperty' => 'staff'
'doRemoveProperty' => 'staff',
'autoPreferences' => 'admin',
'storeAutoPreferences' => 'admin'
],
dbver: 1.00
);
11 changes: 11 additions & 0 deletions _routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use Galette\Middleware\Authenticate;
use GaletteAuto\Controllers\Controller;
use GaletteAuto\Controllers\PreferencesController;
use GaletteAuto\Controllers\Crud\PropertiesController;
use GaletteAuto\Controllers\Crud\ModelsController;

Expand Down Expand Up @@ -219,3 +220,13 @@
'/{property:brand|color|state|finition|body|transmission}/remove[/{id:\d+}]',
[PropertiesController::class, 'doRemoveProperty']
)->setName('doRemoveProperty')->add(Authenticate::class);

$app->get(
'/preferences',
[PreferencesController::class, 'preferences']
)->setName('autoPreferences')->add(Authenticate::class);

$app->post(
'/preferences',
[PreferencesController::class, 'storePreferences']
)->setName('storeAutoPreferences')->add(Authenticate::class);
49 changes: 11 additions & 38 deletions lib/GaletteAuto/Auto.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,6 @@ class Auto
private Plugins $plugins;
private Db $zdb;

/** @var array<string, int> */
private array $required = [
'name' => 1,
'model' => 1,
'first_registration_date' => 1,
'first_circulation_date' => 1,
'color' => 1,
'state' => 1,
'registration' => 1,
'body' => 1,
'transmission' => 1,
'finition' => 1,
'fuel' => 1
];

private ?int $id = null;
private ?string $registration = null;
private ?string $name = null;
Expand Down Expand Up @@ -133,6 +118,8 @@ public function __construct(Plugins $plugins, Db $zdb, ?ArrayObject $args = null
'seats' => mb_strtolower(_T("Seats", "auto")),
'horsepower' => mb_strtolower(_T("Horsepower", "auto")),
'engine_size' => mb_strtolower(_T("Engine size", "auto")),
'chassis_number' => mb_strtolower(_T("Chassis number", "auto")),
'comment' => mb_strtolower(_T("Comment", "auto")),
'color' => mb_strtolower(_T("Color", "auto")),
'state' => mb_strtolower(_T("State", "auto")),
'finition' => mb_strtolower(_T("Finition", "auto")),
Expand Down Expand Up @@ -320,20 +307,20 @@ public function getPropName(string $name): string
/**
* Check posted values validity
*
* @param array<string,mixed> $post All values to check, basically the $_POST array
* after sending the form
* @param VehicleAccess $access Access rules for current user
* @param array<string,mixed> $post All values to check, basically the $_POST array
* after sending the form
* @param VehicleAccess $access Access rules for current user
* @param AutoPreferences $preferences Plugin preferences
*/
public function check(array $post, VehicleAccess $access): bool
public function check(array $post, VehicleAccess $access, AutoPreferences $preferences): bool
{
$this->errors = [];

//check for required fields, and correct values
$required = $this->getRequired();
foreach (self::POSTED_FIELDS as $prop) {
$value = $post[$prop] ?? null;

if (($value == '' || $value == null) && in_array($prop, array_keys($required))) {
if (($value == '' || $value == null) && $preferences->isRequired($prop)) {
$this->errors[] = str_replace(
'%field',
'<a href="#' . $prop . '">' . $this->getPropName($prop) . '</a>',
Expand Down Expand Up @@ -414,7 +401,9 @@ public function check(array $post, VehicleAccess $access): bool
break;
//constants
case 'fuel':
if (in_array((int)$value, array_keys($this->listFuels()), true)) {
if ($value === null || $value === '') {
$this->fuel = null;
} elseif (in_array((int)$value, array_keys($this->listFuels()), true)) {
$this->fuel = (int)$value;
} else {
$this->errors[] = _T("- You must choose a fuel in the list", "auto");
Expand Down Expand Up @@ -480,22 +469,6 @@ public function getErrors(): array
return $this->errors;
}

/**
* Get required fields
*
* @return array<string,int>
*/
public function getRequired(): array
{
$required = $this->required;

if (file_exists(GALETTE_CONFIG_PATH . 'local_auto_required.inc.php')) {
$required = require GALETTE_CONFIG_PATH . 'local_auto_required.inc.php';
}

return $required;
}

/**
* Handle car picture upload
*
Expand Down
169 changes: 169 additions & 0 deletions lib/GaletteAuto/AutoPreferences.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?php

/**
* This file is part of Galette Auto plugin (https://galette.eu).
* SPDX-FileCopyrightText: Copyright © 2009-2026 The Galette Team
* SPDX-License-Identifier: GPL-3.0-or-later
*/

declare(strict_types=1);

namespace GaletteAuto;

use Galette\Core\Preferences;
use Galette\Core\PreferencesSchema;

/**
* Plugin preferences
*
* They are stored by core preferences, which this class declares them to and
* reads them from.
*
* @author Johan Cwiklinski <johan@x-tnd.be>
*/
final class AutoPreferences
{
public const string PREFIX = 'pref_auto_';
/** Prefix of the yes/no preferences making a vehicle field required */
public const string REQUIRED_PREFIX = self::PREFIX . 'required_';

/**
* Former local configuration file for required fields
*
* It only seeds the preferences when core creates them; it can be
* removed afterwards.
*/
public const string LEGACY_FILE = 'local_auto_required.inc.php';

/**
* Vehicle fields that are always required
*
* Database does not allow them to be empty.
*
* @var array<string>
*/
public const array ALWAYS_REQUIRED = [
'model',
'first_registration_date',
'first_circulation_date',
'color',
'state',
'body',
'transmission',
'finition',
];

/**
* Vehicle fields that may be required, with their default
*
* @var array<string, bool>
*/
public const array OPTIONAL_FIELDS = [
'name' => true,
'registration' => true,
'fuel' => true,
'mileage' => false,
'seats' => false,
'horsepower' => false,
'engine_size' => false,
'chassis_number' => false,
'comment' => false,
];

/**
* Constructor
*
* @param Preferences $preferences Core preferences
*/
public function __construct(private readonly Preferences $preferences)
{
}

/**
* Get the preferences the plugin declares
*
* Defaults come from the former local configuration file when there is
* one, so its values are kept when core creates the preferences.
*
* @param string $config_path Configuration directory
*
* @return array<string, array<string, mixed>>
*/
public static function getSchema(string $config_path = GALETTE_CONFIG_PATH): array
{
$legacy = self::getLegacyRequired($config_path);

$schema = [];
foreach (self::OPTIONAL_FIELDS as $field => $default) {
$schema[self::REQUIRED_PREFIX . $field] = [
'type' => PreferencesSchema::TYPE_BOOL,
'default' => $legacy !== null ? isset($legacy[$field]) : $default,
];
}
return $schema;
}

/**
* Get required fields from the former local configuration file
*
* @param string $config_path Configuration directory
*
* @return ?array<string, mixed> Null when there is no such file
*/
private static function getLegacyRequired(string $config_path): ?array
{
$file = $config_path . self::LEGACY_FILE;
if (!file_exists($file)) {
return null;
}
$required = require $file;
return is_array($required) ? $required : null;
}

/**
* Is a vehicle field required?
*
* @param string $field Field name
*/
public function isRequired(string $field): bool
{
if (in_array($field, self::ALWAYS_REQUIRED, true)) {
return true;
}
if (!isset(self::OPTIONAL_FIELDS[$field])) {
return false;
}
//core hands a false boolean back as an empty string
return (bool)$this->preferences->getPluginValue(self::REQUIRED_PREFIX . $field);
}

/**
* Get required vehicle fields
*
* @return array<string, true> Field names as keys
*/
public function getRequired(): array
{
$required = [];
foreach (array_merge(self::ALWAYS_REQUIRED, array_keys(self::OPTIONAL_FIELDS)) as $field) {
if ($this->isRequired($field)) {
$required[$field] = true;
}
}
return $required;
}

/**
* Get the yes/no preferences, named after their field, for templates
*
* @return array<string, bool>
*/
public function toArray(): array
{
$values = [];
foreach (array_keys(self::OPTIONAL_FIELDS) as $field) {
$values[$field] = $this->isRequired($field);
}
return $values;
}
}
15 changes: 12 additions & 3 deletions lib/GaletteAuto/Controllers/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Galette\Repository\Members;
use GaletteAuto\AbstractObject;
use GaletteAuto\Auto;
use GaletteAuto\AutoPreferences;
use GaletteAuto\Body;
use GaletteAuto\Brand;
use GaletteAuto\Color;
Expand Down Expand Up @@ -75,6 +76,14 @@ protected function accessDenied(Response $response, string $log): Response
);
}

/**
* Get plugin preferences
*/
protected function getAutoPreferences(): AutoPreferences
{
return new AutoPreferences($this->preferences);
}

/**
* Get vehicles repository
*/
Expand Down Expand Up @@ -366,7 +375,7 @@ public function showAddEditVehicle(Request $request, Response $response, string
}

if ($this->session->auto !== null) {
$auto->check($this->session->auto, $this->getAccess());
$auto->check($this->session->auto, $this->getAccess(), $this->getAutoPreferences());
$this->session->auto = null;
}

Expand Down Expand Up @@ -397,7 +406,7 @@ public function showAddEditVehicle(Request $request, Response $response, string
'states' => $this->getProperties(State::class),
'fuels' => $auto->listFuels(),
'time' => time(),
'required' => $auto->getRequired()
'required' => $this->getAutoPreferences()->getRequired()
];

// members
Expand Down Expand Up @@ -473,7 +482,7 @@ public function doAddEditVehicle(Request $request, Response $response, string $a
}
}

$res = $auto->check($post, $this->getAccess());
$res = $auto->check($post, $this->getAccess(), $this->getAutoPreferences());
if ($res !== true) {
$error_detected = $auto->getErrors();
}
Expand Down
Loading
Loading