Skip to content

Commit 9cec398

Browse files
committed
Improve FieldtypeFile & FieldtypeImage fields performance.
1 parent b9c3d45 commit 9cec398

File tree

3 files changed

+144
-7
lines changed

3 files changed

+144
-7
lines changed
Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,122 @@
11
<?php namespace ProcessWire\GraphQL\Type\Fieldtype;
22

3+
use ProcessWire\Page;
4+
use ProcessWire\Field;
35
use ProcessWire\GraphQL\Type\FileType;
46
use GraphQL\Type\Definition\Type;
5-
use ProcessWire\GraphQL\Type\Fieldtype\Traits\FieldTrait;
7+
use GraphQL\Deferred;
8+
use ProcessWire\DatabaseQuerySelect;
9+
use ProcessWire\GraphQL\Cache;
10+
use ProcessWire\GraphQL\PagesBuffer;
11+
use ProcessWire\GraphQL\Utils;
612
use ProcessWire\GraphQL\Type\Fieldtype\Traits\InputFieldTrait;
713
use ProcessWire\GraphQL\Type\Fieldtype\Traits\SetValueTrait;
814

915
class FieldtypeFile
1016
{
11-
use FieldTrait;
1217
use InputFieldTrait;
1318
use SetValueTrait;
14-
public static function type($field)
19+
20+
private static $filesData = [];
21+
22+
public static function type()
23+
{
24+
return Type::listOf(FileType::type());
25+
}
26+
27+
public static function field(Field $field)
28+
{
29+
return Cache::field($field->name, function () use ($field) {
30+
// description
31+
$desc = $field->description;
32+
if (!$desc) {
33+
$desc = "Field with the type of {$field->type}";
34+
}
35+
36+
return [
37+
'name' => $field->name,
38+
'description' => $desc,
39+
'type' => self::type($field),
40+
'resolve' => function (Page $page) use ($field) {
41+
PagesBuffer::add($field->name, $page);
42+
return new Deferred(function () use ($page, $field){
43+
$ids = PagesBuffer::get($field->name);
44+
PagesBuffer::clear($field->name);
45+
if ($ids && count($ids)) {
46+
self::loadFilesData($ids, $field);
47+
}
48+
return self::getFieldValue($page, $field);
49+
});
50+
}
51+
];
52+
});
53+
}
54+
55+
public static function loadFilesData(array $pageIDs, Field $field) {
56+
57+
if(!count($pageIDs)) {
58+
return;
59+
}
60+
61+
$database = Utils::database();
62+
$fieldType = $field->type;
63+
$fieldName = $database->escapeCol($field->name);
64+
$schema = $fieldType->getDatabaseSchema($field);
65+
$table = $database->escapeTable($field->table);
66+
$stmt = null;
67+
68+
$query = $fieldType->wire(new DatabaseQuerySelect());
69+
$query = $fieldType->getLoadQuery($field, $query);
70+
$query->select("$table.pages_id AS `{$fieldName}__pages_id`"); // QA
71+
$ids = implode(', ', $pageIDs);
72+
$query->where("$table.pages_id IN ($ids)");
73+
$query->from($table);
74+
75+
try {
76+
$stmt = $query->prepare();
77+
$result = $database->execute($stmt);
78+
} catch(\Exception $e) {
79+
$result = false;
80+
$fieldType->trackException($e, false, true);
81+
}
82+
83+
if(!$result) return null;
84+
85+
$fieldName = $database->escapeCol($field->name);
86+
unset($schema['keys'], $schema['xtra'], $schema['sort']);
87+
$values = [];
88+
89+
/** @noinspection PhpAssignmentInConditionInspection */
90+
while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
91+
$value = [];
92+
foreach($schema as $k => $unused) {
93+
$key = "{$fieldName}__{$k}";
94+
$value[$k] = $row[$key];
95+
}
96+
$pageID = $value['pages_id'];
97+
unset($value['pages_id']);
98+
if (!isset($values[$pageID])) {
99+
$values[$pageID] = [];
100+
}
101+
$values[$pageID][] = $value;
102+
}
103+
104+
$stmt->closeCursor();
105+
106+
self::$filesData[$field->name] = $values;
107+
}
108+
109+
public static function getFieldValue(Page $page, Field $field)
15110
{
16-
return Type::listOf(FileType::type($field));
111+
$id = (string) $page->id;
112+
$key = $field->name;
113+
$filesData = self::$filesData[$key];
114+
$value = [];
115+
if (isset($filesData[$id])) {
116+
$value = $filesData[$id];
117+
$value = $field->type->_callHookMethod('wakeupValue', array($page, $field, $value));
118+
$value = $field->type->sanitizeValue($page, $field, $value);
119+
}
120+
return $value;
17121
}
18122
}
Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,51 @@
11
<?php namespace ProcessWire\GraphQL\Type\Fieldtype;
22

3+
use ProcessWire\Page;
4+
use ProcessWire\Field;
35
use GraphQL\Type\Definition\Type;
6+
use GraphQL\Deferred;
7+
use ProcessWire\GraphQL\Cache;
8+
use ProcessWire\GraphQL\PagesBuffer;
49
use ProcessWire\GraphQL\Type\ImageType;
5-
use ProcessWire\GraphQL\Type\Fieldtype\Traits\FieldTrait;
10+
use ProcessWire\GraphQL\Type\Fieldtype\FieldtypeFile;
611
use ProcessWire\GraphQL\Type\Fieldtype\Traits\InputFieldTrait;
712
use ProcessWire\GraphQL\Type\Fieldtype\Traits\SetValueTrait;
813

914
class FieldtypeImage
1015
{
11-
use FieldTrait;
1216
use InputFieldTrait;
1317
use SetValueTrait;
18+
1419
public static function type()
1520
{
1621
return Type::listOf(ImageType::type());
1722
}
23+
24+
public static function field(Field $field)
25+
{
26+
return Cache::field($field->name, function () use ($field) {
27+
// description
28+
$desc = $field->description;
29+
if (!$desc) {
30+
$desc = "Field with the type of {$field->type}";
31+
}
32+
33+
return [
34+
'name' => $field->name,
35+
'description' => $desc,
36+
'type' => self::type($field),
37+
'resolve' => function (Page $page) use ($field) {
38+
PagesBuffer::add($field->name, $page);
39+
return new Deferred(function () use ($page, $field){
40+
$ids = PagesBuffer::get($field->name);
41+
PagesBuffer::clear($field->name);
42+
if ($ids && count($ids)) {
43+
FieldtypeFile::loadFilesData($ids, $field);
44+
}
45+
return FieldtypeFile::getFieldValue($page, $field);
46+
});
47+
}
48+
];
49+
});
50+
}
1851
}

test/Performance/DBQueryCount.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public static function getSettings()
2626
*
2727
* @var integer
2828
*/
29-
public static $bestQueryCount = 180;
29+
public static $bestQueryCount = 25;
3030

3131
/**
3232
* The query we use to test the performance of the module by counting

0 commit comments

Comments
 (0)