1 | <?php
|
---|
2 |
|
---|
3 | /*! DataItemUpdate class for realization Optimistic concurrency control
|
---|
4 | Wrapper for DataItem object
|
---|
5 | It's used during outputing updates instead of DataItem object
|
---|
6 | Create wrapper for every data item with update information.
|
---|
7 | */
|
---|
8 | class DataItemUpdate extends DataItem {
|
---|
9 |
|
---|
10 |
|
---|
11 | /*! constructor
|
---|
12 | @param data
|
---|
13 | hash of data
|
---|
14 | @param config
|
---|
15 | DataConfig object
|
---|
16 | @param index
|
---|
17 | index of element
|
---|
18 | */
|
---|
19 | public function __construct($data,$config,$index,$type){
|
---|
20 | $this->config=$config;
|
---|
21 | $this->data=$data;
|
---|
22 | $this->index=$index;
|
---|
23 | $this->skip=false;
|
---|
24 | $this->child = new $type($data, $config, $index);
|
---|
25 | }
|
---|
26 |
|
---|
27 | /*! returns parent_id (for Tree and TreeGrid components)
|
---|
28 | */
|
---|
29 | public function get_parent_id(){
|
---|
30 | if (method_exists($this->child, 'get_parent_id')) {
|
---|
31 | return $this->child->get_parent_id();
|
---|
32 | } else {
|
---|
33 | return '';
|
---|
34 | }
|
---|
35 | }
|
---|
36 |
|
---|
37 |
|
---|
38 | /*! generate XML on the data hash base
|
---|
39 | */
|
---|
40 | public function to_xml(){
|
---|
41 | $str= "<update ";
|
---|
42 | $str .= 'status="'.$this->data['type'].'" ';
|
---|
43 | $str .= 'id="'.$this->data['dataId'].'" ';
|
---|
44 | $str .= 'parent="'.$this->get_parent_id().'"';
|
---|
45 | $str .= '>';
|
---|
46 | $str .= $this->child->to_xml();
|
---|
47 | $str .= '</update>';
|
---|
48 | return $str;
|
---|
49 | }
|
---|
50 |
|
---|
51 | /*! return starting tag for XML string
|
---|
52 | */
|
---|
53 | public function to_xml_start(){
|
---|
54 | $str="<update ";
|
---|
55 | $str .= 'status="'.$this->data['type'].'" ';
|
---|
56 | $str .= 'id="'.$this->data['dataId'].'" ';
|
---|
57 | $str .= 'parent="'.$this->get_parent_id().'"';
|
---|
58 | $str .= '>';
|
---|
59 | $str .= $this->child->to_xml_start();
|
---|
60 | return $str;
|
---|
61 | }
|
---|
62 |
|
---|
63 | /*! return ending tag for XML string
|
---|
64 | */
|
---|
65 | public function to_xml_end(){
|
---|
66 | $str = $this->child->to_xml_end();
|
---|
67 | $str .= '</update>';
|
---|
68 | return $str;
|
---|
69 | }
|
---|
70 |
|
---|
71 | /*! returns false for outputing only current item without child items
|
---|
72 | */
|
---|
73 | public function has_kids(){
|
---|
74 | return false;
|
---|
75 | }
|
---|
76 |
|
---|
77 | /*! sets count of child items
|
---|
78 | @param value
|
---|
79 | count of child items
|
---|
80 | */
|
---|
81 | public function set_kids($value){
|
---|
82 | if (method_exists($this->child, 'set_kids')) {
|
---|
83 | $this->child->set_kids($value);
|
---|
84 | }
|
---|
85 | }
|
---|
86 |
|
---|
87 | /*! sets attribute for item
|
---|
88 | */
|
---|
89 | public function set_attribute($name, $value){
|
---|
90 | if (method_exists($this->child, 'set_attribute')) {
|
---|
91 | LogMaster::log("setting attribute: \nname = {$name}\nvalue = {$value}");
|
---|
92 | $this->child->set_attribute($name, $value);
|
---|
93 | } else {
|
---|
94 | LogMaster::log("set_attribute method doesn't exists");
|
---|
95 | }
|
---|
96 | }
|
---|
97 | }
|
---|
98 |
|
---|
99 |
|
---|
100 | class DataUpdate{
|
---|
101 |
|
---|
102 | protected $table; //!< table , where actions are stored
|
---|
103 | protected $url; //!< url for notification service, optional
|
---|
104 | protected $sql; //!< DB wrapper object
|
---|
105 | protected $config; //!< DBConfig object
|
---|
106 | protected $request; //!< DBRequestConfig object
|
---|
107 | protected $event;
|
---|
108 | protected $item_class;
|
---|
109 | protected $demu;
|
---|
110 |
|
---|
111 | //protected $config;//!< DataConfig instance
|
---|
112 | //protected $request;//!< DataRequestConfig instance
|
---|
113 |
|
---|
114 | /*! constructor
|
---|
115 |
|
---|
116 | @param connector
|
---|
117 | Connector object
|
---|
118 | @param config
|
---|
119 | DataConfig object
|
---|
120 | @param request
|
---|
121 | DataRequestConfig object
|
---|
122 | */
|
---|
123 | function __construct($sql, $config, $request, $table, $url){
|
---|
124 | $this->config= $config;
|
---|
125 | $this->request= $request;
|
---|
126 | $this->sql = $sql;
|
---|
127 | $this->table=$table;
|
---|
128 | $this->url=$url;
|
---|
129 | $this->demu = false;
|
---|
130 | }
|
---|
131 |
|
---|
132 | public function set_demultiplexor($path){
|
---|
133 | $this->demu = $path;
|
---|
134 | }
|
---|
135 |
|
---|
136 | public function set_event($master, $name){
|
---|
137 | $this->event = $master;
|
---|
138 | $this->item_class = $name;
|
---|
139 | }
|
---|
140 |
|
---|
141 | private function select_update($actions_table, $join_table, $id_field_name, $version, $user) {
|
---|
142 | $sql = "SELECT * FROM {$actions_table}";
|
---|
143 | $sql .= " LEFT OUTER JOIN {$join_table} ON ";
|
---|
144 | $sql .= "{$actions_table}.DATAID = {$join_table}.{$id_field_name} ";
|
---|
145 | $sql .= "WHERE {$actions_table}.ID > '{$version}' AND {$actions_table}.USER <> '{$user}'";
|
---|
146 | return $sql;
|
---|
147 | }
|
---|
148 |
|
---|
149 | private function get_update_max_version() {
|
---|
150 | $sql = "SELECT MAX(id) as VERSION FROM {$this->table}";
|
---|
151 | $res = $this->sql->query($sql);
|
---|
152 | $data = $this->sql->get_next($res);
|
---|
153 |
|
---|
154 | if ($data == false || $data['VERSION'] == false)
|
---|
155 | return 1;
|
---|
156 | else
|
---|
157 | return $data['VERSION'];
|
---|
158 | }
|
---|
159 |
|
---|
160 | private function log_update_action($actions_table, $dataId, $status, $user) {
|
---|
161 | $sql = "INSERT INTO {$actions_table} (DATAID, TYPE, USER) VALUES ('{$dataId}', '{$status}', '{$user}')";
|
---|
162 | $this->sql->query($sql);
|
---|
163 | if ($this->demu)
|
---|
164 | file_get_contents($this->demu);
|
---|
165 | }
|
---|
166 |
|
---|
167 |
|
---|
168 |
|
---|
169 |
|
---|
170 | /*! records operations in actions_table
|
---|
171 | @param action
|
---|
172 | DataAction object
|
---|
173 | */
|
---|
174 | public function log_operations($action) {
|
---|
175 | $type = $this->sql->escape($action->get_status());
|
---|
176 | $dataId = $this->sql->escape($action->get_new_id());
|
---|
177 | $user = $this->sql->escape($this->request->get_user());
|
---|
178 | if ($type!="error" && $type!="invalid" && $type !="collision") {
|
---|
179 | $this->log_update_action($this->table, $dataId, $type, $user);
|
---|
180 | }
|
---|
181 | }
|
---|
182 |
|
---|
183 |
|
---|
184 | /*! return action version in XMl format
|
---|
185 | */
|
---|
186 | public function get_version() {
|
---|
187 | $version = $this->get_update_max_version();
|
---|
188 | return "<userdata name='version'>".$version."</userdata>";
|
---|
189 | }
|
---|
190 |
|
---|
191 |
|
---|
192 | /*! adds action version in output XML as userdata
|
---|
193 | */
|
---|
194 | public function version_output() {
|
---|
195 | echo $this->get_version();
|
---|
196 | }
|
---|
197 |
|
---|
198 |
|
---|
199 | /*! create update actions in XML-format and sends it to output
|
---|
200 | */
|
---|
201 | public function get_updates() {
|
---|
202 | $sub_request = new DataRequestConfig($this->request);
|
---|
203 | $version = $this->request->get_version();
|
---|
204 | $user = $this->request->get_user();
|
---|
205 |
|
---|
206 | $sub_request->parse_sql($this->select_update($this->table, $this->request->get_source(), $this->config->id['db_name'], $version, $user));
|
---|
207 | $sub_request->set_relation(false);
|
---|
208 |
|
---|
209 | $output = $this->render_set($this->sql->select($sub_request), $this->item_class);
|
---|
210 |
|
---|
211 | ob_clean();
|
---|
212 | header("Content-type:text/xml");
|
---|
213 |
|
---|
214 | echo $this->updates_start();
|
---|
215 | echo $this->get_version();
|
---|
216 | echo $output;
|
---|
217 | echo $this->updates_end();
|
---|
218 | }
|
---|
219 |
|
---|
220 |
|
---|
221 | protected function render_set($res, $name){
|
---|
222 | $output="";
|
---|
223 | $index=0;
|
---|
224 | while ($data=$this->sql->get_next($res)){
|
---|
225 | $data = new DataItemUpdate($data,$this->config,$index, $name);
|
---|
226 | $this->event->trigger("beforeRender",$data);
|
---|
227 | $output.=$data->to_xml();
|
---|
228 | $index++;
|
---|
229 | }
|
---|
230 | return $output;
|
---|
231 | }
|
---|
232 |
|
---|
233 | /*! returns update start string
|
---|
234 | */
|
---|
235 | protected function updates_start() {
|
---|
236 | $start = '<updates>';
|
---|
237 | return $start;
|
---|
238 | }
|
---|
239 |
|
---|
240 | /*! returns update end string
|
---|
241 | */
|
---|
242 | protected function updates_end() {
|
---|
243 | $start = '</updates>';
|
---|
244 | return $start;
|
---|
245 | }
|
---|
246 |
|
---|
247 | /*! checks if action version given by client is deprecated
|
---|
248 | @param action
|
---|
249 | DataAction object
|
---|
250 | */
|
---|
251 | public function check_collision($action) {
|
---|
252 | $version = $this->sql->escape($this->request->get_version());
|
---|
253 | //$user = $this->sql->escape($this->request->get_user());
|
---|
254 | $last_version = $this->get_update_max_version();
|
---|
255 | if (($last_version > $version)&&($action->get_status() == 'update')) {
|
---|
256 | $action->error();
|
---|
257 | $action->set_status('collision');
|
---|
258 | }
|
---|
259 | }
|
---|
260 | }
|
---|
261 |
|
---|
262 | ?> |
---|