Passed
Push — master ( d80e5b...daef31 )
by Russell
12:45
created

VerifiableExtension::keyTable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @author  Russell Michell 2018 <[email protected]>
5
 * @package silverstripe-verifiable
6
 */
7
8
namespace PhpTek\Verifiable\Verify;
9
10
use SilverStripe\ORM\DataExtension;
11
use PhpTek\Verifiable\ORM\Fieldtype\ChainpointProof;
12
use SilverStripe\Forms\FieldList;
13
use SilverStripe\Forms\FormAction;
14
use SilverStripe\Forms\LiteralField;
15
use SilverStripe\Forms\DropdownField;
16
use SilverStripe\Forms\ToggleCompositeField;
17
18
/**
19
 * By attaching this extension to any {@link DataObject} subclass and declaring a
20
 * $verifiable_fields array in YML config, all subsequent database writes will
21
 * be passed through here via {@link $this->onBeforeWrite()};
22
 *
23
 * This {@link DataExtension} also provides a single field to which all verified
24
 * and verifiable chainpoint proofs are stored in a queryable JSON-aware field.
25
 *
26
 * @todo Hard-code "Created" and "LastEdited" fields into "verifiable_fields"
27
 * @todo Prevent "Proof" field from ever being configured in verifiable_fields
28
 * @todo Use AsyncPHP to make the initial write call to the backend, wait ~15s and then request a proof in return
29
 */
30
class VerifiableExtension extends DataExtension
31
{
32
    /**
33
     * Declares a JSON-aware {@link DBField} where all chainpoint proofs are stored.
34
     *
35
     * @var array
36
     * @config
37
     */
38
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
39
        'Proof' => ChainpointProof::class,
40
    ];
41
42
    /**
43
     * The field-values that will be hashed and committed to the current backend.
44
     *
45
     * @var array
46
     * @config
47
     */
48
    private static $verifiable_fields = [];
0 ignored issues
show
introduced by
The private property $verifiable_fields is not used, and could be removed.
Loading history...
49
50
    /**
51
     * Before each write, data from the $verifiable_fields config is compiled
52
     * into a string, hashed and submitted to the current backend.
53
     *
54
     * Once written, we periodically poll the backend to receive the full
55
     * chainpoint proof (it takes time for Bitcoin's PoW confirmations, not so
56
     * much for Ethereum).
57
     *
58
     * We need this "complete" proof for subsequent verification checks
59
     * also made against the same backend in the future.
60
     *
61
     * If only the "Proof" field has been written-to, or no-data is found in the
62
     * verifiable_fields, this should not constitute a write that we need to do
63
     * anything with, and it's therefore skipped.
64
     *
65
     * @return void
66
     */
67
    public function onBeforeWrite()
68
    {
69
        $verifiable = $this->normaliseData();
70
71
        if (count($verifiable) && $proofData = $this->verifiableService->write($verifiable)) {
0 ignored issues
show
Bug introduced by
The property verifiableService does not exist on PhpTek\Verifiable\Verify\VerifiableExtension. Did you mean verifiable_fields?
Loading history...
72
            if (is_array($proofData)) {
73
                $proofData = json_encode($proofData);
74
            }
75
76
            $this->getOwner()->setField('Proof', $proofData);
77
        }
78
79
        parent::onBeforeWrite();
80
    }
81
82
    /**
83
     * Normalise this model's data so it's suited to being hashed.
84
     *
85
     * @param  DataObject $record
0 ignored issues
show
Bug introduced by
The type PhpTek\Verifiable\Verify\DataObject was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
86
     * @return array
87
     */
88
    public function normaliseData($record = null) : array
89
    {
90
        $record = $record ?: $this->getOwner();
91
        $fields = $record->config()->get('verifiable_fields');
92
        $verifiable = [];
93
94
        foreach ($fields as $field) {
95
            $verifiable[] = (string) $record->getField($field);
96
        }
97
98
        return $verifiable;
99
    }
100
101
    /**
102
     * Adds a "Verification" tab to the CMS.
103
     *
104
     * @param  FieldList $fields
105
     * @return void
106
     * @todo Complete a basic CMS UI
107
     */
108
    public function updateCMSFields(FieldList $fields)
109
    {
110
        parent::updateCMSFields($fields);
111
112
        $owner = $this->getOwner();
113
        $list = $owner->Versions()->sort('Version')->map('Version', 'Version');
114
115
        $fields->addFieldsToTab('Root.Verify', FieldList::create([
116
            LiteralField::create('Introduction', '<p class="message">Select a version'
117
                    . ' whose data you wish to verify, then select the "Verify"'
118
                    . ' button. The result will be a verification status'
119
                    . ' as per the "Status Key" table below.</p>'),
120
            DropdownField::create('Version', 'Version', $list->toArray())
121
                ->setEmptyString('-- Select One --'),
122
                FormAction::create('doVerify', 'Verify'),
123
            ToggleCompositeField::create('KeyTable', 'Status Key', LiteralField::create('Foo', $this->keyTable())),
124
        ]));
125
    }
126
127
    /**
128
     * Generate an HTML table comprising status definitions.
129
     *
130
     * @return string
131
     */
132
    public function keyTable()
133
    {
134
135
        return file_get_contents(realpath(__DIR__) . '/../../doc/statuses.txt');
136
    }
137
138
}
139