Completed
Pull Request — master (#90)
by Janis
15:10
created

js/temp/controller.js   B

Complexity

Total Complexity 47
Complexity/F 1.52

Size

Lines of Code 300
Function Count 31

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 47
dl 0
loc 300
rs 8.439
c 0
b 0
f 0
cc 0
nc 128
mnd 2
bc 43
fnc 31
bpm 1.387
cpm 1.5161
noi 48

1 Function

Rating   Name   Duplication   Size   Complexity  
B controller.js ➔ Controller 0 270 5

How to fix   Complexity   

Complexity

Complex classes like js/temp/controller.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/**
2
 * nextCloud - ocr
3
 *
4
 * This file is licensed under the Affero General Public License version 3 or
5
 * later. See the COPYING file.
6
 *
7
 * @author Janis Koehr <[email protected]>
8
 * @copyright Janis Koehr 2017
9
 */
10
(function (OC, OCA, window, $, _) {
11
    'use strict';
12
    /**
13
     * Integrates the service with the view.
14
     * @public
15
     * @class Ocr.Controller
16
     * @param Ocr.View
17
     * @param Ocr.Util
18
     * @param Ocr.HttpService
0 ignored issues
show
Documentation introduced by
The parameter Ocr.HttpService does not exist. Did you maybe forget to remove this comment?
Loading history...
19
     */
20
    var Controller = function (view, util, httpService) {
21
        /** Constructor */
22
        /** Instance of the OCA.Ocr.View. */
23
        var ocrView;
24
        view !== undefined ? ocrView = view : console.error('OCR view is not defined.');
0 ignored issues
show
Bug introduced by
Did you forget to assign or call a function?

This error message can for example pop up if you forget to assign the result of a function call to a variable or pass it to another function:

function someFunction(x) {
    (x > 0) ? callFoo() : callBar();
}

// JSHint expects you to assign the result to a variable:
function someFunction(x) {
    var rs = (x > 0) ? callFoo() : callBar();
}

// If you do not use the result, you could also use if statements in the
// case above.
function someFunction(x) {
    if (x > 0) {
        callFoo();
    } else {
        callBar();
    }
}
Loading history...
25
        /** Instance of the OCA.Ocr.Util. */
26
        var ocrUtil;
27
        util !== undefined ? ocrUtil = util : console.error('OCR util is not defined.');
0 ignored issues
show
Bug introduced by
Did you forget to assign or call a function?

This error message can for example pop up if you forget to assign the result of a function call to a variable or pass it to another function:

function someFunction(x) {
    (x > 0) ? callFoo() : callBar();
}

// JSHint expects you to assign the result to a variable:
function someFunction(x) {
    var rs = (x > 0) ? callFoo() : callBar();
}

// If you do not use the result, you could also use if statements in the
// case above.
function someFunction(x) {
    if (x > 0) {
        callFoo();
    } else {
        callBar();
    }
}
Loading history...
28
        /** Instance of the OCA.Ocr.HttpService. */
29
        var ocrHttpService;
30
        httpService !== undefined ? ocrHttpService = httpService : console.error('OCR http service is not defined.');
0 ignored issues
show
Bug introduced by
Did you forget to assign or call a function?

This error message can for example pop up if you forget to assign the result of a function call to a variable or pass it to another function:

function someFunction(x) {
    (x > 0) ? callFoo() : callBar();
}

// JSHint expects you to assign the result to a variable:
function someFunction(x) {
    var rs = (x > 0) ? callFoo() : callBar();
}

// If you do not use the result, you could also use if statements in the
// case above.
function someFunction(x) {
    if (x > 0) {
        callFoo();
    } else {
        callBar();
    }
}
Loading history...
31
        /** Load the languages that are available for processing. */
32
        var languages = ocrHttpService.loadAvailableLanguages();
0 ignored issues
show
Bug introduced by
The variable ocrHttpService seems to not be initialized for all possible execution paths.
Loading history...
33
        languages.length > 0 ? '' : console.error('No languages available for OCR processing. Please make sure, that the Docker Container is up and running.');
0 ignored issues
show
Bug introduced by
Did you forget to assign or call a function?

This error message can for example pop up if you forget to assign the result of a function call to a variable or pass it to another function:

function someFunction(x) {
    (x > 0) ? callFoo() : callBar();
}

// JSHint expects you to assign the result to a variable:
function someFunction(x) {
    var rs = (x > 0) ? callFoo() : callBar();
}

// If you do not use the result, you could also use if statements in the
// case above.
function someFunction(x) {
    if (x > 0) {
        callFoo();
    } else {
        callBar();
    }
}
Loading history...
34
        /** Currently selected files. */
35
        var selectedFiles = [];
36
        /** Current status. */
37
        var status = {};
38
39
        /**
40
         * Sets the filtered/cleaned selectedFiles array.
41
         * @private
42
         * @param {Array<File>} files 
43
         */
44
        var setSelectedFiles = function (files) {
45
            files = ocrUtil.shrinkData(ocrUtil.filterFilesWithMimeTypes(files));
0 ignored issues
show
Bug introduced by
The variable ocrUtil seems to not be initialized for all possible execution paths.
Loading history...
46
            selectedFiles = files;
47
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
48
49
        /**
50
         * Gets the selectedFiles array
51
         * @private
52
         * @returns {Array<File>}
53
         */
54
        var getSelectedFiles = function () {
55
            return selectedFiles;
56
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
57
58
        /**
59
         * Sets the retrieved status.
60
         * @private
61
         * @param {Object} status
0 ignored issues
show
Documentation introduced by
The parameter status does not exist. Did you maybe forget to remove this comment?
Loading history...
62
         */
63
        var setStatus = function (state) {
64
            status = state;
65
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
66
67
        /**
68
         * Gets the retrieved status.
69
         * @private
70
         * @returns {Object}
71
         */
72
        var getStatus = function () {
73
            return status;
74
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
75
76
        /**
77
         * Checks if the click events target was the OCR dropdown or not.
78
         * @param {Event} event 
79
         */
80
        var clickOnOtherEvent = function (event) {
81
            ocrView.checkClickOther(event) ? setSelectedFiles([]) : '';
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
Bug introduced by
Did you forget to assign or call a function?

This error message can for example pop up if you forget to assign the result of a function call to a variable or pass it to another function:

function someFunction(x) {
    (x > 0) ? callFoo() : callBar();
}

// JSHint expects you to assign the result to a variable:
function someFunction(x) {
    var rs = (x > 0) ? callFoo() : callBar();
}

// If you do not use the result, you could also use if statements in the
// case above.
function someFunction(x) {
    if (x > 0) {
        callFoo();
    } else {
        callBar();
    }
}
Loading history...
82
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
83
84
        /**
85
         * Triggers the rendering of the OCR dropdown for a single file action.
86
         * Is the Actionhandler which is registered within the registerFileActions method.
87
         * @link registerFileActions
88
         * @private
89
         * @param {*} file 
90
         * @param {*} context 
91
         */
92
        var fileActionHandler = function (file, context) {
93
            var id = context.$file.attr('data-id');
94
            var mimetype = context.fileActions.getCurrentMimeType();
95
            var files = [{ id: id, mimetype: mimetype }];
96
            setSelectedFiles(files);
97
            ocrView.renderFileAction(file, languages);
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
98
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
99
100
        /**
101
         * Registers the FileAction options in the file actions menu for pdf and images.
102
         * @private
103
         */
104
        var registerFileActions = function () {
105
            // Register FileAction for mimetype pdf
106
            OCA.Files.fileActions.registerAction({
107
                name: 'Ocr',
108
                displayName: t('ocr', 'OCR'),
109
                order: 100,
110
                mime: 'application/pdf',
111
                permissions: OC.PERMISSION_UPDATE,
112
                altText: t('ocr', 'OCR'),
113
                iconClass: 'icon-ocr',
114
                actionHandler: fileActionHandler
115
            });
116
            // Register FileAction for mimetype image
117
            OCA.Files.fileActions.registerAction({
118
                name: 'Ocr',
119
                displayName: t('ocr', 'OCR'),
120
                order: 100,
121
                mime: 'image',
122
                permissions: OC.PERMISSION_UPDATE,
123
                altText: t('ocr', 'OCR'),
124
                iconClass: 'icon-ocr',
125
                actionHandler: fileActionHandler
126
            });
127
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
128
129
        /**
130
         * Triggers the rendering of the OCR dropdown for the top bar
131
         * selected files action button and sets the selectedFiles.
132
         * @private
133
         */
134
        var clickOnTopBarSelectedFilesActionButton = function () {
135
            ocrView.renderFileAction(undefined, languages);
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
136
            setSelectedFiles(OCA.Files.App.fileList.getSelectedFiles());
137
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
138
139
        /**
140
         * Triggers the view to show the selected files action button in the top bar
141
         * and sets the selectedFiles array.
142
         * @private
143
         */
144
        var toggleSelectedFilesActionButton = function () {
145
            var selFiles = OCA.Files.App.fileList.getSelectedFiles();
146
            if (selFiles.length > 0 && typeof selFiles !== undefined) {
147
                ocrView.toggleSelectedFilesActionButton(true);
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
148
                setSelectedFiles(selFiles);
149
            } else {
150
                ocrView.toggleSelectedFilesActionButton(false);
151
                setSelectedFiles([]);
152
            }
153
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
154
155
        /**
156
         * Triggers the view to hide the selected files action button in the top bar
157
         * and empties the selectedFiles array.
158
         * @private
159
         */
160
        var hideSelectedFilesActionButton = function () {
161
            ocrView.toggleSelectedFilesActionButton(false);
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
162
            setSelectedFiles([]);
163
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
164
165
        /**
166
         * Retrieves the status of the OCR process.
167
         * @private
168
         * @returns {$.Deferred}
169
         */
170
        var checkStatus = function () {
171
            var deferred = $.Deferred();
172
            ocrHttpService.checkStatus().done(function (status) {
0 ignored issues
show
Bug introduced by
The variable ocrHttpService seems to not be initialized for all possible execution paths.
Loading history...
173
                setStatus(status);
174
                deferred.resolve(status);
175
            }).fail(function (jqXHR) {
176
                deferred.reject(jqXHR.responseText);
177
            });
178
            return deferred.promise();
179
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
180
181
        /** 
182
         * Reloads the OCA.Files.App.fileList. 
183
         * @private
184
         */
185
        var updateFileList = function () {
186
            OCA.Files.App.fileList.reload();
187
            toggleSelectedActionButton();
188
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
189
190
        /**
191
         * Trigger the pending notification for the first time (with initialcount)
192
         * or after that without initialcount (undefined).
193
         * @private
194
         * @param {boolean} force - If new files in queue or already in the regular loop.
195
         * @param {number} initialcount - How much files initially to process (number or undefined).
196
         */
197
        var togglePendingState = function (force, initialcount) {
198
            var count;
199
            var pendingcount = getStatus().pending;
200
            initialcount !== undefined ? count = initialcount : count = pendingcount;
0 ignored issues
show
Bug introduced by
Did you forget to assign or call a function?

This error message can for example pop up if you forget to assign the result of a function call to a variable or pass it to another function:

function someFunction(x) {
    (x > 0) ? callFoo() : callBar();
}

// JSHint expects you to assign the result to a variable:
function someFunction(x) {
    var rs = (x > 0) ? callFoo() : callBar();
}

// If you do not use the result, you could also use if statements in the
// case above.
function someFunction(x) {
    if (x > 0) {
        callFoo();
    } else {
        callBar();
    }
}
Loading history...
201
            ocrView.togglePendingNotification(force, count);
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
202
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
203
204
        /**
205
         * Loops as long as there are pending files in the OCR queue.
206
         * @private
207
         */
208
        var loopForStatus = function () {
209
            $.when(checkStatus()).done(function () {
210
                if (getStatus().failed > 0) { ocrView.displayError(n('ocr', 'OCR processing for %n file failed. For details please go to your personal settings.', 'OCR processing for %n files failed. For details please go to your personal settings.', getStatus().failed)); }
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
211
                if (getStatus().pending > 0) {
212
                    if (getStatus().processed > 0) { updateFileList(); }
213
                    togglePendingState(false);
214
                    setTimeout($.proxy(loopForStatus, this), 4500);
215
                } else {
216
                    if (getStatus().processed > 0) { updateFileList(); }
217
                    togglePendingState(false);
218
                }
219
            }).fail(function (message) {
220
                ocrView.displayError(t('ocr', 'OCR status could not be retrieved:') + ' ' + message);
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
221
                setTimeout($.proxy(loopForStatus, self), 4500);
0 ignored issues
show
Bug introduced by
The variable self seems to be never declared. If this is a global, consider adding a /** global: self */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
222
            });
223
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
224
225
        /**
226
         * Triggers the OCR process for the selectedFiles array
227
         * and toggles the "pending" state for the ocr process.
228
         * @private
229
         */
230
		var clickOnProcessButtonEvent = function () {
231
			if (getSelectedFiles().length == 0) {
0 ignored issues
show
Coding Style introduced by
It is recommended to use === to compare with 0.

Generally, it is recommended to use strict comparison whenever possible and not to rely on the weaker type-juggling comparison operator.

Read more about comparison operations.

Loading history...
232
				ocrView.displayError(t('ocr', 'OCR processing failed:') + ' ' + t('ocr', 'Mimetype not supported.'));
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
233
				ocrView.destroyDropdown();
234
			} else {
235
				var selectedLanguages = $('#ocrLanguage').select2('val');
236
				ocrHttpService.process(getSelectedFiles(), selectedLanguages).done(function (status) {
0 ignored issues
show
Bug introduced by
The variable ocrHttpService seems to not be initialized for all possible execution paths.
Loading history...
Unused Code introduced by
The parameter status is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
237
					togglePendingState(true, getSelectedFiles().length);
238
					setSelectedFiles([]);
239
					setTimeout($.proxy(loopForStatus, this), 4500);
240
				}).fail(function (jqXHR) {
241
					ocrView.displayError(t('ocr', 'OCR processing failed:') + ' ' + jqXHR.responseText);
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
242
				}).always(function () {
243
					ocrView.destroyDropdown();
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
244
				});
245
			}
246
		}
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
247
248
        /**
249
         * Registers the events and the appropriate methods of the view.
250
         * @private
251
         */
252
        var registerEvents = function () {
253
            // Click on another element then the dropdown
254
            $(document).click(function (event) {
255
                clickOnOtherEvent(event);
256
            });
257
            // Click on process button
258
            $(document).on('click', '#processOCR', function () {
259
                clickOnProcessButtonEvent();
260
            });
261
            // Click on top bar OCR button
262
            $(document).on('click', '#selectedFilesOCR', function () {
263
                clickOnTopBarSelectedFilesActionButton();
264
                return false;
265
            });
266
267
            // Register click events on file menu OCR option
268
            registerFileActions();
269
270
            // Register checkbox events
271
            _.defer(function () {
272
                OCA.Files.App.fileList.$fileList.on('change', 'td.filename>.selectCheckBox', _.bind(toggleSelectedFilesActionButton, this));
273
                OCA.Files.App.fileList.$el.find('.select-all').click(_.bind(toggleSelectedFilesActionButton, this));
274
                OCA.Files.App.fileList.$el.find('.delete-selected').click(_.bind(hideSelectedFilesActionButton, this));
275
            });
276
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
277
278
        this.init = function () {
279
            registerEvents();
280
            ocrView.renderSelectedFilesActionButton();
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
281
            loopForStatus();
282
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
283
284
        this.destroy = function () {
285
            ocrView.destroy();
0 ignored issues
show
Bug introduced by
The variable ocrView seems to not be initialized for all possible execution paths.
Loading history...
286
            OCA.Files.fileActions.clear();
287
            OCA.Files.fileActions.registerDefaultActions();
288
        }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
289
    }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
290
291
	/**
292
	 * Init OCR Controller
293
	 */
294
    /** We have to be in the Files App! */
295
    if (!OCA.Files) {
296
        return;
297
    }
298
    /** Escape when the requested file is public.php */
299
    if (/(public)\.php/i.exec(window.location.href) !== null) {
300
        return;
301
    }
302
    /** Create namespace Ocr */
303
    if (!OCA.Ocr) {
304
        OCA.Ocr = {};
305
    }
306
    OCA.Ocr.Controller = Controller;
307
308
    /** global: OC, OCA */
309
})(OC, OCA, window, jQuery, _);
0 ignored issues
show
Bug introduced by
The variable _ seems to be never declared. If this is a global, consider adding a /** global: _ */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
310