Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit 29aa315

Browse files
committed
Merge branch 't/58'
Other: `FileRepository` will automatically warn when it's initialized but no upload adapter was enabled. Closes #58.
2 parents 785e88b + b1a61d9 commit 29aa315

File tree

8 files changed

+246
-96
lines changed

8 files changed

+246
-96
lines changed

src/filerepository.js

Lines changed: 110 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,17 @@ import FileReader from './filereader.js';
2020
import uid from '@ckeditor/ckeditor5-utils/src/uid.js';
2121

2222
/**
23-
* FileRepository plugin.
23+
* File repository plugin. A central point for managing file upload.
24+
*
25+
* To use it, first you need an upload adapter. Upload adapter's job is to handle communication with the server
26+
* (sending the file and handling server's response). You can use one of the existing plugins introducing upload adapters
27+
* (e.g. {@link module:easy-image/cloudservicesuploadadapter~CloudServicesUploadAdapter} or
28+
* {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter}) or write your own one
29+
* (which boils down to setting the {@link ~FileRepository#createAdapter} factory function – see
30+
* {@link ~Adapter `Adapter` interface} documentation).
31+
*
32+
* Then, you can use {@link ~FileRepository#createLoader `createLoader()`} and the returned {@link ~FileLoader} instance to
33+
* load and upload files.
2434
*
2535
* @extends module:core/plugin~Plugin
2636
*/
@@ -44,15 +54,15 @@ export default class FileRepository extends Plugin {
4454
this.loaders = new Collection();
4555

4656
/**
47-
* Function that should be defined before using FileRepository. It should return new instance of
48-
* {@link module:upload/filerepository~Adapter Adapter} that will be used to upload files.
49-
* {@link module:upload/filerepository~FileLoader FileLoader} instance associated with the adapter
57+
* A factory function which should be defined before using `FileRepository`.
58+
*
59+
* It should return a new instance of {@link module:upload/filerepository~Adapter} that will be used to upload files.
60+
* {@link module:upload/filerepository~FileLoader} instance associated with the adapter
5061
* will be passed to that function.
51-
* For more information and example see {@link module:upload/filerepository~Adapter Adapter}.
5262
*
53-
* @abstract
54-
* @function
55-
* @name #createAdapter
63+
* For more information and example see {@link module:upload/filerepository~Adapter}.
64+
*
65+
* @member {Function} #createAdapter
5666
*/
5767

5868
/**
@@ -66,6 +76,7 @@ export default class FileRepository extends Plugin {
6676

6777
/**
6878
* Number of total bytes to upload.
79+
*
6980
* It might be different than the file size because of headers and additional data.
7081
* It contains `null` if value is not available yet, so it's better to use {@link #uploadedPercent} to monitor
7182
* the progress.
@@ -88,11 +99,49 @@ export default class FileRepository extends Plugin {
8899
} );
89100
}
90101

102+
afterInit() {
103+
if ( !this.createAdapter ) {
104+
/**
105+
* You need to enable an upload adapter in order to be able to upload files.
106+
*
107+
* This warning shows up when {@link module:upload/filerepository~FileRepository} is being used
108+
* without {@link #createAdapter definining an upload adapter}.
109+
*
110+
* If you see this warning when using one of the {@glink builds/index CKEditor 5 Builds}
111+
* it means that you did not configure any of the upload adapters available by default in those builds.
112+
* See:
113+
*
114+
* * {@link module:core/editor/editorconfig~EditorConfig#cloudServices `config.cloudServices`} for
115+
* Easy Image with Cloud Services integration,
116+
* * {@link module:core/editor/editorconfig~EditorConfig#ckfinder `config.ckfinder`} for CKFinder
117+
* file upload integration.
118+
*
119+
* If you do not need file upload functionality at all and you use one of the builds, you can disable the built-in
120+
* upload adapters to hide this warning:
121+
*
122+
* ClassicEditor
123+
* .create( document.querySelector( '#editor' ), {
124+
* removePlugins: [ 'EasyImage', 'CKFinderUploadAdapter' ]
125+
* } )
126+
* .then( ... )
127+
* .catch( ... );
128+
*
129+
* If you wish to implement your own upload adapter refer to the {@link ~Adapter `Adapter` interface} documentation.
130+
*
131+
* @error filerepository-no-adapter
132+
*/
133+
log.warn( 'filerepository-no-adapter: Upload adapter is not defined.' );
134+
135+
return null;
136+
}
137+
}
138+
91139
/**
92140
* Returns the loader associated with specified file.
141+
*
93142
* To get loader by id use `fileRepository.loaders.get( id )`.
94143
*
95-
* @param {File} file Native File object.
144+
* @param {File} file Native file handle.
96145
* @returns {module:upload/filerepository~FileLoader|null}
97146
*/
98147
getLoader( file ) {
@@ -106,15 +155,16 @@ export default class FileRepository extends Plugin {
106155
}
107156

108157
/**
109-
* Creates loader for specified file.
110-
* Shows console warning and returns `null` if {@link #createAdapter} method is not defined.
158+
* Creates a loader instance for the given file.
159+
*
160+
* Requires {@link #createAdapter} factory to be defined.
111161
*
112162
* @param {File} file Native File object.
113163
* @returns {module:upload/filerepository~FileLoader|null}
114164
*/
115165
createLoader( file ) {
116166
if ( !this.createAdapter ) {
117-
log.warn( 'FileRepository: no createAdapter method found. Please define it before creating a loader.' );
167+
log.error( 'filerepository-no-adapter: Upload adapter is not defined.' );
118168

119169
return null;
120170
}
@@ -150,7 +200,7 @@ export default class FileRepository extends Plugin {
150200
}
151201

152202
/**
153-
* Destroys loader.
203+
* Destroys the given loader.
154204
*
155205
* @param {File|module:upload/filerepository~FileLoader} fileOrLoader File associated with that loader or loader
156206
* itself.
@@ -172,9 +222,9 @@ mix( FileRepository, ObservableMixin );
172222
*/
173223
class FileLoader {
174224
/**
175-
* Creates instance of FileLoader.
225+
* Creates a new instance of `FileLoader`.
176226
*
177-
* @param {File} file
227+
* @param {File} file A native file instance.
178228
* @param {module:upload/filerepository~Adapter} adapter
179229
*/
180230
constructor( file, adapter ) {
@@ -187,15 +237,15 @@ class FileLoader {
187237
this.id = uid();
188238

189239
/**
190-
* File instance associated with FileLoader.
240+
* A `File` instance associated with this file loader.
191241
*
192242
* @readonly
193243
* @member {File}
194244
*/
195245
this.file = file;
196246

197247
/**
198-
* Adapter instance associated with FileLoader.
248+
* Adapter instance associated with this file loader.
199249
*
200250
* @private
201251
* @member {module:upload/filerepository~Adapter}
@@ -212,18 +262,21 @@ class FileLoader {
212262

213263
/**
214264
* Current status of FileLoader. It can be one of the following:
265+
*
215266
* * 'idle',
216267
* * 'reading',
217268
* * 'uploading',
218269
* * 'aborted',
219270
* * 'error'.
220271
*
221272
* When reading status can change in a following way:
273+
*
222274
* `idle` -> `reading` -> `idle`
223275
* `idle` -> `reading -> `aborted`
224276
* `idle` -> `reading -> `error`
225277
*
226278
* When uploading status can change in a following way:
279+
*
227280
* `idle` -> `uploading` -> `idle`
228281
* `idle` -> `uploading` -> `aborted`
229282
* `idle` -> `uploading` -> `error`
@@ -275,17 +328,19 @@ class FileLoader {
275328

276329
/**
277330
* Reads file using {@link module:upload/filereader~FileReader}.
331+
*
278332
* Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `filerepository-read-wrong-status` when status
279333
* is different than `idle`.
334+
*
280335
* Example usage:
281336
*
282337
* fileLoader.read()
283338
* .then( data => { ... } )
284-
* .catch( e => {
285-
* if ( e === 'aborted' ) {
339+
* .catch( err => {
340+
* if ( err === 'aborted' ) {
286341
* console.log( 'Reading aborted.' );
287342
* } else {
288-
* console.log( 'Reading error.', e );
343+
* console.log( 'Reading error.', err );
289344
* }
290345
* } );
291346
*
@@ -317,7 +372,8 @@ class FileLoader {
317372
}
318373

319374
/**
320-
* Reads file using provided {@link module:upload/filerepository~Adapter}.
375+
* Reads file using the provided {@link module:upload/filerepository~Adapter}.
376+
*
321377
* Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `filerepository-upload-wrong-status` when status
322378
* is different than `idle`.
323379
* Example usage:
@@ -398,39 +454,40 @@ mix( FileLoader, ObservableMixin );
398454
* handles file uploads. It should contain logic necessary to initiate upload process and monitor its progress.
399455
*
400456
* It should implement two methods:
401-
* * {@link module:upload/filerepository~Adapter#upload upload()},
402-
* * {@link module:upload/filerepository~Adapter#abort abort()}.
457+
*
458+
* * {@link module:upload/filerepository~Adapter#upload `upload()`},
459+
* * {@link module:upload/filerepository~Adapter#abort `abort()`}.
403460
*
404461
* Example adapter implementation:
405462
*
406-
* class Adapter {
407-
* constructor( loader ) {
408-
* // Save Loader instance to update upload progress.
409-
* this.loader = loader;
410-
* }
463+
* class Adapter {
464+
* constructor( loader ) {
465+
* // Save Loader instance to update upload progress.
466+
* this.loader = loader;
467+
* }
411468
*
412-
* upload() {
413-
* // Update loader's progress.
414-
* server.onUploadProgress( data => {
415-
* loader.uploadTotal = data.total;
416-
* loader.uploaded = data.uploaded;
417-
* } ):
469+
* upload() {
470+
* // Update loader's progress.
471+
* server.onUploadProgress( data => {
472+
* loader.uploadTotal = data.total;
473+
* loader.uploaded = data.uploaded;
474+
* } ):
418475
*
419-
* // Return promise that will be resolved when file is uploaded.
420-
* return server.upload( loader.file );
421-
* }
476+
* // Return promise that will be resolved when file is uploaded.
477+
* return server.upload( loader.file );
478+
* }
422479
*
423-
* abort() {
424-
* // Reject promise returned from upload() method.
425-
* server.abortUpload();
480+
* abort() {
481+
* // Reject promise returned from upload() method.
482+
* server.abortUpload();
483+
* }
426484
* }
427-
* }
428485
*
429486
* Then adapter can be set to be used by {@link module:upload/filerepository~FileRepository FileRepository}:
430487
*
431-
* editor.plugins.get( 'FileRepository' ).createAdapter = function( loader ) {
432-
* return new Adapter( loader );
433-
* };
488+
* editor.plugins.get( 'FileRepository' ).createAdapter = function( loader ) {
489+
* return new Adapter( loader );
490+
* };
434491
*
435492
* @interface Adapter
436493
*/
@@ -440,18 +497,18 @@ mix( FileLoader, ObservableMixin );
440497
* This method should return a promise that will resolve when data will be uploaded to server. Promise should be
441498
* resolved with an object containing information about uploaded file:
442499
*
443-
* {
444-
* default: 'http://server/default-size.image.png'
445-
* }
500+
* {
501+
* default: 'http://server/default-size.image.png'
502+
* }
446503
*
447504
* Additionally, other image sizes can be provided:
448505
*
449-
* {
450-
* default: 'http://server/default-size.image.png',
451-
* '160': 'http://server/size-160.image.png',
452-
* '500': 'http://server/size-500.image.png',
453-
* '1000': 'http://server/size-1000.image.png'
454-
* }
506+
* {
507+
* default: 'http://server/default-size.image.png',
508+
* '160': 'http://server/size-160.image.png',
509+
* '500': 'http://server/size-500.image.png',
510+
* '1000': 'http://server/size-1000.image.png'
511+
* }
455512
*
456513
* Take a look at {@link module:upload/filerepository~Adapter example Adapter implementation} and
457514
* {@link module:upload/filerepository~FileRepository#createAdapter createAdapter method}.

tests/_utils/mocks.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* For licensing, see LICENSE.md.
44
*/
55

6+
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
7+
68
/**
79
* Returns object that mocks native File object.
810
*/
@@ -117,3 +119,10 @@ export class NativeFileReaderMock {
117119
}
118120
}
119121

122+
export class UploadAdapterPluginMock extends Plugin {
123+
init() {
124+
const fileRepository = this.editor.plugins.get( 'FileRepository' );
125+
126+
fileRepository.createAdapter = () => {};
127+
}
128+
}

0 commit comments

Comments
 (0)