Initial commit

This commit is contained in:
2018-08-23 16:44:53 +02:00
commit 1f06564778
115 changed files with 13984 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
# Eclipse specific files
.settings/
.buildpath
.project
# OS files
.directory
.DS_Store
Thumbs.db
# App files
example/
vendor/
.env

20
LICENSE Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2018 Marco Grätsch <magdev3.0@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

29
README.md Normal file
View File

@@ -0,0 +1,29 @@
# dossier
Dossier is a commandline-tool to generate personal dossiers from a set of Markdown files. It creates a single print-first HTML-File which can be printed to PDF with your favorite browser. There is also a integration with PDFShift, but it might requires a paid subscription.
## Install
### Dependencies
Dossier requires PHP 7.2+ and the following extensions enabled:
* Phar
* SPL
* Date
* fileinfo
* mbstring
* Bz2
### Use the Phar-Archive
The easiest way to install dossier is to download the Phar-Archive from the Releases page and copy it somewhere in your $PATH and make it executable. Open a console and type `dossier.phar` to see a list of available commands. To find out more about a command type `dossier.phar help <command>`.
## License
Copyright (c) 2018 Marco Grätsch
This work is licensed under the MIT-License.

2
app/conf/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/dossier_dev.yaml
/dossier_prod.yaml

85
app/conf/dossier.yaml Normal file
View File

@@ -0,0 +1,85 @@
### Settings file for magdev/dossier
charset: utf-8
# Date formats
date:
format:
long: "d. F Y"
short: "d.m.Y"
# Settings for TranslatorService
translator:
locale: en
fallback_locales:
- en
- de
# Settings for the CV
cv:
default_tag: experience
tags:
- experience
- education
- other
# Form settings
form:
label:
length: 40
prefix: ' '
# Available language levels
language:
default_level: native
levels:
- native
- fluent
- good
- beginner
# Monolog settings
monolog:
log_level: 200
skip_class_partials:
- 'Magdev\\Dossier\\'
- 'Symfony\\Component\\'
# Output styles
style:
dossier_status_thresholds:
- { min: 0, max: 54, color: 'lightred' }
- { min: 55, max: 74, color: 'lightyellow' }
- { min: 75, max: 100, color: 'lightgreen' }
# Settings for external editor
editor:
command: '/usr/bin/kate %s'
# PDFShift settings
pdfshift:
apikey: ''
page:
format: A4
margin:
left: 0
right: 0
top: 0
bottom: 0
header:
spacing: 20px
footer:
spacing: 20px
security:
author: ''
userPassword: ''
ownerPassword: ''
noPrint: false
noCopy: false
noModify: true
stylesheet:
use_print: true
http:
user_agent: ''

2
app/conf/parameters.yaml Normal file
View File

@@ -0,0 +1,2 @@
parameters:
scss.formatter: "\\Leafo\\ScssPhp\\Formatter\\Crunched"

59
app/conf/services.yaml Normal file
View File

@@ -0,0 +1,59 @@
imports:
- { resource: 'parameters.yaml' }
- { resource: '/etc/dossier/parameters.yaml', ignore_errors: true }
services:
config:
class: '\Magdev\Dossier\Service\ConfigService'
monolog:
class: '\Magdev\Dossier\Service\MonologService'
arguments: ['@config']
phar_helper:
class: '\Magdev\Dossier\Service\PharHelperService'
arguments: ['@monolog']
minifer:
class: '\Magdev\Dossier\Service\MinifierService'
arguments: ['@monolog']
translator:
class: '\Magdev\Dossier\Service\TranslatorService'
arguments: ['@config', '@monolog']
uri_helper:
class: '\Magdev\Dossier\Service\UriHelperService'
arguments: ['@monolog', '@phar_helper']
formatter:
class: '\Magdev\Dossier\Service\FormatterService'
arguments: ['@translator']
markdown:
class: '\Magdev\Dossier\Service\MarkdownService'
arguments: ['@monolog', '@formatter']
output_helper:
class: '\Magdev\Dossier\Service\OutputHelperService'
arguments: ['@translator']
template:
class: '\Magdev\Dossier\Service\TemplateService'
arguments: ['@markdown', '@translator', '@minifer', '@config', '@monolog']
cssproc:
class: '\Magdev\Dossier\Service\StylesheetProcessorService'
arguments: ['@monolog', '@template', '%scss.formatter%']
analyzer:
class: '\Magdev\Dossier\Service\AnalyzerService'
arguments: ['@config', '@monolog']
pdf:
class: '\Magdev\Dossier\Service\PdfService'
arguments: ['@config', '@monolog', '@template']

190
app/locale/messages.de.yaml Normal file
View File

@@ -0,0 +1,190 @@
app:
header: 'Persönliches Dossier aus Markdown-Dateien erstellen'
date:
start: 'Beginn'
end: 'Ende'
until: 'bis'
today: 'heute'
format:
year: "Ein Jahr|%y Jahre"
month: "Ein Monat|%m Monate"
day: "Ein Tag|%d Tage"
info:
debug_mode: 'DEBUG MODE '
environment: 'ENVIRONMENT '
toc:
resume: 'Einseitiges Résumé'
cv: 'Curriculum Vitae'
certs: 'Zeugnisse und Zertifikate'
projects: 'Aktuelle Seitenprojekte'
form:
init:
header: 'Neues Dossier initialisieren'
use_userstyles: 'Möchten sie benutzerdefinierte Stylesheets verwenden?'
style_type: 'Preprocessor Typ'
intro:
header:
add: 'Einleitungsseite erstellen'
edit: 'Einleitungsseite bearbeiten'
text: 'Bitte geben sie den Einleitungstext ein'
add_quotes: 'Möchten sie Zitate hinzufügen?'
quote_text: 'Zitat'
quote_author: 'Autor des Zitats'
show_quotes: 'Wo sollen die Zitate angezeigt werden?'
person:
header:
add: 'Persönliche Daten erstellen'
edit: 'Persönliche Daten bearbeiten'
firstname: 'Vorname'
lastname: 'Nachname'
nationality: 'Nationalität'
birthdate: 'Geburtsdatum (YYYY-MM-DD)'
birthplace: 'Geburtsort'
residence: 'Aktueller Wohnort'
status: 'Familientstand'
tagline: 'Tagline'
work_license: 'Lizenz'
language: 'Sprache'
level: 'Grad'
text: 'Kurzbiographie'
add_languages: 'Möchten sie Sprachen hinzufügen?'
projects: 'Seitenprojekte'
interests: 'Persönliche Interessen'
links: 'Links'
cv:
header:
add: 'CV-Eintrag erstellen'
edit: 'CV-Eintrag bearbeiten'
text: 'Bitte geben sie einen Text ein'
start_date: 'Start-Datum (YYYY-MM-DD)'
end_date: 'End-Datum (YYYY-MM-DD)'
position: 'Position'
company: 'Unternehmen'
industry: 'Branche'
qualification: 'Abschluss'
tag: 'Tag'
skills: 'Fertigkeiten und Kenntnisse'
achievements: 'Erreichte Ziele'
toolbox: 'Werkzeuge'
use_in_resume: 'In Résumé verwenden?'
cover:
subtitle: 'Bewerbungsdossier'
intro:
toc: 'Auf den folgenden Seiten finden sie als Beilagen:'
projects:
header: 'Aktuelle Projekte'
fields:
status: 'Status'
role: 'Rolle'
status:
development: 'In Entwicklung'
production: 'Produktivbetrieb'
private: 'Privat'
published: 'Veröffentlicht'
eol: 'Nicht mehr im Einsatz'
cv:
header: 'Curriculum Vitae'
headers:
education: "Schule, Aus- und Weiterbildung"
experience: 'Berufserfahrung'
other: 'Sonstiges'
entry:
qualification: "Abschluss:"
skills: 'Erworbene Fähigkeiten und Kenntnisse:'
achievements: 'Erreichte Ziele'
resume:
header: 'Résumé'
headers:
skills: 'Kenntnisse und Fähigkeiten'
personal: 'Persönliche Informationen'
links: 'Links'
contact: 'Kontaktdaten'
achievements: 'Erreichte Ziele'
experience: 'Berufserfahrung'
qualification: 'Qualifikationen'
bio: 'Bio'
toolbox: 'Werkzeuge'
personal_interest: 'Persönliche Interessen'
current_projects: 'Aktuelle Seitenprojekte'
references: Referenzen
personal:
name: 'Name'
birthdate: 'Geboren am'
birthplace: 'in'
status: 'Familienstatus'
nationality: 'Nationalität'
languages: 'Sprachen'
residence: 'Akt. Wohnort'
work_license: 'Lizenz'
language:
level:
native: 'Muttersprache'
fluent: 'Flüssig'
good: 'Gut'
contact:
email: 'E-Mail'
phone: 'Telefon'
chat: 'Hangouts'
certs:
header: 'Zeugnisse und Zertifikate'
server:
index:
header: 'Dossier'
title: 'Dossier Übersicht'
filesize: 'Dateigrösse'
filetime: 'Erstellt am'
new_window: 'In neuen Fenster/Tab öffnen'
message:
input:
required_value: 'Dieser Wert ist erforderlich'
invalid_date: 'Ungültiges Datum'
invalid_tag: 'Ungültige Kategorie: %s'
build:
success: 'Ihr persönliches Dossier wurde erfoglreich erstellt'
dump:
success: 'Eine lokale Kopie des Themes %theme% wurde erfolgreich erstellt'
export:
template_dir: 'Bitte tragen sie folgendes in ihre .bashrc oder .profile ein:'
template_homedir: 'Die Dateien wurden nach ~/.dossier/tpl kopiert'
code:
template_environment: 'export DOSSIER_THEME_DIR="%path%"'
entry:
success: 'Der CV-Eintrag wurde erfolgreich erstellt'
command:
initialized: 'Umgebung initiaisiert'
output_file: 'Ausgabe-Datei'
locale: 'Verwende Sprache: %locale%'
theme: 'Verwende Theme: %theme%'
stylesheet:
less: 'LESS-Stylesheet gefunden'
scss: 'SCSS-Stylesheet gefunden'
model:
person: 'Person-Model geladen'
intro: 'Intro-Model geladen'
letter: 'Letter-Model geladen'
cv: 'CV mit %count% Einträgen geladen'
config:
deleted: 'Konfigurationseintrag %path% wurde gelöscht oder auf den Standardwert zurückgesetzt'
write:
success: 'Datei %name% erfolgreiche gespeichert'
html:
created: 'HTML-Dokument in %file% erstellt'
pdf:
created: 'PDF-Dokument in %file% erstellt'
pdf:
page:
title: '{{title}}'
number: '{{page}}'
date: '{{date}}'

117
app/locale/messages.en.yaml Normal file
View File

@@ -0,0 +1,117 @@
app:
header: 'Create a personal dossier from Markdown files'
date:
start: 'Begin'
end: 'End'
until: 'until'
today: 'today'
format:
year: "One year|%y years"
month: "One month|%m months"
day: "One day|%d days"
info:
debug_mode: 'DEBUG MODE '
environment: 'ENVIRONMENT '
cover:
subtitle: 'Personal Dossier'
cv:
header: 'Curriculum Vitae'
headers:
education: "Education"
experience: 'Job Experience'
other: 'Other'
entry:
qualification: "Degree:"
skills: 'Obtained skills:'
achievements: 'Achievements'
question:
intro: 'Bitte geben sie die entsprechenden Daten ein:'
start_date: ' An welchem Tag begann die Tätigkeit? '
end_date: ' An welchem Tag endete die Tätigkeit? '
tag: ' Zu welcher Kategorie gehört der Eintrag? '
position: ' Welche Position haben sie bekleidet? '
company: ' Wie heisst die Firma, bei der sie angestellt waren? '
industry: ' In welcher Branche waren sie tätig? '
achievements: ' Welche Ziele haben sie während der Tätigkeit erreicht? '
qualification: ' Welche Qualification haben sie erreicht? '
skills: ' Welche fertigkeiten und Kenntnisse haben sie erworben? '
notes: ' Notizen zu diesem Eintrag: '
description: ' Beschreiben sie ihre Tätigkeiten: '
use_in_resume: ' Soll dieser Eintrag im Résumé verwendet werden? '
resume:
header: 'Résumé'
headers:
skills: 'Skills'
personal: 'Personal Information'
links: 'Links'
contact: 'Contact'
achievements: 'Achievements'
experience: 'Job Experience'
qualification: 'Qualifications'
bio: 'Bio'
toolbox: 'Toolbox'
personal_interest: 'Personal Interests'
current_projects: 'Current Sideprojects'
personal:
name: 'Name'
birthdate: 'born at'
birthplace: 'in'
status: 'Familiy status'
nationality: 'Nationality'
languages: 'Languagues'
residence: 'Current Residence'
work_license: 'License'
language:
level:
native: 'native'
fluent: 'fluent'
good: 'good'
rookie: 'rookie'
contact:
email: 'E-Mail'
phone: 'Phone'
chat: 'Hangouts'
certs:
header: 'Certificates'
message:
input:
required_value: 'This value is required'
invalid_date: 'Invalid date'
invalid_tag: 'Invalid tag: %s'
build:
success: 'Your personal dossier has been successfully built'
dump:
success: 'A local copy of the theme %theme% was created successfully'
export:
template_dir: 'Please add the following to your .bashrc or .profile file:'
template_homedir: 'The files are copied to ~/.dossier/tpl'
code:
template_environment: 'export DOSSIER_THEME_DIR="%path%"'
entry:
success: 'Der CV-Eintrag wurde erfolgreich erstellt'
command:
initialized: 'Environment loaded'
output_file: 'Output-File'
locale: 'Using locale: %locale%'
theme: 'Using theme: %theme%'
stylesheet:
less: 'LESS-Stylesheet found'
scss: 'SCSS-Stylesheet found'
model:
person: 'Person-Model loaded'
intro: 'Intro-Model loaded'
cv: 'CV with %count% entries loaded'
config:
deleted: 'Configuration value %path% successfully deleted or resetted to default value'
write:
success: 'File %name% successfully written'

1
app/tpl/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/latex/

View File

@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="{{ locale }}">
<!-- Build with magdev/dossier -->
<head>
<meta char{{ ('set="'~config('charset')~'"')|raw }}>
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
{% if favicon %}<link rel="shortcut icon" href="{{ favicon }}">{% endif %}
<title>{{ 'cover.subtitle'|trans }} | {{ person.name }}</title>
<style media="screen,print">
{{ stylesheet|raw }}
{{ userstyles|raw }}
</style>
</head>
<body class="theme-{{ theme }}">
{% if is_disabled(disabled.cover) == false %}
{{ include('parts/cover.html.twig') }}
{% endif %}
<article>
{% if is_disabled(disabled.intro) == false %}
{{ include('parts/intro.html.twig') }}
{% endif %}
{% if is_disabled(disabled.resume) == false %}
{{ include('parts/resume.html.twig') }}
{% endif %}
{% if is_disabled(disabled.projects) == false %}
{{ include('parts/projects.html.twig') }}
{% endif %}
{% if is_disabled(disabled.cv) == false %}
{{ include('parts/cv.html.twig') }}
{% endif %}
{% if is_disabled(disabled.certs) == false %}
{{ include('parts/certs.html.twig') }}
{% endif %}
</article>
</body>
</html>

BIN
app/tpl/print/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
app/tpl/print/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,603 @@
/**
* LESS for magdev/resume print theme
*/
// MIXINS:START
//
// Mixins
//
.no-page-break-inside() {
page-break-after: auto;
page-break-before: auto;
page-break-inside: avoid;
}
.border-radius(@radius) {
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
border-radius: @radius;
}
.border-box(@width) {
border-right: @width solid @base-accent-color;
border-bottom: (@width * 2) solid @base-background-color;
}
.clearfix() {
&::after {
display: block;
content: '.';
clear: both;
visibility: hidden;
height: 1px;
font-size: 1px;
}
}
// MIXINS:END
// VARS:START
//
// Variables
//
// Base styles
@base-font-family: Arial, Verdana;
@base-font-size: 10pt;
@base-font-color: #222;
@base-background-color: #fff;
@base-accent-color: #68d19b;
// Page format
@page-format: A4 portrait;
@page-margins: 11mm 17mm 17mm 17mm;
// Typography
@headline-small-font-style: italic;
@headline-font-weight: bold;
@headline-border-style: 1px solid @base-accent-color;
@headline-1-size: (@base-font-size + 8pt);
@headline-1-size-small: (@headline-1-size - 5pt);
@headline-1-color: @base-font-color;
@headline-1-color-small: lighten(@base-font-color, 20%);
@headline-2-size: (@base-font-size + 6pt);
@headline-2-size-small: (@headline-2-size - 4pt);
@headline-2-color: @base-font-color;
@headline-2-color-small: lighten(@base-font-color, 20%);
@headline-3-size: @base-font-size;
@headline-3-size-small: (@headline-3-size - 2pt);
@headline-3-color: lighten(@base-font-color, 30%);
@headline-3-color-small: lighten(@base-font-color, 15%);
@headline-3-spacing: .4pt;
@headline-3-transform: uppercase;
@headline-4-size: (@base-font-size + 1pt);
@headline-4-size-small: (@headline-4-size - 2pt);
@headline-4-color: @base-font-color;
@headline-4-color-small: lighten(@base-font-color, 20%);
@paragraph-size: @base-font-size;
@paragraph-size-small: (@paragraph-size - 2pt);
@paragraph-color: @base-font-color;
@paragraph-text-align: left;
@date-base-color: lighten(@base-font-color, 30%);
@date-start-color: @base-accent-color;
// Whitespace
@headline-margin: .5cm 0 .2cm;
@paragraph-margin: 0 0 .3cm;
@paragraph-line-height: (@paragraph-size + 2pt);
@column-space: .3cm;
@blockquote-vertical-space: .5cm;
@blockquote-horizontal-wide: 3cm;
@blockquote-horizontal-narrow: 1.5cm;
// Cover
@cover-border-width: 6pt;
@cover-text-position: 18cm 0 0 8cm;
// Intro
@intro-paragraph-size: (@paragraph-size + .5pt);
@intro-paragraph-line-height: (@intro-paragraph-size + 3pt);
@intro-photo-border-radius: 0;
@intro-photo-margin: .15cm 0 .3cm .5cm;
@intro-photo-align: right;
@intro-text-inset: .1cm;
@intro-text-right-inset: .5cm;
@intro-text-align: justify;
// Resume
@resume-column-space: @column-space;
@resume-border-width: @cv-border-width;
@resume-label-color: lighten(@base-font-color, 30%);
@resume-gutter-padding: .6cm;
@resume-text-inset: .1cm;
@resume-text-align: left;
// CV
@cv-column-space: @column-space;
@cv-border-width: 4pt;
@cv-label-color: lighten(@base-font-color, 30%);
@cv-text-align: @resume-text-align;
// VARS:END
//
// Styles
//
// Reset
* {
margin: 0;
padding: 0;
border: 0;
font-weight: normal;
font-style: normal;
}
// Grid
.row {
display: flex;
}
.col {
flex: 1;
}
.col-border { flex: 0 0 1%; }
.col-tenth { flex: 0 0 10%; }
.col-eighth { flex: 0 0 12.5%; }
.col-fifteen { flex: 0 0 15%; }
.col-fifth { flex: 0 0 20%; }
.col-quarter { flex: 0 0 25%; }
.col-third { flex: 0 0 33.3333334%; }
.col-half { flex: 0 0 50%; }
.col-resume { flex: 0 0 48.5%; }
.col-golden-narrow { flex: 0 0 38%; }
.col-golden-wide { flex: 0 0 62%; }
// Page settings for printing
@page {
size: @page-format;
margin: @page-margins;
}
// Base elements
html, body {
background-color: @base-background-color;
font-family: @base-font-family;
font-size: @base-font-size;
color: @base-font-color;
}
section {
page-break-before: always;
}
h1, h2, h3 {
font-weight: @headline-font-weight;
margin: @headline-margin;
page-break-after: avoid;
small {
font-style: @headline-small-font-style;
}
}
h1 {
font-size: @headline-1-size;
margin-top: 0;
small {
font-size: @headline-1-size-small;
color: @headline-1-color-small;
}
}
h2 {
font-size: @headline-2-size;
border-bottom: @headline-border-style;
margin-top: 0;
small {
font-size: @headline-2-size-small;
color: @headline-2-color-small;
}
}
h3 {
font-size: @headline-3-size;
color: @headline-3-color;
letter-spacing: @headline-3-spacing;
text-transform: @headline-3-transform;
small {
font-size: @headline-3-size-small;
color: @headline-3-color-small;
text-transform: none;
}
}
p {
margin: @paragraph-margin;
font-size: @paragraph-size;
text-align: @paragraph-text-align;
color: @paragraph-color;
small {
font-size: @paragraph-size-small;
}
}
ul, ol, li {
list-style-type: none;
}
a, a:active, a:hover, a:visited {
text-decoration: none;
color: @base-font-color;
}
strong {
font-weight: bold;
}
em {
font-style: italic;
}
blockquote {
padding: .3cm 1cm .15cm;
color: lighten(@base-font-color, 30%);
background-color: lighten(@base-font-color, 80%);
border: 1px solid lighten(@base-font-color, 80%);
font-style: italic;
.border-radius(5pt);
.clearfix();
.text {
font-family: Georgia;
font-size: (@paragraph-size + 2pt);
font-style: italic;
}
.author {
font-family: Georgia;
font-size: (@paragraph-size - 1pt);
font-style: italic;
float: right;
margin-top: .2cm;
}
}
blockquote:nth-child(even) {
margin: @blockquote-vertical-space @blockquote-horizontal-wide @blockquote-vertical-space @blockquote-horizontal-narrow;
}
blockquote:nth-child(odd) {
margin: @blockquote-vertical-space @blockquote-horizontal-narrow @blockquote-vertical-space @blockquote-horizontal-wide;
}
dl.horizontal {
dl {
.no-page-break-inside();
}
dt, dd {
display: inline-block;
line-height: 14pt;
}
dt {
text-align: right;
padding-right: .2cm;
font-size: (@base-font-size - 1pt);
vertical-align: top;
color: @resume-label-color;
margin-top: .5pt;
}
dd {
font-size: @base-font-size;
text-align: @resume-text-align;
li, p {
padding-left: 0;
padding-right: 0;
}
}
}
// Cover page
.cover {
.col-border {
.border-box(@cover-border-width);
}
.col-content {
padding-left: .3cm;
}
.text {
margin: @cover-text-position;
h1 {
font-size: 30pt;
font-weight: bold;
margin-top: 0;
margin-bottom: .5cm;
line-height: 26pt;
}
.tagline {
font-size: 20pt;
color: lighten(@base-font-color, 30%);
}
.subtitle {
font-size: 12pt;
font-style: italic;
color: @base-accent-color;
margin-bottom: 0;
}
}
}
// Certificate pages
.certs {
.certificate {
text-align: center;
page-break-after: always;
figcaption {
text-align: left;
margin-bottom: .2cm;
h3 {
small {
text-transform: none;
display: block;
}
}
}
img {
width: 95%;
height: auto;
}
}
}
// Introduction page
.intro {
h4 {
border-bottom: 1pt solid lighten(@base-font-color, 40%);
margin-bottom: 2pt;
margin-top: 1.2cm;
display: inline-block;
}
.toc {
list-style-position: inside;
padding-left: .3cm;
li {
list-style-type: circle;
font-size: @base-font-size;
}
}
.content {
padding-left: @intro-text-inset;
padding-right: @intro-text-right-inset;
.clearfix();
h2, h3 {
margin-left: -@intro-text-inset;
margin-right: -(@intro-text-inset + @intro-text-right-inset);
}
}
.quotes {
&.top {
margin-bottom: 1cm;
}
&.bottom {
margin-top: 1cm;
}
}
p, li {
line-height: @intro-paragraph-line-height;
font-size: @intro-paragraph-size;
text-align: @intro-text-align;
}
.photo {
float: @intro-photo-align;
margin: @intro-photo-margin;
height: auto;
.border-radius(@intro-photo-border-radius);
}
}
// Curriculum vitae
.cv {
.cv-entry {
.no-page-break-inside();
margin-bottom: .5cm;
h4 {
font-weight: bold;
font-size: @headline-4-size;
color: @headline-4-color;
small {
font-size: @headline-4-size-small;
font-style: italic;
color: @headline-4-color-small;
}
}
p {
text-align: @cv-text-align;
small {
color: @cv-label-color;
font-style: italic;
}
}
.col-date {
padding-right: @column-space;
.border-box(@cv-border-width);
}
.col-info {
padding-left: @column-space;
p {
margin-bottom: .1cm;
&:last-child {
margin-bottom: 0;
}
}
}
.date {
font-size: @base-font-size;
font-weight: bold;
text-align: right;
color: @date-base-color;
.start, .end {
display: block;
}
.start {
font-size: (@base-font-size + 4pt);
font-weight: bold;
color: @date-start-color;
}
}
.company {
font-size: (@base-font-size - 1pt);
font-style: italic;
}
}
}
// Projects
.projects {
.content {
padding-left: @intro-text-inset;
padding-right: @intro-text-right-inset;
.clearfix();
h2, h3 {
margin-left: -@intro-text-inset;
margin-right: -(@intro-text-inset + @intro-text-right-inset);
}
}
.short-description {
font-weight: bold;
font-size: (@base-font-size + .5pt);
}
dl.horizontal {
display: none;
dt {
text-align: left;
width: 1cm;
}
dd {
padding-right: 1cm;
p {
margin: 0;
}
}
}
p, li {
line-height: @intro-paragraph-line-height;
font-size: @intro-paragraph-size;
text-align: @intro-text-align;
}
}
// Resume
.resume {
dl.horizontal {
dt {
width: 2.1cm;
}
dd {
width: 6cm;
}
}
li, p {
font-size: @base-font-size;
text-align: @resume-text-align;
padding-left: @resume-text-inset;
padding-right: @resume-gutter-padding;
}
.col-resume {
margin-top: .45cm;
h3:first-child {
margin-top: .05cm;
}
}
.col-1 {
.border-box(@resume-border-width);
flex: 0 0 47.5%;
}
.col-2 {
padding-left: @resume-gutter-padding;
flex: 0 0 50.5%;
li {
margin-bottom: 3pt;
}
}
}
// Footers and headers or PDF generation
footer,
header {
display: block;
.left {
text-align: left;
}
.center {
text-align: center;
}
.right {
text-align: right;
}
}
// Specific screen styles
@media screen {
html, body {
height: 100%;
}
body {
margin: 20px 30px 0;
width: 19.5cm;
}
section {
margin-bottom: 2cm;
&.cover {
.text {
margin: 0;
}
}
}
.certs {
.certificate {
margin-bottom: 1.5cm;
}
}
}

