Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Зуев Егор
/
wiki.dev
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Authored by
Dan Brown
2015-12-07 23:00:34 +0000
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Commit
c88096b7e2fbcc33dd8a66a3235ff4e9d42df715
c88096b7
1 parent
46c905df
Revamped image system to use driver-agnotstic storage and be more efficent
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
557 additions
and
144 deletions
.env.example
app/Http/Controllers/ImageController.php
app/Http/routes.php
app/Repos/BookRepo.php
app/Repos/ImageRepo.php
composer.json
composer.lock
config/filesystems.php
database/migrations/2015_12_07_195238_add_image_upload_types.php
resources/assets/js/components/image-manager.vue
resources/assets/js/pages/page-form.js
resources/views/settings/index.blade.php
.env.example
View file @
c88096b
...
...
@@ -14,12 +14,23 @@ CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
# Storage
STORAGE_TYPE=local
# Amazon S3 Config
STORAGE_S3_KEY=false
STORAGE_S3_SECRET=false
STORAGE_S3_REGION=false
STORAGE_S3_BUCKET=false
# Storage URL
# Used to prefix image urls for when using custom domains/cdns
STORAGE_URL=false
# Social Authentication information. Defaults as off.
GITHUB_APP_ID=false
GITHUB_APP_SECRET=false
GOOGLE_APP_ID=false
GOOGLE_APP_SECRET=false
# URL for social login redirects, NO TRAILING SLASH
# URL
used
for social login redirects, NO TRAILING SLASH
APP_URL=http://bookstack.dev
# Mail settings
...
...
app/Http/Controllers/ImageController.php
View file @
c88096b
...
...
@@ -2,6 +2,7 @@
namespace
BookStack\Http\Controllers
;
use
BookStack\Repos\ImageRepo
;
use
Illuminate\Filesystem\Filesystem
as
File
;
use
Illuminate\Http\Request
;
use
Illuminate\Support\Facades\Auth
;
...
...
@@ -14,16 +15,19 @@ class ImageController extends Controller
{
protected
$image
;
protected
$file
;
protected
$imageRepo
;
/**
* ImageController constructor.
* @param Image $image
* @param File $file
* @param Image $image
* @param File $file
* @param ImageRepo $imageRepo
*/
public
function
__construct
(
Image
$image
,
File
$file
)
public
function
__construct
(
Image
$image
,
File
$file
,
ImageRepo
$imageRepo
)
{
$this
->
image
=
$image
;
$this
->
file
=
$file
;
$this
->
imageRepo
=
$imageRepo
;
parent
::
__construct
();
}
...
...
@@ -33,108 +37,31 @@ class ImageController extends Controller
* @param int $page
* @return \Illuminate\Http\JsonResponse
*/
public
function
getAll
(
$page
=
0
)
public
function
getAll
Gallery
(
$page
=
0
)
{
$pageSize
=
30
;
$images
=
$this
->
image
->
orderBy
(
'created_at'
,
'desc'
)
->
skip
(
$page
*
$pageSize
)
->
take
(
$pageSize
)
->
get
();
foreach
(
$images
as
$image
)
{
$this
->
loadSizes
(
$image
);
}
$hasMore
=
$this
->
image
->
orderBy
(
'created_at'
,
'desc'
)
->
skip
((
$page
+
1
)
*
$pageSize
)
->
take
(
$pageSize
)
->
count
()
>
0
;
return
response
()
->
json
([
'images'
=>
$images
,
'hasMore'
=>
$hasMore
]);
}
/**
* Loads the standard thumbnail sizes for an image.
* @param Image $image
*/
private
function
loadSizes
(
Image
$image
)
{
$image
->
thumbnail
=
$this
->
getThumbnail
(
$image
,
150
,
150
);
$image
->
display
=
$this
->
getThumbnail
(
$image
,
840
,
0
,
true
);
$imgData
=
$this
->
imageRepo
->
getAllGallery
(
$page
);
return
response
()
->
json
(
$imgData
);
}
/**
* Get the thumbnail for an image.
* If $keepRatio is true only the width will be used.
* @param $image
* @param int $width
* @param int $height
* @param bool $keepRatio
* @return string
*/
public
function
getThumbnail
(
$image
,
$width
=
220
,
$height
=
220
,
$keepRatio
=
false
)
{
$explodedPath
=
explode
(
'/'
,
$image
->
url
);
$dirPrefix
=
$keepRatio
?
'scaled-'
:
'thumbs-'
;
array_splice
(
$explodedPath
,
4
,
0
,
[
$dirPrefix
.
$width
.
'-'
.
$height
]);
$thumbPath
=
implode
(
'/'
,
$explodedPath
);
$thumbFilePath
=
public_path
()
.
$thumbPath
;
// Return the thumbnail url path if already exists
if
(
file_exists
(
$thumbFilePath
))
{
return
$thumbPath
;
}
// Otherwise create the thumbnail
$thumb
=
ImageTool
::
make
(
public_path
()
.
$image
->
url
);
if
(
$keepRatio
)
{
$thumb
->
resize
(
$width
,
null
,
function
(
$constraint
)
{
$constraint
->
aspectRatio
();
$constraint
->
upsize
();
});
}
else
{
$thumb
->
fit
(
$width
,
$height
);
}
// Create thumbnail folder if it does not exist
if
(
!
file_exists
(
dirname
(
$thumbFilePath
)))
{
mkdir
(
dirname
(
$thumbFilePath
),
0775
,
true
);
}
//Save Thumbnail
$thumb
->
save
(
$thumbFilePath
);
return
$thumbPath
;
}
/**
* Handles image uploads for use on pages.
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public
function
upload
(
Request
$request
)
public
function
upload
Gallery
(
Request
$request
)
{
$this
->
checkPermission
(
'image-create'
);
$this
->
validate
(
$request
,
[
'file'
=>
'image|mimes:jpeg,gif,png'
]);
$imageUpload
=
$request
->
file
(
'file'
);
$name
=
str_replace
(
' '
,
'-'
,
$imageUpload
->
getClientOriginalName
());
$storageName
=
substr
(
sha1
(
time
()),
0
,
10
)
.
'-'
.
$name
;
$imagePath
=
'/uploads/images/'
.
Date
(
'Y-m-M'
)
.
'/'
;
$storagePath
=
public_path
()
.
$imagePath
;
$fullPath
=
$storagePath
.
$storageName
;
while
(
file_exists
(
$fullPath
))
{
$storageName
=
substr
(
sha1
(
rand
()),
0
,
3
)
.
$storageName
;
$fullPath
=
$storagePath
.
$storageName
;
}
$imageUpload
->
move
(
$storagePath
,
$storageName
);
// Create and save image object
$this
->
image
->
name
=
$name
;
$this
->
image
->
url
=
$imagePath
.
$storageName
;
$this
->
image
->
created_by
=
auth
()
->
user
()
->
id
;
$this
->
image
->
updated_by
=
auth
()
->
user
()
->
id
;
$this
->
image
->
save
();
$this
->
loadSizes
(
$this
->
image
);
return
response
()
->
json
(
$this
->
image
);
$imageUpload
=
$request
->
file
(
'file'
);
$image
=
$this
->
imageRepo
->
saveNew
(
$imageUpload
,
'gallery'
);
return
response
()
->
json
(
$image
);
}
/**
* Update image details
* @param $imageId
...
...
@@ -147,13 +74,12 @@ class ImageController extends Controller
$this
->
validate
(
$request
,
[
'name'
=>
'required|min:2|string'
]);
$image
=
$this
->
image
->
findOrFail
(
$imageId
);
$image
->
fill
(
$request
->
all
());
$image
->
save
();
$this
->
loadSizes
(
$image
);
return
response
()
->
json
(
$this
->
image
);
$image
=
$this
->
imageRepo
->
getById
(
$imageId
);
$image
=
$this
->
imageRepo
->
updateImageDetails
(
$image
,
$request
->
all
());
return
response
()
->
json
(
$image
);
}
/**
* Deletes an image and all thumbnail/image files
* @param PageRepo $pageRepo
...
...
@@ -164,41 +90,18 @@ class ImageController extends Controller
public
function
destroy
(
PageRepo
$pageRepo
,
Request
$request
,
$id
)
{
$this
->
checkPermission
(
'image-delete'
);
$image
=
$this
->
image
->
findOrFail
(
$id
);
$image
=
$this
->
image
Repo
->
getById
(
$id
);
// Check if this image is used on any pages
$pageSearch
=
$pageRepo
->
searchForImage
(
$image
->
url
);
$isForced
=
(
$request
->
has
(
'force'
)
&&
(
$request
->
get
(
'force'
)
===
'true'
)
||
$request
->
get
(
'force'
)
===
true
);
if
(
$pageSearch
!==
false
&&
!
$isForced
)
{
return
response
()
->
json
(
$pageSearch
,
400
);
}
// Delete files
$folder
=
public_path
()
.
dirname
(
$image
->
url
);
$fileName
=
basename
(
$image
->
url
);
// Delete thumbnails
foreach
(
glob
(
$folder
.
'/*'
)
as
$file
)
{
if
(
is_dir
(
$file
))
{
$thumbName
=
$file
.
'/'
.
$fileName
;
if
(
file_exists
(
$file
))
{
unlink
(
$thumbName
);
}
// Remove thumb folder if empty
if
(
count
(
glob
(
$file
.
'/*'
))
===
0
)
{
rmdir
(
$file
);
}
if
(
!
$isForced
)
{
$pageSearch
=
$pageRepo
->
searchForImage
(
$image
->
url
);
if
(
$pageSearch
!==
false
)
{
return
response
()
->
json
(
$pageSearch
,
400
);
}
}
// Delete file and database entry
unlink
(
$folder
.
'/'
.
$fileName
);
$image
->
delete
();
// Delete parent folder if empty
if
(
count
(
glob
(
$folder
.
'/*'
))
===
0
)
{
rmdir
(
$folder
);
}
$this
->
imageRepo
->
destroyImage
(
$image
);
return
response
()
->
json
(
'Image Deleted'
);
}
...
...
app/Http/routes.php
View file @
c88096b
...
...
@@ -45,8 +45,6 @@ Route::group(['middleware' => 'auth'], function () {
});
// Uploads
Route
::
post
(
'/upload/image'
,
'ImageController@upload'
);
// Users
Route
::
get
(
'/users'
,
'UserController@index'
);
...
...
@@ -58,10 +56,13 @@ Route::group(['middleware' => 'auth'], function () {
Route
::
delete
(
'/users/{id}'
,
'UserController@destroy'
);
// Image routes
Route
::
get
(
'/images/all'
,
'ImageController@getAll'
);
Route
::
put
(
'/images/update/{imageId}'
,
'ImageController@update'
);
Route
::
delete
(
'/images/{imageId}'
,
'ImageController@destroy'
);
Route
::
get
(
'/images/all/{page}'
,
'ImageController@getAll'
);
Route
::
group
([
'prefix'
=>
'images'
],
function
()
{
Route
::
get
(
'/gallery/all'
,
'ImageController@getAllGallery'
);
Route
::
get
(
'/gallery/all/{page}'
,
'ImageController@getAllGallery'
);
Route
::
post
(
'/gallery/upload'
,
'ImageController@uploadGallery'
);
Route
::
put
(
'/update/{imageId}'
,
'ImageController@update'
);
Route
::
delete
(
'/{imageId}'
,
'ImageController@destroy'
);
});
// Links
Route
::
get
(
'/link/{id}'
,
'PageController@redirectFromLink'
);
...
...
app/Repos/BookRepo.php
View file @
c88096b
...
...
@@ -77,6 +77,12 @@ class BookRepo
return
Views
::
getUserRecentlyViewed
(
$count
,
$page
,
$this
->
book
);
}
/**
* Gets the most viewed books.
* @param int $count
* @param int $page
* @return mixed
*/
public
function
getPopular
(
$count
=
10
,
$page
=
0
)
{
return
Views
::
getPopular
(
$count
,
$page
,
$this
->
book
);
...
...
app/Repos/ImageRepo.php
0 → 100644
View file @
c88096b
<?php
namespace
BookStack\Repos
;
use
BookStack\Image
;
use
Illuminate\Contracts\Filesystem\Filesystem
as
FileSystemInstance
;
use
Intervention\Image\ImageManager
as
ImageTool
;
use
Illuminate\Contracts\Filesystem\Factory
as
FileSystem
;
use
Illuminate\Contracts\Cache\Repository
as
Cache
;
use
Setting
;
use
Symfony\Component\HttpFoundation\File\UploadedFile
;
class
ImageRepo
{
protected
$image
;
protected
$imageTool
;
protected
$fileSystem
;
protected
$cache
;
/**
* @var FileSystemInstance
*/
protected
$storageInstance
;
protected
$storageUrl
;
/**
* ImageRepo constructor.
* @param Image $image
* @param ImageTool $imageTool
* @param FileSystem $fileSystem
* @param Cache $cache
*/
public
function
__construct
(
Image
$image
,
ImageTool
$imageTool
,
FileSystem
$fileSystem
,
Cache
$cache
)
{
$this
->
image
=
$image
;
$this
->
imageTool
=
$imageTool
;
$this
->
fileSystem
=
$fileSystem
;
$this
->
cache
=
$cache
;
}
/**
* Get an image with the given id.
* @param $id
* @return mixed
*/
public
function
getById
(
$id
)
{
return
$this
->
image
->
findOrFail
(
$id
);
}
/**
* Get all images for the standard gallery view that's used for
* adding images to shared content such as pages.
* @param int $page
* @param int $pageSize
* @return array
*/
public
function
getAllGallery
(
$page
=
0
,
$pageSize
=
24
)
{
$images
=
$this
->
image
->
where
(
'type'
,
'='
,
'gallery'
)
->
orderBy
(
'created_at'
,
'desc'
)
->
skip
(
$pageSize
*
$page
)
->
take
(
$pageSize
+
1
)
->
get
();
$hasMore
=
count
(
$images
)
>
$pageSize
;
$returnImages
=
$images
->
take
(
24
);
$returnImages
->
each
(
function
(
$image
)
{
$this
->
loadThumbs
(
$image
);
});
return
[
'images'
=>
$returnImages
,
'hasMore'
=>
$hasMore
];
}
/**
* Save a new image into storage and return the new image.
* @param UploadedFile $uploadFile
* @param string $type
* @return Image
*/
public
function
saveNew
(
UploadedFile
$uploadFile
,
$type
)
{
$storage
=
$this
->
getStorage
();
$secureUploads
=
Setting
::
get
(
'app-secure-images'
);
$imageName
=
str_replace
(
' '
,
'-'
,
$uploadFile
->
getClientOriginalName
());
if
(
$secureUploads
)
$imageName
=
str_random
(
16
)
.
'-'
.
$imageName
;
$imagePath
=
'/uploads/images/'
.
$type
.
'/'
.
Date
(
'Y-m-M'
)
.
'/'
;
while
(
$storage
->
exists
(
$imagePath
.
$imageName
))
{
$imageName
=
str_random
(
3
)
.
$imageName
;
}
$fullPath
=
$imagePath
.
$imageName
;
$storage
->
put
(
$fullPath
,
file_get_contents
(
$uploadFile
->
getRealPath
()));
$userId
=
auth
()
->
user
()
->
id
;
$image
=
$this
->
image
->
forceCreate
([
'name'
=>
$imageName
,
'path'
=>
$fullPath
,
'url'
=>
$this
->
getPublicUrl
(
$fullPath
),
'type'
=>
$type
,
'created_by'
=>
$userId
,
'updated_by'
=>
$userId
]);
$this
->
loadThumbs
(
$image
);
return
$image
;
}
/**
* Update the details of an image via an array of properties.
* @param Image $image
* @param array $updateDetails
* @return Image
*/
public
function
updateImageDetails
(
Image
$image
,
$updateDetails
)
{
$image
->
fill
(
$updateDetails
);
$image
->
save
();
$this
->
loadThumbs
(
$image
);
return
$image
;
}
/**
* Destroys an Image object along with its files and thumbnails.
* @param Image $image
* @return bool
*/
public
function
destroyImage
(
Image
$image
)
{
$storage
=
$this
->
getStorage
();
$imageFolder
=
dirname
(
$image
->
path
);
$imageFileName
=
basename
(
$image
->
path
);
$allImages
=
collect
(
$storage
->
allFiles
(
$imageFolder
));
$imagesToDelete
=
$allImages
->
filter
(
function
(
$imagePath
)
use
(
$imageFileName
)
{
$expectedIndex
=
strlen
(
$imagePath
)
-
strlen
(
$imageFileName
);
return
strpos
(
$imagePath
,
$imageFileName
)
===
$expectedIndex
;
});
$storage
->
delete
(
$imagesToDelete
->
all
());
// Cleanup of empty folders
foreach
(
$storage
->
directories
(
$imageFolder
)
as
$directory
)
{
if
(
$this
->
isFolderEmpty
(
$directory
))
$storage
->
deleteDirectory
(
$directory
);
}
if
(
$this
->
isFolderEmpty
(
$imageFolder
))
$storage
->
deleteDirectory
(
$imageFolder
);
$image
->
delete
();
return
true
;
}
/**
* Check whether or not a folder is empty.
* @param $path
* @return int
*/
private
function
isFolderEmpty
(
$path
)
{
$files
=
$this
->
getStorage
()
->
files
(
$path
);
$folders
=
$this
->
getStorage
()
->
directories
(
$path
);
return
count
(
$files
)
===
0
&&
count
(
$folders
)
===
0
;
}
/**
* Load thumbnails onto an image object.
* @param Image $image
*/
private
function
loadThumbs
(
Image
$image
)
{
$image
->
thumbs
=
[
'gallery'
=>
$this
->
getThumbnail
(
$image
,
150
,
150
),
'display'
=>
$this
->
getThumbnail
(
$image
,
840
,
0
,
true
)
];
}
/**
* Get the thumbnail for an image.
* If $keepRatio is true only the width will be used.
* Checks the cache then storage to avoid creating / accessing the filesystem on every check.
*
* @param Image $image
* @param int $width
* @param int $height
* @param bool $keepRatio
* @return string
*/
private
function
getThumbnail
(
Image
$image
,
$width
=
220
,
$height
=
220
,
$keepRatio
=
false
)
{
$thumbDirName
=
'/'
.
(
$keepRatio
?
'scaled-'
:
'thumbs-'
)
.
$width
.
'-'
.
$height
.
'/'
;
$thumbFilePath
=
dirname
(
$image
->
path
)
.
$thumbDirName
.
basename
(
$image
->
path
);
if
(
$this
->
cache
->
has
(
'images-'
.
$image
->
id
.
'-'
.
$thumbFilePath
)
&&
$this
->
cache
->
get
(
'images-'
.
$thumbFilePath
))
{
return
$this
->
getPublicUrl
(
$thumbFilePath
);
}
$storage
=
$this
->
getStorage
();
if
(
$storage
->
exists
(
$thumbFilePath
))
{
return
$this
->
getPublicUrl
(
$thumbFilePath
);
}
// Otherwise create the thumbnail
$thumb
=
$this
->
imageTool
->
make
(
$storage
->
get
(
$image
->
path
));
if
(
$keepRatio
)
{
$thumb
->
resize
(
$width
,
null
,
function
(
$constraint
)
{
$constraint
->
aspectRatio
();
$constraint
->
upsize
();
});
}
else
{
$thumb
->
fit
(
$width
,
$height
);
}
$thumbData
=
(
string
)
$thumb
->
encode
();
$storage
->
put
(
$thumbFilePath
,
$thumbData
);
$this
->
cache
->
put
(
'images-'
.
$image
->
id
.
'-'
.
$thumbFilePath
,
$thumbFilePath
,
60
*
72
);
return
$this
->
getPublicUrl
(
$thumbFilePath
);
}
/**
* Gets a public facing url for an image by checking relevant environment variables.
* @param $filePath
* @return string
*/
private
function
getPublicUrl
(
$filePath
)
{
if
(
$this
->
storageUrl
===
null
)
{
$storageUrl
=
env
(
'STORAGE_URL'
);
// Get the standard public s3 url if s3 is set as storage type
if
(
$storageUrl
==
false
&&
env
(
'STORAGE_TYPE'
)
===
's3'
)
{
$storageDetails
=
config
(
'filesystems.disks.s3'
);
$storageUrl
=
'https://s3-'
.
$storageDetails
[
'region'
]
.
'.amazonaws.com/'
.
$storageDetails
[
'bucket'
]
.
$filePath
;
}
$this
->
storageUrl
=
$storageUrl
;
}
return
(
$this
->
storageUrl
==
false
?
''
:
rtrim
(
$this
->
storageUrl
,
'/'
))
.
$filePath
;
}
/**
* Get the storage that will be used for storing images.
* @return FileSystemInstance
*/
private
function
getStorage
()
{
if
(
$this
->
storageInstance
!==
null
)
return
$this
->
storageInstance
;
$storageType
=
env
(
'STORAGE_TYPE'
);
$this
->
storageInstance
=
$this
->
fileSystem
->
disk
(
$storageType
);
return
$this
->
storageInstance
;
}
}
\ No newline at end of file
composer.json
View file @
c88096b
...
...
@@ -10,7 +10,8 @@
"intervention/image"
:
"^2.3"
,
"laravel/socialite"
:
"^2.0"
,
"barryvdh/laravel-ide-helper"
:
"^2.1"
,
"barryvdh/laravel-debugbar"
:
"^2.0"
"barryvdh/laravel-debugbar"
:
"^2.0"
,
"league/flysystem-aws-s3-v3"
:
"^1.0"
},
"require-dev"
:
{
"fzaninotto/faker"
:
"~1.4"
,
...
...
composer.lock
View file @
c88096b
...
...
@@ -4,10 +4,88 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
,
"This file is @generated automatically"
],
"hash"
:
"
c2067be65a036c540976c649dfd3763a
"
,
"content-hash"
:
"
6581b2cca64df1f4d3df219552fbfd78
"
,
"hash"
:
"
19725116631f01881caafa33052eecb9
"
,
"content-hash"
:
"
f1dbd776f0ae13ec99e4e6d99510cd8e
"
,
"packages"
:
[
{
"name"
:
"aws/aws-sdk-php"
,
"version"
:
"3.11.4"
,
"source"
:
{
"type"
:
"git"
,
"url"
:
"https://github.com/aws/aws-sdk-php.git"
,
"reference"
:
"2524c78e0fa1ed049719b8b6b0696f0b6dfb1ca2"
},
"dist"
:
{
"type"
:
"zip"
,
"url"
:
"https://api.github.com/repos/aws/aws-sdk-php/zipball/2524c78e0fa1ed049719b8b6b0696f0b6dfb1ca2"
,
"reference"
:
"2524c78e0fa1ed049719b8b6b0696f0b6dfb1ca2"
,
"shasum"
:
""
},
"require"
:
{
"guzzlehttp/guzzle"
:
"~5.3|~6.0.1|~6.1"
,
"guzzlehttp/promises"
:
"~1.0"
,
"guzzlehttp/psr7"
:
"~1.0"
,
"mtdowling/jmespath.php"
:
"~2.2"
,
"php"
:
">=5.5"
},
"require-dev"
:
{
"andrewsville/php-token-reflection"
:
"^1.4"
,
"aws/aws-php-sns-message-validator"
:
"~1.0"
,
"behat/behat"
:
"~3.0"
,
"doctrine/cache"
:
"~1.4"
,
"ext-dom"
:
"*"
,
"ext-json"
:
"*"
,
"ext-openssl"
:
"*"
,
"ext-pcre"
:
"*"
,
"ext-simplexml"
:
"*"
,
"ext-spl"
:
"*"
,
"nette/neon"
:
"^2.3"
,
"phpunit/phpunit"
:
"~4.0"
},
"suggest"
:
{
"doctrine/cache"
:
"To use the DoctrineCacheAdapter"
,
"ext-curl"
:
"To send requests using cURL"
,
"ext-openssl"
:
"Allows working with CloudFront private distributions and verifying received SNS messages"
},
"type"
:
"library"
,
"extra"
:
{
"branch-alias"
:
{
"dev-master"
:
"3.0-dev"
}
},
"autoload"
:
{
"psr-4"
:
{
"Aws
\\
"
:
"src/"
},
"files"
:
[
"src/functions.php"
]
},
"notification-url"
:
"https://packagist.org/downloads/"
,
"license"
:
[
"Apache-2.0"
],
"authors"
:
[
{
"name"
:
"Amazon Web Services"
,
"homepage"
:
"http://aws.amazon.com"
}
],
"description"
:
"AWS SDK for PHP - Use Amazon Web Services in your PHP project"
,
"homepage"
:
"http://aws.amazon.com/sdkforphp"
,
"keywords"
:
[
"amazon"
,
"aws"
,
"cloud"
,
"dynamodb"
,
"ec2"
,
"glacier"
,
"s3"
,
"sdk"
],
"time"
:
"2015-12-04 01:19:53"
},
{
"name"
:
"barryvdh/laravel-debugbar"
,
"version"
:
"v2.0.6"
,
"source"
:
{
...
...
@@ -1075,6 +1153,53 @@
"time"
:
"2015-09-30 22:26:59"
},
{
"name"
:
"league/flysystem-aws-s3-v3"
,
"version"
:
"1.0.9"
,
"source"
:
{
"type"
:
"git"
,
"url"
:
"https://github.com/thephpleague/flysystem-aws-s3-v3.git"
,
"reference"
:
"595e24678bf78f8107ebc9355d8376ae0eb712c6"
},
"dist"
:
{
"type"
:
"zip"
,
"url"
:
"https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/595e24678bf78f8107ebc9355d8376ae0eb712c6"
,
"reference"
:
"595e24678bf78f8107ebc9355d8376ae0eb712c6"
,
"shasum"
:
""
},
"require"
:
{
"aws/aws-sdk-php"
:
"^3.0.0"
,
"league/flysystem"
:
"~1.0"
,
"php"
:
">=5.5.0"
},
"require-dev"
:
{
"henrikbjorn/phpspec-code-coverage"
:
"~1.0.1"
,
"phpspec/phpspec"
:
"^2.0.0"
},
"type"
:
"library"
,
"extra"
:
{
"branch-alias"
:
{
"dev-master"
:
"1.0-dev"
}
},
"autoload"
:
{
"psr-4"
:
{
"League
\\
Flysystem
\\
AwsS3v3
\\
"
:
"src/"
}
},
"notification-url"
:
"https://packagist.org/downloads/"
,
"license"
:
[
"MIT"
],
"authors"
:
[
{
"name"
:
"Frank de Jonge"
,
"email"
:
"info@frenky.net"
}
],
"description"
:
"Flysystem adapter for the AWS S3 SDK v3.x"
,
"time"
:
"2015-11-19 08:44:16"
},
{
"name"
:
"league/oauth1-client"
,
"version"
:
"1.6.1"
,
"source"
:
{
...
...
@@ -1315,6 +1440,61 @@
"time"
:
"2015-01-11 23:07:46"
},
{
"name"
:
"mtdowling/jmespath.php"
,
"version"
:
"2.2.0"
,
"source"
:
{
"type"
:
"git"
,
"url"
:
"https://github.com/jmespath/jmespath.php.git"
,
"reference"
:
"a7d99d0c836e69d27b7bfca1d33ca2759fba3289"
},
"dist"
:
{
"type"
:
"zip"
,
"url"
:
"https://api.github.com/repos/jmespath/jmespath.php/zipball/a7d99d0c836e69d27b7bfca1d33ca2759fba3289"
,
"reference"
:
"a7d99d0c836e69d27b7bfca1d33ca2759fba3289"
,
"shasum"
:
""
},
"require"
:
{
"php"
:
">=5.4.0"
},
"require-dev"
:
{
"phpunit/phpunit"
:
"~4.0"
},
"bin"
:
[
"bin/jp.php"
],
"type"
:
"library"
,
"extra"
:
{
"branch-alias"
:
{
"dev-master"
:
"2.0-dev"
}
},
"autoload"
:
{
"psr-4"
:
{
"JmesPath
\\
"
:
"src/"
},
"files"
:
[
"src/JmesPath.php"
]
},
"notification-url"
:
"https://packagist.org/downloads/"
,
"license"
:
[
"MIT"
],
"authors"
:
[
{
"name"
:
"Michael Dowling"
,
"email"
:
"mtdowling@gmail.com"
,
"homepage"
:
"https://github.com/mtdowling"
}
],
"description"
:
"Declaratively specify how to extract elements from a JSON document"
,
"keywords"
:
[
"json"
,
"jsonpath"
],
"time"
:
"2015-05-27 17:21:31"
},
{
"name"
:
"nesbot/carbon"
,
"version"
:
"1.21.0"
,
"source"
:
{
...
...
config/filesystems.php
View file @
c88096b
...
...
@@ -45,7 +45,7 @@ return [
'local'
=>
[
'driver'
=>
'local'
,
'root'
=>
storage_path
(
'app'
),
'root'
=>
public_path
(
),
],
'ftp'
=>
[
...
...
@@ -64,10 +64,10 @@ return [
's3'
=>
[
'driver'
=>
's3'
,
'key'
=>
'your-key'
,
'secret'
=>
'your-secret'
,
'region'
=>
'your-region'
,
'bucket'
=>
'your-bucket'
,
'key'
=>
env
(
'STORAGE_S3_KEY'
,
'your-key'
)
,
'secret'
=>
env
(
'STORAGE_S3_SECRET'
,
'your-secret'
)
,
'region'
=>
env
(
'STORAGE_S3_REGION'
,
'your-region'
)
,
'bucket'
=>
env
(
'STORAGE_S3_BUCKET'
,
'your-bucket'
)
,
],
'rackspace'
=>
[
...
...
database/migrations/2015_12_07_195238_add_image_upload_types.php
0 → 100644
View file @
c88096b
<?php
use
BookStack\Image
;
use
Illuminate\Database\Schema\Blueprint
;
use
Illuminate\Database\Migrations\Migration
;
class
AddImageUploadTypes
extends
Migration
{
/**
* Run the migrations.
*
* @return void
*/
public
function
up
()
{
Schema
::
table
(
'images'
,
function
(
Blueprint
$table
)
{
$table
->
string
(
'path'
,
400
);
$table
->
string
(
'type'
)
->
index
();
});
Image
::
all
()
->
each
(
function
(
$image
)
{
$image
->
path
=
$image
->
url
;
$image
->
type
=
'gallery'
;
$image
->
save
();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public
function
down
()
{
Schema
::
table
(
'images'
,
function
(
Blueprint
$table
)
{
$table
->
dropColumn
(
'type'
);
$table
->
dropColumn
(
'path'
);
});
}
}
resources/assets/js/components/image-manager.vue
View file @
c88096b
...
...
@@ -7,7 +7,7 @@
<div v-for="image in images">
<img class="anim fadeIn"
:class="{selected: (image==selectedImage)}"
:src="image.thumb
nail
" :alt="image.title" :title="image.name"
:src="image.thumb
s.gallery
" :alt="image.title" :title="image.name"
@click="imageClick(image)"
:style="{animationDelay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'}">
</div>
...
...
@@ -88,7 +88,7 @@
methods: {
fetchData: function () {
var _this = this;
this.$http.get('/images/all/' + _this.page, function (data) {
this.$http.get('/images/
gallery/
all/' + _this.page, function (data) {
_this.images = _this.images.concat(data.images);
_this.hasMore = data.hasMore;
_this.page++;
...
...
@@ -98,7 +98,7 @@
setupDropZone: function () {
var _this = this;
var dropZone = new Dropzone(_this.$els.dropZone, {
url: '/
upload/image
',
url: '/
images/gallery/upload
',
init: function () {
var dz = this;
this.on("sending", function (file, xhr, data) {
...
...
@@ -110,8 +110,8 @@
dz.removeFile(file);
});
});
this.on('error', function(file, errorMessage, xhr) {
if(errorMessage.file) {
this.on('error', function
(file, errorMessage, xhr) {
if
(errorMessage.file) {
$(file.previewElement).find('[data-dz-errormessage]').text(errorMessage.file[0]);
}
console.log(errorMessage);
...
...
resources/assets/js/pages/page-form.js
View file @
c88096b
...
...
@@ -100,7 +100,7 @@ module.exports = {
onclick
:
function
()
{
ImageManager
.
show
(
function
(
image
)
{
var
html
=
'<a href="'
+
image
.
url
+
'" target="_blank">'
;
html
+=
'<img src="'
+
image
.
display
+
'" alt="'
+
image
.
name
+
'">'
;
html
+=
'<img src="'
+
image
.
thumbs
.
display
+
'" alt="'
+
image
.
name
+
'">'
;
html
+=
'</a>'
;
editor
.
execCommand
(
'mceInsertContent'
,
false
,
html
);
});
...
...
resources/views/settings/index.blade.php
View file @
c88096b
...
...
@@ -23,6 +23,11 @@
<label>
Allow public viewing?
</label>
<toggle-switch
name=
"setting-app-public"
value=
"{{ Setting::get('app-public') }}"
></toggle-switch>
</div>
<div
class=
"form-group"
>
<label>
Enable higher security image uploads?
</label>
<p
class=
"small"
>
For performance reasons, all images are public by default, This option adds a random, hard-to-guess characters in front of image names. Ensure directory indexes are not enabled to prevent easy access.
</p>
<toggle-switch
name=
"setting-app-secure-images"
value=
"{{ Setting::get('app-secure-images') }}"
></toggle-switch>
</div>
</div>
<div
class=
"col-md-6"
>
<div
class=
"form-group"
id=
"logo-control"
>
...
...
@@ -57,7 +62,7 @@
</select>
</div>
<div
class=
"form-group"
>
<label
for=
"setting-registration-confirmation"
>
Require
Email C
onfirmation?
</label>
<label
for=
"setting-registration-confirmation"
>
Require
email c
onfirmation?
</label>
<p
class=
"small"
>
If domain restriction is used then email confirmation will be required and the below value will be ignored.
</p>
<toggle-switch
name=
"setting-registration-confirmation"
value=
"{{ Setting::get('registration-confirmation') }}"
></toggle-switch>
</div>
...
...
Please
register
or
sign in
to post a comment