Added custom Twig globals, functions. Added Profile icon renderers.

This commit is contained in:
R. Eric Wheeler 2016-07-07 14:50:58 -07:00
parent 85e463c82f
commit f94d82770e
15 changed files with 636 additions and 119 deletions

View File

@ -69,10 +69,23 @@ class App extends Application {
}
/**
* @return \Noodlehaus\Config
* Registers media icons
*
* @param \Sikofitt\Image\Profile\ProfileIconInterface $icon
*/
public function conf2() {
return Noodlehaus\Config::load($this->getConfDirectory());
public function registerIcon(\Sikofitt\Image\Profile\ProfileIconInterface $icon)
{
$this->config(sprintf('app.icons.%s', $icon->getName()), ['icon' => $icon->getIcon(), 'url' => $icon->getDefaultUrl()]);
}
public function boot() {
// register default icons
$this->registerIcon(new \Sikofitt\Image\Profile\TwitterProfileIcon());
$this->registerIcon(new \Sikofitt\Image\Profile\FacebookProfileIcon());
$this->registerIcon(new \Sikofitt\Image\Profile\GithubProfileIcon());
$this->registerIcon(new \Sikofitt\Image\Profile\GitlabProfileIcon());
$this->registerIcon(new \Sikofitt\Image\Profile\LinkedinProfileIcon());
return parent::boot();
}
}

View File