View File

@@ -0,0 +1,50 @@
{% macro show_quotes(quotes, class) %}
<div class="quotes {{ class|default('top') }}">
{% for quote in quotes %}
<blockquote>
<span class="text">{{ quote.quoteText }}</span>
{% if quote.quoteAuthor %}
<span class="author">{{ quote.quoteAuthor }}</span>
{% endif %}
</blockquote>
{% endfor %}
</div>
{% endmacro %}
{% macro list_simple_array(entries, tag) %}
{% set tag = tag|default('li') %}
{% for line in entries %}
<{{ tag }}>{{ line|inlinemd }}</{{ tag }}>
{% endfor %}
{% endmacro %}
{% macro list_link_array(entries, tag) %}
{% set tag = tag|default('li') %}
{% for link in entries %}
<{{ tag }}><a href="{{ link }}" target="_blank">{{ link }}</a></{{ tag }}>
{% endfor %}
{% endmacro %}
{% macro list_entry_attribute(entries, attribute, tag) %}
{% set tag = tag|default('li') %}
{% for entry in entries %}
{% if attribute(entry, attribute)|length > 0 %}
{% for line in attribute(entry, attribute) %}
<{{ tag }}>{{ line|inlinemd }}</{{ tag }}>
{% endfor %}
{% endif %}
{% endfor %}
{% endmacro %}
{% macro list_references(references) %}
{% for reference in references %}
<li>
</li>
{% endfor %}
{% endmacro %}

View File

@@ -0,0 +1,16 @@
<section class="certs">
<h2>{{ 'certs.header'|trans }}</h2>
{% for entry in cv.filterByCertificates() %}
{% for cert in entry.certificates %}
<div class="certificate">
<figure>
<figcaption>
<h3>{{ entry.position }} {% if cert.type %}- {{ cert.type }}{% endif %}
<small>{{ entry.endDate.format('Y') }} - {{ entry.company }}</small></h3>
</figcaption>
<img src="{{ cert.dataUri|raw }}" alt="{{ cert.fileObject.filename }}">
</figure>
</div>
{% endfor %}
{% endfor %}
</section>

View File

@@ -0,0 +1,10 @@
<section class="cover">
<div class="text row">
<div class="col col-border">&nbsp;</div>
<div class="col col-content">
<h1 class="title">{{ person.name }}</h1>
<p class="tagline">{{ person.tagline|splitmerge|raw }}</p>
<p class="subtitle">{{ 'cover.subtitle'|trans }}</p>
</div>
</div>
</section>

View File

@@ -0,0 +1,12 @@
<section class="cv">
<h2>{{ 'cv.header'|trans }}</h2>
{% for tag in tags %}
<div class="tag tag-{{ tag }}">
<h3>{{ ('cv.headers.' ~ tag)|trans }}</h3>
{% for entry in cv.filterByTag(tag) %}
{{ include('parts/cv/entry.html.twig') }}
{% endfor %}
</div>
{% endfor %}
</section>

View File

@@ -0,0 +1,32 @@
<div class="cv-entry row">
<div class="col col-fifteen col-date">
<p class="date">
<span class="start">{{ entry.startDate.format(config('date.format.short')) }}</span>
<span class="end"><small>{{ 'date.until'|trans }}</small>
{% if is_today(entry.endDate) %}
{{ 'date.today'|trans }}
{% else %}
{{ entry.endDate.format(config('date.format.short')) }}
{% endif %}
</span>
</p>
</div>
<div class="col col-info">
<h4>{{ entry.position }} {% if entry.industry %}<small>({{ entry.industry }})</small>{% endif %}</h4>
<p class="company">{{ entry.company }}</p>
{% if entry.description %}
<div class="content">
{{ entry.description|raw }}
</div>
{% endif %}
{% if entry.qualification %}
<p class="qualification"><small>{{ 'cv.entry.qualification'|trans }}</small><br/>{{ entry.qualification }}</p>
{% endif %}
{% if entry.skills|length > 0 %}
<p class="skills"><small>{{ 'cv.entry.skills'|trans }}</small><br/>{{ entry.skills|merge|inlinemd }}</p>
{% endif %}
{% if entry.achievements|length > 0 %}
<p class="achievements"><small>{{ 'cv.entry.achievements'|trans }}</small><br/>{{ entry.achievements|merge|inlinemd }}</p>
{% endif %}
</div>
</div>

View File

@@ -0,0 +1,37 @@
<section class="intro">
{% import "macros.html.twig" as macros %}
{% if is_disabled(disabled.quotes) == false and intro.quotes|length > 0 and intro.showQuotes == 'top' %}
{{ macros.show_quotes(intro.quotes, intro.showQuotes) }}
{% endif %}
<div class="content">
{% if intro.headline %}<h2>{{ intro.headline }}</h2>{% endif %}
{% if intro.hasPhoto() %}
<img src="{{ intro.photoDataUri }}" alt="{{ person.name }}" class="photo" width="{{ intro.photoSize }}">
{% endif %}
{{ intro.content|raw }}
</div>
{% if is_disabled(disabled.quotes) == false and intro.quotes|length > 0 and intro.showQuotes == 'bottom' %}
{{ macros.show_quotes(intro.quotes, intro.showQuotes) }}
{% endif %}
{% if is_disabled(disabled.toc) == false %}
<h4>{{ 'intro.toc'|trans }}</h4>
<ul class="toc">
{% if is_disabled(disabled.resume) == false %}
<li>{{ 'toc.resume'|trans }}</li>
{% endif %}
{% if is_disabled(disabled.projects) == false %}
<li>{{ 'toc.projects'|trans }}</li>
{% endif %}
{% if is_disabled(disabled.cv) == false %}
<li>{{ 'toc.cv'|trans }}</li>
{% endif %}
{% if is_disabled(disabled.certs) == false %}
<li>{{ 'toc.certs'|trans }}</li>
{% endif %}
</ul>
{% endif %}
</section>

View File

@@ -0,0 +1,11 @@
<footer class="row">
<div class="col col-third left">
</div>
<div class="col col-third center">
{{ 'pdf.page.number'|trans|raw }}
</div>
<div class="col col-third right">
</div>
</footer>

View File

@@ -0,0 +1,8 @@
<header class="row">
<div class="col col-half left">
{{ 'pdf.page.title'|trans|raw }}
</div>
<div class="col col-half right">
{{ 'pdf.page.date'|trans|raw }}
</div>
</header>

View File

@@ -0,0 +1,25 @@
{% if projects|length > 0 %}
<section class="projects">
<h2>{{ 'projects.header'|trans }}</h2>
<div class="content">
{% for project in projects %}
<article class="project">
<h3>{{ project.name }} {% if project.stack %}<small>({{ project.stack }})</small>{% endif %}</h3>
<dl class="horizontal">
<dt>{{ 'projects.fields.status'|trans }}</dt>
<dd>
<p class="badge badge-{{ project.status }}">{{ ('projects.status.' ~ project.status)|trans }}</p>
</dd>
{% if project.role %}
<dt>{{ 'projects.fields.role'|trans }}</dt>
<dd>{{ project.role }}</dd>
{% endif %}
</dl>
<p class="short-description">{{ project.shortDescription }}</p>
{{ project.content|raw }}
</article>
{% endfor %}
</div>
</section>
{% endif %}

View File

@@ -0,0 +1,139 @@
{% set useInResume = cv.filterByUseInResume() %}
{% set toolbox = cv.filterByToolbox() %}
{% import "macros.html.twig" as macros %}
<section class="resume">
<h2>{{ 'resume.header'|trans }}</h2>
<div class="row">
<div class="col col-resume col-1">
<!-- Personal Information -->
<h3>{{ 'resume.headers.personal'|trans }}</h3>
<dl class="horizontal">
<dt>{{ 'resume.personal.name'|trans }}</dt>
<dd>{{ person.getName(true) }}</dd>
<dt>{{ 'resume.personal.birthdate'|trans }}</dt>
<dd>{{ person.birthdate.format(config('date.format.long')) }}</dd>
<dt>{{ 'resume.personal.birthplace'|trans }}</dt>
<dd>{{ person.birthplace }}</dd>
<dt>{{ 'resume.personal.residence'|trans }}</dt>
<dd>{{ person.residence }}</dd>
<dt>{{ 'resume.personal.status'|trans }}</dt>
<dd>{{ person.status }}</dd>
<dt>{{ 'resume.personal.nationality'|trans }}</dt>
<dd>{{ person.nationality }}</dd>
{% if person.workLicense %}
<dt>{{ 'resume.personal.work_license'|trans }}</dt>
<dd>{{ person.workLicense }}</dd>
{% endif %}
{% if person.languages|length > 0 %}
<dt>{{ 'resume.personal.languages'|trans }}</dt>
<dd>
<ul>
{% for lang in person.languages %}
<li>{{ lang.language }} <small>({{ ('resume.language.level.' ~ lang.level)|trans }})</small></li>
{% endfor %}
</ul>
</dd>
{% endif %}
</dl>
<!-- Contact Information -->
{% if person.contacts|length > 0 %}
<h3>{{ 'resume.headers.contact'|trans }}</h3>
<dl class="horizontal">
{% for contact in person.contacts %}
{% set type = contact.type %}
{% if contact.type == 'email' or contact.type == 'phone' %}
{% set type = ('resume.contact.' ~ contact.type)|trans %}
{% endif %}
<dt>{{ type }}</dt>
<dd>{{ contact.address }}</dd>
{% endfor %}
</dl>
{% endif %}
<!-- Job Experience -->
<h3>{{ 'resume.headers.experience'|trans }}</h3>
<dl class="horizontal">
{% for industry, length in cv.getExperienceYears() %}
<dt>{{ industry }}</dt>
<dd>{{ length }}</dd>
{% endfor %}
</dl>
<!-- Bio -->
{% if person.content %}
<h3>{{ 'resume.headers.bio'|trans }}</h3>
<div class="bio">{{ person.content|raw }}</div>
{% endif %}
<!-- Qualifications -->
<h3>{{ 'resume.headers.qualification'|trans }}</h3>
<ul>
{% for entry in cv.qualifications %}
<li>{{ entry.qualification|splitmerge(',', '</li><li>') }}</li>
{% endfor %}
</ul>
<!-- Personal Toolbox -->
{% if toolbox|length > 0 %}
<h3>{{ 'resume.headers.toolbox'|trans }}</h3>
<ul>
{% for entry in toolbox %}
{{ macros.list_simple_array(entry.toolbox) }}
{% endfor %}
</ul>
{% endif %}
<!-- Personal Interests -->
{% if person.interests|length > 0 %}
<h3>{{ 'resume.headers.personal_interest'|trans }}</h3>
<ul>
{{ macros.list_simple_array(person.interests) }}
</ul>
{% endif %}
</div>
<div class="col col-resume col-2">
<!-- Links -->
{% if person.links|length > 0 %}
<h3>{{ 'resume.headers.links'|trans }}</h3>
<ul>
{{ macros.list_link_array(person.links) }}
</ul>
{% endif %}
<!-- References -->
{% if person.references|length > 0 %}
<h3>{{ 'resume.headers.references'|trans }}</h3>
<ul>
{{ macros.list_references(person.references) }}
</ul>
{% endif %}
{% if person.projects|length > 0 %}
<h3>{{ 'resume.headers.current_projects'|trans }}</h3>
<ul>
{{ macros.list_simple_array(person.projects) }}
</ul>
{% endif %}
{% if useInResume|length > 0 %}
<h3>{{ 'resume.headers.skills'|trans }}</h3>
<ul>
{{ macros.list_entry_attribute(useInResume, 'skills') }}
</ul>
<h3>{{ 'resume.headers.achievements'|trans }}</h3>
<ul>
{{ macros.list_entry_attribute(useInResume, 'achievements') }}
</ul>
{% endif %}
</div>
</div>
</section>

BIN
app/tpl/server/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
app/tpl/server/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1 @@
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAMAAADzapwJAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABHVBMVEX////Z7vt+xfFEqusonugpnuhDqut+xPHX7fv2+/55wvE4pepBqeuKyvL5/P7W7PuTzvMuoOl9xPH4/P73+/5ZtO0gmudlue4xoulJrevi8vySzfMqnuhWs+18xPFYs+2NzPPq9f37/f/g8fxetu5ouu9Gq+vY7fsim+c3pOne8Puu2vZqvO+Y0PQ2pOl3wfC33/fV7Prt9/0hmudCqeuRzfPl8/wlnOjQ6vqi1fXL5/m13ffu9/2c0vQqn+hHrOu53/et2vaz3ffm9Pwnnejd8PvK5/lxv/Da7vvS6/qHyfL0+v78/v+84PgjnOfc7/tpu+/9/v9wvvD6/f7P6fqCxvJXs+1nuu94wvG94fhtve9dtu6AxvFUse1/xfE/bvvIAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB+IHFREcCLf3d7wAAADsSURBVBjTY2CgImBkYmZhZWPnQBHk5OLm4eXj5BcQFBJGiIqIiolLSPIxMEhJy8iKwIXlxORlFBSVGBiUVVTV5GCi6hpimlpglraOrrKeOlSYSd/AEMwwUhMT0zMWggqbmJpBGAJiIMAGFTa3sLSytgEybMHCdlBhVmElezFuBwYGJUcnVYQwD7+zsZiYi6orkO0mJqYGFWaXZnAH6fYAsj3FxLygwvya3j6yYmL2ILavmJ8/3DsBgUFiEsEgZohYKNyXwmHhES6RIJZ3VHQwIlD4YjRi1ZVE1KW54/hQwpCDndnFhS2OkZqRBQA4TBqQiOWEHQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOC0wNy0yMVQxNToyODowOCswMjowMKEt3m4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTgtMDctMjFUMTU6Mjg6MDgrMDI6MDDQcGbSAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

View File

