Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
42.86% covered (warning)
42.86%
3 / 7
CRAP
82.69% covered (success)
82.69%
43 / 52
AbbyyProvider
0.00% covered (danger)
0.00%
0 / 1
42.86% covered (warning)
42.86%
3 / 7
19.68
82.69% covered (success)
82.69%
43 / 52
 initClient
0.00% covered (danger)
0.00%
0 / 1
2.03
80.00% covered (success)
80.00%
4 / 5
 retrieveResponse
0.00% covered (danger)
0.00%
0 / 1
5.26
57.14% covered (warning)
57.14%
4 / 7
 createTask
0.00% covered (danger)
0.00%
0 / 1
5.33
76.47% covered (success)
76.47%
13 / 17
 getTaskStatus
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 getTaskValue
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
10 / 10
 formatOcrResponse
0.00% covered (danger)
0.00%
0 / 1
3.33
66.67% covered (warning)
66.67%
2 / 3
 deleteTask
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
1<?php
2
3namespace Qmp\Laravel\Ocr\Ocr\Providers\Abbyy;
4
5use Qmp\Laravel\Ocr\Ocr\Providers\ProviderAbstract;
6use Qmp\Laravel\Ocr\Models\Ocr;
7use Qmp\Laravel\Ocr\Exceptions\OcrException;
8use Exception;
9
10// https://support.abbyy.com/hc/en-us/articles/360017269420-api-reference?__hstc=92301634.fcceb8a8eb6477cf844372caabf56bb5.1632142305113.1632207906843.1632305058095.3&__hssc=92301634.13.1632305058095&__hsfp=728737239&_ga=2.261216203.735920226.1632305058-1152664003.1632142259&_gac=1.12665413.1632143524.CjwKCAjw4qCKBhAVEiwAkTYsPA6SXm5abgVRRsWvnjW9E48TGFWW2XnKP61FpCQTkHXjKM1ulsonnRoCq6cQAvD_BwE
11// https://github.com/abbyy/ocrsdk.com/blob/master/PHP/abbyy_php_example.php
12// https://github.com/guzzle/guzzle
13// https://docs.guzzlephp.org/en/stable/handlers-and-middleware.html
14// https://docs.guzzlephp.org/en/stable/testing.html
15use GuzzleHttp\Client as GuzzleClient;
16use Qmp\Laravel\Tests\Ocr\Client\Guzzle\GuzzleClientFake;
17
18class AbbyyProvider extends ProviderAbstract
19{
20    private $client;
21
22    private $dataPattern = [
23        'headers' => [
24            'User-Agent' => 'PHP Cloud OCR SDK',
25        ],
26        'auth' => [],
27        'http_errors' => false,
28        'multipart' => []
29    ];
30
31    protected function initClient()
32    {
33        if (config('app.env') === 'testing') {
34            $this->client = new GuzzleClient(['handler' => GuzzleClientFake::getHandlerStack()]);
35        } else {
36            $this->client = new GuzzleClient();
37        }
38        $this->dataPattern['auth'] = array(config('ocr.abbyy.login'), config('ocr.abbyy.password'));
39    }
40
41    public function retrieveResponse(Ocr $ocr): string
42    {
43        $taskId = $this->createTask($ocr->img_link, $ocr->data_type);
44        for ($cpt = 0; $this->getTaskStatus($taskId) !== 'OK' && $cpt < 20; $cpt++) {
45            sleep(1);
46        }
47        if ($this->getTaskStatus($taskId) === 'OK') {
48            return $this->getTaskValue($taskId, $ocr->data_type);
49        }
50
51        $this->deleteTask($taskId);
52        throw new OcrException("Provider hasn't found a response in the last 20 seconds", true);
53    }
54
55    private function createTask(string $imgLink, string $dataType): string
56    {
57
58        $postData = $this->dataPattern;
59        try {
60            $file = fopen($imgLink, 'r');
61            if (!$file) {
62                throw new OcrException('Unable to open file for reading');
63            }
64        } catch (Exception $e) {
65            throw new OcrException('Url does not exist ' . $e->getMessage());
66        }
67        $postData['multipart'] = [
68            ['name' => 'language', 'contents' => 'english, french'],
69            ['name' => 'typeText', 'contents' => 'normal'],
70            ['name' => 'barcodeType', 'contents' => 'ean13'],
71            ['name' => 'image', 'contents' => $file]
72        ];
73
74        switch ($dataType) {
75            case "bar_code_img":
76                $method = 'processBarcodeField';
77                break;
78            default:
79                $method = 'processTextField';
80        }
81        $res = $this->client->request('POST', 'https://cloud.ocrsdk.com/v2/' . $method, $postData);
82        $jsonResponse = json_decode($res->getBody());
83
84        return $jsonResponse->taskId;
85    }
86
87    private function getTaskStatus(string $taskId): string
88    {
89
90        $getData = $this->dataPattern;
91        array_push($getData['multipart'], array('name' => 'taskId', 'contents' =>  $taskId));
92
93        $res = $this->client->request('GET', 'https://cloud.ocrsdk.com/v2/getTaskStatus', $getData);
94        $jsonResponse = json_decode($res->getBody());
95        return $jsonResponse->status === 'Completed' ? 'OK' : 'KO';
96    }
97
98    private function getTaskValue(string $taskId, string $dataType): string
99    {
100
101        $getData = $this->dataPattern;
102        array_push($getData['multipart'], array('name' => 'taskId', 'contents' =>  $taskId));
103
104        $res = $this->client->request('GET', 'https://cloud.ocrsdk.com/v2/getTaskStatus', $getData);
105        $jsonResponse = json_decode($res->getBody());
106
107        $res = $this->client->request('GET', $jsonResponse->resultUrls[0]);
108
109
110        $cleanRes = str_replace(' xmlns="@link" xmlns:xsi="@link" xsi:schemaLocation="@link"', '', $res->getBody()->getContents());
111        
112        $xml = new \SimpleXMLElement($cleanRes);
113        $value = (string)$xml->field->value;
114        $this->deleteTask($taskId);
115
116        return $this->formatOcrResponse($value, $dataType);
117    }
118
119    private function formatOcrResponse(string $response, string $dataType): string
120    {
121
122        if ($dataType === 'bar_code_img' && base64_decode($response, true)) {
123            $response = base64_decode($response);
124        }
125        return iconv('UTF-8', 'ASCII//TRANSLIT', $response);
126    }
127
128    private function deleteTask(string $taskId)
129    {
130
131        $getData = $this->dataPattern;
132        array_push($getData['multipart'], array('name' => 'taskId', 'contents' =>  $taskId));
133
134        $res = $this->client->request('POST', 'https://cloud.ocrsdk.com/v2/deleteTask', $getData);
135        $jsonResponse = json_decode($res->getBody());
136        return $jsonResponse->status;
137    }
138}