@ -4,64 +4,162 @@
{{ app.config.app.title | default('Resume') }}
{% endblock %}
{% block body %}
{{ dump(basics) }}
<div class="uk-grid" data-uk-grid-margin>
<div class="uk-width-1-1">
<h1 class="uk-heading-large" data-uk-sticky="{top:35}">
<h1 class="uk-heading-large">
{% if basics.name is not empty %}
{{ basics.name }}
{% else %}
{{ app.config.app.title|default('Resume') }}
{% endif %}
{% if basics.label is not empty %}
<small class="uk-h2">{{ basics.label }}</small>
{% endif %}
</h1>
<hr />
{% if basics.summary is not empty %}
<p class="uk-text-large">
{{ basics.summary }}
</p>
<small class="uk-h2 uk-align-right uk-text-bottom">{{ basics.label }}</small>
{% endif %}
</h1>
<hr/>
{% if basics.summary is not empty %}
<p class="uk-text-lead">{{ basics.summary }}</p>
{% endif %}
</div>
</div>
<div class="uk-grid" data-uk-grid-margin>
<div class="uk-width-medium-3-4">
{% set position = work|first %}
{{ dump(position) }}
<p class="resume-positions">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.
Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.
</p>
<h1>Experience</h1>
<div class="uk-panel uk-panel-header">
<div class="resume-positions">
{% for position in work %}
<h3 class="company uk-panel-title uk-animation-slide-left">
{{ position.company }}
<small class="uk-align-right">
{{ position.startDate|date('Y') }} -
{% if position.endDate is not defined %}
Current
{% else %}
{{ position.endDate|date('Y') }}
{% endif %}
(~
{% if position.endDate is not defined %}
{{ position.startDate|date_diff }}
{% else %}
{{ position.startDate|date_diff(position.endDate) }}
{% endif %}
)
</small>
</h3>
<h5>{{ position.position }}</h5>
<p class="summary uk-text-primary uk-text-large">
{{ position.summary|raw }}
</p>
{% if position.highlights is not empty and position.highlights is defined %}
<dl class="uk-description-list-horizontal uk-animation-slide-right">
<dt>Highlights</dt>
{% for highlight in position.highlights %}
<dd class="uk-margin-small-top uk-margin-small-bottom">{{ highlight|raw }}</dd>
{% endfor %}
</dl>
{% endif %}
<hr class="uk-hr-light"/>
{% endfor %}
</div>
</div>
</div>
<div class="uk-width-medium-1-4">
<div class="uk-panel uk-panel-box" data-uk-sticky="{top:35}">
<div class="uk-panel uk-panel-header uk-panel-box" data-uk-sticky="{top:35}">
<div class="uk-panel-header"><h3 class="uk-panel-title">Contact<img class="uk-align-right uk-thumbnail uk-border-circle uk-thumbnail-mini uk-animation-scale-up uk-img-preserve" src="{{ basics.picture }}"/></h3></div>
<!--
--><ul class="uk-list uk-list-line uk-h5">
<div class="uk-panel-image">
<img class="uk-align-right uk-thumbnail uk-border-circle uk-thumbnail-mini uk-animation-scale-up uk-img-preserve"
src="{{ basics.picture }}"/>
</div>
<h3 class="uk-panel-title">Contact</h3>
<ul class="uk-list uk-list-line">
{% if basics.email is not empty %}
<li><a href="#" class="hidden-email">[Click to view email]</a></li>
{% endif %}
{% if basics.phone is not empty %}
<li>{{ basics.phone }}</li>
<li class="uk-list-space"><a href="#" class="hidden-email">[Click to view email]</a></li>
{% endif %}
{% if basics.phone is not empty %}
<li class="uk-list-space">{{ basics.phone }}</li>
{% endif %}
{% if basics.website is not empty %}
<li><a href="{{ basics.website }}" target="_blank" title="Home page">{{ basics.website }}</a></li>
{% endif %}
<li class="uk-list-space"><a href="{{ basics.website }}" target="_blank"
title="Home page">{{ basics.website }}</a></li>
{% endif %}
{% if basics.location|length > 0 and basics.location is not empty %}
<li>
<address>
{% set location = basics.location %}
<li class="uk-list-space">
<address>
{% set location = basics.location %}
{% if location.address is not empty %}
{{ location.address }}<br/>
{% endif %}
{% if location.city is not empty %}
{{ location.city }},
{% endif %}
{% if location.region is not empty %}
&nbsp;{{ location.region }},
{% endif %}
{% if location.countryCode is not empty %}
&nbsp;{{ location.countryCode }}
{% endif %}<br/>
</address>
</li>
{% endif %}
<li class="uk-list-space">
{% for profile in basics.profiles %}
{{ render_profile(profile)|raw }}
{% endfor %}
</li>
<li class="uk-list-divider"></li>
</ul>
{% if skills is defined and skills is not empty %}
<h3 class="uk-panel-title">Skills</h3>
<dl class="uk-description-list-line">
{% for skill in skills %}
<dt class="uk-text-bold">{{ skill.name }}</dt>
<dd>{{ skill.keywords|join(', ')|raw }}</dd>
{% endfor %}
</dl>
{% endif %}
</div>
</div>
</div>
</div>
<div id="offcanvas" class="uk-offcanvas">
<div class="uk-offcanvas-bar">
<ul class="uk-list uk-list-line">
{% if basics.email is not empty %}
<li>{{ basics.email }}</li>
{% endif %}
{% if basics.phone is not empty %}
<li>{{ basics.phone }}</li>
{% endif %}
{% if basics.location|length > 0 and basics.location is not empty %}
<li>
<address>
{% for location in basics.location %}
{% if location.address is not empty %}
{{ location.address }}<br />
{{ location.address }}<br/>
{% endif %}
{% if location.city is not empty %}
{{ location.city }}
@ -70,49 +168,16 @@
{% endif %}
{% if location.countryCode is not empty %}
&nbsp;{{ location.countryCode }}
{% endif %}<br />
{% endif %}<br/>
{% endif %}
{% endfor %}
</address>
</li>
{% endif %}
</li>
{% endif %}
<li>
</ul>
</div>
</div>
</li>
</ul>
</div>
</div>
<div id="offcanvas" class="uk-offcanvas">
<div class="uk-offcanvas-bar">
<ul class="uk-list uk-list-line">
{% if basics.email is not empty %}
<li>{{ basics.email }}</li>
{% endif %}
{% if basics.phone is not empty %}
<li>{{ basics.phone }}</li>
{% endif %}
{% if basics.location|length > 0 and basics.location is not empty %}
<address>
{% for location in basics.location %}
{% if location.address is not empty %}
{{ location.address }}<br />
{% endif %}
{% if location.city is not empty %}
{{ location.city }}
{% if location.postalCode is not empty %}
&nbsp;{{ location.postalCode }}
{% endif %}
{% if location.countryCode is not empty %}
&nbsp;{{ location.countryCode }}
{% endif %}<br />
{% endif %}
{% endfor %}
{% endif %}
</address>
</ul>
</div>
{% endblock %}

View File