@@ -0,0 +1 @@
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAMAAADzapwJAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAw1BMVEX////++/v42dv30tXupqvyu7/0wsbtnaPwsLX54ePWJTL65ef31tjaO0flc3vVIS7xt7vPARD65ufgWmTQBRTPAA/zvsL//v7ldX3YLjryvMDgW2X53uDtnqTZNEDQBBPgWWPzv8PqkpjdSVTUHCnWJzTnf4fRCRfldn7hYmv31df//f34293eUlzXKDX0x8raPEfPAhHfU130xsnjbHXcRlHYMj7toqfeT1nkcnrvqa7smJ7SDhzaOUXcR1L53d/smqDOQe/+AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB+IHFREcCLf3d7wAAACSSURBVBjTY2CgEmBkYmbBIszKxsDOgSnMycXNw4tFOR+/gKAQFsOFRUTFsCgXlxCVZMMiLiXKKygtgyEsKyrEKievoKikrKKK5Fg1dXEGBg1RUVFNLW0dhLCuHoO+gaGRsZQJrymSan4zaXlNHXSjzQVFLbQwLLQUFbXCdJ21jaQtFkfbManaYxFmc2AmNg5IAgAkagqCGD9ZrwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOC0wNy0yMVQxNToyODowOCswMjowMKEt3m4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTgtMDctMjFUMTU6Mjg6MDgrMDI6MDDQcGbSAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 B

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="{{ locale }}">
<!-- Build with magdev/dossier -->
<head>
<meta char{{ ('set="'~config('charset')~'"')|raw }}>
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
{% if favicon %}<link rel="shortcut icon" href="{{ favicon }}">{% endif %}
<title>{{ 'server.index.title'|trans }} | {{ person.name }}</title>
<style media="screen,print">
{{ stylesheet|raw }}
</style>
</head>
<body class="theme-{{ theme }}">
<div class="row row-main">
<div class="col col-left">
<h1>{{ 'server.index.header'|trans }}</h1>
<nav>
<ul>
{% for link in links %}
{% set parts = parseFilename(link.filename) %}
{% set time = link.getCTime()|unixToDateTime %}
<li class="{{ parts.type }}">
<a href="/{{ link.filename }}" target="ifm">
<h2>{{ parts.name }} <small>({{ parts.theme }}, {{ parts.locale }})</small></h2>
</a>
<dl>
<dt>{{ 'server.index.filesize'|trans }}</dt>
<dd>{{ link.size|filesize }}</dd>
<dt>{{ 'server.index.filetime'|trans }}</dt>
<dd>{{ time.format('d.m.Y H:i:s') }}</dd>
</dl>
<a href="/{{ link.filename }}" target="_blank">{{ 'server.index.new_window'|trans }}</a>
</li>
{% endfor %}
</ul>
</nav>
</div>
<div class="col col-main">
<iframe height="100%" width="100%" name="ifm" src="/{{ first_link.filename }}"></iframe>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,153 @@
/**
* LESS for magdev/resume print theme
*/
// MIXINS:START
//
// Mixins
//
.border-radius(@radius) {
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
border-radius: @radius;
}
// MIXINS:END
// VARS:START
//
// Variables
//
@base-font-family: Arial, Verdana;
@base-font-size: 13px;
@base-font-color: #222;
@base-background-color: #fff;
@base-accent-color: #68d19b;
@headline-1-size: (@base-font-size * 3);
@headline-1-color: #fff;
@headline-1-background-color: darken(@base-accent-color, 15%);
@headline-2-color: @base-font-color;
@headline-2-color-small: lighten(@headline-2-color, 30%);
@headline-2-size: floor(@base-font-size * 1.6);
@headline-2-size-small: (@headline-2-size - 5px);
@leftcol-width: 350px;
@leftcol-nav-margin: 10px 10px 0 15px;
@icon-pdf: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAMAAADzapwJAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAw1BMVEX////++/v42dv30tXupqvyu7/0wsbtnaPwsLX54ePWJTL65ef31tjaO0flc3vVIS7xt7vPARD65ufgWmTQBRTPAA/zvsL//v7ldX3YLjryvMDgW2X53uDtnqTZNEDQBBPgWWPzv8PqkpjdSVTUHCnWJzTnf4fRCRfldn7hYmv31df//f34293eUlzXKDX0x8raPEfPAhHfU130xsnjbHXcRlHYMj7toqfeT1nkcnrvqa7smJ7SDhzaOUXcR1L53d/smqDOQe/+AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB+IHFREcCLf3d7wAAACSSURBVBjTY2CgEmBkYmbBIszKxsDOgSnMycXNw4tFOR+/gKAQFsOFRUTFsCgXlxCVZMMiLiXKKygtgyEsKyrEKievoKikrKKK5Fg1dXEGBg1RUVFNLW0dhLCuHoO+gaGRsZQJrymSan4zaXlNHXSjzQVFLbQwLLQUFbXCdJ21jaQtFkfbManaYxFmc2AmNg5IAgAkagqCGD9ZrwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOC0wNy0yMVQxNToyODowOCswMjowMKEt3m4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTgtMDctMjFUMTU6Mjg6MDgrMDI6MDDQcGbSAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==');
@icon-html: url('data:text/html;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAMAAADzapwJAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABHVBMVEX////Z7vt+xfFEqusonugpnuhDqut+xPHX7fv2+/55wvE4pepBqeuKyvL5/P7W7PuTzvMuoOl9xPH4/P73+/5ZtO0gmudlue4xoulJrevi8vySzfMqnuhWs+18xPFYs+2NzPPq9f37/f/g8fxetu5ouu9Gq+vY7fsim+c3pOne8Puu2vZqvO+Y0PQ2pOl3wfC33/fV7Prt9/0hmudCqeuRzfPl8/wlnOjQ6vqi1fXL5/m13ffu9/2c0vQqn+hHrOu53/et2vaz3ffm9Pwnnejd8PvK5/lxv/Da7vvS6/qHyfL0+v78/v+84PgjnOfc7/tpu+/9/v9wvvD6/f7P6fqCxvJXs+1nuu94wvG94fhtve9dtu6AxvFUse1/xfE/bvvIAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB+IHFREcCLf3d7wAAADsSURBVBjTY2CgImBkYmZhZWPnQBHk5OLm4eXj5BcQFBJGiIqIiolLSPIxMEhJy8iKwIXlxORlFBSVGBiUVVTV5GCi6hpimlpglraOrrKeOlSYSd/AEMwwUhMT0zMWggqbmJpBGAJiIMAGFTa3sLSytgEybMHCdlBhVmElezFuBwYGJUcnVYQwD7+zsZiYi6orkO0mJqYGFWaXZnAH6fYAsj3FxLygwvya3j6yYmL2ILavmJ8/3DsBgUFiEsEgZohYKNyXwmHhES6RIJZ3VHQwIlD4YjRi1ZVE1KW54/hQwpCDndnFhS2OkZqRBQA4TBqQiOWEHQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOC0wNy0yMVQxNToyODowOCswMjowMKEt3m4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTgtMDctMjFUMTU6Mjg6MDgrMDI6MDDQcGbSAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAABJRU5ErkJggg==');
// VARS:END
//
// Styles
//
// Reset
* {
margin: 0;
padding: 0;
border: 0;
font-weight: normal;
font-style: normal;
list-style-type: none;
}
// Base elements
html, body {
background-color: @base-background-color;
font-family: @base-font-family;
font-size: @base-font-size;
color: @base-font-color;
}
html,body,.row-main,.col-main,.col-left {
height: 100%
}
body {
overflow: hidden;
}
h1 {
font-size: @headline-1-size;
color: @headline-1-color;
font-weight: bold;
background-color: @headline-1-background-color;
padding: 2px auto;
text-transform: uppercase;
letter-spacing: 3px;
text-align: center;
}
h2 {
font-size: @headline-2-size;
color: @headline-2-color;
font-weight: bold;
small {
font-size: @headline-2-size-small;
color: @headline-2-color-small;
font-style: italic;
}
}
a {
text-decoration: none;
}
// Grid
.row {
display: flex;
}
.col {
flex: 1;
}
.col-golden-narrow { flex: 0 0 38%; }
.col-golden-wide { flex: 0 1 62%; }
.col-left {
flex: 0 0 @leftcol-width;
background-color: lighten(@base-accent-color, 10%);
border-right: 5px solid @headline-1-background-color;
nav {
margin: @leftcol-nav-margin;
li {
margin-bottom: 10px;
background-color: @base-background-color;
padding: 5px 10px;
.border-radius(5px);
&.html {
background: @base-background-color @icon-html no-repeat top right;
}
&.pdf {
background: @base-background-color @icon-pdf no-repeat top right;
}
a:first-child {
color: @base-font-color;
}
dt,dd {
display: inline-block;
}
dt {
width: 38%;
float: left;
}
dd {
width: 62%;
}
}
}
}

4
bin/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
*.phar
lessc
pscss
.directory

67
bin/dossier.php Executable file
View File

@@ -0,0 +1,67 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
declare(strict_types=1);
define('DOSSIER_ROOT', dirname(__DIR__));
define('DOSSIER_CACHE', getenv('HOME').'/.dossier/cache');
define('PROJECT_ROOT', getcwd());
define('DOSSIER_LOGO', 'DQogX19fX19fX18gICAgICAgICAgICAgICAgICAgICAgLl9fICAgICAgICAgICAgICANCiBcX19fX19fIFwgICBfX19fICBfX19fX18gX19fX198X198IF9fX19fX19fX19fIA0KICB8ICAgIHwgIFwgLyAgXyBcLyAgX19fLy8gIF9fXy8gIHwvIF9fIFxfICBfXyBcDQogIHwgICAgYCAgICggIDxfPiApX19fIFwgXF9fXyBcfCAgXCAgX19fL3wgIHwgXC8NCiAvX19fX19fXyAgL1xfX19fL19fX18gID5fX19fICA+X198XF9fXyAgPl9ffCAgIA0KICAgICAgICAgXC8gICAgICAgICAgIFwvICAgICBcLyAgICAgICAgXC8gICAgICAgDQo=');
if (!is_dir(DOSSIER_CACHE)) {
mkdir(DOSSIER_CACHE, 0700, true);
}
require DOSSIER_ROOT.'/vendor/autoload.php';
use Magdev\Dossier\Application;
use Magdev\Dossier\Command;
$app = new Application('dossier.phar', '1.0.0');
$app->add(new Command\Dossier\DossierBuildCommand());
$app->add(new Command\Dossier\DossierInitCommand());
$app->add(new Command\Dossier\DossierStatusCommand());
$app->add(new Command\Intro\IntroAddCommand());
$app->add(new Command\Intro\IntroEditCommand());
$app->add(new Command\Person\PersonAddCommand());
$app->add(new Command\Person\PersonEditCommand());
$app->add(new Command\Cv\CvAddCommand());
$app->add(new Command\Cv\CvEditCommand());
$app->add(new Command\Config\ConfigShowCommand());
$app->add(new Command\Config\ConfigGetCommand());
$app->add(new Command\Config\ConfigSetCommand());
$app->add(new Command\Config\ConfigUnsetCommand());
$app->add(new Command\Theme\ThemeListCommand());
$app->add(new Command\Theme\ThemeDumpCommand());
$app->add(new Command\Cache\CacheClearCommand());
$app->add(new Command\Server\ServerStartCommand());
$app->add(new Command\Dev\PharExtractCommand());
$app->run();

68
composer.json Normal file
View File

@@ -0,0 +1,68 @@
{
"name" : "magdev/dossier",
"type" : "project",
"description" : "Create your dossier from Markdown files",
"license" : "MIT",
"authors" : [{
"name" : "Marco Grätsch",
"email" : "magdev3.0@gmail.com"
}
],
"autoload" : {
"psr-4" : {
"Magdev\\Dossier\\" : "src"
}
},
"require" : {
"php" : "~7.2",
"ext-phar" : "*",
"ext-SPL" : "*",
"ext-date" : "*",
"ext-fileinfo" : "*",
"ext-mbstring" : "*",
"ext-bz2" : "*",
"symfony/console" : "^4.1",
"symfony/translation" : "^4.1",
"symfony/config" : "^4.1",
"symfony/dependency-injection" : "^4.1",
"symfony/event-dispatcher" : "^4.1",
"symfony/process" : "^4.1",
"symfony/dotenv" : "^4.1",
"twig/twig" : "^2.4",
"mnapoli/front-yaml" : "^1.6",
"oyejorge/less.php" : "v1.7.0.14",
"erusev/parsedown-extra" : "^0.7.1",
"zaininnari/html-minifier" : "*",
"leafo/scssphp" : "^0.7.6",
"adbario/php-dot-notation" : "^2.0",
"magdev/console-form" : "^0.0.7",
"monolog/monolog" : "^1.23",
"pdfshift/pdfshift-php" : "~1.0.2"
},
"config" : {
"bin-dir" : "bin"
},
"extra" : {
"phar-builder" : {
"compression" : "BZip2",
"name" : "dossier.phar",
"output-dir" : "./bin/",
"entry-point" : "bin/dossier.php",
"include" : [
"app"
],
"include-dev" : false,
"events" : {
"command.package.end" : [
"chmod +x ./bin/dossier.phar"
]
}
}
},
"repositories" : [{
"type" : "git",
"url" : "git@github.com:magdev/console-form.git",
"name" : "magdev/console-form"
}
]
}

1638
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Analyzer\Base;
/**
* Interface for analyzable models
*
* @author magdev
*/
interface AnalyzableInterface
{
/**
* Get the data to analyze
*
* @return array
*/
public function getAnalyzerData(): array;
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Analyzer\Base;
use Symfony\Component\Console\Exception\RuntimeException;
class AnalyzerException extends RuntimeException
{
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Analyzer\Base;
/**
* Interface for analyzers
*
* @author magdev
*/
interface AnalyzerInterface
{
/**
* Get the name of the analyzer
*
* @return string
*/
public function getName(): string;
/**
* Analyze a model
*
* @param \Magdev\Dossier\Analyzer\Base\AnalyzableInterface $model
* @return mixed
*/
public function analyze(AnalyzableInterface $model);
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Analyzer;
use Magdev\Dossier\Analyzer\Base\AnalyzerInterface;
use Magdev\Dossier\Analyzer\Base\AnalyzableInterface;
/**
* Dossier status analyzer
*
* @author magdev
*/
class ModelStatusAnalyzer implements AnalyzerInterface
{
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Analyzer\Base\AnalyzerInterface::getName()
*/
public function getName(): string
{
return 'model.status';
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Analyzer\Base\AnalyzerInterface::analyze()
* @return int
*/
public function analyze(AnalyzableInterface $model)
{
$data = $model->getAnalyzerData();
$base = sizeof($data);
$counter = 0;
foreach ($data as $key => $value) {
if ($value) {
$counter++;
}
}
return ceil(($counter * 100) / $base);
}
}

132
src/Application.php Normal file
View File

@@ -0,0 +1,132 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier;
use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Droath\ConsoleForm\FormHelper;
use Magdev\Dossier\Form\Extension\FormDiscovery;
use Magdev\Dossier\Helper\ExportHelper;
use Magdev\Dossier\Helper\OutputHelper;
use Magdev\Dossier\Analyzer\DossierStatusAnalyzer;
use Magdev\Dossier\Analyzer\ModelStatusAnalyzer;
use Magdev\Dossier\Helper\SectionManagerHelper;
/**
* ContainerAware Application
*
* @author magdev
*/
class Application extends BaseApplication
{
/**
* Store the di-container
* @var \Symfony\Component\DependencyInjection\ContainerBuilder
*/
protected $container = null;
/**
* Constructor
*
* @param string $name
* @param string $version
*/
public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN')
{
parent::__construct($name, $version);
$this->container = new ContainerBuilder();
$loader = new YamlFileLoader($this->container, new FileLocator(DOSSIER_ROOT.'/app/conf'));
$loader->load('services.yaml');
$formDiscovery = new FormDiscovery($this->container);
$forms = $formDiscovery->discover(DOSSIER_ROOT.'/src/Form', '\Magdev\Dossier\Form');
$helperSet = $this->getHelperSet();
$helperSet->set(new FormHelper($forms));
$helperSet->set(new ExportHelper());
$helperSet->set(new OutputHelper($this->getName(), $this->getVersion()));
$helperSet->set(new SectionManagerHelper($this->container->get('config')));
$this->container->get('analyzer')
->addAnalyzer(new ModelStatusAnalyzer());
}
/**
* Get the service-contianer
*
* @return \Symfony\Component\DependencyInjection\ContainerBuilder
*/
public function getContainer(): ContainerBuilder
{
return $this->container;
}
/**
* Get a service by its name
*
* @param string $name
* @param int $invalidBehavior
* @return object|\Symfony\Component\DependencyInjection\Container|mixed|void|unknown
*/
public function getService(string $name, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
{
return $this->getContainer()->get($name, $invalidBehavior);
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Application::getLongVersion()
*/
public function getLongVersion()
{
$code = '<fg=magenta;options=bold>'.base64_decode(DOSSIER_LOGO).PHP_EOL;
$header = $this->getService('translator')->trans('app.header');
if ('UNKNOWN' !== $this->getName()) {
if ('UNKNOWN' !== $this->getVersion()) {
$code .= ' '.$this->getName().' '.$this->getVersion().PHP_EOL;
} else {
$code .= ' '.$this->getName().PHP_EOL;
}
}
$code .= ' '.$header.'</>';
return $code;
}
}

View File

@@ -0,0 +1,174 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Base;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
/**
* Base command
*
* @author magdev
*/
class BaseCommand extends Command
{
/**
* Configuration service
* @var \Magdev\Dossier\Service\ConfigService
*/
protected $config = null;
/**
* Translator service
* @var \Magdev\Dossier\Service\TranslatorService
*/
protected $translator = null;
/**
* Monolog Service
* @var \Magdev\Dossier\Service\MonologService
*/
protected $logger = null;
/**
* The IO-Style object
* @var \Magdev\Dossier\Style\DossierStyle
*/
protected $io = null;
/**
* Write the application header
*
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @return \Magdev\Dossier\BaseCommand\Base\BaseCommand
* @deprecated
*/
protected function writeHeader(OutputInterface $output): BaseCommand
{
$this->getService('output_helper')
->setOutput($output)
->writeApplicationHeader();
return $this;
}
/**
* Get a service from the container
*
* @param string $name
* @return mixed
*/
protected function getService(string $name)
{
return $this->getApplication()->getService($name);
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->addOption('no-header', 'N', InputOption::VALUE_NONE, 'Suppress header <option>(format=table)</>');
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\BaseCommand\Command::initialize()
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
$this->config = $this->getService('config');
$this->logger = $this->getService('monolog');
$locale = $this->config->get('translator.locale', 'en');
if ($input->hasOption('locale')) {
$locale = $input->getOption('locale');
}
$this->translator = $this->getService('translator')->setLocale($locale);
$this->io = $this->getHelper('output')
->getIoStyle($input, $output);
if (!$input->hasOption('no-header') || !$input->getOption('no-header')) {
$this->io->header($this->translator->trans('app.header'));
}
}
/**
* Log and output debug messages
*
* @param string $message
* @return \Magdev\Dossier\Command\Base\BaseCommand
*/
protected function debugLog(string $message): BaseCommand
{
$this->logger->debug($message);
$this->io->debug($message);
return $this;
}
/**
* Log and output error messages
*
* @param string $message
* @return \Magdev\Dossier\Command\Base\BaseCommand
*/
protected function errorLog(string $message): BaseCommand
{
$this->logger->error($message);
$this->io->error($message);
return $this;
}
/**
* Log and output warnings
*
* @param string $message
* @return \Magdev\Dossier\Command\Base\BaseCommand
*/
protected function warningLog(string $message): BaseCommand
{
$this->logger->warning($message);
$this->io->warning($message);
return $this;
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Cache;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Magdev\Dossier\Command\Base\BaseCommand;
class CacheClearCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('cache:clear')
->setDescription('Clear the cache');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Command\Base\BaseCommand::initialize()
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
$input->setOption('no-header', true);
parent::initialize($input, $output);
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if (DOSSIER_CACHE && DOSSIER_CACHE != '/' && is_dir(DOSSIER_CACHE)) {
system('rm -rf '.DOSSIER_CACHE.' 2>&1 >> /dev/null');
}
}
}

View File

@@ -0,0 +1,139 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Config;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Helper\Table;
use Magdev\Dossier\Command\Base\BaseCommand;
/**
* Get a configuration value
*
* @author magdev
*/
class ConfigGetCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('config:get')
->setDescription('Get a configuration value')
->addArgument('path', InputArgument::REQUIRED, 'Configuration path')
->addOption('format', 'f', InputOption::VALUE_OPTIONAL, 'Output format (table|yaml|json|php)', 'table')
->addOption('plain', 'p', InputOption::VALUE_NONE, 'Show the value only <option>(implies --no-header)</>')
->addOption('include-return', 'R', InputOption::VALUE_NONE, 'Include return statement <option>(format=php)</>')
->addOption('include-tags', 'T', InputOption::VALUE_NONE, 'Include PHP tags <option>(format=php)</>')
->addOption('pretty', 'P', InputOption::VALUE_NONE, 'JSON pretty print <option>(format=json)</>')
->addOption('indent', 'i', InputOption::VALUE_OPTIONAL, 'Indentation width <option>(format=yaml)</>', 2)
->addOption('depth', 'd', InputOption::VALUE_OPTIONAL, 'Render depth before switching to inline YAML <option>(format=yaml)</>', 3);
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::initialize()
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
$input->setOption('no-header', $input->getOption('plain'));
parent::initialize($input, $output);
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$export = $this->getHelper('export');
/* @var $export \Magdev\Dossier\Helper\ExportHelper */
$path = $input->getArgument('path');
$value = $this->config->get($path);
if ($input->getOption('plain')) {
$this->io->write($value);
exit;
}
switch ($input->getOption('format')) {
case 'yaml':
$this->io->write($export->toYAML(
$this->config->getConfig()->all(),
(int) $input->getOption('depth'),
(int) $input->getOption('indent')
));
break;
case 'json':
$this->io->write($export->toJSON(
$this->config->getConfig()->all(),
(bool) $input->getOption('pretty')
));
break;
case 'php':
$this->io->write($export->toPHP(
$this->config->getConfig()->all(),
(bool) $input->getOption('include-return'),
(bool) $input->getOption('include-tags')
));
break;
default:
$global = $this->io->bool($this->config->isGlobalConfig($path, $value));
$this->io->writeln(array(
' '.$this->translator->trans('info.debug_mode').': '.$this->io->debugStatus(),
' '.$this->translator->trans('info.environment').': '.$this->io->environment()
));
$this->io->newLine();
$this->io->table(
array('Path', 'Value', 'Global'),
array(array($path, $value, $this->io->align($global, 6)))
);
break;
}
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Config;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\Table;
use Magdev\Dossier\Command\Base\BaseCommand;
/**
* Set a configuration value
*
* @author magdev
*/
class ConfigSetCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('config:set')
->setDescription('Set a configuration value')
->addOption('global', 'g', InputOption::VALUE_NONE, 'Set in global configuration')
->addArgument('path', InputArgument::REQUIRED, 'Configuration path in dot-notation')
->addArgument('value', InputArgument::REQUIRED, 'Configuration value');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$global = (bool) $input->getOption('global');
$path = $input->getArgument('path');
$value = $input->getArgument('value');
$this->config->set($path, $value, $global)->save();
$this->io->table(array('Path', 'Value', 'Global'), array(
array(
$path,
$this->config->get($path),
$this->io->align($this->io->bool($this->config->isGlobalConfig($path, $value)), 6)
)
));
}
}

View File

@@ -0,0 +1,131 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Config;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\Table;
use Magdev\Dossier\Service\ConfigService;
use Magdev\Dossier\Command\Base\BaseCommand;
/**
* Show the full configuration
*
* @author magdev
*/
class ConfigShowCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('config:show')
->setDescription('Show or export the full configuration')
->addOption('format', 'f', InputOption::VALUE_OPTIONAL, 'Output format (table|yaml|json|php)', 'table')
->addOption('return', 'r', InputOption::VALUE_NONE, 'PHP: Include return statement')
->addOption('tags', 't', InputOption::VALUE_NONE, 'PHP: Include PHP tags')
->addOption('pretty', 'p', InputOption::VALUE_NONE, 'JSON: Output pretty printed')
->addOption('indent', 'i', InputOption::VALUE_OPTIONAL, 'YAML: Indentation width', 2)
->addOption('depth', 'd', InputOption::VALUE_OPTIONAL, 'YAML: Render depth before switching to inline YAML', 3);
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::initialize()
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
if ($input->getOption('format') != 'table') {
$input->setOption('no-header', true);
}
parent::initialize($input, $output);
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$export = $this->getHelper('export');
/* @var $export \Magdev\Dossier\Helper\ExportHelper */
switch ($input->getOption('format')) {
case 'yaml':
$this->io->write($export->toYAML(
$this->config->getConfig()->all(),
(int) $input->getOption('depth'),
(int) $input->getOption('indent')
));
break;
case 'json':
$this->io->write($export->toJSON(
$this->config->getConfig()->all(),
(bool) $input->getOption('pretty')
));
break;
case 'php':
$this->io->write($export->toPHP(
$this->config->getConfig()->all(),
(bool) $input->getOption('include-return'),
(bool) $input->getOption('include-tags')
));
break;
default:
$outHelper = $this->getHelper('output');
/* @var $outHelper \Magdev\Dossier\Helper\OutputHelper */
$this->io->newLine();
$this->io->writeln(array(
' '.$this->translator->trans('info.debug_mode').': '.$this->io->debugStatus(),
' '.$this->translator->trans('info.environment').': '.$this->io->environment()
));
$this->io->newLine();
$this->io->table(
array('Path', 'Value', 'Global'),
$this->config->allTable($this->io, 6)
);
break;
}
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Config;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\Table;
use Magdev\Dossier\Command\Base\BaseCommand;
/**
* Set a configuration value
*
* @author magdev
*/
class ConfigUnsetCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('config:unset')
->setDescription('Unset a configuration value')
->addArgument('path', InputArgument::REQUIRED, 'Configuration path in dot-notation');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$path = $input->getArgument('path');
$this->config->unset($path)->save();
$this->io->success($this->translator->trans('message.config.deleted', array('%path%' => $path)));
}
}

View File

@@ -0,0 +1,124 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Cv;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Exception\RuntimeException;
use Droath\ConsoleForm\Exception\FormException;
use Magdev\Dossier\Command\Base\BaseCommand;
/**
* Write a new CV entry
*
* @author magdev
*/
final class CvAddCommand extends BaseCommand
{
/**
* TheCV Form
* @var \Magdev\Dossier\Form\Extension\Form
*/
protected $form = null;
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('cv:add')
->setDescription('Write a new CV entry')
->addArgument('name', InputArgument::REQUIRED, 'Choose the name of the entry')
->addOption('review', 'r', InputOption::VALUE_NONE, 'Review file in editor');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Command\BaseCommand::initialize()
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
try {
$this->form = $this->getHelper('form')->getFormByName('form.cv', $input, $output);
parent::initialize($input, $output);
} catch (FormException $fe) {
throw new RuntimeException(get_class($fe).': '.$fe->getMessage(), $fe->getCode(), $fe);
}
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::interact()
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
$this->io->title($this->translator->trans('form.cv.header.add'));
$this->io->newLine();
$this->form->process();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($this->form->isProcessed()) {
$markdown = $this->getService('markdown');
/* @var $markdown \Magdev\Dossier\Service\MarkdownService */
try {
$text = $this->form->stripData('text', '');
$name = $input->getArgument('name');
$markdown->save(PROJECT_ROOT.'/cv/'.$name.'.md', $this->form->getResults(), $text, false);
$this->io->success($this->translator->trans('message.write.success', array(
'%name%' => 'CV/'.ucfirst($name)
)));
if ($input->getOption('review') != false) {
$this->getService('uri_helper')->openFileInEditor(PROJECT_ROOT.'/cv/'.$name.'.md');
}
} catch (FormException $fe) {
throw new RuntimeException(get_class($fe).': '.$fe->getMessage(), $fe->getCode(), $fe);
}
}
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Cv;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Exception\RuntimeException;
use Magdev\Dossier\Command\Base\BaseCommand;
class CvEditCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('cv:edit')
->setDescription('Edit a CV entry in your default editor')
->addArgument('file', InputArgument::REQUIRED, 'Filename of the entry w/o extension');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$file = PROJECT_ROOT.'/cv/'.$input->getArgument('file').'.md';
if (!file_exists($file)) {
throw new RuntimeException('File '.$file.' not found');
}
$this->getService('uri_helper')->openFileInEditor($file);
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Dev;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Magdev\Dossier\Command\Base\BaseCommand;
class PharExtractCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('dev:phar:extract')
->setHidden(!getenv('APP_DEBUG'))
->setDescription('Extract the Phar archive')
->addOption('target', 'd', InputOption::VALUE_OPTIONAL, 'Target directory', getcwd().'/_phar');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$targetDir = $input->getOption('target');
$this->getService('phar_helper')->extractArchive($targetDir);
}
}

View File

@@ -0,0 +1,133 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Dossier;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Magdev\Dossier\Model\CurriculumVitae;
use Magdev\Dossier\Model\Person;
use Magdev\Dossier\Model\Intro;
use Magdev\Dossier\Model\Letter;
use Magdev\Dossier\Command\Base\BaseCommand;
use Magdev\Dossier\Util\DataCollector;
/**
* Generate your dossier
*
* @author magdev
*/
final class DossierBuildCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('dossier:build')
->setDescription('Create a dossier from a set of Markdown files')
->addOption('review', 'r', InputOption::VALUE_NONE, 'Review created file')
->addOption('pdf', 'p', InputOption::VALUE_NONE, 'Convert to PDF (requires PDFShift API-Key)')
->addOption('locale', 'l', InputOption::VALUE_OPTIONAL, 'Set the locale', 'de')
->addOption('sort', 's', InputOption::VALUE_OPTIONAL, 'Set the sort direction for the CV', CurriculumVitae::SORT_DESC)
->addOption('theme', 't', InputOption::VALUE_OPTIONAL, 'Select the theme', 'print')
->addOption('docname', 'd', InputOption::VALUE_OPTIONAL, 'Set the name for the output document (w/o extension)', 'dossier')
->addOption('no-cover', null, InputOption::VALUE_NONE, 'Suppress the cover')
->addOption('no-intro', null, InputOption::VALUE_NONE, 'Suppress the introduction')
->addOption('no-resume', null, InputOption::VALUE_NONE, 'Suppress the resume')
->addOption('no-cv', null, InputOption::VALUE_NONE, 'Suppress the curriculum vitae')
->addOption('no-projects', null, InputOption::VALUE_NONE, 'Suppress the projects page')
->addOption('no-certs', null, InputOption::VALUE_NONE, 'Suppress the certificates')
->addOption('no-toc', null, InputOption::VALUE_NONE, 'Suppress the table of contents')
->addOption('no-quotes', null, InputOption::VALUE_NONE, 'Suppress the quotes');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($input->getOption('theme') == 'server') {
$this->warningLog('Template server cannot be used to render dossiers, using print theme');
$input->setOption('theme', 'print');
}
$uriHelper = $this->getService('uri_helper');
/* @var $uriHelper \Magdev\Dossier\Service\UriHelperService */
$tpl = $this->getService('template')->setTheme($input->getOption('theme'));
/* @var $tpl \Magdev\Dossier\Service\TemplateService */
$cssproc = $this->getService('cssproc');
/* @var $cssroc \Magdev\Dossier\Service\StylesheetProcessorService */
try {
$data = new DataCollector(array(
'disabled' => $this->getHelper('section_manager')->getDisabledSections($input),
'theme' => $input->getOption('theme'),
'name' => $input->getOption('docname'),
'tags' => $this->config->get('cv.tags'),
'locale' => $this->translator->getTranslator()->getLocale(),
'stylesheet' => $cssproc->parseThemeStyles(),
'userstyles' => $cssproc->parseUserstyles(),
'favicon' => $uriHelper->getDataUriFromFile($tpl->getThemeFile('favicon.ico')),
));
$models = $this->getService('markdown')->getFileSet($input->getOption('sort'));
$data->merge($models);
$outputFile = $tpl->render('document.html.twig', $data, PROJECT_ROOT.'/_output');
if ($input->getOption('pdf')) {
$outputFile = $this->getService('pdf')->createPdf($outputFile);
}
$this->io->result($this->translator->trans('message.output_file').': '.$uriHelper->getRelativePath($outputFile));
$this->io->newLine();
$this->io->success($this->translator->trans('message.build.success'));
$this->io->newLine();
if ($input->getOption('review')) {
$uriHelper->openFileInEditor($outputFile);
}
} catch (\Exception $e) {
$this->errorLog($e->getMessage());
}
}
}

