Test Failed
Push — develop ( 5be0e5...3f5c00 )
by Paul
14:23
created

ImportManager::tempFilePath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
dl 0
loc 11
rs 10
c 1
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Database;
4
5
use GeminiLabs\League\Csv\Reader;
6
use GeminiLabs\League\Csv\Statement;
7
use GeminiLabs\League\Csv\TabularDataReader;
8
use GeminiLabs\SiteReviews\Commands\CreateReview;
9
use GeminiLabs\SiteReviews\Database;
10
use GeminiLabs\SiteReviews\Defaults\ImportResultDefaults;
11
use GeminiLabs\SiteReviews\Helpers\Cast;
12
use GeminiLabs\SiteReviews\Request;
13
use GeminiLabs\SiteReviews\Review;
14
15
class ImportManager
16
{
17
    public function flush(): void
18
    {
19
        glsr(Database::class)->dbQuery(
20
            glsr(Query::class)->sql("TRUNCATE TABLE table|tmp")
21
        );
22
    }
23
24
    public function import(int $limit = 1, int $offset = 0): array
25
    {
26
        if (!defined('WP_IMPORTING')) {
27
            define('WP_IMPORTING', true);
28
        }
29
        set_time_limit(0);
30
        wp_raise_memory_limit('admin');
31
        wp_defer_term_counting(true);
32
        wp_suspend_cache_invalidation(true);
33
        $reader = Reader::createFromPath($this->tempFilePath());
34
        $reader->setHeaderOffset(0);
35
        $records = Statement::create()
36
            ->offset(max(0, $offset))
37
            ->limit(max(1, $limit))
38
            ->process($reader);
39
        $result = glsr(ImportResultDefaults::class)->defaults();
40
        foreach ($records as $values) {
41
            $request = new Request($values);
42
            $command = new CreateReview($request);
43
            if ($review = $this->importedReview($command->request)) {
44
                $result['attachments'] += glsr()->filterInt('import/review/attachments', 0, $request, $review, false);
45
                $result['skipped']++;
46
                continue;
47
            }
48
            if ($review = glsr(ReviewManager::class)->create($command)) {
49
                $result['attachments'] += glsr()->filterInt('import/review/attachments', 0, $request, $review, true);
50
                $result['imported']++;
51
                continue;
52
            }
53
            $result['skipped']++;
54
        }
55
        wp_defer_term_counting(false);
56
        wp_suspend_cache_invalidation(false);
57
        unset($reader, $records);
58
        return $result;
59
    }
60
61
    public function importAttachments(int $limit = 1, int $offset = 0): array
62
    {
63
        if (!defined('WP_IMPORTING')) {
64
            define('WP_IMPORTING', true);
65
        }
66
        set_time_limit(0);
67
        wp_raise_memory_limit('image');
68
        wp_suspend_cache_invalidation(true);
69
        $limit = max(1, $limit);
70
        $offset = max(0, $offset);
71
        $result = glsr()->filterArray('import/reviews/attachments', [], $limit, $offset);
72
        wp_suspend_cache_invalidation(false);
73
        return glsr(ImportResultDefaults::class)->restrict($result);
74
75
    }
76
77
    public function importedReview(Request $request): ?Review
78
    {
79
        $submittedHash = md5(maybe_serialize($request->toArray()));
80
        $sql = "
81
            SELECT p.ID
82
            FROM table|posts AS p
83
            INNER JOIN table|postmeta AS pm ON (pm.post_id = p.ID)
84
            WHERE 1=1
85
            AND p.post_type = %s
86
            AND pm.meta_key = '_submitted_hash'
87
            AND pm.meta_value = %s
88
        ";
89
        $sql = glsr(Query::class)->sql($sql, glsr()->post_type, $submittedHash);
90
        $reviewId = glsr(Database::class)->dbGetVar($sql);
91
        $reviewId = Cast::toInt($reviewId);
92
        $review = glsr_get_review($reviewId);
93
        if (!$review->isValid()) {
94
            return null;
95
        }
96
        return $review;
97
    }
98
99
    public function tempFilePath(): string
100
    {
101
        $uploads = wp_upload_dir();
102
        if (!file_exists($uploads['basedir'])) {
103
            $uploads = wp_upload_dir(null, true, true); // maybe the site has been moved, so refresh the cached uploads path
104
        }
105
        $path = trailingslashit($uploads['basedir']);
106
        $path = trailingslashit($path.glsr()->id);
107
        $path = trailingslashit($path.'temp');
108
        wp_mkdir_p($path);
109
        return $path.'import.csv';
110
    }
111
112
    public function unlinkTempFile(): bool
113
    {
114
        $path = $this->tempFilePath();
115
        if (!is_file($path)) {
116
            return false;
117
        }
118
        unlink($path); // delete the temporary import file
119
        return true;
120
    }
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    public function chunkIt(\Iterator $records, int $chunkSize): \Generator
143
    {
144
        $records->rewind();
145
        $chunk = [];
146
        for ($i = 0; $records->valid(); ++$i) {
147
            $chunk[] = $records->current();
148
            $records->next();
149
            if (count($chunk) === $chunkSize) {
150
                yield $chunk;
151
                $chunk = [];
152
            }
153
        }
154
        if (count($chunk) > 0) {
155
            yield $chunk;
156
        }
157
    }
158
159
    /**
160
     * Temporarily store the CSV rows to the database for later processing.
161
     */
162
    public function store(TabularDataReader $records, int $chunkSize = 50): int
163
    {
164
        $this->flush();
165
        $chunks = $this->chunkIt($records->getIterator(), $chunkSize);
166
        $stored = 0;
167
        foreach ($chunks as $index => $chunk) {
168
            $values = array_map(fn ($row) => ['data' => maybe_serialize($row)], $chunk);
169
            $result = glsr(Database::class)->insertBulk('tmp', $values, ['data']);
170
            $stored += (int) $result;
171
            unset($values);
172
        }
173
        return $stored;
174
    }
175
176
177
}
178