@ -38,7 +38,8 @@
"symfony/monolog-bridge": "^3.1",
"google/recaptcha": "^1.1",
"hassankhan/config": "^0.10.0",
"silex/web-profiler": "^2.0"
"silex/web-profiler": "^2.0",
"twig/extensions": "^1.3"
},
"require-dev": {
"symfony/debug": "~2.8|^3.0",

56
composer.lock generated
View File

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "b95f44a2d8bcbac673a62298f16f4ad9",
"content-hash": "d0a7cfefe30599f33ddbe16cd3cce33d",
"hash": "d47e1d8d6470d4d29deb55649ecc969b",
"content-hash": "3c41da3f56c72d6c1bc86d0a1889d6d9",
"packages": [
{
"name": "google/recaptcha",
@ -2187,6 +2187,58 @@
"homepage": "https://symfony.com",
"time": "2016-06-29 05:41:56"
},
{
"name": "twig/extensions",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig-extensions.git",
"reference": "449e3c8a9ffad7c2479c7864557275a32b037499"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/449e3c8a9ffad7c2479c7864557275a32b037499",
"reference": "449e3c8a9ffad7c2479c7864557275a32b037499",
"shasum": ""
},
"require": {
"twig/twig": "~1.20|~2.0"
},
"require-dev": {
"symfony/translation": "~2.3"
},
"suggest": {
"symfony/translation": "Allow the time_diff output to be translated"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3-dev"
}
},
"autoload": {
"psr-0": {
"Twig_Extensions_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Common additional features for Twig that do not directly belong in core",
"homepage": "http://twig.sensiolabs.org/doc/extensions/index.html",
"keywords": [
"i18n",
"text"
],
"time": "2015-08-22 16:38:35"
},
{
"name": "twig/twig",
"version": "v1.24.1",

View File

@ -6,7 +6,7 @@
"email": "eric@ericwheeler.net",
"phone": "",
"website": "https://code.reric.me",
"summary": "",
"summary": "My name is Eric Wheeler. I enjoy programming, working on computer hardware/electronics, music and gardening.",
"location": {
"address": "",
"postalCode": "CA 94578",
@ -18,7 +18,7 @@
{
"network": "Twitter",
"username": "sikofitt",
"url": ""
"url": "https://twitter.com/sikofitt"
},
{
"network": "Github",
@ -26,7 +26,7 @@
"url": ""
},
{
"network": "Private Git",
"network": "Gitlab",
"username": "sikofitt",
"url": "https://repos.bgemi.net/u/sikofitt"
},
@ -43,12 +43,12 @@
"position": "Developer / Systems Administrator",
"website": "https://ee.stanford.edu",
"startDate": "2007-05-27",
"endDate": "2016-07-02",
"summary": "",
"summary": "I have done many different things during my employment at Stanford University.<br />A few of things things have been : Desktop Support, Computer cluster administration for the NSF and NNIN using Scyld Clusterware, General programing/debugging and frontend as well as backend web development using a number of different technologies.",
"highlights": [
"Build an algorithm for artist to detect if their music was violating copy right infringement laws",
"Successfully won Techcrunch Disrupt",
"Optimized an algorithm that holds the current world record for Weisman Scores"
"Upgraded and Maintained a 64 node research computing cluster for the NNIN funded by the <b>NSF</b>.",
"Converted Electrical Engineering's static web site to Drupal 7.",
"Created many Drupal 7 modules for the EE website including a custom events, lecture and committe minutes content type, a CDN module for uploading and recieving images/videos/documents, an Orglist module for displaying Faculty, Students, and Staff from a custom API.",
"Created a custom Drupal 7 site for the SystemX organization with integrated login for affiliates as well as Stanford staff."
]
},
{
@ -80,6 +80,22 @@
"Let's Encrypt"
]
},
{
"name": "PHP",
"level": "",
"keywords": [
"PHP5",
"PHP7",
"<b>Drupal 7</b>",
"Symfony 2",
"Symfony 3",
"OOP",
"Silex",
"Slim",
"Doctrine",
"Composer"
]
},
{
"name": "PHP",
"level": "",
@ -95,6 +111,7 @@
"Composer"
]
}
],
"languages": [],
"interests": [

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,40 @@
<?php
/**
* This file is part of test.
*
* @file GithubProfileIcon.php
*
* R. Eric Wheeler <reric@ee.stanford.edu>
*
* 7/7/16 / 9:18 AM
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sikofitt\Image\Profile;
/**
* Class GithubProfileIcon
* @package Sikofitt\Image\Profile
*/
class GithubProfileIcon implements ProfileIconInterface
{
/**
* {@inheritdoc}
*/
public function getName() {
return 'github';
}
public function getDefaultUrl() {
return 'https://github.com';
}
/**
* {@inheritdoc}
*/
public function getIcon() {
return 'data:image/png;base64,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';
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* This file is part of test.
*
* @file GitlabProfileIcon.php
*
* R. Eric Wheeler <reric@ee.stanford.edu>
*
* 7/7/16 / 9:36 AM
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sikofitt\Image\Profile;
/**
* Class GitlabProfileIcon
* @package Sikofitt\Image\Profile
*/
class GitlabProfileIcon implements ProfileIconInterface {
/**
* {@inheritdoc}
*/
public function getName() {
return 'gitlab';
}
public function getDefaultUrl() {
return 'https://gitlab.com';
}
/**
* {@inheritdoc}
*/
public function getIcon() {
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAXCAYAAAD+4+QTAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AcHECQRchk3rwAAA3VJREFUSMe1lU1oXFUYhp/vnJtJMplJ2iQttElMbCY3uYlaKAqCddEm00K1iFakZFIQoVBciNalRURdueim4MqFYCJ0Uze6sGqhCxcuXCia1JtuatJpuhAUxJ9m7ve5mJnM3PyQZOELF845l/e87/dzzhGasDw5JiLuGvBW39fz8+wCvxUj/jHGzLjS/81Csfmfqw/uHB8jEIeanTSz99gler5aQI1TClPlYjS8qcjgjVtUzIoG7QZHl6fGszsVuHdioj58FUCV5zYVAUB4H8CgB7O+nYocuP4z5WL0MDBc458EWDoepUXKU9F+NZ6oTT3w4m7Spcrr1phOAgzcWEiLqHGsmWQiF3ey+a2nRlkuRi1197VI/N2p8ZkN6TJ4JiVi1luejI5sJ5Lv8JiSNxhax39ns5o8vyEF8Mp2In3X5wGeBVpTIjB0dyoauHNshABg6enohCq56r8GEji6o4IYb5vV914TcaY8PnhzcSkAOHg+uSQ/AQ/WcY3DS0Fkplvv71vgQJSApQwKDrNxXuImnzmbDbtNOKyHUE2Q5g+D7F5LzLYWyXapagVS3ApohFkbZwFcAiNAnhyOAkmzHzPo3KeyzmUKmRyyLnXwEEo7DoNkLjzrBF6Aqmu68fSizVuKx2WyW4u0tltaoAulvypQW7vogFMpVgFHG9pMbO0w2aTYZLssEdcUSRtGiJA0dzKPORwvi/Brys0j1cKtcfO2IWEG5PaZNNXLGMVwqfTdF88Z56fj751LhkS41mgZhBCtO2rNmaxv7yCDBRlrnLNRoK1x7sTxnTiG/XT8havGFJific+I4wJSa+Q9eAZraTOko8dStcpkazEosB9lTyMCcbzhS/GTvhT/Ve3nGiqfFAjO3Sb5NDyI8oMZvQjwI8rfOK2gK794h1S7rntAtb3THHkSJvAoINxD7EhQWlzZ9KoPzt0mmQvx03FZHH3iuAy1+rRi4nE+Q/1cW7bTBMEYQVAQ4Yp3hEFpcWV1doQt3xNfiuvDB74UvynCaYTfKSAi0NJWbYDsXlME4VGghX+957yfiV9LjD8BWmYWtxZZW5yOSWZDfCn+3DkKkudbRqGjy8wMct3qrB8ky6LAIZmOP7Kr4wQNk7uDzoXVy3I2/EDfDVeXi5GuXgpNr4aX+T9gX4YTf1wYvV/5MFx71Fc/LmzL+w9fiFeX9RDTWwAAAABJRU5ErkJggg==';
}
}

View File

@ -0,0 +1,31 @@
<?php
/**
* This file is part of test.
*
* @file LinkedinProfileIcon.php
*
* R. Eric Wheeler <reric@ee.stanford.edu>
*
* 7/7/16 / 10:51 AM
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sikofitt\Image\Profile;
class LinkedinProfileIcon implements ProfileIconInterface {
public function getName() {
return 'linkedin';
}
public function getDefaultUrl() {
return 'https://linkedin.com/in';
}
public function getIcon() {
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AcHETMTmFa4IgAAA/1JREFUSMeVlk2IXEUQx3/V783sfOxKdjeKQqImCJpsBC9qwFxC1KCiEW8eRQVBPXjxInjwJoin6CXEsyhCcvIDRUQkGoOgyaJgPlAS2GQlX7tmZ3fm1d9D93tvZnZzsKHpnqrurqp//aveGMDk7qdnWlt37DSzhrDcwABE2qQ9lcJKSTUEmNWX5N5bPXfy1NKJzy/n3YeempnZ/9Lh0J58BrNQPmxYekbUTxpChLSOGwnJC0kg0Znbc5SJzouhfefOXaE9+SwQJDAJSbgcKPfxkuSYiLokQ4BUyd2jToC1ugead2yfy2WhJQIux0wUDjf6BQImmxm2DrYUXxVe0lpcJVVnMQMLrSCgSFcHLu6e6XDmzb2ceH0PU60GnmDzBJynvWtYJiTDUwTCRmaQQC7cRWaBL154kE2tnO3TbQ49d38M3eN0OUpwyoUE7l7rvIa3hE4SuZJXAJu7TbrNrErmbKdBMwusDKLP46ySJ2iSWIqEibkECxGFUHrmLv5cXOLI/CVIhj87ucC1Xj95Fc946akLIZyx3+6RKOXeRe4SRRK2mhmvHPmNg8em6Lvz+6VlQrB0yWI2VFOgKEQhyIKRGeDGEN8RQiZyIgMp163Tba71Bgi4rTvBwtIqjWBs3dTGESt9Z+F6j9luk913zXD71ASnF5f5Y3GZxX/XIhuSITNDDnmkewz16kqff95+rML85/NX2XfoR7ZNT3L8tUcAOH7+Gu9/f44PDswx22lUZ6/3Brzz7WkO//QXWQgJ8uh9ZJcMFRGNQnVie33HCyi8ruwdt3b5+PkHRgwA3NLKee+J+9iyqUNRCC8EHiMJoqzu2vJwqxguQICpiRyAT04u8O53Zzj295WRO2/tu4cbawPKd2UiL2vEyhYxZqZwj14NjY9+ucCrn/7KRCPwYbvJVy8/zL2buwDs3TbL2sBp5QFLfSyUPcCHGUBNBAGyUfnBH86SZYYLLi71uLi0WummW3nVu8quk8eqjbVSVeXQcBfyUdmFKyup+ERJnHLkmYGr7p+q2LUBUkPRjOeqKOoedbM8uupPRF2MG0RSGhjqq1U3cK+rWuMepjxj8X5VJ+tPloaE3NfJqoreAGJSq6ogLGP04U45Hs06ztUQymwD1yxFb2UkYjCUGHdBSNh7lJXeFhKZGYWXDRFwp3BVRewePS7cMTOQYfbkG4+HXfu+jL1GDG70a4eCkU3k8YHeoAojpGovYyhWByMoZJ1GbPVm6NQ3+3Pce0pemSC0GmMsgUCAVmMELw2dCc28+pNhUFE+5bMXWDw7773lo/HbQDU1NH1Mt16fSDByRnhv+agWz87HiOcenWHL3C6CtW5aMP9nGODqcX7+FPNfX/4PZFb8sTBvluQAAAAASUVORK5CYII=';
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* This file is part of resume.
*
* @file ProfileIconInterface.php
*
* R. Eric Wheeler <reric@ee.stanford.edu>
*
* 7/7/16 / 7:16 AM
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sikofitt\Image\Profile;
/**
* Interface ProfileIconInterface
* @package Sikofitt\Image\Profile
*/
interface ProfileIconInterface {
/**
* @return string
* The name of the network.
*/
public function getName();
/**
* @return string
* The default url prefix if no url was given.
* (e.g. https://twitter.com for twitter, https://facebook.com for facebook.)
*/
public function getDefaultUrl();
/**
* @return string
* The social icon.
* Can be a url, a relative path, or base64 encoded uri.
*/
public function getIcon();
}

View File

@ -0,0 +1,32 @@
<?php
/**
* This file is part of resume.
*
* @file TwitterProfileIcon.php
*
* R. Eric Wheeler <reric@ee.stanford.edu>
*
* 7/7/16 / 7:20 AM
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sikofitt\Image\Profile;
class TwitterProfileIcon implements ProfileIconInterface {
public function getName()
{
return 'twitter';
}
public function getDefaultUrl() {
return 'https://twitter.com';
}
public function getIcon() {
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4AcHEBgWn47b8wAAAedJREFUSMfllj1LHEEYgJ/du/hxCYOkCXIOwSJdhIQUAZGYwtJGsVA4mFb8ARYGo5WQgCmSOsVgJfgLrAImZfQHWCg3mNjYDJxwp5e1mdNhsnu74bSJb7PszDvvs+/nLPwvEoULUluMEl0PdXSktn1A7JYToAUk/nmp7Q1EahsDkVGinQOIjBKJ1LYGLAH9busPsGWU+Cy1HQLmgH2jxH7UoQFDwAnwEEj1xvNgGfiQ8g2Jg0XOw6dGiXrsGawBFeAUmPDg1+IALx0gyQh/yQE2gA2pbSX2FJ655xNgT2q7npGb6ax8Bh6tAJtGiXMfsh0orkltL6S281LbqtT2gRf7PGkDL4wSB9eJd2EpAYfAaMqh38AZ0ABGgGoO5CcwDrSMEvg5mQEOMmI9DDwHXhcAADT94ikHhmZvqf++GyVanZfYC5e+qyb3w2WBj1519CJf88bKJPCtB8CeUeLNX54EstujF7VwIQ0y3wNgyyhRDydFlDGbFoFV4DEwUBBwCrwCfoWTIuoyBCNgp2BZN4Axo8RR2mbZGS4Dgw5akdrOAV8KemCASeA4S6HTjAPAJrAAPCpovAm8Bz4ZJS5zm8YL0VvgHTDVpVfqLsGr/9yZ4bUrtR0Pxg5A2yjxw78h7+SnICzP+yVXFk+tI1UN56QAAAAASUVORK5CYII=';
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* This file is part of resume.
*
* @file Date.php
*
* R. Eric Wheeler <reric@ee.stanford.edu>
*
* 7/7/16 / 6:57 AM
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sikofitt\Twig;
class Date extends \Twig_Extension {
public function getName() {
return 'date_diff';
}
/**
* @return array
* Array of Twig simple filters.
*/
public function getFilters()
{
return [
new \Twig_SimpleFilter('date_diff', [$this, 'dateDiff']),
];
}
/**
* Calculates the difference in time.
*
* @param $startDate
* @param string $endDate
*
* @return \DateTimeInterface
*/
public function dateDiff($startDate, $endDate = 'now')
{
$dt = new \DateTimeImmutable($startDate);
$dateDifference = $dt->diff(new \DateTime($endDate));
return $dateDifference->format('%y years');
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* This file is part of test.
*
* @file Icon.php
*
* R. Eric Wheeler <reric@ee.stanford.edu>
*
* 7/7/16 / 9:39 AM
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sikofitt\Twig;
class RenderProfile extends \Twig_Extension {
public function getName() {
return 'render_profile';
}
public function getFunctions() {
return [
new \Twig_SimpleFunction('render_profile', [$this, 'renderProfile'], ['needs_context' => true]),
];
}
public function renderProfile($context, $iconData)
{
$imageData = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAIAAABLixI0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AcHEQYsjAFXqQAAAEVpVFh0Q29tbWVudAAAAAAAQ1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2ODApLCBxdWFsaXR5ID0gOTAKqozFDgAAAiVJREFUOMutlT/oOWEcx+8OX5fLDVwx2ZQFSQYzmZgMzCaDzaCUMpmQkowM2G+gFFnUGXRKSQwGIYtyisif+w2n+973ucef4fde7u75fD6v5/l8Ps/zHMLDxHFcp9OJxWJOp1Ov1ysUChzHLRZLNBrt9Xrn8xkahciH6vW6VqtFXouiqOFw+JmVz+eR79Rqtd6xSqUS8rUwDGNZFs7a7/c4jku9lUplOByuVqvtdpum6Xg8jqKo1MHn88FZHo8HmPnn50co8+PxeLVwjuNA1mq1giaSTCaDwaDX653P58+Av6pUKiJLKQxNJhMUReWumUxGeGFZ1mw2yydbLpe/FRQeh8NBDhJFkmQgEEAQJJ1OAyaDwfD7ISyv2+0CdZV2YL1e8zw/Go3UajXQSkjtj8fjK1YkEnmWQ6kETEajUcp65qjRaAqFApRls9kQBBkMBrfbDTBtt9tGowHmKMhqtUJzJAhCpVJBZ9LpdKfTCbLvGYaRe2ez2d1uV6vV5CahLAzDwM9jIpEAAjabDXRnCSqXy5fLBc46HA4kSUq9c7kcz/PQdQElAlnX69XhcHx5vP1+P6SP0i0DnPD3rD+xgPnxeJhMpm9AKIra7faXCYtaLBYURUHjRWEYJnbw5R0t6HK5hEIhKYggiGazOZ1O+/1+u90ej8ef73up3G63yEqlUu+dP7Du97vL5RL+F/wnIR89ZrMZhmHFYvE/sHiep2lavFff6B8xFGrMmf/uPQAAAABJRU5ErkJggg==';
//network": "Twitter" +"username": "sikofitt" +"url": ""
$icons = $context['app']->config('app.icons');
$network = strtolower($iconData->network);
$haveNetwork = isset($icons[$network]);
if($haveNetwork) {
$imageData = $icons[strtolower($iconData->network)];
} else {
return;
}
if(!isset($iconData->url) || empty($iconData->url))
{
$iconData->url = $icons[strtolower($iconData->network)]['url'] . '/' . $iconData->username;
}
$imageUrl = sprintf('<img src="%s" alt="%s" />', $imageData['icon'], $iconData->network);
if(isset($iconData->url) && !empty($iconData->url)) {
return sprintf('<a class="profile-link" href="%s" title="%s" target="_blank">%s</a>', $iconData->url, $iconData->network,$imageUrl);
} else {
return $imageUrl;
}
}
}

View File

@ -2,7 +2,49 @@
@import 'https://fonts.googleapis.com/css?family=Lato:300|Eczar';
@base-body-font-family : 'Lato';
@base-body-font-size : 26px;
@base-body-font-size : 16px;
@base-heading-font-family : 'Eczar';
@base-body-line-height : 1.2em;
@thumbnail-mini-width : 100px;
@thumbnail-mini-width : 100px;
@panel-box-background : #fff;
.uk-panel.uk-panel-box {
border: 1px solid @base-hr-border;
border-radius:2px;
}
hr.uk-hr-light {
border-top-color:#fafafa;
}
a.profile-link {
filter: grayscale(100%);
-webkit-transition: filter 500ms;
-moz-transition: filter 500ms;
-ms-transition: filter 500ms;
-o-transition: filter 500ms;
transition: filter 500ms;
&:hover {
filter: grayscale(0%);
}
}
.uk-panel-image {
position: absolute;
top: 10px;
right: 16px;
> img {
width:34px;
padding: 2px;
}
}
.uk-text-lead {
font-size: 24px;
line-height: 38px;
font-weight: normal;
margin-bottom: 16px;
border-bottom: 1px solid #ccc;
padding-bottom: 12px;
}

View File

@ -1,37 +1,40 @@
<?php
use Sikofitt\Json\ResumeBuilder;
use Symfony\Component\HttpFoundation\Response;
use Silex\Provider\TwigServiceProvider;
use WhoopsSilex\WhoopsServiceProvider;
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../app/App.php';
define ('APP_ROOT', __DIR__ . '/../');
define ('SCHEMA_URL', 'https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json');
define('APP_ROOT', __DIR__ . '/../');
define('SCHEMA_URL', 'https://raw.githubusercontent.com/jsonresume/resume-schema/v1.0.0/schema.json');
$app = new App();
$app['debug'] = true;
$app->register(new Sikofitt\Config\ConfigServiceProvider(), [
'config.path' => $app->getConfDirectory(),
'config.path' => $app->getConfDirectory(),
]);
$app->register (new TwigServiceProvider(), [
'twig.path' => [APP_ROOT . 'app/views', APP_ROOT .'vendor/symfony/web-profiler-bundle/Resources/views/Profiler'],
$app->register(new TwigServiceProvider(), [
'twig.path' => [
APP_ROOT . 'app/views',
APP_ROOT . 'vendor/symfony/web-profiler-bundle/Resources/views/Profiler'
],
]);
$app->register (new WhoopsServiceProvider());
$app->register (new \Silex\Provider\AssetServiceProvider());
$app->register (new \Silex\Provider\MonologServiceProvider());
$app->register(new WhoopsServiceProvider());
$app->register(new \Silex\Provider\AssetServiceProvider());
$app->register(new \Silex\Provider\MonologServiceProvider());
$app->register (new \Silex\Provider\HttpKernelServiceProvider());
$app->register(new \Silex\Provider\HttpKernelServiceProvider());
$app->register(new \Silex\Provider\AssetServiceProvider());
$app->register(new \Silex\Provider\FormServiceProvider());
$app->register(new \Silex\Provider\HttpFragmentServiceProvider());
$app->register(new \Silex\Provider\ServiceControllerServiceProvider());
$app->register(new \Silex\Provider\RoutingServiceProvider());
$app->register (new \Silex\Provider\VarDumperServiceProvider(), array(
$app->register(new \Silex\Provider\VarDumperServiceProvider(), array(
'var_dumper.dump_destination' => new \Symfony\Component\VarDumper\Cloner\VarCloner(),
));
@ -41,35 +44,39 @@ $app->register(new \Silex\Provider\MonologServiceProvider(), array(
$app->register(new \Silex\Provider\SessionServiceProvider());
$app->register(new \Silex\Provider\WebProfilerServiceProvider(), array(
'profiler.cache_dir' => $app->getDataDirectory() .'/cache/profiler',
'profiler.cache_dir' => $app->getDataDirectory() . '/cache/profiler',
));
$app->extend('twig', function(\Twig_Environment $twig, $app) {
$twig->enableDebug();
return $twig;
$app->extend('twig', function (\Twig_Environment $twig, $app) {
$twig->enableDebug();
$twig->addExtension(new Twig_Extensions_Extension_Date());
$twig->addExtension(new Sikofitt\Twig\Date());
$twig->addExtension(new Sikofitt\Twig\RenderProfile());
$twig->addGlobal('config', $app['config']->all());
return $twig;
});
$app->error(function (\Exception $e, $code) use($app) {
switch ($code) {
case 404:
$message = $app['twig']->render('error404.html.twig');
break;
default:
$message = $app['twig']->render('error500.html.twig');
}
return new Response($message, $code);
$app->error(function (\Exception $e, $code) use ($app) {
switch ($code) {
case 404:
$message = $app['twig']->render('error404.html.twig');
break;
default:
$message = $app['twig']->render('error500.html.twig');
}
return new Response($message, $code);
});
$app['json.decoder'] = function ($app) {
return new Webmozart\Json\JsonDecoder();
return new Webmozart\Json\JsonDecoder();
};
$app['json.encoder'] = function ($app) {
return new Webmozart\Json\JsonEncoder();
return new Webmozart\Json\JsonEncoder();
};
$app['json.validator'] = function ($app) {
return new Webmozart\Json\JsonValidator();
return new Webmozart\Json\JsonValidator();
};
$app->get ('/', function () use ($app) {
$resumeData = $app['json.decoder']->decodeFile($app->getDataDirectory() .'/resume.json', $app->getDataDirectory() . '/resume.schema.json');
$app->registerIcon(new \Sikofitt\Image\Profile\TwitterProfileIcon());
$app->get('/', function () use ($app) {
$resumeData = $app['json.decoder']->decodeFile($app->getDataDirectory() . '/resume.json', $app->getDataDirectory() . '/resume.schema.json');
$basics = (isset($resumeData->basics) && count($resumeData->basics) > 0) ? $resumeData->basics : null;
$work = (isset($resumeData->work) && count($resumeData->work) > 0) ? $resumeData->work : null;
$volunteer = (isset($resumeData->volunteer) && count($resumeData->volunteer) > 0) ? $resumeData->volunteer : null;
@ -80,7 +87,7 @@ $app->get ('/', function () use ($app) {
$languages = (isset($resumeData->languages) && count($resumeData->languages) > 0) ? $resumeData->languages : null;
$interests = (isset($resumeData->interests) && count($resumeData->interests) > 0) ? $resumeData->interests : null;
$references = (isset($resumeData->references) && count($resumeData->references) > 0) ? $resumeData->references : null;
return $app['twig']->render('resume.html.twig', [
'basics' => $basics,
@ -96,4 +103,4 @@ $app->get ('/', function () use ($app) {
]);
});
$app->run ();
$app->run();