View File

@@ -0,0 +1,205 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Dossier;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Exception\RuntimeException;
use Magdev\Dossier\Command\Base\BaseCommand;
/**
* Initialize a new project directory
*
* @author magdev
*/
final class DossierInitCommand extends BaseCommand
{
/**
* The InitForm
* @var \Magdev\Dossier\Form\Extension\Form
*/
protected $form = null;
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('dossier:init')
->setDescription('Initialize a directory as dossier project')
->setHelp('Initialize a new project. Creates the folder structure and some example markdown files')
->addOption('directory', 'd', InputOption::VALUE_OPTIONAL, 'Set the output directory', getcwd());
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::initialize()
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
parent::initialize($input, $output);
try {
$this->form = $this->getHelper('form')
->getFormByName('form.init', $input, $output);
} catch (FormException $fe) {
throw new RuntimeException(get_class($fe).': '.$fe->getMessage(), $fe->getCode(), $fe);
}
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::interact()
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
$this->io->title($this->translator->trans('form.init.header'));
$this->io->newLine();
$this->form->process();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$targetDir = $input->getOption('directory');
if ($this->isDossierProjectDirectory($targetDir)) {
throw new RuntimeException('Directory '.$targetDir.' seems to be an existing dossier project');
}
$this->initTargetDirectory($targetDir);
if ($this->form->isProcessed()) {
if ($this->form->hasData('userstyle_type')) {
$type = strtolower($this->form->getData('userstyle_type'));
$file = $targetDir.'/.conf/'.$type.'/userstyles.'.$type;
if (!is_dir(dirname($file))) {
mkdir(dirname($file), 0755, true);
}
file_put_contents($file, '');
}
$formatter = $this->getHelper('formatter');
$output->writeln($formatter->formatBlock(array(
' $ dossier.phar add:person',
' $ dossier.phar add:intro',
' $ dossier.phar add:cv',
), 'cmd', true));
}
}
/**
* Check if the path is a valid dossier project
*
* @param string $path
* @return bool
*/
private function isDossierProjectDirectory(string $path): bool
{
if (!is_dir($path)) {
return false;
}
if (!is_dir($path.'/cv')) {
return false;
}
if (!is_dir($path.'/certs')) {
return false;
}
if (!is_dir($path.'/.conf')) {
return false;
}
if (!file_exists($path.'/.conf/dossier.yaml')) {
return false;
}
if (!file_exists($path.'/.env')) {
return false;
}
if (!file_exists($path.'/intro.md')) {
return false;
}
if (!file_exists($path.'/person.md')) {
return false;
}
if (!file_exists($path.'/letter.md')) {
return false;
}
return true;
}
/**
* Create the directory structure
*
* @return string
*/
private function initTargetDirectory(string $dir): string
{
if (!is_dir($dir)) {
if (mkdir($dir, 0755, true) === false) {
throw new RuntimeException('Creating directory '.$dir.' failed');
}
}
if (!is_dir($dir.'/cv')) {
mkdir($dir.'/cv', 0755, true);
}
if (!is_dir($dir.'/certs/pdf')) {
mkdir($dir.'/certs/pdf', 0755, true);
}
if (!is_dir($dir.'/certs/png')) {
mkdir($dir.'/certs/png', 0755, true);
}
if (!is_dir($dir.'/.conf')) {
mkdir($dir.'/.conf', 0755, true);
}
file_put_contents($dir.'/.conf/dossier.yaml', '');
file_put_contents($dir.'/.env', 'APP_DEBUG=false'.PHP_EOL.'APP_ENV=prod'.PHP_EOL);
return $dir;
}
}

View File

