1 | <?php
|
---|
2 |
|
---|
3 | /*
|
---|
4 | Requirements:
|
---|
5 | Meta information: Modules, Lists, Items, Menu, Icons, Localization
|
---|
6 | Permissions ?
|
---|
7 | Actions:
|
---|
8 | * List: Add, Remove
|
---|
9 | * Item: Add, Edit, Delete
|
---|
10 |
|
---|
11 | Possible protocols: XML-RPC
|
---|
12 | How to transfer table data efficiently, binary protocol, compression, encryption
|
---|
13 | Multi queries in single command
|
---|
14 |
|
---|
15 | */
|
---|
16 |
|
---|
17 | class ModuleAPI extends Module
|
---|
18 | {
|
---|
19 | function __construct(System $System)
|
---|
20 | {
|
---|
21 | parent::__construct($System);
|
---|
22 | $this->Name = 'API';
|
---|
23 | $this->Version = '1.0';
|
---|
24 | $this->Creator = 'Chronos';
|
---|
25 | $this->License = 'GNU/GPLv3';
|
---|
26 | $this->Description = 'Remote API for support of other clients';
|
---|
27 | $this->Dependencies = array(ModuleUser::GetName());
|
---|
28 | $this->Models = array(APIToken::GetClassName());
|
---|
29 | }
|
---|
30 |
|
---|
31 | function DoStart(): void
|
---|
32 | {
|
---|
33 | $this->System->RegisterPage(['api'], 'PageAPI');
|
---|
34 | }
|
---|
35 | }
|
---|
36 |
|
---|
37 | class ApiToken extends Model
|
---|
38 | {
|
---|
39 | static function GetModelDesc(): ModelDesc
|
---|
40 | {
|
---|
41 | $Desc = new ModelDesc(self::GetClassName());
|
---|
42 | $Desc->AddReference('User', User::GetClassName());
|
---|
43 | $Desc->AddString('Token');
|
---|
44 | return $Desc;
|
---|
45 | }
|
---|
46 | }
|
---|
47 |
|
---|
48 | class PageAPI extends Page
|
---|
49 | {
|
---|
50 | public string $DataFormat;
|
---|
51 |
|
---|
52 | function __construct(System $System)
|
---|
53 | {
|
---|
54 | parent::__construct($System);
|
---|
55 | $this->RawPage = true;
|
---|
56 | $this->DataFormat = '';
|
---|
57 | }
|
---|
58 |
|
---|
59 | function Show(): string
|
---|
60 | {
|
---|
61 | // p - token
|
---|
62 | if (array_key_exists('p', $_GET)) {
|
---|
63 | $Token = $_GET['p'];
|
---|
64 | $DbResult = $this->Database->query('SELECT `User` FROM `APIToken` WHERE `Token`="'.$Token.'"');
|
---|
65 | if ($DbResult->num_rows > 0)
|
---|
66 | {
|
---|
67 | $DbRow = $DbResult->fetch_assoc();
|
---|
68 | $this->UserId = $DbRow['User'];
|
---|
69 | } else die('Wrong token');
|
---|
70 | } else die('Missing access token');
|
---|
71 | // f - data format
|
---|
72 | if (array_key_exists('f', $_GET)) $this->DataFormat = $_GET['f'];
|
---|
73 | else $this->DataFormat = 'php';
|
---|
74 | // a - action
|
---|
75 | if (array_key_exists('a', $_GET)) $Action = $_GET['a'];
|
---|
76 | else $Action = '';
|
---|
77 | // t - table
|
---|
78 | if (array_key_exists('t', $_GET)) $Table = $_GET['t'];
|
---|
79 | else $Table = '';
|
---|
80 | // i - index of item
|
---|
81 | if (array_key_exists('i', $_GET)) $ItemId = $_GET['i'];
|
---|
82 | else $ItemId = 0;
|
---|
83 |
|
---|
84 | if ($Action == 'list') $Output = $this->ShowList($Table, $ItemId);
|
---|
85 | else $Output = 'Unsupported action';
|
---|
86 |
|
---|
87 | return $Output;
|
---|
88 | }
|
---|
89 |
|
---|
90 | function ShowList(string $Table, $ItemId): string
|
---|
91 | {
|
---|
92 | if (($Table != '') and (array_key_exists($Table, $this->System->FormManager->Classes)))
|
---|
93 | $FormClass = $this->System->FormManager->Classes[$Table];
|
---|
94 | else return 'Table not found';
|
---|
95 |
|
---|
96 | if (array_key_exists('SQL', $FormClass))
|
---|
97 | $SourceTable = '('.$FormClass['SQL'].') AS `TX`';
|
---|
98 | else $SourceTable = '`'.$FormClass['Table'].'` AS `TX`';
|
---|
99 |
|
---|
100 | $Filter = '';
|
---|
101 | if ($ItemId != 0)
|
---|
102 | {
|
---|
103 | $Filter .= '`Id`='.$ItemId;
|
---|
104 | }
|
---|
105 | if ($Filter != '') $Filter = ' WHERE '.$Filter;
|
---|
106 |
|
---|
107 | $Result = array();
|
---|
108 | $DbResult = $this->Database->query('SELECT * FROM '.$SourceTable.$Filter);
|
---|
109 | while ($DbRow = $DbResult->fetch_assoc())
|
---|
110 | {
|
---|
111 | $Result[] = $DbRow;
|
---|
112 | }
|
---|
113 | if ($this->DataFormat == 'php') $Output = serialize($Result);
|
---|
114 | else if ($this->DataFormat == 'xml') $Output = $this->array2xml($Result);
|
---|
115 | else if ($this->DataFormat == 'json') $Output = json_encode($Result);
|
---|
116 | else die('Unknown data format '.$this->DataFormat);
|
---|
117 | return $Output;
|
---|
118 | }
|
---|
119 |
|
---|
120 | function array2xml($array, $node_name = "root")
|
---|
121 | {
|
---|
122 | $dom = new DOMDocument('1.0', 'UTF-8');
|
---|
123 | $dom->formatOutput = true;
|
---|
124 | $root = $dom->createElement($node_name);
|
---|
125 | $dom->appendChild($root);
|
---|
126 |
|
---|
127 | $array2xml = function ($node, $array) use ($dom, &$array2xml)
|
---|
128 | {
|
---|
129 | foreach ($array as $key => $value)
|
---|
130 | {
|
---|
131 | if ( is_array($value) )
|
---|
132 | {
|
---|
133 | if (is_numeric($key)) $key = 'N'.$key; //die('XML tag name "'.$key.'" can\'t be numeric');
|
---|
134 | $n = $dom->createElement($key);
|
---|
135 | $node->appendChild($n);
|
---|
136 | $array2xml($n, $value);
|
---|
137 | } else {
|
---|
138 | if (is_numeric($key)) $key = 'N'.$key; //die('XML attribute name "'.$key.'" can\'t be numeric');
|
---|
139 | $attr = $dom->createAttribute($key);
|
---|
140 | $attr->value = $value;
|
---|
141 | $node->appendChild($attr);
|
---|
142 | }
|
---|
143 | }
|
---|
144 | };
|
---|
145 | $array2xml($root, $array);
|
---|
146 | return $dom->saveXML();
|
---|
147 | }
|
---|
148 | }
|
---|
149 |
|
---|