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
2017-02-26 14:25:02 +0000
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Commit
253132afdf54b9200bcf33c95c0414798a3554d5
253132af
1 parent
eded8abd
Added chapter export options
Closes #177
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
207 additions
and
7 deletions
app/Http/Controllers/ChapterController.php
app/Http/Controllers/PageController.php
app/Services/ExportService.php
resources/views/chapters/export.blade.php
resources/views/chapters/show.blade.php
routes/web.php
tests/Entity/ExportTest.php
app/Http/Controllers/ChapterController.php
View file @
253132a
...
...
@@ -3,6 +3,7 @@
use
Activity
;
use
BookStack\Repos\EntityRepo
;
use
BookStack\Repos\UserRepo
;
use
BookStack\Services\ExportService
;
use
Illuminate\Http\Request
;
use
Illuminate\Http\Response
;
use
Views
;
...
...
@@ -12,16 +13,19 @@ class ChapterController extends Controller
protected
$userRepo
;
protected
$entityRepo
;
protected
$exportService
;
/**
* ChapterController constructor.
* @param EntityRepo $entityRepo
* @param UserRepo $userRepo
* @param ExportService $exportService
*/
public
function
__construct
(
EntityRepo
$entityRepo
,
UserRepo
$userRepo
)
public
function
__construct
(
EntityRepo
$entityRepo
,
UserRepo
$userRepo
,
ExportService
$exportService
)
{
$this
->
entityRepo
=
$entityRepo
;
$this
->
userRepo
=
$userRepo
;
$this
->
exportService
=
$exportService
;
parent
::
__construct
();
}
...
...
@@ -236,4 +240,52 @@ class ChapterController extends Controller
session
()
->
flash
(
'success'
,
trans
(
'entities.chapters_permissions_success'
));
return
redirect
(
$chapter
->
getUrl
());
}
/**
* Exports a chapter to pdf .
* @param string $bookSlug
* @param string $chapterSlug
* @return \Illuminate\Http\Response
*/
public
function
exportPdf
(
$bookSlug
,
$chapterSlug
)
{
$chapter
=
$this
->
entityRepo
->
getBySlug
(
'chapter'
,
$chapterSlug
,
$bookSlug
);
$pdfContent
=
$this
->
exportService
->
chapterToPdf
(
$chapter
);
return
response
()
->
make
(
$pdfContent
,
200
,
[
'Content-Type'
=>
'application/octet-stream'
,
'Content-Disposition'
=>
'attachment; filename="'
.
$chapterSlug
.
'.pdf'
]);
}
/**
* Export a chapter to a self-contained HTML file.
* @param string $bookSlug
* @param string $chapterSlug
* @return \Illuminate\Http\Response
*/
public
function
exportHtml
(
$bookSlug
,
$chapterSlug
)
{
$chapter
=
$this
->
entityRepo
->
getBySlug
(
'chapter'
,
$chapterSlug
,
$bookSlug
);
$containedHtml
=
$this
->
exportService
->
chapterToContainedHtml
(
$chapter
);
return
response
()
->
make
(
$containedHtml
,
200
,
[
'Content-Type'
=>
'application/octet-stream'
,
'Content-Disposition'
=>
'attachment; filename="'
.
$chapterSlug
.
'.html'
]);
}
/**
* Export a chapter to a simple plaintext .txt file.
* @param string $bookSlug
* @param string $chapterSlug
* @return \Illuminate\Http\Response
*/
public
function
exportPlainText
(
$bookSlug
,
$chapterSlug
)
{
$chapter
=
$this
->
entityRepo
->
getBySlug
(
'chapter'
,
$chapterSlug
,
$bookSlug
);
$containedHtml
=
$this
->
exportService
->
chapterToPlainText
(
$chapter
);
return
response
()
->
make
(
$containedHtml
,
200
,
[
'Content-Type'
=>
'application/octet-stream'
,
'Content-Disposition'
=>
'attachment; filename="'
.
$chapterSlug
.
'.txt'
]);
}
}
...
...
app/Http/Controllers/PageController.php
View file @
253132a
...
...
@@ -429,7 +429,7 @@ class PageController extends Controller
}
/**
* Exports a page to
pdf format using barryvdh/laravel-dompdf wrapper
.
* Exports a page to
a PDF
.
* https://github.com/barryvdh/laravel-dompdf
* @param string $bookSlug
* @param string $pageSlug
...
...
app/Services/ExportService.php
View file @
253132a
<?php
namespace
BookStack\Services
;
use
BookStack\Book
;
use
BookStack\Chapter
;
use
BookStack\Page
;
use
BookStack\Repos\EntityRepo
;
...
...
@@ -34,6 +35,24 @@ class ExportService
}
/**
* Convert a chapter to a self-contained HTML file.
* @param Chapter $chapter
* @return mixed|string
*/
public
function
chapterToContainedHtml
(
Chapter
$chapter
)
{
$pages
=
$this
->
entityRepo
->
getChapterChildren
(
$chapter
);
$pages
->
each
(
function
(
$page
)
{
$page
->
html
=
$this
->
entityRepo
->
renderPage
(
$page
);
});
$html
=
view
(
'chapters/export'
,
[
'chapter'
=>
$chapter
,
'pages'
=>
$pages
])
->
render
();
return
$this
->
containHtml
(
$html
);
}
/**
* Convert a book to a self-contained HTML file.
* @param Book $book
* @return mixed|string
...
...
@@ -63,6 +82,24 @@ class ExportService
}
/**
* Convert a chapter to a PDF file.
* @param Chapter $chapter
* @return mixed|string
*/
public
function
chapterToPdf
(
Chapter
$chapter
)
{
$pages
=
$this
->
entityRepo
->
getChapterChildren
(
$chapter
);
$pages
->
each
(
function
(
$page
)
{
$page
->
html
=
$this
->
entityRepo
->
renderPage
(
$page
);
});
$html
=
view
(
'chapters/export'
,
[
'chapter'
=>
$chapter
,
'pages'
=>
$pages
])
->
render
();
return
$this
->
htmlToPdf
(
$html
);
}
/**
* Convert a book to a PDF file
* @param Book $book
* @return string
...
...
@@ -169,6 +206,21 @@ class ExportService
}
/**
* Convert a chapter into a plain text string.
* @param Chapter $chapter
* @return string
*/
public
function
chapterToPlainText
(
Chapter
$chapter
)
{
$text
=
$chapter
->
name
.
"
\n\n
"
;
$text
.=
$chapter
->
description
.
"
\n\n
"
;
foreach
(
$chapter
->
pages
as
$page
)
{
$text
.=
$this
->
pageToPlainText
(
$page
);
}
return
$text
;
}
/**
* Convert a book into a plain text string.
* @param Book $book
* @return string
...
...
@@ -179,11 +231,7 @@ class ExportService
$text
=
$book
->
name
.
"
\n\n
"
;
foreach
(
$bookTree
as
$bookChild
)
{
if
(
$bookChild
->
isA
(
'chapter'
))
{
$text
.=
$bookChild
->
name
.
"
\n\n
"
;
$text
.=
$bookChild
->
description
.
"
\n\n
"
;
foreach
(
$bookChild
->
pages
as
$page
)
{
$text
.=
$this
->
pageToPlainText
(
$page
);
}
$text
.=
$this
->
chapterToPlainText
(
$bookChild
);
}
else
{
$text
.=
$this
->
pageToPlainText
(
$bookChild
);
}
...
...
resources/views/chapters/export.blade.php
0 → 100644
View file @
253132a
<!doctype html>
<html
lang=
"en"
>
<head>
<meta
http-equiv=
"Content-Type"
content=
"text/html; charset=utf-8"
/>
<title>
{{ $chapter->name }}
</title>
<style>
{
!!
file_get_contents(public_path('/css/export-styles.css'))
!!
}
.page-break
{
page-break-after
:
always
;
}
ul
.contents
ul
li
{
list-style
:
circle
;
}
@media
screen
{
.page-break
{
border-top
:
1px
solid
#DDD
;
}
}
</style>
@yield('head')
</head>
<body>
<div
class=
"container"
>
<div
class=
"row"
>
<div
class=
"col-md-8 col-md-offset-2"
>
<div
class=
"page-content"
>
<h1
style=
"font-size: 4.8em"
>
{{$chapter->name}}
</h1>
<p>
{{ $chapter->description }}
</p>
@if(count($pages) > 0)
<ul
class=
"contents"
>
@foreach($pages as $page)
<li><a
href=
"#page-{{$page->id}}"
>
{{ $page->name }}
</a></li>
@endforeach
</ul>
@endif
@foreach($pages as $page)
<div
class=
"page-break"
></div>
<h1
id=
"page-{{$page->id}}"
>
{{ $page->name }}
</h1>
{!! $page->html !!}
@endforeach
</div>
</div>
</div>
</div>
</body>
</html>
resources/views/chapters/show.blade.php
View file @
253132a
...
...
@@ -10,6 +10,14 @@
</div>
<div
class=
"col-sm-4 faded"
>
<div
class=
"action-buttons"
>
<span
dropdown
class=
"dropdown-container"
>
<div
dropdown-toggle
class=
"text-button text-primary"
><i
class=
"zmdi zmdi-open-in-new"
></i>
{{ trans('entities.pages_export') }}
</div>
<ul
class=
"wide"
>
<li><a
href=
"{{ $chapter->getUrl('/export/html') }}"
target=
"_blank"
>
{{ trans('entities.pages_export_html') }}
<span
class=
"text-muted float right"
>
.html
</span></a></li>
<li><a
href=
"{{ $chapter->getUrl('/export/pdf') }}"
target=
"_blank"
>
{{ trans('entities.pages_export_pdf') }}
<span
class=
"text-muted float right"
>
.pdf
</span></a></li>
<li><a
href=
"{{ $chapter->getUrl('/export/plaintext') }}"
target=
"_blank"
>
{{ trans('entities.pages_export_text') }}
<span
class=
"text-muted float right"
>
.txt
</span></a></li>
</ul>
</span>
@if(userCan('page-create', $chapter))
<a
href=
"{{ $chapter->getUrl('/create-page') }}"
class=
"text-pos text-button"
><i
class=
"zmdi zmdi-plus"
></i>
{{ trans('entities.pages_new') }}
</a>
@endif
...
...
routes/web.php
View file @
253132a
...
...
@@ -67,6 +67,9 @@ Route::group(['middleware' => 'auth'], function () {
Route
::
put
(
'/{bookSlug}/chapter/{chapterSlug}/move'
,
'ChapterController@move'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}/edit'
,
'ChapterController@edit'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}/permissions'
,
'ChapterController@showRestrict'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}/export/pdf'
,
'ChapterController@exportPdf'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}/export/html'
,
'ChapterController@exportHtml'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}/export/plaintext'
,
'ChapterController@exportPlainText'
);
Route
::
put
(
'/{bookSlug}/chapter/{chapterSlug}/permissions'
,
'ChapterController@restrict'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}/delete'
,
'ChapterController@showDelete'
);
Route
::
delete
(
'/{bookSlug}/chapter/{chapterSlug}'
,
'ChapterController@destroy'
);
...
...
tests/Entity/ExportTest.php
View file @
253132a
<?php
namespace
Tests
;
use
BookStack\Chapter
;
use
BookStack\Page
;
class
ExportTest
extends
TestCase
...
...
@@ -75,4 +76,40 @@ class ExportTest extends TestCase
$resp
->
assertHeader
(
'Content-Disposition'
,
'attachment; filename="'
.
$book
->
slug
.
'.html'
);
}
public
function
test_chapter_text_export
()
{
$chapter
=
Chapter
::
first
();
$page
=
$chapter
->
pages
[
0
];
$this
->
asEditor
();
$resp
=
$this
->
get
(
$chapter
->
getUrl
(
'/export/plaintext'
));
$resp
->
assertStatus
(
200
);
$resp
->
assertSee
(
$chapter
->
name
);
$resp
->
assertSee
(
$page
->
name
);
$resp
->
assertHeader
(
'Content-Disposition'
,
'attachment; filename="'
.
$chapter
->
slug
.
'.txt'
);
}
public
function
test_chapter_pdf_export
()
{
$chapter
=
Chapter
::
first
();
$this
->
asEditor
();
$resp
=
$this
->
get
(
$chapter
->
getUrl
(
'/export/pdf'
));
$resp
->
assertStatus
(
200
);
$resp
->
assertHeader
(
'Content-Disposition'
,
'attachment; filename="'
.
$chapter
->
slug
.
'.pdf'
);
}
public
function
test_chapter_html_export
()
{
$chapter
=
Chapter
::
first
();
$page
=
$chapter
->
pages
[
0
];
$this
->
asEditor
();
$resp
=
$this
->
get
(
$chapter
->
getUrl
(
'/export/html'
));
$resp
->
assertStatus
(
200
);
$resp
->
assertSee
(
$chapter
->
name
);
$resp
->
assertSee
(
$page
->
name
);
$resp
->
assertHeader
(
'Content-Disposition'
,
'attachment; filename="'
.
$chapter
->
slug
.
'.html'
);
}
}
\ No newline at end of file
...
...
Please
register
or
sign in
to post a comment