@@ -0,0 +1,122 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Dossier;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\TableSeparator;
use Magdev\Dossier\Model\Person;
use Magdev\Dossier\Model\Intro;
use Magdev\Dossier\Model\CurriculumVitae\Entry;
use Magdev\Dossier\Model\Letter;
use Magdev\Dossier\Style\DossierStyle;
use Magdev\Dossier\Command\Base\BaseCommand;
/**
* Command to show the current status of your dossier
*
* @author magdev
*/
class DossierStatusCommand extends BaseCommand
{
/**
* Markdown service
* @var \Magdev\Dossier\Service\MarkdownService
*/
private $markdown = null;
private $models = array(
'Person' => 'person.md',
'Intro' => 'intro.md',
'Letter' => 'letter.md'
);
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('dossier:status')
->setDescription('Get the status of the current dossier files');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$markdown = $this->getService('markdown');
/* @var $markdown \Magdev\Dossier\Service\MarkdownService */
$analyzer = $this->getService('analyzer')->getAnalyzer('model.status');
/* @var $analyzer \Magdev\Dossier\Analyzer\DossierStatusAnalyzer */
$thresholds = $this->config->get('style.dossier_status_thresholds');
$person = new Person($markdown->getDocument(PROJECT_ROOT.'/person.md'));
$intro = new Intro($markdown->getDocument(PROJECT_ROOT.'/intro.md'));
$status = array();
$status[] = array(get_class($person), 'person.md',
$this->io->align('---', 9, DossierStyle::ALIGN_CENTER),
$this->io->align($this->io->percent($analyzer->analyze($person), $thresholds), 6, DossierStyle::ALIGN_RIGHT)
);
$status[] = array(get_class($intro), 'intro.md',
$this->io->align('---', 9, DossierStyle::ALIGN_CENTER),
$this->io->align($this->io->percent($analyzer->analyze($intro), $thresholds), 6, DossierStyle::ALIGN_RIGHT)
);
$status[] = new TableSeparator();
$files = new \FilesystemIterator(PROJECT_ROOT.'/cv');
foreach ($files as $file) {
/* @var $file \SplFileInfo */
$document = $markdown->getDocument($file->getPathname());
$entry = new Entry($document);
$status[] = array(get_class($entry), 'cv/'.$file->getFilename(),
$this->io->align($this->io->bool($entry->useInResume()), 9, DossierStyle::ALIGN_CENTER),
$this->io->align($this->io->percent($analyzer->analyze($entry), $thresholds), 6, DossierStyle::ALIGN_RIGHT)
);
}
$this->io->table(array('Model', 'File',
$this->io->align('In Resume', 9),
$this->io->align('Status', 6, DossierStyle::ALIGN_RIGHT)
), $status);
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Intro;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Exception\RuntimeException;
use Droath\ConsoleForm\Exception\FormException;
use Magdev\Dossier\Command\Base\BaseCommand;
final class IntroAddCommand extends BaseCommand
{
/**
* The IntroForm
* @var \Magdev\Dossier\Form\Extension\Form
*/
protected $form = null;
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('intro:add')
->setDescription('Write the Intro page')
->addOption('review', 'r', InputOption::VALUE_NONE, 'Review file in editor');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Command\BaseCommand::initialize()
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
parent::initialize($input, $output);
try {
$this->form = $this->getHelper('form')
->getFormByName('form.intro', $input, $output);
} catch (FormException $fe) {
throw new RuntimeException(get_class($fe).': '.$fe->getMessage(), $fe->getCode(), $fe);
}
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::interact()
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
$this->io->title('<info> '.$this->translator->trans('form.intro.header.add').'</>');
$this->io->newLine();
$this->form->process();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($this->form->isProcessed()) {
$markdown = $this->getService('markdown');
/* @var $markdown \Magdev\Dossier\Service\MarkdownService */
try {
$text = $this->form->stripData('text', '');
$markdown->save(PROJECT_ROOT.'/intro.md', $this->form->getResults(), $text, false);
$this->io->success($this->translator->trans('message.write.success', array(
'%name%' => 'Intro'
)));
if ($input->getOption('review') != false) {
$this->getService('uri_helper')->openFileInEditor(PROJECT_ROOT.'/intro.md');
}
} catch (FormException $fe) {
throw new RuntimeException(get_class($fe).': '.$fe->getMessage(), $fe->getCode(), $fe);
}
}
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Intro;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Exception\RuntimeException;
use Magdev\Dossier\Command\Base\BaseCommand;
class IntroEditCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('intro:edit')
->setDescription('Edit the intro in your default editor');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$file = PROJECT_ROOT.'/intro.md';
if (!file_exists($file)) {
throw new RuntimeException('File '.$file.' not found');
}
$this->getService('uri_helper')->openFileInEditor($file);
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Person;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Exception\RuntimeException;
use Droath\ConsoleForm\Exception\FormException;
use Magdev\Dossier\Command\Base\BaseCommand;
final class PersonAddCommand extends BaseCommand
{
/**
* The IntroForm
* @var \Magdev\Dossier\Form\Extension\Form
*/
protected $form = null;
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('person:add')
->setDescription('Write the Person page')
->addOption('review', 'r', InputOption::VALUE_NONE, 'Review file in editor');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Command\BaseCommand::initialize()
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
parent::initialize($input, $output);
try {
$this->form = $this->getHelper('form')
->getFormByName('form.person', $input, $output);
} catch (FormException $fe) {
throw new RuntimeException(get_class($fe).': '.$fe->getMessage(), $fe->getCode(), $fe);
}
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::interact()
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
$this->io->title($this->translator->trans('form.person.header.add'));
$this->io->newLine();
$this->form->process();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($this->form->isProcessed()) {
$markdown = $this->getService('markdown');
/* @var $markdown \Magdev\Dossier\Service\MarkdownService */
try {
$text = $this->form->stripData('text', '');
$markdown->save(PROJECT_ROOT.'/person.md', $this->form->getResults(), $text, false);
$this->io->success($this->translator->trans('message.write.success', array(
'%name%' => 'Person'
)));
if ($input->getOption('review') != false) {
$this->getService('uri_helper')->openFileInEditor(PROJECT_ROOT.'/person.md');
}
} catch (FormException $fe) {
throw new RuntimeException(get_class($fe).': '.$fe->getMessage(), $fe->getCode(), $fe);
}
}
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Person;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Exception\RuntimeException;
use Magdev\Dossier\Command\Base\BaseCommand;
class PersonEditCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('person:edit')
->setDescription('Edit personal data in your default editor');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$file = PROJECT_ROOT.'/person.md';
if (!file_exists($file)) {
throw new RuntimeException('File '.$file.' not found');
}
$this->getService('uri_helper')->openFileInEditor($file);
}
}

View File

@@ -0,0 +1,143 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Server;
use Magdev\Dossier\Command\Base\BaseCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Magdev\Dossier\Util\DataCollector;
use Symfony\Component\Console\Exception\RuntimeException;
/**
* Start the local HTTP server
*
* @author magdev
*/
class ServerStartCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Command\Base\BaseCommand::configure()
*/
public function configure()
{
$this->setName('server:start')
->setDescription('Start a local HTTP server')
->addOption('socket', 's', InputOption::VALUE_OPTIONAL, 'Set the HTTP socket (host, port or host:port)', 'localhost:8000')
->addOption('no-index', null, InputOption::VALUE_NONE, 'Suppress rendering of index.html before starting the server');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
public function execute(InputInterface $input, OutputInterface $output)
{
$socket = $input->getOption('socket');
$docroot = PROJECT_ROOT.'/_output';
if (!$input->getOption('no-index')) {
$this->createIndex($docroot);
}
$cmd = sprintf('/usr/bin/env php -S %s -t %s', $socket, $docroot);
try {
$process = new Process($cmd);
$process->setTimeout((60*60*24*365))
->start();
$this->io->info(sprintf('Starting HTTP server on %s, press CTRL+C to stop', $socket));
$process->wait(function($type, $buffer) {
if (getenv('APP_DEBUG')) {
$this->io->write(' <lightyellow>[GET] <fg=cyan>'.$buffer.'</>');
}
});
} catch (\Exception $e) {
$this->io->error($e->getMessage());
}
}
/**
* Create an index.html file before server start
*
* @param string $docroot
* @return void
*/
protected function createIndex(string $docroot): void
{
if (file_exists($docroot.'/index.html')) {
unlink($docroot.'/index.html');
}
try {
$tpl = $this->getService('template')->setTheme('server');
/* @var $tpl \Magdev\Dossier\Service\TemplateService */
$cssproc = $this->getService('cssproc');
/* @var $cssroc \Magdev\Dossier\Service\StylesheetProcessorService */
$uriHelper = $this->getService('uri_helper');
/* @var $uriHelper \Magdev\Dossier\Service\UriHelperService */
$data = new DataCollector(array(
'locale' => $this->translator->getTranslator()->getLocale(),
'stylesheet' => $cssproc->parseThemeStyles(),
'favicon' => $uriHelper->getDataUriFromFile($tpl->getThemeFile('favicon.ico')),
));
$files = array();
$fs = new \FilesystemIterator($docroot);
foreach ($fs as $file) {
if (!sizeof($files)) {
$data->setData('first_link', $file);
}
$files[] = $file;
}
$data->setData('links', $files);
$html = $tpl->renderDocument('index.html.twig', $data);
if (false === file_put_contents($docroot.'/index.html', $html)) {
throw new RuntimeException('Error while writing index.html file');
}
$this->debugLog(sprintf('File index.html created with %s bytes', mb_strlen($html)));
} catch (\Exception $e) {
$this->errorLog($e->getMessage());
}
}
}

View File

@@ -0,0 +1,108 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Theme;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Magdev\Dossier\Command\Base\BaseCommand;
/**
* Create a local copy of a template
*
* @author magdev
*/
final class ThemeDumpCommand extends BaseCommand
{
/**
* Phar helper service
* @var \Magdev\Dossier\Service\PharHelperService
*/
private $pharHelper = null;
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('theme:dump')
->setDescription('Create a local copy of a theme')
->addArgument('theme', InputArgument::REQUIRED, 'The name of the theme')
->addOption('locale', 'l', InputOption::VALUE_OPTIONAL, 'Set the locale', 'de')
->addOption('rename', 'r', InputOption::VALUE_OPTIONAL, 'Rename the theme', '')
->addOption('output', 'o', InputOption::VALUE_OPTIONAL, 'Output folder', getenv('HOME').'/.dossier/tpl');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::initialize()
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
$this->pharHelper = $this->getService('phar_helper');
parent::initialize($input, $output);
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$theme = $input->getArgument('theme');
$outDir = $input->getOption('output');
$newName = $input->getOption('rename');
$themeDir = 'app/tpl/'.$theme;
$targetDir = !$newName ? $outDir.'/'.$theme : $outDir.'/'.$newName;
$this->pharHelper->copyDir($themeDir, $targetDir);
$this->io->success($this->translator->trans('message.dump.success', array('%theme%' => $theme)));
/*
if ($outDir != getenv('HOME').'/.dossier/tpl') {
$output->writeln('<fg=cyan> '.$this->translator->trans('message.export.template_dir').'</>');
$output->writeln('<fg=blue> '.$this->translator->trans('message.export.code.template_environment', array('%path%' => $outDir)).'</>');
} else {
$output->writeln('<fg=cyan> '.$this->translator->trans('message.export.template_homedir').'</>');
}*/
$this->io->newLine();
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Command\Theme;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Magdev\Dossier\Command\Base\BaseCommand;
/**
* Create a local copy of a template
*
* @author magdev
*/
final class ThemeListCommand extends BaseCommand
{
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this->setName('theme:list')
->setDescription('List available themes')
->addOption('all', 'a', InputOption::VALUE_NONE, 'List all themes, icluding the overridden ones');
parent::configure();
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$all = (bool) $input->getOption('all');
$helper = $this->getHelper('export');
/* @var $helper \Magdev\Dossier\Helper\ExportHelper */
$themes = $this->config->findThemes($all);
}
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Config;
use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Yaml\Yaml;
/**
* Configuration loader
*
* @author magdev
*/
class ConfigLoader extends FileLoader
{
private $config = array();
private $global = array();
/**
* {@inheritDoc}
* @see \Symfony\Component\Config\Loader\LoaderInterface::load()
*/
public function load($resource, $type = null)
{
$content = file_get_contents($resource);
if ($content) {
$config = Yaml::parse($content);
if (is_array($config)) {
$this->config = array_replace_recursive($this->config, $config);
if (strstr($resource, PROJECT_ROOT, true) === false) {
$this->global = array_replace_recursive($this->global, $config);
}
}
}
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Config\Loader\LoaderInterface::supports()
*/
public function supports($resource, $type = null)
{
return is_string($resource) && 'yaml' === pathinfo($resource, PATHINFO_EXTENSION);
}
/**
* Get the config as PHP array sourcecode
*
* @return string
*/
public function __toString(): string
{
return 'array(
"config" => '.var_export($this->config, true).',
"global" => '.var_export($this->global, true).'
)';
}
}

View File

@@ -0,0 +1,185 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form\Base;
use Magdev\Dossier\Service\ConfigService;
use Magdev\Dossier\Service\TranslatorService;
use Magdev\Dossier\Form\Extension\Form;
use Magdev\Dossier\Form\PersonFormBuilder;
use Magdev\Dossier\Form\Field\TextField;
use Droath\ConsoleForm\FieldGroup;
abstract class BaseFormBuilder implements FormBuilderInterface
{
protected $flatGroupFields = array();
/**
* Configuration service
* @var \Magdev\Dossier\Service\ConfigService
*/
protected $config = null;
/**
* Translation service
* @var \Magdev\Dossier\Service\TranslatorService
*/
protected $translator = null;
/**
* Get the configuration service
*
* @return \Magdev\Dossier\Service\ConfigService
*/
public function getConfig(): ConfigService
{
return $this->config;
}
/**
* Set the configuration service
*
* @param \Magdev\Dossier\Service\ConfigService $config
* @return \Magdev\Dossier\Form\Base\FormBuilderInterface
*/
public function setConfig(ConfigService $config): FormBuilderInterface
{
$this->config = $config;
return $this;
}
/**
* Get the translator service
*
* @return \Magdev\Dossier\Service\TranslatorService
*/
public function getTranslator(): TranslatorService
{
return $this->translator;
}
/**
* Set the translator service
*
* @param \Magdev\Dossier\Service\TranslatorService $translator
* @return \Magdev\Dossier\Form\Base\FormBuilderInterface
*/
public function setTranslator(TranslatorService $translator): FormBuilderInterface
{
$this->translator = $translator;
return $this;
}
/**
* Get the flatten callback
*
* @return callable
*/
protected function getFlattenCallback(): callable
{
$flatGroupFields = $this->flatGroupFields;
return function(array $results, Form $form) use ($flatGroupFields){
foreach ($flatGroupFields as $field) {
if (isset($results[$field]) && is_array($results[$field])) {
array_walk($results[$field], function(&$value, $key) {
if (is_array($value)) {
$value = (string) array_shift($value);
}
});
}
}
return $results;
};
}
/**
* Get the unflatten callback
*
* @return callable
*/
protected function getUnflattenCallback(): callable
{
$flatGroupFields = $this->flatGroupFields;
return function(array $results, Form $form) use ($flatGroupFields){
foreach ($flatGroupFields as $field) {
if (isset($results[$field]) && is_array($results[$field])) {
array_walk($results[$field], function(&$value, $key) {
if (!is_array($value)) {
$value = array($value);
}
});
}
}
return $results;
};
}
/**
* Add a flat group array for single line array
*
* @param \Magdev\Dossier\Form\Extension\Form $form
* @param string $key
* @param bool $required
* @param string $langPrefix
* @return \Magdev\Dossier\Form\Base\PersonFormBuilder
*/
protected function addFlatGroupField(Form $form, string $key, bool $required = true, string $langPrefix = ''): FormBuilderInterface
{
$name = substr($key, 0, -1);
$label = 'form.';
if ($langPrefix) {
$label .= $langPrefix.'.';
}
$label .= $key;
$this->flatGroupFields[] = $key;
$form->addField((new FieldGroup($key))
->addFields(array(
(new TextField($name, $this->translator->trans($label), false)),
))->setLoopUntil(function($result) use ($name) {
if (!isset($result[$name]) || empty($result[$name])) {
return false;
}
return true;
}));
return $this;
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form\Base;
/**
* Interface for elements with decorable label
*
* @author magdev
*/
interface DecoratableLabelInterface
{
/**
* Set a label prefix
*
* @param string $prefix
* @return \Magdev\Dossier\Form\Base\DecoratableLabelInterface
*/
public function setLabelPrefix(string $prefix): DecoratableLabelInterface;
/**
* Set the fixed length of the label
*
* @param int $length
* @return \Magdev\Dossier\Form\Base\DecoratableLabelInterface
*/
public function setLabelLength(int $length): DecoratableLabelInterface;
/**
* Get the label prefix
*
* @return string
*/
public function getLabelPrefix(): string;
/**
* Get the label length
*
* @return int
*/
public function getLabelLength(): int;
/**
* Get the decorated label
*
* @param string $label
* @return string
*/
public function decorateLabel(string $label): string;
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form\Base;
use Magdev\Dossier\Service\ConfigService;
use Magdev\Dossier\Service\TranslatorService;
use Droath\ConsoleForm\FormInterface;
interface FormBuilderInterface extends FormInterface
{
/**
* Get the configuration service
*
* @return \Magdev\Dossier\Service\ConfigService
*/
public function getConfig(): ConfigService;
/**
* Set the configuration service
*
* @param \Magdev\Dossier\Service\ConfigService $config
* @return \Magdev\Dossier\Form\Base\FormBuilderInterface
*/
public function setConfig(ConfigService $config): FormBuilderInterface;
/**
* Get the translator service
*
* @return \Magdev\Dossier\Service\TranslatorService
*/
public function getTranslator(): TranslatorService;
/**
* Set the translator service
*
* @param \Magdev\Dossier\Service\TranslatorService $translator
* @return \Magdev\Dossier\Form\Base\FormBuilderInterface
*/
public function setTranslator(TranslatorService $translator): FormBuilderInterface;
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form;
use Magdev\Dossier\Form\Extension\Form;
use Magdev\Dossier\Form\Base\BaseFormBuilder;
use Magdev\Dossier\Form\Base\FormBuilderInterface;
use Magdev\Dossier\Form\Field\TextField;
use Magdev\Dossier\Form\Field\SelectField;
use Magdev\Dossier\Form\Field\BooleanField;
class EmailFormBuilder extends BaseFormBuilder implements FormBuilderInterface
{
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::getName()
*/
public function getName()
{
return 'form.email';
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::buildForm()
*/
public function buildForm()
{
$form = new Form();
$form->setLabelPrefix($this->config->get('form.label.prefix'))
->setLabelLength($this->config->get('form.label.length'));
$form->addField(new TextField('company', $this->translator->trans('form.email.company')));
$form->addField((new SelectField('salutation', $this->translator->trans('form.email.salutation')))
->setOptions(array(
$this->translator->trans('form.email.salutation.female'),
$this->translator->trans('form.email.salutation.male'),
))
->setRequired(true));
$form->addField(new TextField('firstname', $this->translator->trans('form.email.firstname')));
$form->addField(new TextField('lastname', $this->translator->trans('form.email.lastname')));
$form->addField(new TextField('email', $this->translator->trans('form.email.email')));
$form->addField(new TextField('offer_title', $this->translator->trans('form.email.offer_title')));
$form->addField(new TextField('offer_link', $this->translator->trans('form.email.offer_link'), false));
$form->addField((new BooleanField('add_subject', $this->translator->trans('form.email.add_subject')))
->setSubform(function($subform, $value) {
if ($value === true) {
$form->addField(new TextField('subject', $this->translator->trans('form.email.subject')));
}
}));
return $form;
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form;
use Magdev\Dossier\Form\Extension\Form;
use Magdev\Dossier\Form\Field\SelectField;
use Magdev\Dossier\Form\Field\TextField;
use Magdev\Dossier\Form\Field\BooleanField;
/**
* EntryFormBuilder
*
* @author magdev
*/
class EntryFormBuilder extends Base\BaseFormBuilder implements Base\FormBuilderInterface
{
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::getName()
*/
public function getName()
{
return 'form.cv';
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::buildForm()
*/
public function buildForm()
{
$form = new Form();
$form->setLabelPrefix($this->config->get('form.label.prefix'))
->setLabelLength($this->config->get('form.label.length'))
->addFormLoadCallback($this->getUnflattenCallback())
->addFormResultsCallback($this->getFlattenCallback());
$form->addField(new TextField('start_date', $this->translator->trans('form.cv.start_date')));
$form->addField(new TextField('end_date', $this->translator->trans('form.cv.end_date')));
$form->addField(new TextField('position', $this->translator->trans('form.cv.position')));
$form->addField(new TextField('company', $this->translator->trans('form.cv.company')));
$form->addField((new SelectField('tag', $this->translator->trans('form.cv.tag')))
->setOptions($this->config->get('cv.tags'))
->setDefault($this->config->get('cv.default_tag'))
->setRequired(true));
$form->addField(new TextField('industry', $this->translator->trans('form.cv.industry')));
$form->addField(new TextField('qualification', $this->translator->trans('form.cv.qualification'), false));
$this->addFlatGroupField($form, 'skills', false, 'cv')
->addFlatGroupField($form, 'achievements', false, 'cv')
->addFlatGroupField($form, 'toolbox', false, 'cv');
$form->addField(new TextField('text', $this->translator->trans('form.cv.text'), false));
$form->addField(new BooleanField('use_in_resume', $this->translator->trans('form.cv.use_in_resume')));
return $form;
}
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form\Extension;
use Droath\ConsoleForm\Field\Field as BaseField;
use Magdev\Dossier\Form\Field\SelectField;
use Magdev\Dossier\Form\Base\DecoratableLabelInterface;
use Magdev\Dossier\Form\Traits\DecoratableLabelTrait;
/**
* Field extension to use multiselect option on SelectField
*
* @author magdev
*/
class Field extends BaseField implements DecoratableLabelInterface
{
use DecoratableLabelTrait;
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Field\Field::setCondition()
*/
public function setCondition($field_name, $value, $operation = '=')
{
if (is_callable($value)) {
$this->condition[$field_name] = $value;
return $this;
}
$this->condition[$field_name] = [
'value' => $value,
'operation' => $operation
];
return $this;
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Field\Field::asQuestion()
*/
public function asQuestion()
{
$instance = $this->questionClassInstance()
->setMaxAttempts($this->maxAttempt);
if ($this->hidden) {
$instance->setHidden(true);
}
if ($this instanceof SelectField) {
$instance->setMultiselect($this->isMultiSelect());
}
if ($this->isRequire()) {
$this->setValidation(function ($answer) {
if ($answer == '' && $this->dataType() !== 'boolean') {
throw new \Exception('Field is required.');
}
});
}
$instance->setValidator(function ($answer) {
foreach ($this->validation as $callback) {
if (!is_callable($callback)) {
continue;
}
$callback($answer);
}
return $answer;
});
if (isset($this->normalizer) && is_callable($this->normalizer)) {
$instance->setNormalizer($this->normalizer);
}
return $instance;
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Field\Field::formattedLabel()
*/
protected function formattedLabel()
{
$label[] = '<fg=cyan;options=bold>'.$this->decorateLabel($this->label, (string) $this->default, '[*]').'</> ';
$label[] = isset($this->default) ? "<fg=yellow;options=bold>[$this->default]</> " : '';
$label[] = $this->isRequire() ? '<fg=red;options=bold>[*]</>: ' : ': ';
return implode('', $label);
}
}

339
src/Form/Extension/Form.php Normal file
View File

@@ -0,0 +1,339 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form\Extension;
use Droath\ConsoleForm\Form as BaseForm;
use Droath\ConsoleForm\Field\Field;
use Droath\ConsoleForm\Exception\FormException;
use Droath\ConsoleForm\FieldDefinitionInterface;
use Droath\ConsoleForm\Field\FieldInterface;
use Magdev\Dossier\Form\Base\DecoratableLabelInterface;
use Magdev\Dossier\Form\Traits\DecoratableLabelTrait;
/**
* Base Form class
*
* @author magdev
*/
class Form extends BaseForm implements DecoratableLabelInterface
{
use DecoratableLabelTrait;
/**
* Callback to post-process form results
* @var array
*/
protected $formResultsCallbacks = array();
/**
* Callback to pre-process data on load
* @var array
*/
protected $formLoadCallbacks = array();
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Form::addField()
*/
public function addField(FieldDefinitionInterface $field)
{
if ($field instanceof DecoratableLabelInterface) {
$field->setLabelLength($this->getLabelLength())
->setLabelPrefix($this->getLabelPrefix());
}
$this->fields[] = $field;
return $this;
}
/**
* Get a field by name
*
* @param string $name
* @throws \Droath\ConsoleForm\Exception\FormException
* @return \Droath\ConsoleForm\FieldDefinitionInterface
*/
public function getField(string $name): FieldDefinitionInterface
{
foreach ($this->fields as $field) {
if ($field->getName() == $name) {
return $field;
}
}
throw new FormException('Field '.$field.' not found');
}
/**
* Check if a field exists
*
* @param string $name
* @return bool
*/
public function hasField(string $name): bool
{
try {
$this->getField($name);
return true;
} catch (FormException $e) {
return false;
}
}
/**
* Set default values
*
* @param array $defaults
* @return \Magdev\Dossier\Form\Extension\Form
*/
public function setDefaults(array $defaults): Form
{
if ($this->hasFormLoadCallbacks()) {
$defaults = $this->onFormLoad($defaults);
}
foreach ($defaults as $field => $value) {
if ($this->hasField($field)) {
$field = $this->getField($field)->setDefault($value);
}
}
return $this;
}
/**
* Check if the is already processed
*
* @return bool
*/
public function isProcessed(): bool
{
return sizeof($this->results) > 0 ? true : false;
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Form::process()
*/
public function process()
{
if (!$this->isProcessed()) {
$this->results = $this->processFields($this->fields, $this->results);
if ($this->hasFormResultsCallbacks()) {
$this->results = $this->onFormResults($this->results);
}
}
return $this;
}
/**
* Ceck if a data value is set
*
* @param string $name
* @throws \Droath\ConsoleForm\Exception\FormException
* @return bool
*/
public function hasData(string $name): bool
{
if (!$this->isProcessed()) {
throw new FormException('Please process the form first');
}
return isset($this->results[$name]) && !empty($this->results[$name]) ? true : false;
}
/**
* Get a value from result and optional delete the field
*
* @param string $name
* @param bool $unset
* @throws \Droath\ConsoleForm\Exception\FormException
* @return string|bool|array
*/
public function getData(string $name = null, bool $unset = false, $default = null)
{
if (!$this->isProcessed()) {
throw new FormException('Please process the form first');
}
if (is_null($name)) {
return $this->results;
}
$value = $default;
if ($this->hasData($name)) {
$value = $this->results[$name];
if ($unset) {
unset($this->results[$name]);
}
}
return $value;
}
/**
* Get a value and strip it from results
*
* @param string $key
* @param string|boolean|array|null $default
* @return string|boolean|array
*/
public function stripData(string $key, $default = null)
{
return $this->hasData($key) ? $this->getData($key, true) : $default;
}
/**
* Check if the form has result callbacks
*
* @return bool
*/
public function hasFormResultsCallbacks(): bool
{
return sizeof($this->formResultsCallbacks) > 0;
}
/**
* Add a callback to perform on results after processing
*
* @param callable $function
* @return \Magdev\Dossier\Form\Extension\Form
*/
public function addFormResultsCallback(callable $callback): Form
{
$this->formResultsCallbacks[] = $callback;
return $this;
}
/**
* Form results callback handler
*
* @param array $results
* @return array
*/
public function onFormResults(array $results): array
{
foreach ($this->formResultsCallbacks as $callback) {
$results = call_user_func_array($callback, array($results, $this));
}
return $results;
}
/**
* Check if the form has load callbacks
*
* @return bool
*/
public function hasFormLoadCallbacks(): bool
{
return sizeof($this->formLoadCallbacks) > 0;
}
/**
* Add a callback to perform on results after processing
*
* @param callable $function
* @return \Magdev\Dossier\Form\Extension\Form
*/
public function addFormLoadCallback(callable $callback): Form
{
$this->formLoadCallbacks[] = $callback;
return $this;
}
/**
* Form results callback handler
*
* @param array $results
* @return array
*/
public function onFormLoad(array $results): arry
{
foreach ($this->formLoadCallbacks as $callback) {
$results = call_user_func_array($callback, array($results, $this));
}
return $results;
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Form::fieldConditionMet()
*/
protected function fieldConditionMet(FieldInterface $field, array $results)
{
$conditions = [];
foreach ($field->getCondition() as $field_name => $condition) {
$field_value = $this->getFieldValue($field_name, $results);
if (is_callable($condition)) {
$conditions[] = call_user_func_array($condition, array($field_value, $results, $this));
} else {
if (is_array($field_value) && key_exists($field_name, $field_value)) {
$field_value = $field_value[$field_name];
}
$value = $condition['value'];
$operation = $condition['operation'];
switch ($operation) {
case "!=":
$conditions[] = $field_value != $value;
break;
case '=':
default:
$conditions[] = $field_value == $value;
break;
}
}
}
$conditions = array_unique($conditions);
return sizeof($conditions) === 1 ? reset($conditions) : false;
}
}

View File

@@ -0,0 +1,97 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Droath\ConsoleForm\FormDiscovery as BaseFormDiscovery;
use Droath\ConsoleForm\FormInterface;
use Magdev\Dossier\Form\Base\FormBuilderInterface;
class FormDiscovery extends BaseFormDiscovery
{
/**
* Container
* @var \Symfony\Component\DependencyInjection\ContainerBuilder
*/
protected $container = null;
/**
* Constructor
*
* @param string $depth
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
*/
public function __construct(ContainerBuilder $container, $depth = '< 3')
{
parent::__construct($depth);
$this->container = $container;
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormDiscovery::doDiscovery()
*/
protected function doDiscovery(array $directories, $base_namespace)
{
$forms = [];
$filter = $this->filterByNamespace($base_namespace);
$config = $this->container->get('config');
$translator = $this->container->get('translator');
foreach ($this->searchFiles($directories, $filter) as $file) {
$ext = $file->getExtension();
$classname = $base_namespace . '\\' . $file->getBasename(".$ext");
if (!class_exists($classname)) {
throw new \Exception('Missing class found during form discovery. '.$classname);
}
$instance = new $classname();
/* @var $instance \Magdev\Dossier\Form\Base\FormBuilderInterface */
if (!$instance instanceof FormInterface) {
throw new \Exception(sprintf('Form class (%s) is missing \Droath\ConsoleForm\Form\FormInterface.', $classname));
}
if ($instance instanceof FormBuilderInterface) {
$forms[$instance->getName()] = $instance->setConfig($config)
->setTranslator($translator)
->buildForm();
} else {
$forms[$instance->getName()] = $instance->buildForm();
}
}
return $forms;
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form\Field;
use Droath\ConsoleForm\Field\BooleanField as BaseBooleanField;
use Magdev\Dossier\Form\Base\DecoratableLabelInterface;
use Magdev\Dossier\Form\Traits\DecoratableLabelTrait;
/**
* Override BooleanField
*
* @author magdev
*/
class BooleanField extends BaseBooleanField implements DecoratableLabelInterface
{
use DecoratableLabelTrait;
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Field\BooleanField::formattedValue()
*/
public function formattedValue($value)
{
return $value === true ? true : false;
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Field\BooleanField::formattedLabel()
*/
protected function formattedLabel()
{
// Convert boolean default into a readable format.
$default = $this->default ? 'yes' : 'no';
$l = $this->decorateLabel($this->label);
$label[] = "<fg=cyan;options=bold>'.$l.'</>";
$label[] = isset($default) ? "<fg=yellow>[$default]</>" : '';
return implode(' ', $label);
}
}

View File

@@ -0,0 +1,100 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form\Field;
use Droath\ConsoleForm\Field\SelectField as BaseSelectField;
use Magdev\Dossier\Form\Base\DecoratableLabelInterface;
use Magdev\Dossier\Form\Traits\DecoratableLabelTrait;
/**
* Extension for Field class to allow multiselects
*
* @author magdev
*/
class SelectField extends BaseSelectField implements DecoratableLabelInterface
{
use DecoratableLabelTrait;
/**
* Multiselect status
* @var bool
*/
protected $multiSelect = false;
/**
* Set field to multiselect
*
* @param bool $multiSelect
* @return \Magdev\Dossier\Form\Field\SelectField
*/
public function setMultiSelect(bool $multiSelect = true): SelectField
{
$this->multiSelect = $multiSelect;
return $this;
}
/**
* Checkif field is multiselect
*
* @return bool
*/
public function isMultiSelect(): bool
{
return $this->multiSelect;
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Field\SelectField::dataType()
*/
public function dataType()
{
return $this->isMultiSelect() ? 'array' : 'string';
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\Field\Field::formattedLabel()
*/
protected function formattedLabel()
{
$label[] = '<fg=cyan;options=bold>'.$this->decorateLabel($this->label).'</>';
$label[] = isset($this->default) ? '<fg=yellow;options=bold>['.$this->default.']</>' : '';
$label[] = $this->isRequire() ? '<fg=red;options=bold>[*]</>: ' : ': ';
return implode(' ', $label);
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Magdev\Dossier\Form\Field;
use Droath\ConsoleForm\Field\FieldInterface;
use Droath\ConsoleForm\Exception\FormException;
use Magdev\Dossier\Form\Extension\Field;
/**
* Define the text field as input via vim.
*/
class TextField extends Field implements FieldInterface
{
/**
* {@inheritdoc}
*/
public function dataType()
{
return 'string';
}
/**
* {@inheritdoc}
*/
public function questionClassArgs()
{
return [$this->formattedLabel(), $this->default];
}
/**
* {@inheritdoc}
*/
public function questionClass()
{
return '\Symfony\Component\Console\Question\Question';
}
}

View File

@@ -0,0 +1,80 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form;
use Magdev\Dossier\Form\Extension\Form;
use Magdev\Dossier\Form\Field\SelectField;
use Magdev\Dossier\Form\Field\TextField;
use Magdev\Dossier\Form\Field\BooleanField;
/**
* IntroFormBuilder
*
* @author magdev
*/
class InitFormBuilder extends Base\BaseFormBuilder implements Base\FormBuilderInterface
{
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::getName()
*/
public function getName()
{
return 'form.init';
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::buildForm()
*/
public function buildForm()
{
$form = new Form();
$form->setLabelPrefix($this->config->get('form.label.prefix'))
->setLabelLength($this->config->get('form.label.length'));
$form->addField((new BooleanField('use_userstyles', $this->translator->trans('form.init.use_userstyles')))
->setSubform(function($subform, $value) {
if ($value === true) {
$subform->addFields(array(
(new SelectField('userstyle_type', $this->translator->trans('form.init.userstyle_type')))
->setOptions(array('SCSS', 'LESS'))
->setDefault('SCSS')
->setRequired(true)
));
}
}));
return $form;
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form;
use Magdev\Dossier\Form\Extension\Form;
use Magdev\Dossier\Form\Field\SelectField;
use Magdev\Dossier\Form\Field\TextField;
use Magdev\Dossier\Form\Field\BooleanField;
/**
* IntroFormBuilder
*
* @author magdev
*/
class IntroFormBuilder extends Base\BaseFormBuilder implements Base\FormBuilderInterface
{
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::getName()
*/
public function getName()
{
return 'form.intro';
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::buildForm()
*/
public function buildForm()
{
$form = new Form();
$form->setLabelPrefix($this->config->get('form.label.prefix'))
->setLabelLength($this->config->get('form.label.length'));
$form->addField(new TextField('text', $this->translator->trans('form.intro.text'), false));
$form->addField((new BooleanField('addquotes', $this->translator->trans('form.intro.add_quotes')))
->setSubform(function($subform, $value) {
if ($value === true) {
$subform->addField((new FieldGroup('quotes'))
->addFields(array(
(new TextField('quoteText', $this->translator->trans('form.intro.quote_text'), false)),
(new TextField('quoteAuthor', $this->translator->trans('form.intro.quote_author')))
->setCondition('quoteText', '', '!=')
))->setLoopUntil(function($result) {
if (!isset($result['quoteText']) || empty($result['quoteText'])) {
return false;
}
return true;
}));
$subform->addFeld((new SelectField('show_quotes', $this->translator->trans('form.intro.show_quotes')))
->setOptions(array('top', 'bottom'))
->setDefault('bottom')
->setCondition('quotes', function($value, $results, $f) {
return is_array($value) && sizeof($value) > 0 ? true : false;
}));
}
}));
return $form;
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form;
use Droath\ConsoleForm\FieldGroup;
use Magdev\Dossier\Form\Extension\Form;
use Magdev\Dossier\Form\Field\SelectField;
use Magdev\Dossier\Form\Field\TextField;
use Magdev\Dossier\Form\Field\BooleanField;
/**
* IntroFormBuilder
*
* @author magdev
*/
class PersonFormBuilder extends Base\BaseFormBuilder implements Base\FormBuilderInterface
{
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::getName()
*/
public function getName()
{
return 'form.person';
}
/**
* {@inheritDoc}
* @see \Droath\ConsoleForm\FormInterface::buildForm()
*/
public function buildForm()
{
$form = new Form();
$form->setLabelPrefix($this->config->get('form.label.prefix'))
->setLabelLength($this->config->get('form.label.length'))
->addFormLoadCallback($this->getUnflattenCallback())
->addFormResultsCallback($this->getFlattenCallback());
$form->addField(new TextField('firstame', $this->translator->trans('form.person.firstname')));
$form->addField(new TextField('lastame', $this->translator->trans('form.person.lastname')));
$form->addField(new TextField('tagline', $this->translator->trans('form.person.tagline'), false));
$form->addField(new TextField('nationality', $this->translator->trans('form.person.nationality'), false));
$form->addField(new TextField('birthdate', $this->translator->trans('form.person.birthdate'), false));
$form->addField((new TextField('birthplace', $this->translator->trans('form.person.birthplace'), false))
->setCondition('birthdate', '', '!='));
$form->addField(new TextField('residence', $this->translator->trans('form.person.residence'), false));
$form->addField(new TextField('status', $this->translator->trans('form.person.status'), false));
$form->addField(new TextField('work_license', $this->translator->trans('form.person.work_license'), false));
$form->addField((new BooleanField('addlang', $this->translator->trans('form.person.add_languages')))
->setSubform(function($subform, $value) {
if ($value === true) {
$subform->addField((new FieldGroup('languages'))
->addFields(array(
(new TextField('language', $this->translator->trans('form.person.language'), false)),
(new SelectField('level', $this->translator->trans('form.person.level')))
->setOptions($this->config->get('language.levels'))
->setDefault($this->config->get('language.default_level'))
->setRequired(true)
->setCondition('language', '', '!=')
))->setLoopUntil(function($result) {
if (!isset($result['language']) || empty($result['language'])) {
return false;
}
return true;
}));
}
}));
$this->addFlatGroupField($form, 'skills', false, 'person')
->addFlatGroupField($form, 'projects', false, 'person')
->addFlatGroupField($form, 'links', false, 'person')
->addFlatGroupField($form, 'interests', false, 'person');
$form->addField(new TextField('text', $this->translator->trans('form.person.text'), false));
return $form;
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Form\Traits;
use Magdev\Dossier\Form\Extension\Form;
use Magdev\Dossier\Form\Base\DecoratableLabelInterface;
/**
* Trait for classes with decoratable labels
*
* @author magdev
*/
trait DecoratableLabelTrait
{
/**
* Label prefix
* @var string
*/
protected $labelPrefix = '';
/**
* Label length
* @var int
*/
protected $labelLength = -1;
/**
* Set a label prefix
*
* @param string $prefix
* @return \Magdev\Dossier\Form\Base\DecoratableLabelInterface
*/
public function setLabelPrefix(string $prefix): DecoratableLabelInterface
{
$this->labelPrefix = $prefix;
return $this;
}
/**
* Set a label fixed length
*
* @param int $length
* @return \Magdev\Dossier\Form\Base\DecoratableLabelInterface
*/
public function setLabelLength(int $length): DecoratableLabelInterface
{
$this->labelLength = $length;
return $this;
}
/**
* Get the label prefix
*
* @return string
*/
public function getLabelPrefix(): string
{
return $this->labelPrefix;
}
/**
* Get the label length
*
* @return int
*/
public function getLabelLength(): int
{
return $this->labelLength;
}
/**
* Get the decorated label
*
* @param string $label
* @return string
*/
public function decorateLabel(string $label, string $default = '', string $required = ''): string
{
$labelLength = strlen($label);
$defaultLength = (strlen($default) + 2);
$requiredLength = strlen($required);
if ($requiredLength > 0) {
$requiredLength++;
}
$length = $this->labelLength - ($defaultLength + $requiredLength);
$l = $this->labelPrefix;
if ($this->labelLength > 0) {
$l .= str_pad($label, $length, ' ', STR_PAD_RIGHT);
} else {
$l .= $label;
}
return $l;
}
}

220
src/Helper/ExportHelper.php Normal file
View File

@@ -0,0 +1,220 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Helper;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Yaml\Yaml;
/**
* Export helper class
*
* @author magdev
*/
class ExportHelper extends Helper
{
const JSON = 'json';
const YAML = 'yaml';
const PHP = 'php';
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Helper\HelperInterface::getName()
*/
public function getName()
{
return 'export';
}
/**
* Convert an assoziatve array to a tablerow-style array
*
* @param array $source
* @return array
*/
public function arrayToTableRow(array $source): array
{
return array(array_values($source));
}
/**
* Convert an array of assoziatve arrays to a tablerows-style array
*
* @param array $source
* @return array
*/
public function arrayToTableRows(array $source): array
{
$rows = array();
foreach ($source as $values) {
$rows[] = $this->arrayToTableRow($values);
}
return $rows;
}
/**
* Convert tablerow-style array to an assoziatve array
*
* @param array $source
* @return array
*/
public function tableRowToArray(array $source, array $keys): array
{
return array_combine($keys, array_shift($source));
}
/**
* Convert an array of tablerow-style arrays to an array of assoziatve arrays
*
* @param array $source
* @return array
*/
public function tableRowsToArray(array $source, array $keys): array
{
$array = array();
foreach ($source as $row) {
$array[] = $this->tableRowToArray($row, $keys);
}
return $array;
}
/**
* Check if an array is a tablerow-style array
*
* @param array $array
* @return bool
*/
public function isTableRowStyle(array $source): bool
{
return isset($source[0]) === true;
}
/**
* Export data to a given format
*
* @param array $source
* @param string $type (json|yaml)
* @param string $file
* @throws \Symfony\Component\Console\Exception\RuntimeException
* @return bool
*/
public function export(array $source, string $type, string $file): bool
{
$code = $this->convert($source, $type);
if ($bytes = file_put_contents($file, $code) === false) {
throw new RuntimeException('Error while writing target: '.$file);
}
return true;
}
/**
* Convert data to a given format
*
* @param array $source
* @param string $type
* @throws \Symfony\Component\Console\Exception\RuntimeException
* @return string
*/
public function convert(array $source, string $type): string
{
switch ($type) {
case self::JSON: return $this->toJSON($source);
case self::YAML: return $this->toYAML($source);
case self::PHP: return $this->toPHP($source);
default:
throw new RuntimeException('Invalid export type: '.strtoupper($type));
}
}
/**
* Convert an assoziatve array to JSON
*
* @param array $source
* @param bool $pretty
* @return string
*/
public function toJSON(array $source, bool $pretty = true): string
{
if ($pretty) {
return json_encode($source, JSON_FORCE_OBJECT|JSON_PRETTY_PRINT);
}
return json_encode($source, JSON_FORCE_OBJECT);
}
/**
* Convert an assoziatve array to YAML
*
* @param array $source
* @param int $depth
* @param int $indent
* @return string
*/
public function toYAML(array $source, int $depth = 3, int $indent = 2): string
{
return Yaml::dump($source, $depth, $indent);
}
/**
* Convert values to PHP sourcecode
*
* @param mixed $source
* @param bool $includeReturn
* @param bool $includeTags
* @return string
*/
public function toPHP($source, bool $includeReturn = false, bool $includeTags = false): string
{
$code = '';
if ($includeTags) {
$code .= '<?php'.PHP_EOL;
}
if ($includeReturn) {
$code .= 'return ';
}
$code .= var_export($source, true);
if ($includeReturn || $includeTags) {
$code .= ';'.PHP_EOL;
}
return $code;
}
}

106
src/Helper/OutputHelper.php Normal file
View File

@@ -0,0 +1,106 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Helper;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Magdev\Dossier\Style\DossierStyle;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
class OutputHelper extends Helper
{
/**
* IO style object
* @var \Magdev\Dossier\Style\DossierStyle
*/
private $io = null;
private $appName = '';
private $appVersion = '';
public function __construct(string $appName = '', string $appVersion = '')
{
$this->appName = $appName;
$this->appVersion = $appVersion;
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Helper\HelperInterface::getName()
*/
public function getName()
{
return 'output';
}
/**
* Get the style helper for dossier
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @return \Magdev\Dossier\Style\DossierStyle
*/
public function getIoStyle(InputInterface $input, OutputInterface $output): DossierStyle
{
if (!$this->io) {
$this->addOutputStyles($input, $output);
$this->io = new DossierStyle($input, $output);
$this->io->setAppName($this->appName)
->setAppVersion($this->appVersion);
}
return $this->io;
}
/**
* Add some output styles to the output object
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @return \Magdev\Dossier\Helper\OutputHelper
*/
protected function addOutputStyles(InputInterface $input, OutputInterface $output): OutputHelper
{
$formatter = $output->getFormatter();
$formatter->setStyle('cmd', new OutputFormatterStyle('white', 'blue', array('bold')));
$formatter->setStyle('option', new OutputFormatterStyle('cyan', null, array('bold')));
$formatter->setStyle('lightmagenta', new OutputFormatterStyle('magenta', null, array('bold')));
$formatter->setStyle('lightgreen', new OutputFormatterStyle('green', null, array('bold')));
$formatter->setStyle('lightred', new OutputFormatterStyle('red', null, array('bold')));
$formatter->setStyle('lightyellow', new OutputFormatterStyle('yellow', null, array('bold')));
return $this;
}
}

View File

@@ -0,0 +1,94 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Helper;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Magdev\Dossier\Service\ConfigService;
/**
* Section manager
*
* @author magdev
*/
class SectionManagerHelper extends Helper
{
/**
* Configuration service
* @var \Magdev\Dossier\Service\ConfigService
*/
protected $config = null;
/**
* Constructor
*
* @param \Magdev\Dossier\Service\ConfigService $config
*/
public function __construct(ConfigService $config)
{
$this->config = $config;
}
/**
* {@inheritDoc}
* @see \Symfony\Component\Console\Helper\HelperInterface::getName()
*/
public function getName()
{
return 'section_manager';
}
/**
* Get an array with section visibility settings
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @return array
*/
public function getDisabledSections(InputInterface $input): array
{
return array(
'cover' => (bool) $input->getOption('no-cover') || $this->config->get('disable.cover', false),
'intro' => (bool) $input->getOption('no-intro') || $this->config->get('disable.intro', false),
'resume' => (bool) $input->getOption('no-resume') || $this->config->get('disable.resume', false),
'cv' => (bool) $input->getOption('no-cv') || $this->config->get('disable.cv', false),
'certs' => (bool) $input->getOption('no-certs') || $this->config->get('disable.certs', false),
'quotes' => (bool) $input->getOption('no-quotes') || $this->config->get('disable.quotes', false),
'toc' => (bool) $input->getOption('no-toc') || $this->config->get('disable.toc', false),
'projects' => (bool) $input->getOption('no-projects') || $this->config->get('disable.projects', false),
);
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Base;
/**
* Interface for objects with a postal address
*
* @author magdev
*/
interface AddressInterface
{
/**
* Get address line 1
*
* @return string
*/
public function getAddress1(): string;
/**
* Get address line 2
*
* @return string
*/
public function getAddress2(): string;
/**
* Get the name of the city
*
* @return string
*/
public function getCity(): string;
/**
* Get the postcode
*
* @return string
*/
public function getPostcode(): string;
/**
* Get the country code
*
* @return string
*/
public function getCountry(): string;
/**
* Get the full location string
*
* @return string
*/
public function getLocation(): string;
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Base;
abstract class BaseCollection extends \ArrayObject
{
const SORT_ASC = 'asc';
const SORT_DESC = 'desc';
/**
* Set the sort direction
* @var string
*/
protected $sortDirection = self::SORT_ASC;
/**
* The last sort direction, used for reset
* @var string
*/
protected $storedDirection = null;
/**
* Set the sort direction
*
* @param string $sortDirection
* @param bool $temporary
* @return \Magdev\Dossier\Model\BaseCollection
*/
public function setSortDirection(string $sortDirection, bool $temporary = false): BaseCollection
{
if (!$temporary) {
$this->storedDirection = $this->sortDirection;
}
$this->sortDirection = $sortDirection;
return $this;
}
/**
* Reset a temporary sort direction
*
* @return \Magdev\Dossier\Model\BaseCollection
*/
public function resetSortDirection(): BaseCollection
{
if ($this->storedDirection) {
$this->sortDirection = $this->storedDirection;
$this->storedDirection = null;
}
return $this;
}
}

View File

@@ -0,0 +1,253 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Base;
use Mni\FrontYAML\Document;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Magdev\Dossier\Model\Traits\VarnameConverterTrait;
/**
* Abstract model for Markdown files
*
* @author magdev
*/
abstract class BaseModel
{
use VarnameConverterTrait;
/**
* FrontYAML Document
* @var \Mni\FrontYAML\Document
*/
protected $document = null;
/**
* Additional data
* @var \ArrayObject
*/
protected $additionalData = null;
/**
* Set some properties to ignore while analysing
* @var \ArrayObject
*/
protected $ignoredProperties = null;
/**
* Constructor
*
* @param \Mni\FrontYAML\Document $document
*/
public function __construct(Document $document)
{
$this->document = $document;
$this->additionalData = new \ArrayObject();
$this->ignoredProperties = new \ArrayObject(array(
'ignoreProperties',
'document'
));
$this->load();
}
/**
* Get the document object
*
* @return \Mni\FrontYAML\Document
*/
public function getDocument(): Document
{
return $this->document;
}
/**
* Get the parsed Markdown part of the file
*
* @return string
*/
public function getContent(): string
{
return $this->document->getContent();
}
/**
* Get the YAML content of the file
*
* @return array
*/
public function getYAML(): array
{
$yaml = $this->document->getYAML();
if (is_null($yaml)) {
return array();
}
return $yaml;
}
/**
* Wrapper to access the page content as description
*
* @return string
*/
public function getDescription(): string
{
return $this->getContent();
}
/**
* Get additional data
*
* @return \ArrayObject
*/
public function getAdditionalData(): \ArrayObject
{
return $this->additionalData;
}
/**
* Check if model has additional data
*
* @return bool
*/
public function hasAdditionalData(): bool
{
return $this->additionalData->count() > 0 ? true : false;
}
/**
* Get an array with all data values
*
* @return array
*/
public function toArray(): array
{
return get_object_vars($this);
}
/**
* Add an ignored property
*
* @param string $prop
* @return BaseModel
*/
protected function addIgnoredProperty(string $prop): BaseModel
{
if (!in_array($prop, $this->ignoredProperties->getArrayCopy())) {
$this->ignoredProperties->append($prop);
}
return $this;
}
/**
* Add multiple ignored prperties
*
* @param array $props
* @return BaseModel
*/
protected function addIgnoredProperties(array $props): BaseModel
{
foreach ($props as $prop) {
$this->addIgnoredProperty($prop);
}
return $this;
}
/**
* Add additional data
*
* @param string $key
* @param mixed $value
* @return \Magdev\Dossier\Model\Base\BaseModel
*/
protected function addAdditionalData(string $key, $value): BaseModel
{
$this->additionalData->append(array('key' => $key, 'value' => $value));
return $this;
}
/**
* Set a property
*
* @param string $key
* @param mixed $value
* @return \Magdev\Dossier\Model\Base\BaseModel
*/
protected function setProperty(string $key, $value): BaseModel
{
$prop = $this->convertCase($key);
if (property_exists($this, $prop)) {
$this->{$prop} = $value;
} else if ($this instanceof BaseModel) {
$this->addAdditionalData($prop, $value);
} else {
throw new InvalidArgumentException('Unknow property: '.__CLASS__.'::'.$prop);
}
return $this;
}
/**
* Load YAML data into model properties
*
* @return \Magdev\Dossier\Model\Base\BaseModel
*/
protected function load(): BaseModel
{
$yaml = $this->getYAML();
return $this->loadArray($yaml);
}
/**
* Laod data from array
*
* @param array $data
* @return \Magdev\Dossier\Model\Base\BaseModel
*/
protected function loadArray(array $data): BaseModel
{
foreach ($data as $key => $value) {
$this->setProperty($key, $value);
}
return $this;
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Base;
/**
* Interface for exportable models
*
* @author magdev
*/
interface ModelExportableInterface extends ModelInterface
{
/**
* Get the data as assoziative array
*
* @return array
*/
public function getData(): array;
/**
* Get the text content as string
*
* @return string
*/
public function getText(): string;
/**
* Check if the model has data
*
* @return bool
*/
public function hasData(): bool;
/**
* Check if the model has text content
*
* @return bool
*/
public function hasText(): bool;
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Base;
interface ModelInterface
{
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Base;
/**
* Interface for modle with photo capabilities
*
* @author magdev
*/
interface PhotoInterface
{
/**
* Get the photo
*
* @return \SplFileInfo
*/
public function getPhoto(): \SplFileInfo;
/**
* Check if the model has a photo
*
* @return bool
*/
public function hasPhoto(): bool;
/**
* Get the size of the photo
*
* @return int
*/
public function getPhotoSize(): int;
/**
* Set the photo
*
* @param string $path
* @return \Magdev\Dossier\Model\Base\PhotoInterface
*/
public function setPhoto(string $path): PhotoInterface;
}

View File

@@ -0,0 +1,240 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model;
use Magdev\Dossier\Model\CurriculumVitae\Entry;
use Magdev\Dossier\Service\FormatterService;
use Magdev\Dossier\Model\Base\BaseCollection;
/**
* Collection of CV-Entries
*
* @author magdev
*/
class CurriculumVitae extends BaseCollection
{
/**
* Formatter Service
* @var \Magdev\Dossier\Service\FormatterService
*/
protected $formatter = null;
/**
* Constructor
*
* @param \Magdev\Dossier\Service\FormatterService $formatter
*/
public function __construct(FormatterService $formatter)
{
$this->formatter = $formatter;
}
/**
* Filter entries by tag
*
* @param string $tag
* @return \Magdev\Dossier\Model\CurriculumVitae
*/
public function filterByTag(string $tag): CurriculumVitae
{
$result = new self($this->formatter);
foreach ($this as $entry) {
/* @var $entry \Magdev\Dossier\Model\CurriculumVitae\Entry */
if ($entry->getTag() == $tag) {
$result->append($entry);
}
}
$result->setSortDirection($this->sortDirection)->sort();
return $result;
}
/**
* Filter entries by industry
*
* @param string $industry
* @return \Magdev\Dossier\Model\CurriculumVitae
*/
public function filterByIndustry(string $industry): CurriculumVitae
{
$result = new self($this->formatter);
foreach ($this as $entry) {
/* @var $entry \Magdev\Dossier\Model\CurriculumVitae\Entry */
if ($entry->getIndustry() == $industry) {
$result->append($entry);
}
}
$result->setSortDirection($this->sortDirection)->sort();
return $result;
}
/**
* Filter entries by certificates
*
* @return \Magdev\Dossier\Model\CurriculumVitae
*/
public function filterByCertificates(): CurriculumVitae
{
$result = new self($this->formatter);
foreach ($this as $entry) {
/* @var $entry \Magdev\Dossier\Model\CurriculumVitae\Entry */
if ($entry->hasCertificates()) {
$result->append($entry);
}
}
$result->setSortDirection($this->sortDirection)->sort();
return $result;
}
/**
* Get entries with qualification
*
* @return \Magdev\Dossier\Model\CurriculumVitae
*/
public function getQualifications(): CurriculumVitae
{
$result = new self($this->formatter);
foreach ($this as $entry) {
/* @var $entry \Magdev\Dossier\Model\CurriculumVitae\Entry */
if ($entry->getQualification()) {
$result->append($entry);
}
}
$result->setSortDirection($this->sortDirection)->sort();
return $result;
}
/**
* Filter entries used for resume
*
* @param bool $useInResume
* @return \Magdev\Dossier\Model\CurriculumVitae
*/
public function filterByUseInResume(bool $useInResume = true): CurriculumVitae
{
$result = new self($this->formatter);
foreach ($this as $entry) {
/* @var $entry \Magdev\Dossier\Model\CurriculumVitae\Entry */
if ($entry->useInResume()) {
$result->append($entry);
}
}
$result->setSortDirection($this->sortDirection)->sort();
return $result;
}
/**
* Filter entries by toolbox contents
*
* @return \Magdev\Dossier\Model\CurriculumVitae
*/
public function filterByToolbox(): CurriculumVitae
{
$result = new self($this->formatter);
foreach ($this as $entry) {
/* @var $entry \Magdev\Dossier\Model\CurriculumVitae\Entry */
if ($entry->getToolbox()->count() > 0) {
$result->append($entry);
}
}
$result->setSortDirection($this->sortDirection)->sort();
return $result;
}
/**
* Get the length of experience sorted by industry
*
* @return \ArrayObject
*/
public function getExperienceYears(): \ArrayObject
{
$result = new \ArrayObject();
$entries = $this->filterByTag('experience');
foreach ($entries as $entry) {
/* @var $entry \Magdev\Dossier\Model\CurriculumVitae\Entry */
if ($industry = $entry->getIndustry()) {
if (!array_key_exists($industry, $result)) {
$result[$industry] = 0;
}
$result[$industry] += $entry->getExperienceLength();
}
}
$result->uasort(function(int $a, int $b) {
return $a > $b ? -1 : 1;
});
$formatter = $this->formatter;
array_walk($result, function(int &$seconds, string $key) use ($formatter) {
$seconds = $formatter->formatExperience($seconds);
});
return $result;
}
/**
* Sort by start date
*
* @return \Magdev\Dossier\Model\CurriculumVitae
*/
public function sort(): CurriculumVitae
{
$this->uasort(array($this, 'sortByStartDate'));
return $this;
}
/**
* Sort function to sort by start date
*
* @param \Magdev\Dossier\Model\CurriculumVitae\Entry $a
* @param \Magdev\Dossier\Model\CurriculumVitae\Entry $b
* @return int
*/
protected function sortByStartDate(Entry $a, Entry $b): int
{
$first = $a->getStartDate()->format('U');
$second = $b->getStartDate()->format('U');
if ($first == $second) {
return 0;
}
if ($this->sortDirection == self::SORT_DESC) {
return $first > $second ? -1 : 1;
}
return $first < $second ? -1 : 1;
}
}

View File

@@ -0,0 +1,357 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\CurriculumVitae;
use Magdev\Dossier\Model\AbstractModel;
use Magdev\Dossier\Model\Traits\PhotoTrait;
use Mni\FrontYAML\Document;
use Magdev\Dossier\Model\Base\BaseModel;
use Magdev\Dossier\Analyzer\Base\AnalyzableInterface;
use Magdev\Dossier\Model\Base\PhotoInterface;
/**
* Model for CV entries
*
* @author magdev
*/
final class Entry extends BaseModel implements PhotoInterface, AnalyzableInterface
{
use PhotoTrait;
/**
* Start date
* @var \DateTime
*/
protected $startDate = null;
/**
* End date
* @var \DateTime
*/
protected $endDate = null;
/**
* Tag - either education, experience or other
* @var string
*/
protected $tag = '';
/**
* Employer information
* @var string
*/
protected $company = '';
/**
* Obtained Qualification, i.e. graduations
* @var string
*/
protected $qualification = '';
/**
* Name of the position or role
* @var string
*/
protected $position = '';
/**
* Obtained skills
* @var array
*/
protected $skills = array();
/**
* Achievements - for the sake of glory!
* @var array
*/
protected $achievements = array();
/**
* Industry title
* @var string
*/
protected $industry = '';
/**
* Use this entry in resume
* @var bool
*/
protected $useInResume = false;
/**
* Certificate models
* @var \ArrayObject
*/
protected $certs = null;
/**
* Notes
* @var string
*/
protected $notes = '';
/**
* Toolbox
* @var array
*/
protected $toolbox = array();
/**
* Constrctor
*
* @param \Mni\FrontYAML\Document $document
*/
public function __construct(Document $document)
{
$this->certs = new \ArrayObject();
parent::__construct($document);
}
/**
* Get the start date
*
* @return \DateTime
*/
public function getStartDate(): \DateTime
{
if ($this->startDate) {
$date = new \DateTime($this->startDate);
$date->setTime(0, 0);
return $date;
}
return null;
}
/**
* Get the end date
*
* @return \DateTime
*/
public function getEndDate(): \DateTime
{
if ($this->endDate) {
$date = new \DateTime($this->endDate);
$date->setTime(23, 59, 59);
return $date;
}
$date = new \DateTime();
$date->setTime(23, 59, 59);
return $date;
}
/**
* Get the tag for this entry
*
* @return string
*/
public function getTag(): string
{
return $this->tag;
}
/**
* get the company name
*
* @return string
*/
public function getCompany(): string
{
return $this->company;
}
/**
* Get the qualification obtained
*
* @return string
*/
public function getQualification(): string
{
return $this->qualification;
}
/**
* Get the position/job title
*
* @return string
*/
public function getPosition(): string
{
return $this->position;
}
/**
* Get the achievements
*
* @return array
*/
public function getAchievements(): array
{
return $this->achievements;
}
/**
* Get the obtained skills
*
* @return array
*/
public function getSkills(): array
{
return $this->skills;
}
/**
* Get the industry
*
* @return string
*/
public function getIndustry(): string
{
return $this->industry;
}
/**
* Get notes
*
* @return string
*/
public function getNotes(): string
{
return $this->notes;
}
/**
* Check if this entry should be included in the resume
*
* @return bool
*/
public function useInResume(): bool
{
return $this->useInResume;
}
/**
* Get the attachted certificates
*
* @return \ArrayObject(\Magdev\Dossier\Model\CurriculumVitae\Entry\Certificate[])
*/
public function getCertificates(): \ArrayObject
{
return $this->certs;
}
/**
* Check if entry has certificates
*
* @return bool
*/
public function hasCertificates(): bool
{
return $this->certs->count() > 0;
}
/**
* Get the toolbox
*
* @return \ArrayObject
*/
public function getToolbox(): \ArrayObject
{
return new \ArrayObject($this->toolbox);
}
/**
* Get the length of this entry in seconds
*
* @return int
*/
public function getExperienceLength(): int
{
return $this->getEndDate()->format('U') - $this->getStartDate()->format('U');
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Analyzer\Base\AnalyzableInterface::getAnalyzerData()
*/
public function getAnalyzerData(): array
{
$props = get_object_vars($this);
foreach ($this->ignoredProperties as $prop) {
unset($props[$prop]);
}
$props['text'] = $this->getContent();
return $props;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\BaseModel::loadArray()
*/
protected function loadArray(array $data): BaseModel
{
foreach ($data as $key => $value) {
if ($key == 'certs') {
foreach ($value as $cert) {
$c = new Entry\Certificate(PROJECT_ROOT.'/certs/'.$cert['path'], $cert['type']);
$this->certs->append($c);
}
} else if ($key == 'photo') {
$this->setPhoto($value);
} else {
$prop = $this->convertCase($key);
if (property_exists($this, $prop)) {
$this->{$prop} = $value;
} else {
$this->addAdditionalData($prop, $value);
}
}
}
return $this;
}
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\CurriculumVitae\Entry;
/**
* Certificate Model
*
* @author magdev
*/
class Certificate
{
/**
* Store the file object
*
* @var \SplFileObject
*/
protected $file = null;
/**
* Store the type of this certificate
*
* @var string
*/
protected $type = '';
/**
* Constructor
*
* @param string $path
* @param string $type
*/
public function __construct(string $path, string $type = '')
{
$this->file = new \SplFileObject($path);
$this->setType($type);
}
/**
* Get the file object
*
* @return \SplFileObject
*/
public function getFileObject(): \SplFileObject
{
return $this->file;
}
/**
* Set the type og the certificate
*
* @param string $type
* @return \Magdev\Dossier\Model\CurriculumVitae\Entry\Certificate
*/
public function setType(string $type): Certificate
{
$this->type = $type;
return $this;
}
/**
* Get the type of the certificate
*
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* Get the file contents as Data-URI
*
* @TODO Refactor to use UriHelperService
* @deprecated Use UriHelperService instead
* @return string
*/
public function getDataUri(): string
{
$fi = new \finfo();
$mimetype = $fi->file($this->file->getRealPath(), FILEINFO_MIME);
return 'data:'.$mimetype.'; base64,'.base64_encode(file_get_contents($this->file->getRealPath()));
}
}

154
src/Model/Intro.php Normal file
View File

@@ -0,0 +1,154 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model;
use Mni\FrontYAML\Document;
use Magdev\Dossier\Model\Base\BaseModel;
use Magdev\Dossier\Model\Base\ModelExportableInterface;
use Magdev\Dossier\Model\Base\PhotoInterface;
use Magdev\Dossier\Model\Traits\PhotoTrait;
use Magdev\Dossier\Analyzer\Base\AnalyzableInterface;
/**
* Model for introduction page
*
* @author magdev
*/
class Intro extends BaseModel implements PhotoInterface, AnalyzableInterface
{
const SHOW_TOP = 'top';
const SHOW_BOTTOM = 'bottom';
use PhotoTrait;
/**
* Quotes
* @var \ArrayObject
*/
protected $quotes = null;
/**
* Headline for intro page
* @var string
*/
protected $headline = '';
/**
* Place to show the quotes
*
* @var string
*/
protected $showQuotes = self::SHOW_TOP;
/**
* Get the headline
*
* @return string
*/
public function getHeadline(): string
{
return $this->headline;
}
/**
* Constructor
*
* @param Document $document
*/
public function __construct(Document $document)
{
$this->quotes = new \ArrayObject();
parent::__construct($document);
}
/**
* Get the quotes
*
* @return \ArrayObject
*/
public function getQuotes(): \ArrayObject
{
return $this->quotes;
}
/**
* Get the place where to show the quotes
*
* @return string
*/
public function getShowQuotes(): string
{
return $this->showQuotes;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\BaseModel::loadArray()
*/
protected function loadArray(array $data): BaseModel
{
foreach ($data as $key => $value) {
if ($key == 'quotes') {
foreach ($value as $quote) {
$q = new Intro\Quote($quote);
$this->quotes->append($q);
}
} else if ($key == 'photo') {
$this->setPhoto($value);
} else {
$this->setProperty($key, $value);
}
}
return $this;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Analyzer\Base\AnalyzableInterface::getAnalyzerData()
*/
public function getAnalyzerData(): array
{
$props = get_object_vars($this);
foreach ($this->ignoredProperties as $prop) {
unset($props[$prop]);
}
$props['text'] = $this->getContent();
return $props;
}
}

91
src/Model/Intro/Quote.php Normal file
View File

@@ -0,0 +1,91 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Intro;
use Magdev\Dossier\Model\AbstractModel;
/**
* Quote Model
*
* @author magdev
*/
final class Quote
{
/**
* Quote text
* @var string
*/
protected $quoteText = '';
/**
* Author of the quote
* @var string
*/
protected $quoteAuthor = '';
/**
* Constructor
*
* @param array $quote
*/
public function __construct(array $quote)
{
$this->quoteText = $quote['text'];
if (isset($quote['author'])) {
$this->quoteAuthor = $quote['author'];
}
}
/**
* Get the quote text
*
* @return string
*/
public function getQuoteText(): string
{
return $this->quoteText;
}
/**
* Get the author of the quote
*
* @return string
*/
public function getQuoteAuthor(): string
{
return $this->quoteAuthor;
}
}

422
src/Model/Person.php Normal file
View File

@@ -0,0 +1,422 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model;
use Magdev\Dossier\Model\Traits\PhotoTrait;
use Magdev\Dossier\Model\Base\BaseModel;
use Mni\FrontYAML\Document;
use Magdev\Dossier\Model\Person\Contact;
use Magdev\Dossier\Analyzer\Base\AnalyzableInterface;
use Magdev\Dossier\Model\Base\PhotoInterface;
use Magdev\Dossier\Model\Person\Reference;
/**
* Model for the person object
*
* @author magdev
*/
final class Person extends BaseModel implements PhotoInterface, AnalyzableInterface
{
use PhotoTrait;
/**
* First name
* @var string
*/
protected $firstname = '';
/**
* Last name
* @var string
*/
protected $lastname = '';
/**
* Birthdate
* @var string
*/
protected $birthdate = '';
/**
* Birthplace
* @var string
*/
protected $birthplace = '';
/**
* Tagline
* @var string
*/
protected $tagline = '';
/**
* Current residence
* @var string
*/
protected $residence = '';
/**
* Status
* @var string
*/
protected $status = '';
/**
* Nationality
* @var string
*/
protected $nationality = '';
/**
* Work license
* @var string
*/
protected $workLicense = '';
/**
* Languages
* @var array
*/
protected $languages = array();
/**
* Personal Links
* @var array
*/
protected $links = array();
/**
* Contact
* @var \ArrayObject
*/
protected $contacts = null;
/**
* References
* @var \ArrayObject
*/
protected $references = null;
/**
* Personal Interests
* @var array
*/
protected $interests = array();
/**
* Current Projects
* @var array
*/
protected $projects = array();
/**
* Constructor
*
* @param Mni\FrontYAML\Document $document
*/
public function __construct(Document $document)
{
$this->contacts = new \ArrayObject();
$this->references = new \ArrayObject();
parent::__construct($document);
}
/**
* Get the first name
*
* @return string
*/
public function getFirstname(): string
{
return $this->firstname;
}
/**
* Get the last name
*
* @return string
*/
public function getLastname(): string
{
return $this->lastname;
}
/**
* Get the full name
*
* @param bool $reversed
* @return string
*/
public function getName(bool $reversed = false): string
{
if ($reversed) {
return $this->lastname.', '.$this->firstname;
}
return $this->firstname.' '.$this->lastname;
}
/**
* Get the persons tagline
*
* @return string
*/
public function getTagline(): string
{
return $this->tagline;
}
/**
* Get the persons current residence
*
* @return string
*/
public function getResidence(): string
{
return $this->residence;
}
/**
* Get the birthday date
*
* @return \DateTime
*/
public function getBirthdate(): \DateTime
{
if ($this->birthdate) {
return new \DateTime($this->birthdate);
}
return null;
}
/**
* Get the birthplace
*
* @return string
*/
public function getBirthplace(): string
{
return $this->birthplace;
}
/**
* Get the family status
*
* @return string
*/
public function getStatus(): string
{
return $this->status;
}
/**
* Get the nationality
*
* @return string
*/
public function getNationality(): string
{
return $this->nationality;
}
/**
* Get languages
*
* @return array
*/
public function getLanguages(): array
{
return $this->languages;
}
/**
* Get personal links
*
* @return array
*/
public function getLinks(): array
{
return $this->links;
}
/**
* Get contact info
*
* @return \ArrayObject
*/
public function getContacts(): \ArrayObject
{
return $this->contacts;
}
/**
* Get references
*
* @return \ArrayObject
*/
public function getReferences(): \ArrayObject
{
return $this->references;
}
/**
* Get personal interests
*
* @return array
*/
public function getInterests(): array
{
return $this->interests;
}
/**
* Get current projects
*
* @return array
*/
public function getProjects(): array
{
return $this->projects;
}
/**
* Get the work license
*
* @return string
*/
public function getWorkLicense(): string
{
return $this->workLicense;
}
/**
* Get the email address
*
* @return string
*/
public function getEmail(): string
{
return $this->getContactType('email')->getAddress();
}
/**
* Get the phone number
*
* @return string
*/
public function getPhone(): string
{
return $this->getContactType('phone')->getAddress();
}
/**
* Get a contact with a specific type
*
* @param string $type
* @return \Magdev\Dossier\ModelContact
*/
public function getContactType(string $type): Contact
{
foreach ($this->getContacts() as $contact) {
/* @var $contact \Magdev\Dossier\Model\Person\Contact */
if ($contact->getType() == $type) {
return $contact->getAddress();
}
}
return '';
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\BaseModel::loadArray()
*/
protected function loadArray(array $data): BaseModel
{
foreach ($data as $key => $value) {
if ($key == 'photo') {
$this->setPhoto($value);
} else if ($key == 'contact') {
foreach ($value as $type => $address) {
if ($type == 'accounts' && is_array($address)) {
foreach ($address as $a) {
$this->contacts->append(new Contact($a['address'], $a['type']));
}
} else {
$this->contacts->append(new Contact($address, $type));
}
}
} else if ($key == 'references') {
foreach ($value as $reference) {
$this->references->append(new Reference($reference));
}
} else {
$this->setProperty($key, $value);
}
}
return $this;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Analyzer\Base\AnalyzableInterface::getAnalyzerData()
*/
public function getAnalyzerData(): array
{
$props = get_object_vars($this);
foreach ($this->ignoredProperties as $prop) {
unset($props[$prop]);
}
$props['text'] = $this->getContent();
return $props;
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Person;
/**
* Contact model
*
* @author magdev
*/
class Contact
{
/**
* Contact address
* @var string
*/
protected $address = '';
/**
* Contact type
* @var string
*/
protected $type = '';
/**
* Constructor
*
* @param string $address
* @param string $type
*/
public function __construct(string $address, string $type)
{
$this->address = $address;
$this->type = $type;
}
/**
* Get the contact type
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* Get the contact address
* @return string
*/
public function getAddress(): string
{
return $this->address;
}
}

View File

@@ -0,0 +1,192 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Person;
use Magdev\Dossier\Model\Base\BaseModel;
/**
* Model for job references
*
* @author magdev
*/
class Reference extends BaseModel
{
/**
* Reference description
* @var string
*/
protected $decription = '';
/**
* Name of a possible contact person
* @var string
*/
protected $contactName = '';
/**
* Email address of a possible contact person
* @var string
*/
protected $contactEmail = '';
/**
* Phone number of a possible contact person
* @var string
*/
protected $contactPhone = '';
/**
* Refrence is published and can be viewed online
* @var bool
*/
protected $public = false;
/**
* Link to a published reference
* @var string
*/
protected $publicLink = '';
/**
* Example work as file
* @var \SplFileObject
*/
protected $file = null;
/**
* Link to an example work
* @var string
*/
protected $fileLink = null;
/**
* Constructor
*
* @param array $data
*/
public function __construct(array $data)
{
$this->loadArray($data);
}
/**
* Get the description of the reference
*
* @return string
*/
public function getDecription(): string
{
return $this->decription;
}
/**
* Get the name of a possible contact person
*
* @return string
*/
public function getContactName(): string
{
return $this->contactName;
}
/**
* Get the email address of a possible contact person
*
* @return string
*/
public function getContactEmail(): string
{
return $this->contactEmail;
}
/**
* Get the phone number of a possible contact person
*
* @return string
*/
public function getContactPhone(): string
{
return $this->contactPhone;
}
/**
* Check if the reference is published and can be viewed online
*
* @return boolean
*/
public function isPublic(): bool
{
return $this->public;
}
/**
* Lik to a published example work
*
* @return unknown
*/
public function getPublicLink(): string
{
return $this->publicLink;
}
/**
* Example work file
*
* @return \SplFileObject
*/
public function getFile(): \SplFileObject
{
return $this->file;
}
/**
* Get the link to a file with example work
*
* @return string
*/
public function getFileLink(): string
{
return $this->fileLink;
}
}

91
src/Model/Project.php Normal file
View File

@@ -0,0 +1,91 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model;
use Magdev\Dossier\Model\Base\BaseModel;
class Project extends BaseModel
{
protected $name = '';
protected $status = '';
protected $url = '';
protected $shortDescription = '';
protected $stack = '';
protected $role = '';
public function getRole(): string
{
return $this->role;
}
public function getStack(): string
{
return $this->stack;
}
public function getName(): string
{
return $this->name;
}
public function getStatus(): string
{
return $this->status;
}
public function getUrl(): string
{
return $this->url;
}
public function getShortDescription(): string
{
return $this->shortDescription;
}
}

View File

@@ -0,0 +1,149 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Traits;
trait AddressTrait
{
/**
* Address line 1
* @var string
*/
protected $address1 = '';
/**
* Address line 2
* @var string
*/
protected $address2 = '';
/**
* Name of the city
* @var string
*/
protected $city = '';
/**
* Postcode
* @var string
*/
protected $postcode = '';
/**
* Conutry code
* @var string
*/
protected $country = '';
/**
* Constructor
*
* @param array $data
*/
public function __construct(array $data)
{
foreach ($data as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\AddressInterface::getAddress1()
*/
public function getAddress1(): string
{
return $this->address1;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\AddressInterface::getAddress2()
*/
public function getAddress2(): string
{
return $this->address2;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\AddressInterface::getCity()
*/
public function getCity(): string
{
return $this->city;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\AddressInterface::getPostcode()
*/
public function getPostcode(): string
{
return $this->postcode;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\AddressInterface::getCountry()
*/
public function getCountry(): string
{
return $this->country;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\AddressInterface::getLocation()
*/
public function getLocation(): string
{
$location = '';
if ($this->postcode) {
$location .= $this->postcode.' ';
}
if ($this->city) {
$location .= $this->city;
}
if ($this->country) {
$location .= ' ('.$this->country.')';
}
return $location;
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Traits;
trait MarkdownExportTrait
{
protected $text = '';
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\ModelExportableInterface::getData()
*/
public function getData(): array
{
return get_object_vars($this);
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\ModelExportableInterface::getText()
*/
public function getText(): string
{
return $this->text;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\ModelExportableInterface::hasData()
*/
public function hasData(): bool
{
return sizeof($this->getData()) > 0 ? true : false;
}
/**
* {@inheritDoc}
* @see \Magdev\Dossier\Model\Base\ModelExportableInterface::hasText()
*/
public function hasText(): bool
{
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Traits;
use Magdev\Dossier\Model\AbstractModel;
use Magdev\Dossier\Model\Base\BaseModel;
use Magdev\Dossier\Model\Base\PhotoInterface;
/**
* Trait to add a photo to a model
*
* @author magdev
*/
trait PhotoTrait
{
/**
* Photo object
* @var \SplFileInfo
*/
protected $photo = null;
/**
* Size of the Photo
* @var int
*/
protected $photoSize = -1;
/**
* Get the photo
*
* @return \SplFileInfo
*/
public function getPhoto(): \SplFileInfo
{
return $this->photo;
}
/**
* Check if the model has a photo
*
* @return bool
*/
public function hasPhoto(): bool
{
return $this->photo instanceof \SplFileInfo;
}
/**
* Get the file contents as Data-URI
*
* @TODO Refactor to use UriHelperService
* @deprecated Use UriHelperService instead
* @return string
*/
public function getPhotoDataUri(): string
{
if ($this->hasPhoto()) {
$fi = new \finfo();
$mimetype = $fi->file($this->photo->getRealPath(), FILEINFO_MIME);
return 'data:'.$mimetype.'; base64,'.base64_encode(file_get_contents($this->photo->getRealPath()));
}
return '';
}
/**
* Get the size of the photo
*
* @return int
*/
public function getPhotoSize(): int
{
if ($this->photoSize == -1) {
if ($this->hasPhoto()) {
if ($size = getimagesize($this->photo->getRealPath())) {
$this->photoSize = $size[0];
}
}
}
return $this->photoSize;
}
/**
* Set the photo
*
* @param string $path
* @return \Magdev\Dossier\Model\Base\PhotoInterface
*/
public function setPhoto(string $path): PhotoInterface
{
$this->photo = new \SplFileInfo(PROJECT_ROOT.'/'.$path);
return $this;
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Model\Traits;
trait VarnameConverterTrait
{
/**
* Convert snake_case to camelCase
*
* @param string $string
* @return string
*/
protected function convertCase(string $string): string
{
$res = str_replace('_', '', ucwords($string, '_'));
$res[0] = strtolower($res[0]);
return $res;
}
}

View File

@@ -0,0 +1,147 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Service;
use Magdev\Dossier\Analyzer\Base\AnalyzableInterface;
use Magdev\Dossier\Analyzer\Base\AnalyzerInterface;
use Magdev\Dossier\Analyzer\Base\AnalyzerException;
/**
* Service to analyze models
*
* @author magdev
*/
class AnalyzerService
{
/**
* Configuration service
* @var \Magdev\Dossier\Service\AnalyzerService
*/
protected $config = null;
/**
* Monolog service
* @var \Magdev\Dossier\Service\MonologService
*/
protected $logger = null;
/**
* Analyzer objects
* @var \ArrayObject
*/
protected $analyzers = null;
/**
* Constructor
*
* @param \Magdev\Dossier\Service\ConfigService $config
* @param \Magdev\Dossier\Service\MonologService $logger
*/
public function __construct(ConfigService $config, MonologService $logger)
{
$this->config = $config;
$this->logger = $logger;
$this->analyzers = new \ArrayObject();
}
/**
* Get all analyzers
*
* @return \ArrayObject
*/
public function getAnalyzers(): \ArrayObject
{
return $this->analyzers;
}
/**
* Add an analyzer
*
* @param \Magdev\Dossier\Analyzer\Base\AnalyzerInterface $analyzer
* @return \Magdev\Dossier\Service\AnalyzerService
* @throws \Magdev\Dossier\Analyzer\Base\AnalyzerException
*/
public function addAnalyzer(AnalyzerInterface $analyzer): AnalyzerService
{
if ($this->hasAnalyzer($analyzer->getName())) {
throw new AnalyzerException('Analyzer with name '.$name.' already exists');
}
$this->analyzers->append($analyzer);
$this->logger->debug('Analyzer '.get_class($analyzer).' added with name '.$analyzer->getName());
return $this;
}
/**
* Check if an analyzer name is already taken
*
* @param string $name
* @return bool
*/
public function hasAnalyzer(string $name): bool
{
return $this->getAnalyzers() instanceof AnalyzableInterface;
}
/**
* Get an analyzer by name
*
* @param string $name
* @return \Magdev\Dossier\Analyzer\Base\AnalyzerInterface
*/
public function getAnalyzer(string $name): ?AnalyzerInterface
{
foreach ($this->analyzers as $a) {
if ($a->getName() == $name) {
return $a;
}
}
return null;
}
/**
* Set analyzers
*
* @param \ArrayObject $analyzers
* @return AnalyzerService
*/
public function setAnalyzers(\ArrayObject $analyzers): AnalyzerService
{
$this->analyzers = $analyzers;
return $this;
}
}

View File

@@ -0,0 +1,464 @@
<?php
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 magdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author magdev
* @copyright 2018 Marco Grätsch
* @package magdev/dossier
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Magdev\Dossier\Service;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Finder\Finder;
use Magdev\Dossier\Config\ConfigLoader;
use Magdev\Dossier\Config\Config;
use Magdev\Dossier\Style\DossierStyle;
use Adbar\Dot;
/**
* Cnfiguration service
*
* @author magdev
*/
class ConfigService
{
const FORMAT_FLAT_ARRAY = 1;
const FORMAT_TABLE_ROWS = 2;
const FORMAT_PHP_ARRAY = 3;
const VALUE_SCALAR = 1;
const VALUE_INDEXED_ARRAY = 2;
/**
* The config object
* @var \Adbar\Dot
*/
protected $config = null;
/**
* The global config object
* @var \Adbar\Dot
*/
protected $global = null;
/**
* Constructor
*/
public function __construct()
{
if (file_exists(PROJECT_ROOT.'/.env')) {
$dotenv = new Dotenv();
$dotenv->load(PROJECT_ROOT.'/.env');
}
$this->loadConfig();
mb_internal_encoding(strtoupper($this->config->get('charset')));
}
/**
* Get the differences between current and global config
*
* @return array
*/
public function getDiff(array $current = null, array $global = null): array
{
if (is_null($current)) {
$current = $this->config->all();
}
if (is_null($global)) {
$global = $this->global->all();
}
$diff = array();
foreach ($current as $key => $value) {
if (is_array($value)) {
if (!isset($global[$key]) || !is_array($global[$key])) {
$diff[$key] = $value;
} else {
$newDiff = $this->getDiff($value, $global[$key]);
if (!empty($newDiff)) {
$diff[$key] = $newDiff;
}
}
} else if (!array_key_exists($key, $global) || $global[$key] !== $value) {
$diff[$key] = $value;
}
}
return $diff;
}
/**
* Get the Dot object
*
* @return \Adbar\Dot
*/
public function getConfig(): Dot
{
return $this->config;
}
/**
* Get the global Dot object
*
* @return \Adbar\Dot
*/
public function getGlobalConfig(): Dot
{
return $this->global;
}
/**
* Delegate method calls to Dot
*
* @param string $method
* @param array $args
* @throws \BadFunctionCallException
* @return mixed
*/
public function __call(string $method, array $args)
{
if (!method_exists($this->config, $method)) {
throw new \BadFunctionCallException('Unknown method: '.$method);
}
return call_user_func_array(array($this->config, $method), $args);
}
/**
* Get all configuration values
*
* @param int $format One of FORMAT_* constants
* @return array
*/
public function all(int $format = self::FORMAT_PHP_ARRAY): array
{
switch ($format) {
case self::FORMAT_FLAT_ARRAY:
$data = $this->allFlat();
break;
default:
case self::FORMAT_PHP_ARRAY:
$data = $this->config->all();
break;
}
ksort($data, SORT_NATURAL);
return $data;
}
/**
* Set a configuration value
*
* @param array|int|string $keys
* @param mixed $value
* @param bool $global
* @return \Magdev\Dossier\Service\ConfigService
*/
public function set($keys, $value, bool $global = false): ConfigService
{
$this->config->set($keys, $value);
if ($global) {
$this->global->set($keys, $value);
}
return $this;
}
/**
* Unset a configuration value
*
* @param unknown $keys
* @return \Magdev\Dossier\Service\ConfigService
*/
public function unset($keys): ConfigService
{
if ($this->config->has($keys)) {
$this->config->delete($keys);
}
if ($this->global->has($keys)) {
$this->global->delete($keys);
}
return $this;
}
/**
* Save the global configuration
*
* @return \Magdev\Dossier\Service\ConfigService
*/
public function saveGlobalConfig(): ConfigService
{
$yaml = '';
$config = $this->global->all();
if (!empty($config)) {
$yaml = Yaml::dump($config, 4, 3);
}
return $this->saveYaml(getenv('HOME').'/.dossier', $yaml);
}
/**
* Save the local configuration
*
* @return \Magdev\Dossier\Service\ConfigService
*/
public function saveProjectConfig(): ConfigService
{
$yaml = '';
$config = $this->getDiff();
if (!empty($config)) {
$yaml = Yaml::dump($config, 4, 3);
}
return $this->saveYaml(PROJECT_ROOT.'/.conf', $yaml);
}
/**
* Check if a value is stored in global configuration
*
* @param string $path
* @param mixed $value
* @return bool
*/
public function isGlobalConfig(string $path, $value): bool
{
if ($this->global->has($path) && $this->global->get($path) == $value) {
return true;
}
return false;
}
/**
* Save configuration
*
* @return \Magdev\Dossier\Service\ConfigService
*/
public function save(): ConfigService
{
return $this->saveGlobalConfig()
->saveProjectConfig()
->loadConfig();
}
/**
* Get all config values as flat array
*
* @return array
*/
public function allFlat(): array
{
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($this->all()), \RecursiveIteratorIterator::SELF_FIRST);
$path = array();
$flatArray = array();
foreach ($iterator as $key => $value) {
$path[$iterator->getDepth()] = $key;
if (!is_array($value)) {
$flatArray[implode('.', array_slice($path, 0, $iterator->getDepth() + 1))] = $value;
}
}
return $flatArray;
}
/**
* Get all config values as table rows
*
* @param \Magdev\Dossier\Style\DossierStyle $io
* @param int $booleanWidth
* @return array
*/
public function allTable(DossierStyle $io, int $booleanWidth = null): array
{
$all = $this->allFlat();
$rows = array();
foreach ($all as $path => $value) {
$global = $this->isGlobalConfig($path, $value);
switch (gettype($value)) {
case 'string':
if ($value !== trim($value)) {
$value = "'$value'";
}
break;
case 'bool':
case 'boolean':
$value = $value ? 'true' : 'false';
break;
}
$rows[] = array($path, $value, $io->align($io->bool($global), $booleanWidth, DossierStyle::ALIGN_CENTER));
}
return $rows;
}
/**
* Find all themes in available directories
*
* @return array
*/
public function findThemes(bool $all = true): array
{
$folders = array(
PROJECT_ROOT.'/.conf/tpl',
getenv('HOME').'/.dossier/tpl',
DOSSIER_ROOT.'/app/tpl'
);
$finder = new Finder();
$finder->ignoreUnreadableDirs()
->directories()
->sortByName()
->depth('== 0');
foreach ($folders as $folder) {
if (file_exists($folder)) {
$finder->in($folder);
}
}
$themes = array();
foreach ($finder as $file) {
/* @var $file \SplFileInfo */
$path = str_replace(
array(DOSSIER_ROOT, PROJECT_ROOT, getenv('HOME')),
array('${DOSSIER}', '${PROJECT}', '${HOME}'),
$file->getPathInfo()->getRealpath()
);
$themes[$file->getFilename()] = $path;
}
ksort($themes);
if ($all) {
return $themes;
}
$themesSorted = array();
foreach ($themes as $name => $path) {
$index = array_search($path, $folders);
if (!array_key_exists($name, $themesSorted)) {
$themesSorted[$name] = $path;
} else {
$existingIndex = array_search($themesSorted[$name], $folders);
if ($index < $existingIndex) {
$themesSorted[$name] = $path;
}
}
}
return $themesSorted;
}
/**
* Save YAML to config file
*
* @param string $targetDir
* @param string $yaml
* @return \Magdev\Dossier\Service\ConfigService
*/
protected function saveYaml(string $targetDir, string $yaml): ConfigService
{
if (!is_dir($targetDir)) {
mkdir($targetDir, 0755, true);
}
file_put_contents($targetDir.'/dossier.yaml', $yaml);
return $this;
}
/**
* Load the configuration
*
* @return ConfigService
*/
protected function loadConfig(): ConfigService
{
clearstatcache();
$configDirectories = array(DOSSIER_ROOT.'/app/conf', getenv('HOME').'/.dossier', PROJECT_ROOT.'/.conf');
$env = getenv('APP_ENV') ?: 'prod';
$cachePath = DOSSIER_CACHE.'/src/'.strtolower($env).'DossierCachedConfig.php';
$fileLocator = new FileLocator($configDirectories);
$loader = new ConfigLoader($fileLocator);
$cache = new ConfigCache($cachePath, getenv('APP_DEBUG'));
if (!$cache->isFresh()) {
$resources = array();
$configFiles = $fileLocator->locate('dossier.yaml', null, false);
$envConfigFiles = $fileLocator->locate('dossier_'.strtolower($env).'.yaml', null, false);
if (!is_array($envConfigFiles)) {
$envConfigFiles = array($envConfigFiles);
}
$configFiles = array_merge($configFiles, $envConfigFiles);
foreach ($configFiles as $configFile) {
$loader->load($configFile);
$resources[] = new FileResource($configFile);
}
$code = '<?php'.PHP_EOL.'return '.(string) $loader.';'.PHP_EOL;
$cache->write($code, $resources);
}
$config = require $cachePath;
$this->config = new Dot($config['config']);
$this->global = new Dot($config['global']);
return $this;
}
/**
* Check if an array is an index flat array
*
* @param array $array
* @return bool
*/
protected function isIndexedFlatArray(array $array): bool
{
return array_key_exists(0, $array) !== false && is_scalar($array[0]) !== false;
}
}

Some files were not shown because too many files have changed in this diff Show More