Skip to content

Commit aac5b8e

Browse files
committed
Allow to select which method should be used to in "Create from URL feature"
1 parent a2b9ee7 commit aac5b8e

7 files changed

Lines changed: 198 additions & 15 deletions

File tree

src/Controller/InfoProviderController.php

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
use App\Entity\Parts\Manufacturer;
2727
use App\Entity\Parts\Part;
2828
use App\Exceptions\OAuthReconnectRequiredException;
29+
use App\Form\InfoProviderSystem\FromURLFormType;
2930
use App\Form\InfoProviderSystem\PartSearchType;
3031
use App\Services\InfoProviderSystem\ExistingPartFinder;
32+
use App\Services\InfoProviderSystem\CreateFromUrlHelper;
3133
use App\Services\InfoProviderSystem\PartInfoRetriever;
3234
use App\Services\InfoProviderSystem\ProviderRegistry;
3335
use App\Services\InfoProviderSystem\Providers\GenericWebProvider;
@@ -219,35 +221,31 @@ public function search(Request $request, #[MapEntity(id: 'target')] ?Part $updat
219221
}
220222

221223
#[Route('/from_url', name: 'info_providers_from_url')]
222-
public function fromURL(Request $request, GenericWebProvider $provider): Response
224+
public function fromURL(Request $request, GenericWebProvider $provider, CreateFromUrlHelper $fromUrlHelper): Response
223225
{
224226
$this->denyAccessUnlessGranted('@info_providers.create_parts');
225227

226-
if (!$provider->isActive()) {
228+
if (!$fromUrlHelper->canCreateFromUrl()) {
227229
$this->addFlash('error', "Generic Web Provider is not active. Please enable it in the provider settings.");
228230
return $this->redirectToRoute('info_providers_list');
229231
}
230232

231-
$formBuilder = $this->createFormBuilder();
232-
$formBuilder->add('url', UrlType::class, [
233-
'label' => 'info_providers.from_url.url.label',
234-
'required' => true,
235-
]);
236-
$formBuilder->add('submit', SubmitType::class, [
237-
'label' => 'info_providers.search.submit',
238-
]);
239-
240-
$form = $formBuilder->getForm();
233+
$form = $this->createForm(FromURLFormType::class);
241234
$form->handleRequest($request);
242235

243236
$partDetail = null;
244237
if ($form->isSubmitted() && $form->isValid()) {
245238
//Try to retrieve the part detail from the given URL
246239
$url = $form->get('url')->getData();
240+
241+
$method = $form->get('method')->getData();
242+
$no_cache = $form->get('no_cache')->getData();
243+
247244
try {
245+
//It's okay if we use the cached results here, as its just for convenience
248246
$searchResult = $this->infoRetriever->searchByKeyword(
249247
keyword: $url,
250-
providers: [$provider]
248+
providers: [$method],
251249
);
252250

253251
if (count($searchResult) === 0) {
@@ -258,6 +256,7 @@ public function fromURL(Request $request, GenericWebProvider $provider): Respons
258256
return $this->redirectToRoute('info_providers_create_part', [
259257
'providerKey' => $searchResult->provider_key,
260258
'providerId' => $searchResult->provider_id,
259+
'no_cache' => $no_cache ? 1 : null,
261260
]);
262261
}
263262
} catch (ExceptionInterface $e) {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
24+
namespace App\Form\InfoProviderSystem;
25+
26+
use App\Services\InfoProviderSystem\ProviderRegistry;
27+
use Symfony\Component\Form\AbstractType;
28+
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
29+
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
30+
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
31+
use Symfony\Component\Form\Extension\Core\Type\UrlType;
32+
use Symfony\Component\Form\FormBuilderInterface;
33+
34+
class FromURLFormType extends AbstractType
35+
{
36+
public function __construct(private readonly ProviderRegistry $providerRegistry)
37+
{
38+
39+
}
40+
41+
public function buildForm(FormBuilderInterface $builder, array $options): void
42+
{
43+
$builder->add('url', UrlType::class, [
44+
'label' => 'info_providers.from_url.url.label',
45+
'required' => true,
46+
]);
47+
48+
49+
$builder->add('method', ChoiceType::class, [
50+
'expanded' => true,
51+
'data' => 'generic_web', //Default value
52+
'label' => 'info_providers.from_url.method',
53+
'choices' => [
54+
'info_providers.from_url.method.generic_web' => 'generic_web',
55+
'info_providers.from_url.method.ai_web' => 'ai_web',
56+
],
57+
'choice_attr' => function ($choice, $key, $value) {
58+
//Disable all providers that are not active
59+
$provider = $this->providerRegistry->getProviderByKey($value);
60+
if (!$provider->isActive()) {
61+
return ['disabled' => 'disabled'];
62+
}
63+
64+
return [];
65+
},
66+
67+
//Render the choices as inline radio buttons
68+
'label_attr' => [
69+
'class' => 'radio-inline',
70+
],
71+
]);
72+
73+
$builder->add('no_cache', CheckboxType::class, [
74+
'label' => 'info_providers.from_url.no_cache',
75+
'required' => false,
76+
]);
77+
78+
$builder->add('submit', SubmitType::class, [
79+
'label' => 'info_providers.search.submit',
80+
]);
81+
}
82+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
24+
namespace App\Services\InfoProviderSystem;
25+
26+
use App\Entity\UserSystem\User;
27+
use Symfony\Bundle\SecurityBundle\Security;
28+
29+
final readonly class CreateFromUrlHelper
30+
{
31+
public function __construct(private Security $security, private ProviderRegistry $providerRegistry)
32+
{
33+
}
34+
35+
/**
36+
* Checks if at least one provider can create parts from an URL and the current user is allowed to use it.
37+
* This is used to determine if the "From URL" feature should be shown to the user.
38+
* @return bool
39+
*/
40+
public function canCreateFromUrl(): bool
41+
{
42+
if (!$this->security->isGranted('@info_providers.create_parts')) {
43+
return false;
44+
}
45+
46+
//Check if either the generic web provider or the ai web provider is active
47+
$genericWebProvider = $this->providerRegistry->getProviderByKey('generic_web');
48+
$aiWebProvider = $this->providerRegistry->getProviderByKey('ai_web');
49+
50+
return $genericWebProvider->isActive() || $aiWebProvider->isActive();
51+
}
52+
}

src/Twig/MiscExtension.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
*/
2323
namespace App\Twig;
2424

25+
use App\Services\InfoProviderSystem\CreateFromUrlHelper;
2526
use Twig\Attribute\AsTwigFunction;
2627
use App\Settings\SettingsIcon;
2728
use Symfony\Component\HttpFoundation\Request;
@@ -34,7 +35,7 @@
3435

3536
final readonly class MiscExtension
3637
{
37-
public function __construct(private EventCommentNeededHelper $eventCommentNeededHelper)
38+
public function __construct(private EventCommentNeededHelper $eventCommentNeededHelper, private CreateFromUrlHelper $fromUrlHelper)
3839
{
3940
}
4041

@@ -84,4 +85,14 @@ public function uri_without_host(Request $request): string
8485

8586
return $request->getBaseUrl().$request->getPathInfo().$qs;
8687
}
88+
89+
/**
90+
* Returns true if the from url provider is active, false otherwise.
91+
* @return bool
92+
*/
93+
#[AsTwigFunction(name: 'create_from_url_active')]
94+
public function create_from_url_active(): bool
95+
{
96+
return $this->fromUrlHelper->canCreateFromUrl();
97+
}
8798
}

templates/_navbar.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
{% trans %}info_providers.search.title{% endtrans %}
5353
</a>
5454
</li>
55-
{% if settings_instance('generic_web_provider').enabled %}
55+
{% if create_from_url_active() %}
5656
<li>
5757
<a class="dropdown-item" href="{{ path('info_providers_from_url') }}">
5858
<i class="fa-fw fa-solid fa-book-atlas"></i>

templates/info_providers/from_url/from_url.html.twig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@
1616

1717
{{ form_start(form) }}
1818
{{ form_row(form.url) }}
19+
20+
{{ form_row(form.method) }}
21+
22+
<div class="row mb-2">
23+
<div class="{{ col_input }} {{ offset_label }}">
24+
<a data-bs-toggle="collapse" href="#infoSearchAdvancedPanel">{% trans %}info_providers.search.advanced_options{% endtrans %}</a>
25+
</div>
26+
</div>
27+
28+
<div class="collapse" id="infoSearchAdvancedPanel">
29+
<div class="card card-body mb-2">
30+
{{ form_row(form.no_cache) }}
31+
</div>
32+
</div>
33+
1934
{{ form_row(form.submit) }}
2035
{{ form_end(form) }}
2136
{% endblock %}

translations/messages.en.xlf

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13157,5 +13157,29 @@ Buerklin-API Authentication server:
1315713157
<target>Do not cache result details / Force fresh part detail retrieval</target>
1315813158
</segment>
1315913159
</unit>
13160+
<unit id="Ja8CCDb" name="info_providers.from_url.method.generic_web">
13161+
<segment>
13162+
<source>info_providers.from_url.method.generic_web</source>
13163+
<target>Classic Web Scraper</target>
13164+
</segment>
13165+
</unit>
13166+
<unit id="s0kUzFW" name="info_providers.from_url.method.ai_web">
13167+
<segment>
13168+
<source>info_providers.from_url.method.ai_web</source>
13169+
<target>AI Web Scraper</target>
13170+
</segment>
13171+
</unit>
13172+
<unit id="HEFB1OC" name="info_providers.from_url.method">
13173+
<segment>
13174+
<source>info_providers.from_url.method</source>
13175+
<target>Method</target>
13176+
</segment>
13177+
</unit>
13178+
<unit id="9pG0VtU" name="info_providers.from_url.no_cache">
13179+
<segment>
13180+
<source>info_providers.from_url.no_cache</source>
13181+
<target>Ignore cache / Force fresh info retrieval</target>
13182+
</segment>
13183+
</unit>
1316013184
</file>
1316113185
</xliff>

0 commit comments

Comments
 (0)