[TASK] Split `Storage` module
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Resources / Private / TypeScript / Storage / Persistent.ts
1 /*
2  * This file is part of the TYPO3 CMS project.
3  *
4  * It is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License, either version 2
6  * of the License, or any later version.
7  *
8  * For the full copyright and license information, please read the
9  * LICENSE.txt file that was distributed with this source code.
10  *
11  * The TYPO3 project - inspiring people to share!
12  */
13
14 import $ = require('jquery');
15
16 /**
17  * Module: TYPO3/CMS/Backend/Storage/Persistent
18  * Wrapper for persistent storage in UC
19  * @exports TYPO3/CMS/Backend/Storage/Persistent
20  */
21 class Persistent {
22   private data: any = false;
23
24   /**
25    * Persistent storage, stores everything on the server via AJAX, does a greedy load on read
26    * common functions get/set/clear
27    *
28    * @param {String} key
29    * @returns {*}
30    */
31   public get = (key: string): any => {
32     const me = this;
33
34     if (this.data === false) {
35       let value;
36       this.loadFromServer().done(() => {
37         value = me.getRecursiveDataByDeepKey(me.data, key.split('.'));
38       });
39       return value;
40     }
41
42     return this.getRecursiveDataByDeepKey(this.data, key.split('.'));
43   }
44
45   /**
46    * Store data persistent on server
47    *
48    * @param {String} key
49    * @param {String} value
50    * @returns {$}
51    */
52   public set = (key: string, value: string): any => {
53     if (this.data !== false) {
54       this.data = this.setRecursiveDataByDeepKey(this.data, key.split('.'), value);
55     }
56     return this.storeOnServer(key, value);
57   }
58
59   /**
60    * @param {string} key
61    * @param {string} value
62    * @returns {$}
63    */
64   public addToList = (key: string, value: string): any => {
65     const me = this;
66     return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
67       data: {
68         action: 'addToList',
69         key,
70         value,
71       },
72       method: 'post',
73     }).done((data: any): any => {
74       me.data = data;
75     });
76   }
77
78   /**
79    * @param {string} key
80    * @param {string} value
81    * @returns {$}
82    */
83   public removeFromList = (key: string, value: string): any => {
84     const me = this;
85     return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
86       data: {
87         action: 'removeFromList',
88         key,
89         value,
90       },
91       method: 'post',
92     }).done((data: any): any => {
93       me.data = data;
94     });
95   }
96
97   public unset = (key: string): any => {
98     const me = this;
99     return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
100       data: {
101         action: 'unset',
102         key,
103       },
104       method: 'post',
105     }).done((data: any): any => {
106       me.data = data;
107     });
108   }
109
110   /**
111    * Clears the UC
112    */
113   public clear = (): any => {
114     $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
115       data: {
116         action: 'clear',
117       },
118     });
119     this.data = false;
120   }
121
122   /**
123    * Checks if a key was set before, useful to not do all the undefined checks all the time
124    *
125    * @param {string} key
126    * @returns {boolean}
127    */
128   public isset = (key: string): boolean => {
129     const value = this.get(key);
130     return (typeof value !== 'undefined' && value !== null);
131   }
132
133   /**
134    * Loads the data from outside, only used for the initial call from BackendController
135    *
136    * @param {String} data
137    */
138   public load = (data: any): any => {
139     this.data = data;
140   }
141
142   /**
143    * Loads all data from the server
144    *
145    * @returns {$}
146    */
147   private loadFromServer = (): any => {
148     const me = this;
149     return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
150       async: false,
151       data: {
152         action: 'getAll',
153       },
154     }).done((data) => {
155       me.data = data;
156     });
157   }
158
159   /**
160    * Stores data on the server, and gets the updated data on return
161    * to always be up-to-date inside the browser
162    *
163    * @param {string} key
164    * @param {string} value
165    * @returns {*}
166    */
167   private storeOnServer = (key: string, value: string): any => {
168     const me = this;
169     return $.ajax(TYPO3.settings.ajaxUrls.usersettings_process, {
170       data: {
171         action: 'set',
172         key,
173         value,
174       },
175       method: 'post',
176     }).done((data): any => {
177       me.data = data;
178     });
179   }
180
181   /**
182    * Helper function used to set a value which could have been a flat object key data["my.foo.bar"] to
183    * data[my][foo][bar] is called recursively by itself
184    *
185    * @param {Object} data the data to be uased as base
186    * @param {String} keyParts the keyParts for the subtree
187    * @returns {Object}
188    */
189   private getRecursiveDataByDeepKey = (data: any, keyParts: any[]): any => {
190     if (keyParts.length === 1) {
191       return (data || {})[keyParts[0]];
192     }
193
194     const firstKey = keyParts.shift();
195     return this.getRecursiveDataByDeepKey(data[firstKey] || {}, keyParts);
196   }
197
198   /**
199    * helper function used to set a value which could have been a flat object key data["my.foo.bar"] to
200    * data[my][foo][bar]
201    * is called recursively by itself
202    *
203    * @param data
204    * @param {any[]} keyParts
205    * @param {string} value
206    * @returns {any[]}
207    */
208   private setRecursiveDataByDeepKey = (data: any, keyParts: any[], value: string): any[] => {
209     if (keyParts.length === 1) {
210       data = data || {};
211       data[keyParts[0]] = value;
212     } else {
213       const firstKey = keyParts.shift();
214       data[firstKey] = this.setRecursiveDataByDeepKey(data[firstKey] || {}, keyParts, value);
215     }
216     return data;
217   }
218 }
219
220 export = new Persistent();