FormAddressGeocoder::process()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 2
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace WebTheory\Saveyour\Processor;
4
5
use CommerceGuys\Addressing\Address;
6
use CommerceGuys\Addressing\AddressFormat\AddressFormatRepository;
7
use CommerceGuys\Addressing\Country\CountryRepository;
8
use CommerceGuys\Addressing\Formatter\DefaultFormatter;
9
use CommerceGuys\Addressing\Subdivision\SubdivisionRepository;
10
use Geocoder\Provider\Provider;
11
use Geocoder\Query\GeocodeQuery;
12
use Psr\Http\Message\ServerRequestInterface;
13
use WebTheory\Saveyour\Contracts\Data\FieldDataManagerInterface;
14
use WebTheory\Saveyour\Contracts\Formatting\InputFormatterInterface;
15
use WebTheory\Saveyour\Contracts\Processor\FormDataProcessorInterface;
16
use WebTheory\Saveyour\Contracts\Report\FormProcessReportInterface;
17
use WebTheory\Saveyour\Formatting\LazyDataFormatter;
18
use WebTheory\Saveyour\Processor\Abstracts\AbstractRestrictedFormDataProcessor;
19
use WebTheory\Saveyour\Report\Builder\FormProcessReportBuilder;
20
21
class FormAddressGeocoder extends AbstractRestrictedFormDataProcessor implements FormDataProcessorInterface
22
{
23
    protected string $countryCode = 'US';
24
25
    protected Provider $provider;
26
27
    protected FieldDataManagerInterface $addressDataManager;
28
29
    protected InputFormatterInterface $geoDataFormatter;
30
31
    protected FieldDataManagerInterface $geoDataManager;
32
33
    protected InputFormatterInterface $addressDataFormatter;
34
35
    /**
36
     * {@inheritDoc}
37
     */
38
    public const ACCEPTED_FIELDS = ['street', 'city', 'state', 'zip', 'country'];
39
40 9
    public function __construct(
41
        string $name,
42
        array $fields,
43
        Provider $provider,
44
        FieldDataManagerInterface $geoDataManager,
45
        ?InputFormatterInterface $geoDataFormatter = null,
46
        ?FieldDataManagerInterface $addressDataManager = null,
47
        ?InputFormatterInterface $addressDataFormatter = null,
48
        string $countryCode = 'US'
49
    ) {
50 9
        parent::__construct($name, $fields);
51
52 9
        $this->provider = $provider;
53 9
        $this->geoDataManager = $geoDataManager;
54 9
        $this->geoDataFormatter = $geoDataFormatter ?? new LazyDataFormatter();
55
56 9
        if ($addressDataManager) {
57 9
            $this->addressDataManager = $addressDataManager;
58 9
            $this->addressDataFormatter = $addressDataFormatter ?? new LazyDataFormatter();
59
        }
60
61 9
        $this->countryCode = $countryCode;
62
    }
63
64 9
    public function process(ServerRequestInterface $request, array $results): ?FormProcessReportInterface
65
    {
66 9
        return $this->valueUpdated($results)
67 9
            ? $this->processResults($request, $results)
68 9
            : null;
69
    }
70
71 9
    protected function processResults(ServerRequestInterface $request, $results): FormProcessReportInterface
72
    {
73 9
        $address = $this->getFormattedAddress($this->extractValues($results));
74
75 9
        $query = $this->provider->geocodeQuery(GeocodeQuery::create($address));
76 9
        $data = $query->first()->getCoordinates();
77
78 6
        $coordinates = [
79 9
            'lat' => $data->getLatitude(),
80 9
            'lng' => $data->getLongitude(),
81
        ];
82
83 9
        $geoUpdated = $this->geoDataManager->handleSubmittedData(
84
            $request,
85 9
            $this->formatGeoDataInput($coordinates)
86
        );
87
88 9
        if (isset($this->addressDataManager)) {
89 6
            $addressUpdated = $this->addressDataManager->handleSubmittedData(
90
                $request,
91 6
                $this->formatAddressInput($address)
92
            );
93
        }
94
95 9
        $reportBuilder = new FormProcessReportBuilder();
96
97
        return $reportBuilder
98 9
            ->withProcessResult('coordinates', $coordinates)
99 9
            ->withProcessResult('coordinates_updated', $geoUpdated)
100 9
            ->withProcessResult('address_updated', $addressUpdated ?? false)
101 9
            ->build();
102
    }
103
104 9
    protected function getFormattedAddress(array $fields): string
105
    {
106 9
        $address = (new Address())
107 9
            ->withAddressLine1($fields['street'])
108 9
            ->withLocality($fields['city'])
109 9
            ->withAdministrativeArea($fields['state'])
110 9
            ->withPostalCode($fields['zip'])
111 9
            ->withCountryCode($fields['country'] ?? $this->countryCode);
112
113 6
        $options = [
114
            'html' => false,
115
        ];
116
117 9
        $formatter = new DefaultFormatter(
118 9
            new AddressFormatRepository(),
119 9
            new CountryRepository(),
120 9
            new SubdivisionRepository(),
121
            $options
122
        );
123
124 9
        return str_replace("\n", ", ", $formatter->format($address));
125
    }
126
127 9
    protected function formatGeoDataInput($value)
128
    {
129 9
        return $this->geoDataFormatter->formatInput($value);
130
    }
131
132 6
    protected function formatAddressInput($value)
133
    {
134 6
        return $this->addressDataFormatter->formatInput($value);
135
    }
136
}
137