ExportReviews::handle()   A
last analyzed

Complexity

Conditions 4
Paths 14

Size

Total Lines 31
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 31
ccs 0
cts 27
cp 0
rs 9.504
c 0
b 0
f 0
cc 4
nc 14
nop 0
crap 20
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Commands;
4
5
use GeminiLabs\League\Csv\CannotInsertRecord;
6
use GeminiLabs\League\Csv\EscapeFormula;
7
use GeminiLabs\League\Csv\Writer;
8
use GeminiLabs\SiteReviews\Arguments;
9
use GeminiLabs\SiteReviews\Database\ExportManager;
10
use GeminiLabs\SiteReviews\Defaults\AdditionalFieldsDefaults;
11
use GeminiLabs\SiteReviews\Helpers\Str;
12
use GeminiLabs\SiteReviews\Modules\Notice;
13
use GeminiLabs\SiteReviews\Request;
14
15
class ExportReviews extends AbstractCommand
16
{
17
    protected Request $request;
18
19
    public function __construct(Request $request)
20
    {
21
        $this->request = $request;
22
    }
23
24
    public function handle(): void
25
    {
26
        if (!glsr()->hasPermission('tools', 'general')) {
27
            glsr(Notice::class)->addError(
28
                _x('You do not have permission to export reviews.', 'admin-text', 'site-reviews')
29
            );
30
            $this->fail();
31
            return;
32
        }
33
        try {
34
            $records = $this->fetchReviews();
35
            $firstRecord = $records->current();
36
            if (empty($firstRecord)) {
37
                glsr(Notice::class)->addWarning(_x('No reviews were found to export.', 'admin-text', 'site-reviews'));
38
                $this->fail();
39
                return;
40
            }
41
            nocache_headers();
42
            $filename = sprintf('%s_%s.csv', date('YmdHi'), glsr()->id);
43
            $writer = Writer::createFromString('');
0 ignored issues
show
Deprecated Code introduced by
The function GeminiLabs\League\Csv\Ab...Csv::createFromString() has been deprecated: since version 9.27.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

43
            $writer = /** @scrutinizer ignore-deprecated */ Writer::createFromString('');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
44
            $writer->addFormatter(new EscapeFormula());
45
            $writer->insertOne(array_keys($firstRecord));
46
            $writer->insertAll($records);
47
            $writer->output($filename);
0 ignored issues
show
Deprecated Code introduced by
The function GeminiLabs\League\Csv\AbstractCsv::output() has been deprecated: since version 9.18.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

47
            /** @scrutinizer ignore-deprecated */ $writer->output($filename);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
48
            exit;
49
        } catch (CannotInsertRecord $e) {
50
            $this->fail();
51
            glsr(Notice::class)->addError($e->getMessage());
52
            glsr_log()
53
                ->warning('Unable to insert row into CSV export file')
54
                ->debug($e->getRecord());
55
        }
56
    }
57
58
    protected function fetchReviews(): \Generator
59
    {
60
        $args = glsr()->args([
61
            'assigned_posts' => $this->request->assigned_posts,
62
            'assigned_terms' => $this->request->assigned_terms,
63
            'assigned_users' => $this->request->assigned_users,
64
            'author_id' => $this->request->author_id,
65
            'date' => $this->request->cast('date', 'date'),
66
            'limit' => 500,
67
            'post_status' => $this->request->post_status,
68
        ]);
69
        $header = [];
70
        $postId = 0;
71
        while (true) {
72
            $reviews = glsr(ExportManager::class)->export($args->merge([
73
                'post_id' => $postId,
74
            ]));
75
            if (empty($reviews)) {
76
                break;
77
            }
78
            if (empty($header)) {
79
                $header = $this->headerValues($args, $reviews[0]);
80
            }
81
            foreach ($reviews as $review) {
82
                $meta = $this->postMeta($review['ID']);
83
                $custom = wp_parse_args($meta, array_fill_keys($header, ''));
84
                $record = wp_parse_args($review, $custom);
85
                unset($record['ID']);
86
                yield $record;
87
            }
88
            $postId = end($reviews)['ID'];
89
        }
90
    }
91
92
    protected function headerValues(Arguments $args, array $record): array
93
    {
94
        $additionalHeader = array_keys(glsr(AdditionalFieldsDefaults::class)->defaults());
95
        $customHeader = glsr(ExportManager::class)->customHeader($args);
96
        $header = array_merge(array_keys($record), $additionalHeader, $customHeader);
97
        return $header;
98
    }
99
100
    protected function postMeta(int $postId): array
101
    {
102
        $meta = get_post_meta($postId);
103
        if (!is_array($meta)) {
104
            return [];
105
        }
106
        $additionalKeys = array_keys(glsr(AdditionalFieldsDefaults::class)->defaults());
107
        $additionalKeys = array_map(fn ($key) => Str::prefix($key, '_'), $additionalKeys);
108
        $meta = array_map(fn ($val) => $val[0] ?? '', $meta);
109
        $meta = array_filter($meta, function ($key) use ($additionalKeys) {
110
            return str_starts_with($key, '_custom_') || in_array($key, $additionalKeys);
111
        }, ARRAY_FILTER_USE_KEY);
112
        $results = [];
113
        foreach ($meta as $key => $value) {
114
            $key = Str::removePrefix($key, '_');
115
            $results[$key] = $value;
116
        }
117
        return $results;
118
    }
119
}
120