.
9 |
10 | .list-group {
11 | // No need to set list-style: none; since .list-group-item is block level
12 | margin-bottom: 20px;
13 | padding-left: 0; // reset padding because ul and ol
14 | }
15 |
16 |
17 | // Individual list items
18 | //
19 | // Use on `li`s or `div`s within the `.list-group` parent.
20 |
21 | .list-group-item {
22 | position: relative;
23 | display: block;
24 | padding: 10px 15px;
25 | // Place the border on the list items and negative margin up for better styling
26 | margin-bottom: -1px;
27 | background-color: $list-group-bg;
28 | border: 1px solid $list-group-border;
29 |
30 | // Round the first and last items
31 | &:first-child {
32 | @include border-top-radius($list-group-border-radius);
33 | }
34 | &:last-child {
35 | margin-bottom: 0;
36 | @include border-bottom-radius($list-group-border-radius);
37 | }
38 | }
39 |
40 |
41 | // Linked list items
42 | //
43 | // Use anchor elements instead of `li`s or `div`s to create linked list items.
44 | // Includes an extra `.active` modifier class for showing selected items.
45 |
46 | a.list-group-item {
47 | color: $list-group-link-color;
48 |
49 | .list-group-item-heading {
50 | color: $list-group-link-heading-color;
51 | }
52 |
53 | // Hover state
54 | &:hover,
55 | &:focus {
56 | text-decoration: none;
57 | color: $list-group-link-hover-color;
58 | background-color: $list-group-hover-bg;
59 | }
60 | }
61 |
62 | .list-group-item {
63 | // Disabled state
64 | &.disabled,
65 | &.disabled:hover,
66 | &.disabled:focus {
67 | background-color: $list-group-disabled-bg;
68 | color: $list-group-disabled-color;
69 | cursor: $cursor-disabled;
70 |
71 | // Force color to inherit for custom content
72 | .list-group-item-heading {
73 | color: inherit;
74 | }
75 | .list-group-item-text {
76 | color: $list-group-disabled-text-color;
77 | }
78 | }
79 |
80 | // Active class on item itself, not parent
81 | &.active,
82 | &.active:hover,
83 | &.active:focus {
84 | z-index: 2; // Place active items above their siblings for proper border styling
85 | color: $list-group-active-color;
86 | background-color: $list-group-active-bg;
87 | border-color: $list-group-active-border;
88 |
89 | // Force color to inherit for custom content
90 | .list-group-item-heading,
91 | .list-group-item-heading > small,
92 | .list-group-item-heading > .small {
93 | color: inherit;
94 | }
95 | .list-group-item-text {
96 | color: $list-group-active-text-color;
97 | }
98 | }
99 | }
100 |
101 |
102 | // Contextual variants
103 | //
104 | // Add modifier classes to change text and background color on individual items.
105 | // Organizationally, this must come after the `:hover` states.
106 |
107 | @include list-group-item-variant(success, $state-success-bg, $state-success-text);
108 | @include list-group-item-variant(info, $state-info-bg, $state-info-text);
109 | @include list-group-item-variant(warning, $state-warning-bg, $state-warning-text);
110 | @include list-group-item-variant(danger, $state-danger-bg, $state-danger-text);
111 |
112 |
113 | // Custom content options
114 | //
115 | // Extra classes for creating well-formatted content within `.list-group-item`s.
116 |
117 | .list-group-item-heading {
118 | margin-top: 0;
119 | margin-bottom: 5px;
120 | }
121 | .list-group-item-text {
122 | margin-bottom: 0;
123 | line-height: 1.3;
124 | }
125 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_media.scss:
--------------------------------------------------------------------------------
1 | .media {
2 | // Proper spacing between instances of .media
3 | margin-top: 15px;
4 |
5 | &:first-child {
6 | margin-top: 0;
7 | }
8 | }
9 |
10 | .media,
11 | .media-body {
12 | zoom: 1;
13 | overflow: hidden;
14 | }
15 |
16 | .media-body {
17 | width: 10000px;
18 | }
19 |
20 | .media-object {
21 | display: block;
22 | }
23 |
24 | .media-right,
25 | .media > .pull-right {
26 | padding-left: 10px;
27 | }
28 |
29 | .media-left,
30 | .media > .pull-left {
31 | padding-right: 10px;
32 | }
33 |
34 | .media-left,
35 | .media-right,
36 | .media-body {
37 | display: table-cell;
38 | vertical-align: top;
39 | }
40 |
41 | .media-middle {
42 | vertical-align: middle;
43 | }
44 |
45 | .media-bottom {
46 | vertical-align: bottom;
47 | }
48 |
49 | // Reset margins on headings for tighter default spacing
50 | .media-heading {
51 | margin-top: 0;
52 | margin-bottom: 5px;
53 | }
54 |
55 | // Media list variation
56 | //
57 | // Undo default ul/ol styles
58 | .media-list {
59 | padding-left: 0;
60 | list-style: none;
61 | }
62 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_mixins.scss:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // --------------------------------------------------
3 |
4 | // Utilities
5 | @import "mixins/hide-text";
6 | @import "mixins/opacity";
7 | @import "mixins/image";
8 | @import "mixins/labels";
9 | @import "mixins/reset-filter";
10 | @import "mixins/resize";
11 | @import "mixins/responsive-visibility";
12 | @import "mixins/size";
13 | @import "mixins/tab-focus";
14 | @import "mixins/text-emphasis";
15 | @import "mixins/text-overflow";
16 | @import "mixins/vendor-prefixes";
17 |
18 | // Components
19 | @import "mixins/alerts";
20 | @import "mixins/buttons";
21 | @import "mixins/panels";
22 | @import "mixins/pagination";
23 | @import "mixins/list-group";
24 | @import "mixins/nav-divider";
25 | @import "mixins/forms";
26 | @import "mixins/progress-bar";
27 | @import "mixins/table-row";
28 |
29 | // Skins
30 | @import "mixins/background-variant";
31 | @import "mixins/border-radius";
32 | @import "mixins/gradients";
33 |
34 | // Layout
35 | @import "mixins/clearfix";
36 | @import "mixins/center-block";
37 | @import "mixins/nav-vertical-align";
38 | @import "mixins/grid-framework";
39 | @import "mixins/grid";
40 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_modals.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Modals
3 | // --------------------------------------------------
4 |
5 | // .modal-open - body class for killing the scroll
6 | // .modal - container to scroll within
7 | // .modal-dialog - positioning shell for the actual modal
8 | // .modal-content - actual modal w/ bg and corners and shit
9 |
10 | // Kill the scroll on the body
11 | .modal-open {
12 | overflow: hidden;
13 | }
14 |
15 | // Container that the modal scrolls within
16 | .modal {
17 | display: none;
18 | overflow: hidden;
19 | position: fixed;
20 | top: 0;
21 | right: 0;
22 | bottom: 0;
23 | left: 0;
24 | z-index: $zindex-modal;
25 | -webkit-overflow-scrolling: touch;
26 |
27 | // Prevent Chrome on Windows from adding a focus outline. For details, see
28 | // https://github.com/twbs/bootstrap/pull/10951.
29 | outline: 0;
30 |
31 | // When fading in the modal, animate it to slide down
32 | &.fade .modal-dialog {
33 | @include translate(0, -25%);
34 | @include transition-transform(0.3s ease-out);
35 | }
36 | &.in .modal-dialog { @include translate(0, 0) }
37 | }
38 | .modal-open .modal {
39 | overflow-x: hidden;
40 | overflow-y: auto;
41 | }
42 |
43 | // Shell div to position the modal with bottom padding
44 | .modal-dialog {
45 | position: relative;
46 | width: auto;
47 | margin: 10px;
48 | }
49 |
50 | // Actual modal
51 | .modal-content {
52 | position: relative;
53 | background-color: $modal-content-bg;
54 | border: 1px solid $modal-content-fallback-border-color; //old browsers fallback (ie8 etc)
55 | border: 1px solid $modal-content-border-color;
56 | border-radius: $border-radius-large;
57 | @include box-shadow(0 3px 9px rgba(0,0,0,.5));
58 | background-clip: padding-box;
59 | // Remove focus outline from opened modal
60 | outline: 0;
61 | }
62 |
63 | // Modal background
64 | .modal-backdrop {
65 | position: fixed;
66 | top: 0;
67 | right: 0;
68 | bottom: 0;
69 | left: 0;
70 | z-index: $zindex-modal-background;
71 | background-color: $modal-backdrop-bg;
72 | // Fade for backdrop
73 | &.fade { @include opacity(0); }
74 | &.in { @include opacity($modal-backdrop-opacity); }
75 | }
76 |
77 | // Modal header
78 | // Top section of the modal w/ title and dismiss
79 | .modal-header {
80 | padding: $modal-title-padding;
81 | border-bottom: 1px solid $modal-header-border-color;
82 | min-height: ($modal-title-padding + $modal-title-line-height);
83 | }
84 | // Close icon
85 | .modal-header .close {
86 | margin-top: -2px;
87 | }
88 |
89 | // Title text within header
90 | .modal-title {
91 | margin: 0;
92 | line-height: $modal-title-line-height;
93 | }
94 |
95 | // Modal body
96 | // Where all modal content resides (sibling of .modal-header and .modal-footer)
97 | .modal-body {
98 | position: relative;
99 | padding: $modal-inner-padding;
100 | }
101 |
102 | // Footer (for actions)
103 | .modal-footer {
104 | padding: $modal-inner-padding;
105 | text-align: right; // right align buttons
106 | border-top: 1px solid $modal-footer-border-color;
107 | @include clearfix; // clear it in case folks use .pull-* classes on buttons
108 |
109 | // Properly space out buttons
110 | .btn + .btn {
111 | margin-left: 5px;
112 | margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs
113 | }
114 | // but override that for button groups
115 | .btn-group .btn + .btn {
116 | margin-left: -1px;
117 | }
118 | // and override it for block buttons as well
119 | .btn-block + .btn-block {
120 | margin-left: 0;
121 | }
122 | }
123 |
124 | // Measure scrollbar width for padding body during modal show/hide
125 | .modal-scrollbar-measure {
126 | position: absolute;
127 | top: -9999px;
128 | width: 50px;
129 | height: 50px;
130 | overflow: scroll;
131 | }
132 |
133 | // Scale up the modal
134 | @media (min-width: $screen-sm-min) {
135 | // Automatically set modal's width for larger viewports
136 | .modal-dialog {
137 | width: $modal-md;
138 | margin: 30px auto;
139 | }
140 | .modal-content {
141 | @include box-shadow(0 5px 15px rgba(0,0,0,.5));
142 | }
143 |
144 | // Modal sizes
145 | .modal-sm { width: $modal-sm; }
146 | }
147 |
148 | @media (min-width: $screen-md-min) {
149 | .modal-lg { width: $modal-lg; }
150 | }
151 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_pager.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Pager pagination
3 | // --------------------------------------------------
4 |
5 |
6 | .pager {
7 | padding-left: 0;
8 | margin: $line-height-computed 0;
9 | list-style: none;
10 | text-align: center;
11 | @include clearfix;
12 | li {
13 | display: inline;
14 | > a,
15 | > span {
16 | display: inline-block;
17 | padding: 5px 14px;
18 | background-color: $pager-bg;
19 | border: 1px solid $pager-border;
20 | border-radius: $pager-border-radius;
21 | }
22 |
23 | > a:hover,
24 | > a:focus {
25 | text-decoration: none;
26 | background-color: $pager-hover-bg;
27 | }
28 | }
29 |
30 | .next {
31 | > a,
32 | > span {
33 | float: right;
34 | }
35 | }
36 |
37 | .previous {
38 | > a,
39 | > span {
40 | float: left;
41 | }
42 | }
43 |
44 | .disabled {
45 | > a,
46 | > a:hover,
47 | > a:focus,
48 | > span {
49 | color: $pager-disabled-color;
50 | background-color: $pager-bg;
51 | cursor: $cursor-disabled;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_pagination.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Pagination (multiple pages)
3 | // --------------------------------------------------
4 | .pagination {
5 | display: inline-block;
6 | padding-left: 0;
7 | margin: $line-height-computed 0;
8 | border-radius: $border-radius-base;
9 |
10 | > li {
11 | display: inline; // Remove list-style and block-level defaults
12 | > a,
13 | > span {
14 | position: relative;
15 | float: left; // Collapse white-space
16 | padding: $padding-base-vertical $padding-base-horizontal;
17 | line-height: $line-height-base;
18 | text-decoration: none;
19 | color: $pagination-color;
20 | background-color: $pagination-bg;
21 | border: 1px solid $pagination-border;
22 | margin-left: -1px;
23 | }
24 | &:first-child {
25 | > a,
26 | > span {
27 | margin-left: 0;
28 | @include border-left-radius($border-radius-base);
29 | }
30 | }
31 | &:last-child {
32 | > a,
33 | > span {
34 | @include border-right-radius($border-radius-base);
35 | }
36 | }
37 | }
38 |
39 | > li > a,
40 | > li > span {
41 | &:hover,
42 | &:focus {
43 | color: $pagination-hover-color;
44 | background-color: $pagination-hover-bg;
45 | border-color: $pagination-hover-border;
46 | }
47 | }
48 |
49 | > .active > a,
50 | > .active > span {
51 | &,
52 | &:hover,
53 | &:focus {
54 | z-index: 2;
55 | color: $pagination-active-color;
56 | background-color: $pagination-active-bg;
57 | border-color: $pagination-active-border;
58 | cursor: default;
59 | }
60 | }
61 |
62 | > .disabled {
63 | > span,
64 | > span:hover,
65 | > span:focus,
66 | > a,
67 | > a:hover,
68 | > a:focus {
69 | color: $pagination-disabled-color;
70 | background-color: $pagination-disabled-bg;
71 | border-color: $pagination-disabled-border;
72 | cursor: $cursor-disabled;
73 | }
74 | }
75 | }
76 |
77 | // Sizing
78 | // --------------------------------------------------
79 |
80 | // Large
81 | .pagination-lg {
82 | @include pagination-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $border-radius-large);
83 | }
84 |
85 | // Small
86 | .pagination-sm {
87 | @include pagination-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $border-radius-small);
88 | }
89 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_popovers.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Popovers
3 | // --------------------------------------------------
4 |
5 |
6 | .popover {
7 | position: absolute;
8 | top: 0;
9 | left: 0;
10 | z-index: $zindex-popover;
11 | display: none;
12 | max-width: $popover-max-width;
13 | padding: 1px;
14 | // Reset font and text properties given new insertion method
15 | font-family: $font-family-base;
16 | font-size: $font-size-base;
17 | font-weight: normal;
18 | line-height: $line-height-base;
19 | text-align: left;
20 | background-color: $popover-bg;
21 | background-clip: padding-box;
22 | border: 1px solid $popover-fallback-border-color;
23 | border: 1px solid $popover-border-color;
24 | border-radius: $border-radius-large;
25 | @include box-shadow(0 5px 10px rgba(0,0,0,.2));
26 |
27 | // Overrides for proper insertion
28 | white-space: normal;
29 |
30 | // Offset the popover to account for the popover arrow
31 | &.top { margin-top: -$popover-arrow-width; }
32 | &.right { margin-left: $popover-arrow-width; }
33 | &.bottom { margin-top: $popover-arrow-width; }
34 | &.left { margin-left: -$popover-arrow-width; }
35 | }
36 |
37 | .popover-title {
38 | margin: 0; // reset heading margin
39 | padding: 8px 14px;
40 | font-size: $font-size-base;
41 | background-color: $popover-title-bg;
42 | border-bottom: 1px solid darken($popover-title-bg, 5%);
43 | border-radius: ($border-radius-large - 1) ($border-radius-large - 1) 0 0;
44 | }
45 |
46 | .popover-content {
47 | padding: 9px 14px;
48 | }
49 |
50 | // Arrows
51 | //
52 | // .arrow is outer, .arrow:after is inner
53 |
54 | .popover > .arrow {
55 | &,
56 | &:after {
57 | position: absolute;
58 | display: block;
59 | width: 0;
60 | height: 0;
61 | border-color: transparent;
62 | border-style: solid;
63 | }
64 | }
65 | .popover > .arrow {
66 | border-width: $popover-arrow-outer-width;
67 | }
68 | .popover > .arrow:after {
69 | border-width: $popover-arrow-width;
70 | content: "";
71 | }
72 |
73 | .popover {
74 | &.top > .arrow {
75 | left: 50%;
76 | margin-left: -$popover-arrow-outer-width;
77 | border-bottom-width: 0;
78 | border-top-color: $popover-arrow-outer-fallback-color; // IE8 fallback
79 | border-top-color: $popover-arrow-outer-color;
80 | bottom: -$popover-arrow-outer-width;
81 | &:after {
82 | content: " ";
83 | bottom: 1px;
84 | margin-left: -$popover-arrow-width;
85 | border-bottom-width: 0;
86 | border-top-color: $popover-arrow-color;
87 | }
88 | }
89 | &.right > .arrow {
90 | top: 50%;
91 | left: -$popover-arrow-outer-width;
92 | margin-top: -$popover-arrow-outer-width;
93 | border-left-width: 0;
94 | border-right-color: $popover-arrow-outer-fallback-color; // IE8 fallback
95 | border-right-color: $popover-arrow-outer-color;
96 | &:after {
97 | content: " ";
98 | left: 1px;
99 | bottom: -$popover-arrow-width;
100 | border-left-width: 0;
101 | border-right-color: $popover-arrow-color;
102 | }
103 | }
104 | &.bottom > .arrow {
105 | left: 50%;
106 | margin-left: -$popover-arrow-outer-width;
107 | border-top-width: 0;
108 | border-bottom-color: $popover-arrow-outer-fallback-color; // IE8 fallback
109 | border-bottom-color: $popover-arrow-outer-color;
110 | top: -$popover-arrow-outer-width;
111 | &:after {
112 | content: " ";
113 | top: 1px;
114 | margin-left: -$popover-arrow-width;
115 | border-top-width: 0;
116 | border-bottom-color: $popover-arrow-color;
117 | }
118 | }
119 |
120 | &.left > .arrow {
121 | top: 50%;
122 | right: -$popover-arrow-outer-width;
123 | margin-top: -$popover-arrow-outer-width;
124 | border-right-width: 0;
125 | border-left-color: $popover-arrow-outer-fallback-color; // IE8 fallback
126 | border-left-color: $popover-arrow-outer-color;
127 | &:after {
128 | content: " ";
129 | right: 1px;
130 | border-right-width: 0;
131 | border-left-color: $popover-arrow-color;
132 | bottom: -$popover-arrow-width;
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_print.scss:
--------------------------------------------------------------------------------
1 | /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
2 |
3 | // ==========================================================================
4 | // Print styles.
5 | // Inlined to avoid the additional HTTP request: h5bp.com/r
6 | // ==========================================================================
7 |
8 | @media print {
9 | *,
10 | *:before,
11 | *:after {
12 | background: transparent !important;
13 | color: #000 !important; // Black prints faster: h5bp.com/s
14 | box-shadow: none !important;
15 | text-shadow: none !important;
16 | }
17 |
18 | a,
19 | a:visited {
20 | text-decoration: underline;
21 | }
22 |
23 | a[href]:after {
24 | content: " (" attr(href) ")";
25 | }
26 |
27 | abbr[title]:after {
28 | content: " (" attr(title) ")";
29 | }
30 |
31 | // Don't show links that are fragment identifiers,
32 | // or use the `javascript:` pseudo protocol
33 | a[href^="#"]:after,
34 | a[href^="javascript:"]:after {
35 | content: "";
36 | }
37 |
38 | pre,
39 | blockquote {
40 | border: 1px solid #999;
41 | page-break-inside: avoid;
42 | }
43 |
44 | thead {
45 | display: table-header-group; // h5bp.com/t
46 | }
47 |
48 | tr,
49 | img {
50 | page-break-inside: avoid;
51 | }
52 |
53 | img {
54 | max-width: 100% !important;
55 | }
56 |
57 | p,
58 | h2,
59 | h3 {
60 | orphans: 3;
61 | widows: 3;
62 | }
63 |
64 | h2,
65 | h3 {
66 | page-break-after: avoid;
67 | }
68 |
69 | // Bootstrap specific changes start
70 | //
71 | // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245
72 | // Once fixed, we can just straight up remove this.
73 | select {
74 | background: #fff !important;
75 | }
76 |
77 | // Bootstrap components
78 | .navbar {
79 | display: none;
80 | }
81 | .btn,
82 | .dropup > .btn {
83 | > .caret {
84 | border-top-color: #000 !important;
85 | }
86 | }
87 | .label {
88 | border: 1px solid #000;
89 | }
90 |
91 | .table {
92 | border-collapse: collapse !important;
93 |
94 | td,
95 | th {
96 | background-color: #fff !important;
97 | }
98 | }
99 | .table-bordered {
100 | th,
101 | td {
102 | border: 1px solid #ddd !important;
103 | }
104 | }
105 |
106 | // Bootstrap specific changes end
107 | }
108 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_progress-bars.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Progress bars
3 | // --------------------------------------------------
4 |
5 |
6 | // Bar animations
7 | // -------------------------
8 |
9 | // WebKit
10 | @-webkit-keyframes progress-bar-stripes {
11 | from { background-position: 40px 0; }
12 | to { background-position: 0 0; }
13 | }
14 |
15 | // Spec and IE10+
16 | @keyframes progress-bar-stripes {
17 | from { background-position: 40px 0; }
18 | to { background-position: 0 0; }
19 | }
20 |
21 |
22 | // Bar itself
23 | // -------------------------
24 |
25 | // Outer container
26 | .progress {
27 | overflow: hidden;
28 | height: $line-height-computed;
29 | margin-bottom: $line-height-computed;
30 | background-color: $progress-bg;
31 | border-radius: $progress-border-radius;
32 | @include box-shadow(inset 0 1px 2px rgba(0,0,0,.1));
33 | }
34 |
35 | // Bar of progress
36 | .progress-bar {
37 | float: left;
38 | width: 0%;
39 | height: 100%;
40 | font-size: $font-size-small;
41 | line-height: $line-height-computed;
42 | color: $progress-bar-color;
43 | text-align: center;
44 | background-color: $progress-bar-bg;
45 | @include box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));
46 | @include transition(width .6s ease);
47 | }
48 |
49 | // Striped bars
50 | //
51 | // `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the
52 | // `.progress-bar-striped` class, which you just add to an existing
53 | // `.progress-bar`.
54 | .progress-striped .progress-bar,
55 | .progress-bar-striped {
56 | @include gradient-striped;
57 | background-size: 40px 40px;
58 | }
59 |
60 | // Call animation for the active one
61 | //
62 | // `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the
63 | // `.progress-bar.active` approach.
64 | .progress.active .progress-bar,
65 | .progress-bar.active {
66 | @include animation(progress-bar-stripes 2s linear infinite);
67 | }
68 |
69 |
70 | // Variations
71 | // -------------------------
72 |
73 | .progress-bar-success {
74 | @include progress-bar-variant($progress-bar-success-bg);
75 | }
76 |
77 | .progress-bar-info {
78 | @include progress-bar-variant($progress-bar-info-bg);
79 | }
80 |
81 | .progress-bar-warning {
82 | @include progress-bar-variant($progress-bar-warning-bg);
83 | }
84 |
85 | .progress-bar-danger {
86 | @include progress-bar-variant($progress-bar-danger-bg);
87 | }
88 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_responsive-embed.scss:
--------------------------------------------------------------------------------
1 | // Embeds responsive
2 | //
3 | // Credit: Nicolas Gallagher and SUIT CSS.
4 |
5 | .embed-responsive {
6 | position: relative;
7 | display: block;
8 | height: 0;
9 | padding: 0;
10 | overflow: hidden;
11 |
12 | .embed-responsive-item,
13 | iframe,
14 | embed,
15 | object,
16 | video {
17 | position: absolute;
18 | top: 0;
19 | left: 0;
20 | bottom: 0;
21 | height: 100%;
22 | width: 100%;
23 | border: 0;
24 | }
25 | }
26 |
27 | // Modifier class for 16:9 aspect ratio
28 | .embed-responsive-16by9 {
29 | padding-bottom: 56.25%;
30 | }
31 |
32 | // Modifier class for 4:3 aspect ratio
33 | .embed-responsive-4by3 {
34 | padding-bottom: 75%;
35 | }
36 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_scaffolding.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Scaffolding
3 | // --------------------------------------------------
4 |
5 |
6 | // Reset the box-sizing
7 | //
8 | // Heads up! This reset may cause conflicts with some third-party widgets.
9 | // For recommendations on resolving such conflicts, see
10 | // http://getbootstrap.com/getting-started/#third-box-sizing
11 | * {
12 | @include box-sizing(border-box);
13 | }
14 | *:before,
15 | *:after {
16 | @include box-sizing(border-box);
17 | }
18 |
19 |
20 | // Body reset
21 |
22 | html {
23 | font-size: 10px;
24 | -webkit-tap-highlight-color: rgba(0,0,0,0);
25 | }
26 |
27 | body {
28 | font-family: $font-family-base;
29 | font-size: $font-size-base;
30 | line-height: $line-height-base;
31 | color: $text-color;
32 | background-color: $body-bg;
33 | }
34 |
35 | // Reset fonts for relevant elements
36 | input,
37 | button,
38 | select,
39 | textarea {
40 | font-family: inherit;
41 | font-size: inherit;
42 | line-height: inherit;
43 | }
44 |
45 |
46 | // Links
47 |
48 | a {
49 | color: $link-color;
50 | text-decoration: none;
51 |
52 | &:hover,
53 | &:focus {
54 | color: $link-hover-color;
55 | text-decoration: $link-hover-decoration;
56 | }
57 |
58 | &:focus {
59 | @include tab-focus;
60 | }
61 | }
62 |
63 |
64 | // Figures
65 | //
66 | // We reset this here because previously Normalize had no `figure` margins. This
67 | // ensures we don't break anyone's use of the element.
68 |
69 | figure {
70 | margin: 0;
71 | }
72 |
73 |
74 | // Images
75 |
76 | img {
77 | vertical-align: middle;
78 | }
79 |
80 | // Responsive images (ensure images don't scale beyond their parents)
81 | .img-responsive {
82 | @include img-responsive;
83 | }
84 |
85 | // Rounded corners
86 | .img-rounded {
87 | border-radius: $border-radius-large;
88 | }
89 |
90 | // Image thumbnails
91 | //
92 | // Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.
93 | .img-thumbnail {
94 | padding: $thumbnail-padding;
95 | line-height: $line-height-base;
96 | background-color: $thumbnail-bg;
97 | border: 1px solid $thumbnail-border;
98 | border-radius: $thumbnail-border-radius;
99 | @include transition(all .2s ease-in-out);
100 |
101 | // Keep them at most 100% wide
102 | @include img-responsive(inline-block);
103 | }
104 |
105 | // Perfect circle
106 | .img-circle {
107 | border-radius: 50%; // set radius in percents
108 | }
109 |
110 |
111 | // Horizontal rules
112 |
113 | hr {
114 | margin-top: $line-height-computed;
115 | margin-bottom: $line-height-computed;
116 | border: 0;
117 | border-top: 1px solid $hr-border;
118 | }
119 |
120 |
121 | // Only display content to screen readers
122 | //
123 | // See: http://a11yproject.com/posts/how-to-hide-content/
124 |
125 | .sr-only {
126 | position: absolute;
127 | width: 1px;
128 | height: 1px;
129 | margin: -1px;
130 | padding: 0;
131 | overflow: hidden;
132 | clip: rect(0,0,0,0);
133 | border: 0;
134 | }
135 |
136 | // Use in conjunction with .sr-only to only display content when it's focused.
137 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
138 | // Credit: HTML5 Boilerplate
139 |
140 | .sr-only-focusable {
141 | &:active,
142 | &:focus {
143 | position: static;
144 | width: auto;
145 | height: auto;
146 | margin: 0;
147 | overflow: visible;
148 | clip: auto;
149 | }
150 | }
151 |
152 |
153 | // iOS "clickable elements" fix for role="button"
154 | //
155 | // Fixes "clickability" issue (and more generally, the firing of events such as focus as well)
156 | // for traditionally non-focusable elements with role="button"
157 | // see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
158 | // Upstream patch for normalize.css submitted: https://github.com/necolas/normalize.css/pull/379 - remove this fix once that is merged
159 |
160 | [role="button"] {
161 | cursor: pointer;
162 | }
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_thumbnails.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Thumbnails
3 | // --------------------------------------------------
4 |
5 |
6 | // Mixin and adjust the regular image class
7 | .thumbnail {
8 | display: block;
9 | padding: $thumbnail-padding;
10 | margin-bottom: $line-height-computed;
11 | line-height: $line-height-base;
12 | background-color: $thumbnail-bg;
13 | border: 1px solid $thumbnail-border;
14 | border-radius: $thumbnail-border-radius;
15 | @include transition(border .2s ease-in-out);
16 |
17 | > img,
18 | a > img {
19 | @include img-responsive;
20 | margin-left: auto;
21 | margin-right: auto;
22 | }
23 |
24 | // [converter] extracted a&:hover, a&:focus, a&.active to a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active
25 |
26 | // Image captions
27 | .caption {
28 | padding: $thumbnail-caption-padding;
29 | color: $thumbnail-caption-color;
30 | }
31 | }
32 |
33 | // Add a hover state for linked versions only
34 | a.thumbnail:hover,
35 | a.thumbnail:focus,
36 | a.thumbnail.active {
37 | border-color: $link-color;
38 | }
39 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_tooltip.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Tooltips
3 | // --------------------------------------------------
4 |
5 |
6 | // Base class
7 | .tooltip {
8 | position: absolute;
9 | z-index: $zindex-tooltip;
10 | display: block;
11 | // Reset font and text properties given new insertion method
12 | font-family: $font-family-base;
13 | font-size: $font-size-small;
14 | font-weight: normal;
15 | line-height: 1.4;
16 | @include opacity(0);
17 |
18 | &.in { @include opacity($tooltip-opacity); }
19 | &.top { margin-top: -3px; padding: $tooltip-arrow-width 0; }
20 | &.right { margin-left: 3px; padding: 0 $tooltip-arrow-width; }
21 | &.bottom { margin-top: 3px; padding: $tooltip-arrow-width 0; }
22 | &.left { margin-left: -3px; padding: 0 $tooltip-arrow-width; }
23 | }
24 |
25 | // Wrapper for the tooltip content
26 | .tooltip-inner {
27 | max-width: $tooltip-max-width;
28 | padding: 3px 8px;
29 | color: $tooltip-color;
30 | text-align: center;
31 | text-decoration: none;
32 | background-color: $tooltip-bg;
33 | border-radius: $border-radius-base;
34 | }
35 |
36 | // Arrows
37 | .tooltip-arrow {
38 | position: absolute;
39 | width: 0;
40 | height: 0;
41 | border-color: transparent;
42 | border-style: solid;
43 | }
44 | // Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1
45 | .tooltip {
46 | &.top .tooltip-arrow {
47 | bottom: 0;
48 | left: 50%;
49 | margin-left: -$tooltip-arrow-width;
50 | border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
51 | border-top-color: $tooltip-arrow-color;
52 | }
53 | &.top-left .tooltip-arrow {
54 | bottom: 0;
55 | right: $tooltip-arrow-width;
56 | margin-bottom: -$tooltip-arrow-width;
57 | border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
58 | border-top-color: $tooltip-arrow-color;
59 | }
60 | &.top-right .tooltip-arrow {
61 | bottom: 0;
62 | left: $tooltip-arrow-width;
63 | margin-bottom: -$tooltip-arrow-width;
64 | border-width: $tooltip-arrow-width $tooltip-arrow-width 0;
65 | border-top-color: $tooltip-arrow-color;
66 | }
67 | &.right .tooltip-arrow {
68 | top: 50%;
69 | left: 0;
70 | margin-top: -$tooltip-arrow-width;
71 | border-width: $tooltip-arrow-width $tooltip-arrow-width $tooltip-arrow-width 0;
72 | border-right-color: $tooltip-arrow-color;
73 | }
74 | &.left .tooltip-arrow {
75 | top: 50%;
76 | right: 0;
77 | margin-top: -$tooltip-arrow-width;
78 | border-width: $tooltip-arrow-width 0 $tooltip-arrow-width $tooltip-arrow-width;
79 | border-left-color: $tooltip-arrow-color;
80 | }
81 | &.bottom .tooltip-arrow {
82 | top: 0;
83 | left: 50%;
84 | margin-left: -$tooltip-arrow-width;
85 | border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
86 | border-bottom-color: $tooltip-arrow-color;
87 | }
88 | &.bottom-left .tooltip-arrow {
89 | top: 0;
90 | right: $tooltip-arrow-width;
91 | margin-top: -$tooltip-arrow-width;
92 | border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
93 | border-bottom-color: $tooltip-arrow-color;
94 | }
95 | &.bottom-right .tooltip-arrow {
96 | top: 0;
97 | left: $tooltip-arrow-width;
98 | margin-top: -$tooltip-arrow-width;
99 | border-width: 0 $tooltip-arrow-width $tooltip-arrow-width;
100 | border-bottom-color: $tooltip-arrow-color;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_utilities.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Utility classes
3 | // --------------------------------------------------
4 |
5 |
6 | // Floats
7 | // -------------------------
8 |
9 | .clearfix {
10 | @include clearfix;
11 | }
12 | .center-block {
13 | @include center-block;
14 | }
15 | .pull-right {
16 | float: right !important;
17 | }
18 | .pull-left {
19 | float: left !important;
20 | }
21 |
22 |
23 | // Toggling content
24 | // -------------------------
25 |
26 | // Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1
27 | .hide {
28 | display: none !important;
29 | }
30 | .show {
31 | display: block !important;
32 | }
33 | .invisible {
34 | visibility: hidden;
35 | }
36 | .text-hide {
37 | @include text-hide;
38 | }
39 |
40 |
41 | // Hide from screenreaders and browsers
42 | //
43 | // Credit: HTML5 Boilerplate
44 |
45 | .hidden {
46 | display: none !important;
47 | }
48 |
49 |
50 | // For Affix plugin
51 | // -------------------------
52 |
53 | .affix {
54 | position: fixed;
55 | }
56 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/_wells.scss:
--------------------------------------------------------------------------------
1 | //
2 | // Wells
3 | // --------------------------------------------------
4 |
5 |
6 | // Base class
7 | .well {
8 | min-height: 20px;
9 | padding: 19px;
10 | margin-bottom: 20px;
11 | background-color: $well-bg;
12 | border: 1px solid $well-border;
13 | border-radius: $border-radius-base;
14 | @include box-shadow(inset 0 1px 1px rgba(0,0,0,.05));
15 | blockquote {
16 | border-color: #ddd;
17 | border-color: rgba(0,0,0,.15);
18 | }
19 | }
20 |
21 | // Sizes
22 | .well-lg {
23 | padding: 24px;
24 | border-radius: $border-radius-large;
25 | }
26 | .well-sm {
27 | padding: 9px;
28 | border-radius: $border-radius-small;
29 | }
30 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_alerts.scss:
--------------------------------------------------------------------------------
1 | // Alerts
2 |
3 | @mixin alert-variant($background, $border, $text-color) {
4 | background-color: $background;
5 | border-color: $border;
6 | color: $text-color;
7 |
8 | hr {
9 | border-top-color: darken($border, 5%);
10 | }
11 | .alert-link {
12 | color: darken($text-color, 10%);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_background-variant.scss:
--------------------------------------------------------------------------------
1 | // Contextual backgrounds
2 |
3 | // [converter] $parent hack
4 | @mixin bg-variant($parent, $color) {
5 | #{$parent} {
6 | background-color: $color;
7 | }
8 | a#{$parent}:hover {
9 | background-color: darken($color, 10%);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_border-radius.scss:
--------------------------------------------------------------------------------
1 | // Single side border-radius
2 |
3 | @mixin border-top-radius($radius) {
4 | border-top-right-radius: $radius;
5 | border-top-left-radius: $radius;
6 | }
7 | @mixin border-right-radius($radius) {
8 | border-bottom-right-radius: $radius;
9 | border-top-right-radius: $radius;
10 | }
11 | @mixin border-bottom-radius($radius) {
12 | border-bottom-right-radius: $radius;
13 | border-bottom-left-radius: $radius;
14 | }
15 | @mixin border-left-radius($radius) {
16 | border-bottom-left-radius: $radius;
17 | border-top-left-radius: $radius;
18 | }
19 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_buttons.scss:
--------------------------------------------------------------------------------
1 | // Button variants
2 | //
3 | // Easily pump out default styles, as well as :hover, :focus, :active,
4 | // and disabled options for all buttons
5 |
6 | @mixin button-variant($color, $background, $border) {
7 | color: $color;
8 | background-color: $background;
9 | border-color: $border;
10 |
11 | &:hover,
12 | &:focus,
13 | &.focus,
14 | &:active,
15 | &.active,
16 | .open > &.dropdown-toggle {
17 | color: $color;
18 | background-color: darken($background, 10%);
19 | border-color: darken($border, 12%);
20 | }
21 | &:active,
22 | &.active,
23 | .open > &.dropdown-toggle {
24 | background-image: none;
25 | }
26 | &.disabled,
27 | &[disabled],
28 | fieldset[disabled] & {
29 | &,
30 | &:hover,
31 | &:focus,
32 | &.focus,
33 | &:active,
34 | &.active {
35 | background-color: $background;
36 | border-color: $border;
37 | }
38 | }
39 |
40 | .badge {
41 | color: $background;
42 | background-color: $color;
43 | }
44 | }
45 |
46 | // Button sizes
47 | @mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {
48 | padding: $padding-vertical $padding-horizontal;
49 | font-size: $font-size;
50 | line-height: $line-height;
51 | border-radius: $border-radius;
52 | }
53 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_center-block.scss:
--------------------------------------------------------------------------------
1 | // Center-align a block level element
2 |
3 | @mixin center-block() {
4 | display: block;
5 | margin-left: auto;
6 | margin-right: auto;
7 | }
8 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_clearfix.scss:
--------------------------------------------------------------------------------
1 | // Clearfix
2 | //
3 | // For modern browsers
4 | // 1. The space content is one way to avoid an Opera bug when the
5 | // contenteditable attribute is included anywhere else in the document.
6 | // Otherwise it causes space to appear at the top and bottom of elements
7 | // that are clearfixed.
8 | // 2. The use of `table` rather than `block` is only necessary if using
9 | // `:before` to contain the top-margins of child elements.
10 | //
11 | // Source: http://nicolasgallagher.com/micro-clearfix-hack/
12 |
13 | @mixin clearfix() {
14 | &:before,
15 | &:after {
16 | content: " "; // 1
17 | display: table; // 2
18 | }
19 | &:after {
20 | clear: both;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_forms.scss:
--------------------------------------------------------------------------------
1 | // Form validation states
2 | //
3 | // Used in forms.less to generate the form validation CSS for warnings, errors,
4 | // and successes.
5 |
6 | @mixin form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) {
7 | // Color the label and help text
8 | .help-block,
9 | .control-label,
10 | .radio,
11 | .checkbox,
12 | .radio-inline,
13 | .checkbox-inline,
14 | &.radio label,
15 | &.checkbox label,
16 | &.radio-inline label,
17 | &.checkbox-inline label {
18 | color: $text-color;
19 | }
20 | // Set the border and box shadow on specific inputs to match
21 | .form-control {
22 | border-color: $border-color;
23 | @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work
24 | &:focus {
25 | border-color: darken($border-color, 10%);
26 | $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%);
27 | @include box-shadow($shadow);
28 | }
29 | }
30 | // Set validation states also for addons
31 | .input-group-addon {
32 | color: $text-color;
33 | border-color: $border-color;
34 | background-color: $background-color;
35 | }
36 | // Optional feedback icon
37 | .form-control-feedback {
38 | color: $text-color;
39 | }
40 | }
41 |
42 |
43 | // Form control focus state
44 | //
45 | // Generate a customized focus state and for any input with the specified color,
46 | // which defaults to the `$input-border-focus` variable.
47 | //
48 | // We highly encourage you to not customize the default value, but instead use
49 | // this to tweak colors on an as-needed basis. This aesthetic change is based on
50 | // WebKit's default styles, but applicable to a wider range of browsers. Its
51 | // usability and accessibility should be taken into account with any change.
52 | //
53 | // Example usage: change the default blue border and shadow to white for better
54 | // contrast against a dark gray background.
55 | @mixin form-control-focus($color: $input-border-focus) {
56 | $color-rgba: rgba(red($color), green($color), blue($color), .6);
57 | &:focus {
58 | border-color: $color;
59 | outline: 0;
60 | @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba);
61 | }
62 | }
63 |
64 | // Form control sizing
65 | //
66 | // Relative text size, padding, and border-radii changes for form controls. For
67 | // horizontal sizing, wrap controls in the predefined grid classes. `
`
68 | // element gets special love because it's special, and that's a fact!
69 | // [converter] $parent hack
70 | @mixin input-size($parent, $input-height, $padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) {
71 | #{$parent} {
72 | height: $input-height;
73 | padding: $padding-vertical $padding-horizontal;
74 | font-size: $font-size;
75 | line-height: $line-height;
76 | border-radius: $border-radius;
77 | }
78 |
79 | select#{$parent} {
80 | height: $input-height;
81 | line-height: $input-height;
82 | }
83 |
84 | textarea#{$parent},
85 | select[multiple]#{$parent} {
86 | height: auto;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_grid-framework.scss:
--------------------------------------------------------------------------------
1 | // Framework grid generation
2 | //
3 | // Used only by Bootstrap to generate the correct number of grid classes given
4 | // any value of `$grid-columns`.
5 |
6 | // [converter] This is defined recursively in LESS, but Sass supports real loops
7 | @mixin make-grid-columns($i: 1, $list: ".col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}") {
8 | @for $i from (1 + 1) through $grid-columns {
9 | $list: "#{$list}, .col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}";
10 | }
11 | #{$list} {
12 | position: relative;
13 | // Prevent columns from collapsing when empty
14 | min-height: 1px;
15 | // Inner gutter via padding
16 | padding-left: ($grid-gutter-width / 2);
17 | padding-right: ($grid-gutter-width / 2);
18 | }
19 | }
20 |
21 |
22 | // [converter] This is defined recursively in LESS, but Sass supports real loops
23 | @mixin float-grid-columns($class, $i: 1, $list: ".col-#{$class}-#{$i}") {
24 | @for $i from (1 + 1) through $grid-columns {
25 | $list: "#{$list}, .col-#{$class}-#{$i}";
26 | }
27 | #{$list} {
28 | float: left;
29 | }
30 | }
31 |
32 |
33 | @mixin calc-grid-column($index, $class, $type) {
34 | @if ($type == width) and ($index > 0) {
35 | .col-#{$class}-#{$index} {
36 | width: percentage(($index / $grid-columns));
37 | }
38 | }
39 | @if ($type == push) and ($index > 0) {
40 | .col-#{$class}-push-#{$index} {
41 | left: percentage(($index / $grid-columns));
42 | }
43 | }
44 | @if ($type == push) and ($index == 0) {
45 | .col-#{$class}-push-0 {
46 | left: auto;
47 | }
48 | }
49 | @if ($type == pull) and ($index > 0) {
50 | .col-#{$class}-pull-#{$index} {
51 | right: percentage(($index / $grid-columns));
52 | }
53 | }
54 | @if ($type == pull) and ($index == 0) {
55 | .col-#{$class}-pull-0 {
56 | right: auto;
57 | }
58 | }
59 | @if ($type == offset) {
60 | .col-#{$class}-offset-#{$index} {
61 | margin-left: percentage(($index / $grid-columns));
62 | }
63 | }
64 | }
65 |
66 | // [converter] This is defined recursively in LESS, but Sass supports real loops
67 | @mixin loop-grid-columns($columns, $class, $type) {
68 | @for $i from 0 through $columns {
69 | @include calc-grid-column($i, $class, $type);
70 | }
71 | }
72 |
73 |
74 | // Create grid for specific class
75 | @mixin make-grid($class) {
76 | @include float-grid-columns($class);
77 | @include loop-grid-columns($grid-columns, $class, width);
78 | @include loop-grid-columns($grid-columns, $class, pull);
79 | @include loop-grid-columns($grid-columns, $class, push);
80 | @include loop-grid-columns($grid-columns, $class, offset);
81 | }
82 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_grid.scss:
--------------------------------------------------------------------------------
1 | // Grid system
2 | //
3 | // Generate semantic grid columns with these mixins.
4 |
5 | // Centered container element
6 | @mixin container-fixed($gutter: $grid-gutter-width) {
7 | margin-right: auto;
8 | margin-left: auto;
9 | padding-left: ($gutter / 2);
10 | padding-right: ($gutter / 2);
11 | @include clearfix;
12 | }
13 |
14 | // Creates a wrapper for a series of columns
15 | @mixin make-row($gutter: $grid-gutter-width) {
16 | margin-left: ($gutter / -2);
17 | margin-right: ($gutter / -2);
18 | @include clearfix;
19 | }
20 |
21 | // Generate the extra small columns
22 | @mixin make-xs-column($columns, $gutter: $grid-gutter-width) {
23 | position: relative;
24 | float: left;
25 | width: percentage(($columns / $grid-columns));
26 | min-height: 1px;
27 | padding-left: ($gutter / 2);
28 | padding-right: ($gutter / 2);
29 | }
30 | @mixin make-xs-column-offset($columns) {
31 | margin-left: percentage(($columns / $grid-columns));
32 | }
33 | @mixin make-xs-column-push($columns) {
34 | left: percentage(($columns / $grid-columns));
35 | }
36 | @mixin make-xs-column-pull($columns) {
37 | right: percentage(($columns / $grid-columns));
38 | }
39 |
40 | // Generate the small columns
41 | @mixin make-sm-column($columns, $gutter: $grid-gutter-width) {
42 | position: relative;
43 | min-height: 1px;
44 | padding-left: ($gutter / 2);
45 | padding-right: ($gutter / 2);
46 |
47 | @media (min-width: $screen-sm-min) {
48 | float: left;
49 | width: percentage(($columns / $grid-columns));
50 | }
51 | }
52 | @mixin make-sm-column-offset($columns) {
53 | @media (min-width: $screen-sm-min) {
54 | margin-left: percentage(($columns / $grid-columns));
55 | }
56 | }
57 | @mixin make-sm-column-push($columns) {
58 | @media (min-width: $screen-sm-min) {
59 | left: percentage(($columns / $grid-columns));
60 | }
61 | }
62 | @mixin make-sm-column-pull($columns) {
63 | @media (min-width: $screen-sm-min) {
64 | right: percentage(($columns / $grid-columns));
65 | }
66 | }
67 |
68 | // Generate the medium columns
69 | @mixin make-md-column($columns, $gutter: $grid-gutter-width) {
70 | position: relative;
71 | min-height: 1px;
72 | padding-left: ($gutter / 2);
73 | padding-right: ($gutter / 2);
74 |
75 | @media (min-width: $screen-md-min) {
76 | float: left;
77 | width: percentage(($columns / $grid-columns));
78 | }
79 | }
80 | @mixin make-md-column-offset($columns) {
81 | @media (min-width: $screen-md-min) {
82 | margin-left: percentage(($columns / $grid-columns));
83 | }
84 | }
85 | @mixin make-md-column-push($columns) {
86 | @media (min-width: $screen-md-min) {
87 | left: percentage(($columns / $grid-columns));
88 | }
89 | }
90 | @mixin make-md-column-pull($columns) {
91 | @media (min-width: $screen-md-min) {
92 | right: percentage(($columns / $grid-columns));
93 | }
94 | }
95 |
96 | // Generate the large columns
97 | @mixin make-lg-column($columns, $gutter: $grid-gutter-width) {
98 | position: relative;
99 | min-height: 1px;
100 | padding-left: ($gutter / 2);
101 | padding-right: ($gutter / 2);
102 |
103 | @media (min-width: $screen-lg-min) {
104 | float: left;
105 | width: percentage(($columns / $grid-columns));
106 | }
107 | }
108 | @mixin make-lg-column-offset($columns) {
109 | @media (min-width: $screen-lg-min) {
110 | margin-left: percentage(($columns / $grid-columns));
111 | }
112 | }
113 | @mixin make-lg-column-push($columns) {
114 | @media (min-width: $screen-lg-min) {
115 | left: percentage(($columns / $grid-columns));
116 | }
117 | }
118 | @mixin make-lg-column-pull($columns) {
119 | @media (min-width: $screen-lg-min) {
120 | right: percentage(($columns / $grid-columns));
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_hide-text.scss:
--------------------------------------------------------------------------------
1 | // CSS image replacement
2 | //
3 | // Heads up! v3 launched with with only `.hide-text()`, but per our pattern for
4 | // mixins being reused as classes with the same name, this doesn't hold up. As
5 | // of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.
6 | //
7 | // Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
8 |
9 | // Deprecated as of v3.0.1 (will be removed in v4)
10 | @mixin hide-text() {
11 | font: 0/0 a;
12 | color: transparent;
13 | text-shadow: none;
14 | background-color: transparent;
15 | border: 0;
16 | }
17 |
18 | // New mixin to use as of v3.0.1
19 | @mixin text-hide() {
20 | @include hide-text;
21 | }
22 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_image.scss:
--------------------------------------------------------------------------------
1 | // Image Mixins
2 | // - Responsive image
3 | // - Retina image
4 |
5 |
6 | // Responsive image
7 | //
8 | // Keep images from scaling beyond the width of their parents.
9 | @mixin img-responsive($display: block) {
10 | display: $display;
11 | max-width: 100%; // Part 1: Set a maximum relative to the parent
12 | height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching
13 | }
14 |
15 |
16 | // Retina image
17 | //
18 | // Short retina mixin for setting background-image and -size. Note that the
19 | // spelling of `min--moz-device-pixel-ratio` is intentional.
20 | @mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {
21 | background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-1x}"), "#{$file-1x}"));
22 |
23 | @media
24 | only screen and (-webkit-min-device-pixel-ratio: 2),
25 | only screen and ( min--moz-device-pixel-ratio: 2),
26 | only screen and ( -o-min-device-pixel-ratio: 2/1),
27 | only screen and ( min-device-pixel-ratio: 2),
28 | only screen and ( min-resolution: 192dpi),
29 | only screen and ( min-resolution: 2dppx) {
30 | background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-2x}"), "#{$file-2x}"));
31 | background-size: $width-1x $height-1x;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_labels.scss:
--------------------------------------------------------------------------------
1 | // Labels
2 |
3 | @mixin label-variant($color) {
4 | background-color: $color;
5 |
6 | &[href] {
7 | &:hover,
8 | &:focus {
9 | background-color: darken($color, 10%);
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_list-group.scss:
--------------------------------------------------------------------------------
1 | // List Groups
2 |
3 | @mixin list-group-item-variant($state, $background, $color) {
4 | .list-group-item-#{$state} {
5 | color: $color;
6 | background-color: $background;
7 |
8 | // [converter] extracted a& to a.list-group-item-#{$state}
9 | }
10 |
11 | a.list-group-item-#{$state} {
12 | color: $color;
13 |
14 | .list-group-item-heading {
15 | color: inherit;
16 | }
17 |
18 | &:hover,
19 | &:focus {
20 | color: $color;
21 | background-color: darken($background, 5%);
22 | }
23 | &.active,
24 | &.active:hover,
25 | &.active:focus {
26 | color: #fff;
27 | background-color: $color;
28 | border-color: $color;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_nav-divider.scss:
--------------------------------------------------------------------------------
1 | // Horizontal dividers
2 | //
3 | // Dividers (basically an hr) within dropdowns and nav lists
4 |
5 | @mixin nav-divider($color: #e5e5e5) {
6 | height: 1px;
7 | margin: (($line-height-computed / 2) - 1) 0;
8 | overflow: hidden;
9 | background-color: $color;
10 | }
11 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_nav-vertical-align.scss:
--------------------------------------------------------------------------------
1 | // Navbar vertical align
2 | //
3 | // Vertically center elements in the navbar.
4 | // Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.
5 |
6 | @mixin navbar-vertical-align($element-height) {
7 | margin-top: (($navbar-height - $element-height) / 2);
8 | margin-bottom: (($navbar-height - $element-height) / 2);
9 | }
10 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_opacity.scss:
--------------------------------------------------------------------------------
1 | // Opacity
2 |
3 | @mixin opacity($opacity) {
4 | opacity: $opacity;
5 | // IE8 filter
6 | $opacity-ie: ($opacity * 100);
7 | filter: alpha(opacity=$opacity-ie);
8 | }
9 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_pagination.scss:
--------------------------------------------------------------------------------
1 | // Pagination
2 |
3 | @mixin pagination-size($padding-vertical, $padding-horizontal, $font-size, $border-radius) {
4 | > li {
5 | > a,
6 | > span {
7 | padding: $padding-vertical $padding-horizontal;
8 | font-size: $font-size;
9 | }
10 | &:first-child {
11 | > a,
12 | > span {
13 | @include border-left-radius($border-radius);
14 | }
15 | }
16 | &:last-child {
17 | > a,
18 | > span {
19 | @include border-right-radius($border-radius);
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_panels.scss:
--------------------------------------------------------------------------------
1 | // Panels
2 |
3 | @mixin panel-variant($border, $heading-text-color, $heading-bg-color, $heading-border) {
4 | border-color: $border;
5 |
6 | & > .panel-heading {
7 | color: $heading-text-color;
8 | background-color: $heading-bg-color;
9 | border-color: $heading-border;
10 |
11 | + .panel-collapse > .panel-body {
12 | border-top-color: $border;
13 | }
14 | .badge {
15 | color: $heading-bg-color;
16 | background-color: $heading-text-color;
17 | }
18 | }
19 | & > .panel-footer {
20 | + .panel-collapse > .panel-body {
21 | border-bottom-color: $border;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_progress-bar.scss:
--------------------------------------------------------------------------------
1 | // Progress bars
2 |
3 | @mixin progress-bar-variant($color) {
4 | background-color: $color;
5 |
6 | // Deprecated parent class requirement as of v3.2.0
7 | .progress-striped & {
8 | @include gradient-striped;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_reset-filter.scss:
--------------------------------------------------------------------------------
1 | // Reset filters for IE
2 | //
3 | // When you need to remove a gradient background, do not forget to use this to reset
4 | // the IE filter for IE9 and below.
5 |
6 | @mixin reset-filter() {
7 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
8 | }
9 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_resize.scss:
--------------------------------------------------------------------------------
1 | // Resize anything
2 |
3 | @mixin resizable($direction) {
4 | resize: $direction; // Options: horizontal, vertical, both
5 | overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible`
6 | }
7 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_responsive-visibility.scss:
--------------------------------------------------------------------------------
1 | // Responsive utilities
2 |
3 | //
4 | // More easily include all the states for responsive-utilities.less.
5 | // [converter] $parent hack
6 | @mixin responsive-visibility($parent) {
7 | #{$parent} {
8 | display: block !important;
9 | }
10 | table#{$parent} { display: table; }
11 | tr#{$parent} { display: table-row !important; }
12 | th#{$parent},
13 | td#{$parent} { display: table-cell !important; }
14 | }
15 |
16 | // [converter] $parent hack
17 | @mixin responsive-invisibility($parent) {
18 | #{$parent} {
19 | display: none !important;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_size.scss:
--------------------------------------------------------------------------------
1 | // Sizing shortcuts
2 |
3 | @mixin size($width, $height) {
4 | width: $width;
5 | height: $height;
6 | }
7 |
8 | @mixin square($size) {
9 | @include size($size, $size);
10 | }
11 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_tab-focus.scss:
--------------------------------------------------------------------------------
1 | // WebKit-style focus
2 |
3 | @mixin tab-focus() {
4 | // Default
5 | outline: thin dotted;
6 | // WebKit
7 | outline: 5px auto -webkit-focus-ring-color;
8 | outline-offset: -2px;
9 | }
10 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_table-row.scss:
--------------------------------------------------------------------------------
1 | // Tables
2 |
3 | @mixin table-row-variant($state, $background) {
4 | // Exact selectors below required to override `.table-striped` and prevent
5 | // inheritance to nested tables.
6 | .table > thead > tr,
7 | .table > tbody > tr,
8 | .table > tfoot > tr {
9 | > td.#{$state},
10 | > th.#{$state},
11 | &.#{$state} > td,
12 | &.#{$state} > th {
13 | background-color: $background;
14 | }
15 | }
16 |
17 | // Hover states for `.table-hover`
18 | // Note: this is not available for cells or rows within `thead` or `tfoot`.
19 | .table-hover > tbody > tr {
20 | > td.#{$state}:hover,
21 | > th.#{$state}:hover,
22 | &.#{$state}:hover > td,
23 | &:hover > .#{$state},
24 | &.#{$state}:hover > th {
25 | background-color: darken($background, 5%);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_text-emphasis.scss:
--------------------------------------------------------------------------------
1 | // Typography
2 |
3 | // [converter] $parent hack
4 | @mixin text-emphasis-variant($parent, $color) {
5 | #{$parent} {
6 | color: $color;
7 | }
8 | a#{$parent}:hover {
9 | color: darken($color, 10%);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/bootstrap/mixins/_text-overflow.scss:
--------------------------------------------------------------------------------
1 | // Text overflow
2 | // Requires inline-block or block for proper styling
3 |
4 | @mixin text-overflow() {
5 | overflow: hidden;
6 | text-overflow: ellipsis;
7 | white-space: nowrap;
8 | }
9 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome
3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
4 | */
5 |
6 | @import "font-awesome/variables";
7 | @import "font-awesome/mixins";
8 | @import "font-awesome/path";
9 | @import "font-awesome/core";
10 | @import "font-awesome/larger";
11 | @import "font-awesome/fixed-width";
12 | @import "font-awesome/list";
13 | @import "font-awesome/bordered-pulled";
14 | @import "font-awesome/animated";
15 | @import "font-awesome/rotated-flipped";
16 | @import "font-awesome/stacked";
17 | @import "font-awesome/icons";
18 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_animated.scss:
--------------------------------------------------------------------------------
1 | // Spinning Icons
2 | // --------------------------
3 |
4 | .#{$fa-css-prefix}-spin {
5 | -webkit-animation: fa-spin 2s infinite linear;
6 | animation: fa-spin 2s infinite linear;
7 | }
8 |
9 | .#{$fa-css-prefix}-pulse {
10 | -webkit-animation: fa-spin 1s infinite steps(8);
11 | animation: fa-spin 1s infinite steps(8);
12 | }
13 |
14 | @-webkit-keyframes fa-spin {
15 | 0% {
16 | -webkit-transform: rotate(0deg);
17 | transform: rotate(0deg);
18 | }
19 | 100% {
20 | -webkit-transform: rotate(359deg);
21 | transform: rotate(359deg);
22 | }
23 | }
24 |
25 | @keyframes fa-spin {
26 | 0% {
27 | -webkit-transform: rotate(0deg);
28 | transform: rotate(0deg);
29 | }
30 | 100% {
31 | -webkit-transform: rotate(359deg);
32 | transform: rotate(359deg);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_bordered-pulled.scss:
--------------------------------------------------------------------------------
1 | // Bordered & Pulled
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-border {
5 | padding: .2em .25em .15em;
6 | border: solid .08em $fa-border-color;
7 | border-radius: .1em;
8 | }
9 |
10 | .pull-right { float: right; }
11 | .pull-left { float: left; }
12 |
13 | .#{$fa-css-prefix} {
14 | &.pull-left { margin-right: .3em; }
15 | &.pull-right { margin-left: .3em; }
16 | }
17 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_core.scss:
--------------------------------------------------------------------------------
1 | // Base Class Definition
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix} {
5 | display: inline-block;
6 | font: normal normal normal #{$fa-font-size-base}/1 FontAwesome; // shortening font declaration
7 | font-size: inherit; // can't have font-size inherit on line above, so need to override
8 | text-rendering: auto; // optimizelegibility throws things off #1094
9 | -webkit-font-smoothing: antialiased;
10 | -moz-osx-font-smoothing: grayscale;
11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_fixed-width.scss:
--------------------------------------------------------------------------------
1 | // Fixed Width Icons
2 | // -------------------------
3 | .#{$fa-css-prefix}-fw {
4 | width: (18em / 14);
5 | text-align: center;
6 | }
7 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_larger.scss:
--------------------------------------------------------------------------------
1 | // Icon Sizes
2 | // -------------------------
3 |
4 | /* makes the font 33% larger relative to the icon container */
5 | .#{$fa-css-prefix}-lg {
6 | font-size: (4em / 3);
7 | line-height: (3em / 4);
8 | vertical-align: -15%;
9 | }
10 | .#{$fa-css-prefix}-2x { font-size: 2em; }
11 | .#{$fa-css-prefix}-3x { font-size: 3em; }
12 | .#{$fa-css-prefix}-4x { font-size: 4em; }
13 | .#{$fa-css-prefix}-5x { font-size: 5em; }
14 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_list.scss:
--------------------------------------------------------------------------------
1 | // List Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-ul {
5 | padding-left: 0;
6 | margin-left: $fa-li-width;
7 | list-style-type: none;
8 | > li { position: relative; }
9 | }
10 | .#{$fa-css-prefix}-li {
11 | position: absolute;
12 | left: -$fa-li-width;
13 | width: $fa-li-width;
14 | top: (2em / 14);
15 | text-align: center;
16 | &.#{$fa-css-prefix}-lg {
17 | left: -$fa-li-width + (4em / 14);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_mixins.scss:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // --------------------------
3 |
4 | @mixin fa-icon() {
5 | display: inline-block;
6 | font: normal normal normal #{$fa-font-size-base}/1 FontAwesome; // shortening font declaration
7 | font-size: inherit; // can't have font-size inherit on line above, so need to override
8 | text-rendering: auto; // optimizelegibility throws things off #1094
9 | -webkit-font-smoothing: antialiased;
10 | -moz-osx-font-smoothing: grayscale;
11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox
12 |
13 | }
14 |
15 | @mixin fa-icon-rotate($degrees, $rotation) {
16 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
17 | -webkit-transform: rotate($degrees);
18 | -ms-transform: rotate($degrees);
19 | transform: rotate($degrees);
20 | }
21 |
22 | @mixin fa-icon-flip($horiz, $vert, $rotation) {
23 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
24 | -webkit-transform: scale($horiz, $vert);
25 | -ms-transform: scale($horiz, $vert);
26 | transform: scale($horiz, $vert);
27 | }
28 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_path.scss:
--------------------------------------------------------------------------------
1 | /* FONT PATH
2 | * -------------------------- */
3 |
4 | @font-face {
5 | font-family: 'FontAwesome';
6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}');
7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'),
8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'),
9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'),
10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'),
11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg');
12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
13 | font-weight: normal;
14 | font-style: normal;
15 | }
16 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_rotated-flipped.scss:
--------------------------------------------------------------------------------
1 | // Rotated & Flipped Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); }
5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); }
6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); }
7 |
8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); }
9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); }
10 |
11 | // Hook for IE8-9
12 | // -------------------------
13 |
14 | :root .#{$fa-css-prefix}-rotate-90,
15 | :root .#{$fa-css-prefix}-rotate-180,
16 | :root .#{$fa-css-prefix}-rotate-270,
17 | :root .#{$fa-css-prefix}-flip-horizontal,
18 | :root .#{$fa-css-prefix}-flip-vertical {
19 | filter: none;
20 | }
21 |
--------------------------------------------------------------------------------
/app/Resources/assets/scss/font-awesome/_stacked.scss:
--------------------------------------------------------------------------------
1 | // Stacked Icons
2 | // -------------------------
3 |
4 | .#{$fa-css-prefix}-stack {
5 | position: relative;
6 | display: inline-block;
7 | width: 2em;
8 | height: 2em;
9 | line-height: 2em;
10 | vertical-align: middle;
11 | }
12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x {
13 | position: absolute;
14 | left: 0;
15 | width: 100%;
16 | text-align: center;
17 | }
18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; }
19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; }
20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; }
21 |
--------------------------------------------------------------------------------
/app/Resources/translations/messages.ro.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | title.post_list
7 | Lista de articole
8 |
9 |
10 | action.show
11 | Vezi
12 |
13 |
14 | action.edit
15 | Modifică
16 |
17 |
18 | action.create_post
19 | Creează un articol nou
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/Resources/translations/validators.cs.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | post.blank_summary
7 | Napište shrnutí příspěvku!
8 |
9 |
10 | post.too_short_content
11 | Příspěvek je příliš krátký (musí mít minimálně {{ limit }} znak)|Příspěvek je příliš krátký (musí mít minimálně {{ limit }} znaky)|Příspěvek je příliš krátký (musí mít minimálně {{ limit }} znaků)
12 |
13 |
17 |
21 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/Resources/translations/validators.en.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | post.blank_summary
7 | Give your post a summary!
8 |
9 |
10 | post.too_short_content
11 | Post content is too short ({{ limit }} characters minimum)
12 |
13 |
17 |
21 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/Resources/translations/validators.es.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | post.blank_summary
7 | No es posible dejar el resumen del artículo vacío.
8 |
9 |
10 | post.too_short_content
11 | El contenido del artículo es demasiado corto ({{ limit }} caracteres como mínimo)
12 |
13 |
17 |
21 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/Resources/translations/validators.fr.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | post.blank_summary
7 | Veuillez donner un résumé à votre post.
8 |
9 |
10 | post.too_short_content
11 | Le contenu de votre post est trop court ({{ limit }} caractères minimum)
12 |
13 |
17 |
21 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/Resources/translations/validators.pt_BR.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | post.blank_summary
7 | Informe um sumário para o seu post!
8 |
9 |
10 | post.too_short_content
11 | O conteúdo do post está muito curto (mínimo de {{ limit }} caracteres)
12 |
13 |
17 |
21 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/Resources/translations/validators.ru.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | post.blank_summary
7 | Введите краткое содержание вашей записи!
8 |
9 |
10 | post.too_short_content
11 | Содержание записи слишком короткое (минимум {{ limit }} символов).
12 |
13 |
17 |
21 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/Resources/translations/validators.uk.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | post.blank_summary
7 | Введіть короткий зміст вашого запису!
8 |
9 |
10 | post.too_short_content
11 | Зміст запису занадто короткий (мінімум {{limit}} символів).
12 |
13 |
17 |
21 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/Resources/views/admin/blog/_form.html.twig:
--------------------------------------------------------------------------------
1 | {#
2 | By default, forms enable client-side validation. This means that you can't
3 | test the server-side validation errors from the browser. To temporarily
4 | disable this validation, add the 'novalidate' attribute:
5 |
6 | {{ form_start(form, { attr: { novalidate: 'novalidate' } }) }}
7 | #}
8 |
9 | {{ form_start(form) }}
10 | {{ form_widget(form) }}
11 |
12 |
14 |
15 | {% if include_back_to_home_link is not defined or include_back_to_home_link == true %}
16 |
17 | {{ 'action.back_to_list'|trans }}
18 |
19 | {% endif %}
20 | {{ form_end(form) }}
21 |
--------------------------------------------------------------------------------
/app/Resources/views/admin/blog/edit.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block body_id 'admin_post_edit' %}
4 |
5 | {% block main %}
6 | {{ 'title.edit_post'|trans({'%id%': post.id}) }}
7 |
8 | {{ include('admin/blog/_form.html.twig', {
9 | form: edit_form,
10 | button_label: 'action.save'|trans,
11 | }, with_context = false) }}
12 | {% endblock %}
13 |
14 | {% block sidebar %}
15 |
16 | {{ include('admin/blog/_form.html.twig', {
17 | form: delete_form,
18 | button_label: 'action.delete_post'|trans,
19 | button_css: 'btn btn-lg btn-block btn-danger',
20 | include_back_to_home_link: false
21 | }, with_context = false) }}
22 |
23 |
24 | {{ parent() }}
25 | {% endblock %}
26 |
--------------------------------------------------------------------------------
/app/Resources/views/admin/blog/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block body_id 'admin_post_index' %}
4 |
5 | {% block main %}
6 | {{ 'title.post_list'|trans }}
7 |
8 |
9 |
10 |
11 | {{ 'label.title'|trans }}
12 | {{ 'label.author'|trans }}
13 | {{ 'label.comments'|trans }}
14 | {{ 'label.published_at'|trans }}
15 | {{ 'label.actions'|trans }}
16 |
17 |
18 |
19 | {% for post in posts %}
20 |
21 | {{ post.title }}
22 | {{ post.authorEmail }}
23 | {{ post.comments|length }}
24 | {% if post.publishedAt %}{{ post.publishedAt|localizeddate('short', 'short', 'en') }}{% endif %}
25 |
26 |
37 |
38 |
39 | {% endfor %}
40 |
41 |
42 | {% endblock %}
43 |
44 | {% block sidebar %}
45 |
50 |
51 | {{ parent() }}
52 | {% endblock %}
53 |
--------------------------------------------------------------------------------
/app/Resources/views/admin/blog/new.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block body_id 'admin_post_new' %}
4 |
5 | {% block main %}
6 | {{ 'title.post_new'|trans }}
7 |
8 | {{ include('admin/blog/_form.html.twig') }}
9 | {% endblock %}
10 |
--------------------------------------------------------------------------------
/app/Resources/views/admin/blog/show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block body_id 'admin_post_show' %}
4 |
5 | {% block main %}
6 | {{ post.title }}
7 |
8 |
9 |
10 |
11 | {{ 'label.summary'|trans }}
12 | {{ post.summary|md2html }}
13 |
14 |
15 | {{ 'label.content'|trans }}
16 | {{ post.content|md2html }}
17 |
18 |
19 | {{ 'label.author'|trans }}
20 | {{ post.authorEmail }}
21 |
22 |
23 | {{ 'label.comments'|trans }}
24 | {{ post.comments|length }}
25 |
26 |
27 | {{ 'label.published_at'|trans }}
28 | {{ post.publishedAt|localizeddate('long', 'medium', 'en') }}
29 |
30 |
31 |
32 | {% endblock %}
33 |
34 | {% block sidebar %}
35 |
40 |
41 |
42 | {{ include('admin/blog/_form.html.twig', {
43 | form: delete_form,
44 | button_label: 'action.delete_post'|trans,
45 | button_css: 'btn btn-lg btn-block btn-danger',
46 | include_back_to_home_link: false
47 | }, with_context = false) }}
48 |
49 | {% endblock %}
50 |
--------------------------------------------------------------------------------
/app/Resources/views/admin/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'admin/layout.html.twig' %}
2 |
3 | {% block body_id 'admin_index' %}
4 |
5 | {% block main %}
6 | {{ 'title.dashboard'|trans }}
7 |
8 |
9 | {{ 'dashboard.posts_count' | trans }}
10 | {{ posts_count }}
11 | {{ 'dashboard.comments_count' | trans }}
12 | {{ comments_count }}
13 |
14 | {% endblock %}
15 |
16 | {% block sidebar %}
17 |
22 |
23 | {{ parent() }}
24 | {% endblock %}
25 |
--------------------------------------------------------------------------------
/app/Resources/views/admin/layout.html.twig:
--------------------------------------------------------------------------------
1 | {#
2 | This is the base template of the all backend pages. Since this layout is similar
3 | to the global layout, we inherit from it to just change the contents of some
4 | blocks. In practice, backend templates are using a three-level inheritance,
5 | showing how powerful, yet easy to use, is Twig's inheritance mechanism.
6 | See http://symfony.com/doc/current/book/templating.html#template-inheritance-and-layouts
7 | #}
8 | {% extends 'base.html.twig' %}
9 |
10 | {% block header_navigation_links %}
11 |
12 |
13 | {{ 'menu.dashboard'|trans }}
14 |
15 |
16 |
17 |
18 | {{ 'menu.post_list'|trans }}
19 |
20 |
21 |
22 |
23 | {{ 'menu.back_to_blog'|trans }}
24 |
25 |
26 | {% endblock %}
27 |
28 | {% block sidebar %}
29 |
30 |
31 |
32 | {{ 'dashboard.posts_count' | trans }}: {{ stats_posts_count() }}
33 | {{ 'dashboard.comments_count' | trans }}: {{ stats_comments_count() }}
34 |
35 |
36 |
37 |
38 | {{ parent() }}
39 | {% endblock %}
40 |
--------------------------------------------------------------------------------
/app/Resources/views/blog/comment_form.html.twig:
--------------------------------------------------------------------------------
1 | {#
2 | By default, forms enable client-side validation. This means that you can't
3 | test the server-side validation errors from the browser. To temporarily
4 | disable this validation, add the 'novalidate' attribute:
5 |
6 | {{ form_start(form, { method: ..., action: ..., attr: { novalidate: 'novalidate' } }) }}
7 | #}
8 |
9 | {{ form_start(form, { method: 'POST', action: path('comment_new', { 'postSlug': post.slug }) }) }}
10 | {# instead of displaying form fields one by one, you can also display them
11 | all with their default options and styles just by calling to this function:
12 |
13 | {{ form_widget(form) }}
14 | #}
15 |
16 |
17 | {{ 'title.add_comment'|trans }}
18 |
19 |
20 | {{ form_label(form.content, 'Content', { label_attr: { class: 'hidden' }}) }}
21 |
22 | {% if not form.vars.valid %}
23 | {{ form_errors(form.content) }}
24 | {% endif %}
25 |
26 | {{ form_widget(form.content, { attr: { rows: 10 } }) }}
27 |
28 |
29 |
30 | {{ form_widget(form.submit, { attr: { class: 'btn-primary pull-right' }, label: 'action.publish_comment'|trans }) }}
31 |
32 |
33 | {{ form_end(form) }}
34 |
--------------------------------------------------------------------------------
/app/Resources/views/blog/comment_form_error.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block body_id 'comment_form_error' %}
4 |
5 | {% block main %}
6 | {{ 'title.comment_error'|trans }}
7 |
8 |
9 | {{ include('blog/comment_form.html.twig') }}
10 |
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/app/Resources/views/blog/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block body_id 'blog_index' %}
4 |
5 | {% block main %}
6 | {% for post in posts %}
7 |
8 |
13 |
14 | {{ post.summary|md2html }}
15 |
16 | {% endfor %}
17 | {% endblock %}
18 |
--------------------------------------------------------------------------------
/app/Resources/views/blog/post_show.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block body_id 'blog_post_show' %}
4 |
5 | {% block main %}
6 | {{ post.title }}
7 |
8 | {{ post.content|md2html }}
9 |
10 |
28 |
29 | {{ 'post.num_comments'|transchoice(post.comments|length) }}
30 |
31 | {% for comment in post.comments %}
32 |
41 | {% else %}
42 |
45 | {% endfor %}
46 | {% endblock %}
47 |
48 | {% block sidebar %}
49 | {% if app.user and post.isAuthor(app.user) %}
50 |
55 | {% endif %}
56 |
57 | {# the parent() function includes the contents defined by the parent template
58 | ('base.html.twig') for this block ('sidebar'). This is a very convenient way
59 | to share common contents in different templates #}
60 | {{ parent() }}
61 |
62 | {{ render(controller('AppBundle:Forecast:info')) }}
63 | {% endblock %}
64 |
65 | {% block javascripts %}
66 | {{ parent() }}
67 |
84 | {% endblock %}
85 |
--------------------------------------------------------------------------------
/app/Resources/views/default/homepage.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block body_id 'homepage' %}
4 |
5 | {#
6 | the homepage is a special page which displays neither a header nor a footer.
7 | this is done with the 'trick' of defining empty Twig blocks without any content
8 | #}
9 | {% block header %}{% endblock %}
10 | {% block footer %}{% endblock %}
11 |
12 | {% block body %}
13 |
16 |
17 |
44 | {% endblock %}
45 |
--------------------------------------------------------------------------------
/app/Resources/views/forecast/info.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ forecast.temperature|round }} °C
5 |
{{ forecast.summary }}
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/Resources/views/security/login.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block body_id 'login' %}
4 |
5 | {% block main %}
6 | {% if error %}
7 |
8 | {{ error.messageKey|trans(error.messageData, 'security') }}
9 |
10 | {% endif %}
11 |
12 |
13 |
34 |
35 |
36 |
37 |
38 | {{ 'help.login_users'|trans }}
39 |
40 |
41 |
42 |
43 |
44 | {{ 'label.username'|trans }}
45 | {{ 'label.password'|trans }}
46 | {{ 'label.role'|trans }}
47 |
48 |
49 |
50 |
51 | john_user
52 | kitten
53 | ROLE_USER
({{ 'help.role_user'|trans }})
54 |
55 |
56 | anna_admin
57 | kitten
58 | ROLE_ADMIN
({{ 'help.role_admin'|trans }})
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | {{ 'note'|trans }}
67 | {{ 'help.reload_fixtures'|trans }}
68 |
69 | $ php app/console doctrine:fixtures:load
70 |
71 |
72 |
73 | {{ 'tip'|trans }}
74 | {{ 'help.add_user'|trans }}
75 |
76 | $ php app/console app:add-user
77 |
78 |
79 |
80 |
81 |
82 | {% endblock %}
83 |
84 | {% block javascripts %}
85 | {{ parent() }}
86 |
87 |
93 | {% endblock %}
94 |
--------------------------------------------------------------------------------
/app/autoload.php:
--------------------------------------------------------------------------------
1 | save_run($xhprof_data, $app);
21 | });
22 | uprofiler_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
23 |
--------------------------------------------------------------------------------
/app/cache/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/app/cache/.gitkeep
--------------------------------------------------------------------------------
/app/config/config.yml:
--------------------------------------------------------------------------------
1 | # This is the main configuration file of your application. It stores all the
2 | # common options for every execution environment ('prod', 'dev', 'test').
3 |
4 | # To avoid creating configuration files that are too long, we first import some
5 | # files that define the values for important parts of the Symfony application,
6 | # such as the security component and the dependency injection services
7 | imports:
8 | - { resource: parameters.yml }
9 | - { resource: security.yml }
10 | - { resource: services.yml }
11 |
12 | # These are the configuration parameters that define the application's behavior
13 | # and which are independent from the underlying technical infrastructure
14 | # See http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
15 | parameters:
16 | # This parameter defines the codes of the locales (languages) enabled in the application
17 | app_locales: en
18 |
19 | # Basic configuration for the Symfony framework features
20 | framework:
21 | # Uncomment the 'ide' option to turn all of the file paths in an exception
22 | # page into clickable links that open the given file using your favorite IDE.
23 | # Supported values are 'textmate', 'macvim', 'emacs' and 'sublime' shortcuts
24 | # and any custom configuration string, such as: "phpstorm://open?file=%%f&line=%%l"
25 | # See http://symfony.com/doc/current/reference/configuration/framework.html#ide
26 | ide: sublime
27 |
28 | # esi: ~
29 | translator: { fallback: "%locale%" }
30 | secret: "%secret%"
31 | router:
32 | resource: "%kernel.root_dir%/config/routing.yml"
33 | strict_requirements: ~
34 | profiler: { only_exceptions: false }
35 | form: ~
36 | csrf_protection: ~
37 | validation: { enable_annotations: true }
38 | templating:
39 | engines: ['twig']
40 | default_locale: "%locale%"
41 | trusted_hosts: ~
42 | trusted_proxies: ~
43 | session:
44 | # handler_id set to null will use default session handler from php.ini
45 | handler_id: ~
46 | fragments: ~
47 | http_method_override: true
48 |
49 | # Twig Configuration (used for rendering application templates)
50 | twig:
51 | debug: "%kernel.debug%"
52 | strict_variables: "%kernel.debug%"
53 | form_themes:
54 | - "bootstrap_3_layout.html.twig"
55 |
56 | # Assetic Configuration (used for managing web assets: CSS, JavaScript, Sass, etc.)
57 | assetic:
58 | debug: "%kernel.debug%"
59 | use_controller: false
60 | bundles: [ ]
61 | filters:
62 | cssrewrite: ~
63 | jsqueeze: ~
64 | scssphp:
65 | # the formatter must be the FQCN (don't use the 'compressed' value)
66 | formatter: "Leafo\\ScssPhp\\Formatter\\Compressed"
67 |
68 | # Doctrine Configuration (used to access databases and manipulate their information)
69 | doctrine:
70 | dbal:
71 | # instead of configuring the database access options in this file, we pull
72 | # them from the app/config/parameters.yml file. The reason is that config.yml
73 | # stores options that change the application behavior and parameters.yml
74 | # stores options that change from one server to another
75 | driver: "%database_driver%"
76 | host: "%database_host%"
77 | port: "%database_port%"
78 | dbname: "%database_name%"
79 | user: "%database_user%"
80 | password: "%database_password%"
81 | logging: true
82 | profiling: true
83 | charset: UTF8
84 | # if using pdo_sqlite as your database driver, add the path in parameters.yml
85 | # e.g. database_path: "%kernel.root_dir%/data/data.db3"
86 | path: "%database_path%"
87 |
88 | orm:
89 | auto_generate_proxy_classes: "%kernel.debug%"
90 | auto_mapping: true
91 |
92 | # Swiftmailer Configuration (used to send emails)
93 | swiftmailer:
94 | transport: "%mailer_transport%"
95 | host: "%mailer_host%"
96 | username: "%mailer_user%"
97 | password: "%mailer_password%"
98 | spool: { type: memory }
99 |
--------------------------------------------------------------------------------
/app/config/config_dev.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: config.yml }
3 |
4 | framework:
5 | router:
6 | resource: "%kernel.root_dir%/config/routing_dev.yml"
7 | strict_requirements: true
8 | profiler: { only_exceptions: false }
9 |
10 | web_profiler:
11 | toolbar: %kernel.debug%
12 | intercept_redirects: false
13 |
14 | monolog:
15 | handlers:
16 | main:
17 | type: stream
18 | path: "%kernel.logs_dir%/%kernel.environment%.log"
19 | level: info
20 | console:
21 | type: console
22 | bubble: false
23 | # uncomment to get logging in your browser
24 | # you may have to allow bigger header sizes in your Web server configuration
25 | #firephp:
26 | # type: firephp
27 | # level: info
28 | #chromephp:
29 | # type: chromephp
30 | # level: info
31 |
32 | assetic:
33 | use_controller: true
34 |
35 | #swiftmailer:
36 | # delivery_address: me@example.com
37 |
38 | parameters:
39 | app.forecast.class: AppBundle\Mocks\Utils\Forecast
40 | app.spam_validator.class: AppBundle\Mocks\Utils\SpamValidator
41 |
--------------------------------------------------------------------------------
/app/config/config_prod.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: config.yml }
3 |
4 | #framework:
5 | # validation:
6 | # cache: apc
7 |
8 | #doctrine:
9 | # orm:
10 | # metadata_cache_driver: apc
11 | # result_cache_driver: apc
12 | # query_cache_driver: apc
13 |
14 | monolog:
15 | handlers:
16 | main:
17 | type: fingers_crossed
18 | action_level: error
19 | handler: nested
20 | nested:
21 | type: stream
22 | path: "%kernel.logs_dir%/%kernel.environment%.log"
23 | level: debug
24 | console:
25 | type: console
26 |
--------------------------------------------------------------------------------
/app/config/config_test.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: config_dev.yml }
3 |
4 | framework:
5 | test: ~
6 | session:
7 | storage_id: session.storage.mock_file
8 | profiler:
9 | collect: false
10 |
11 | web_profiler:
12 | toolbar: false
13 | intercept_redirects: false
14 |
15 | swiftmailer:
16 | disable_delivery: true
17 |
18 | # It's recommended to use a separate database for tests. This allows to have a
19 | # fixed and known set of data fixtures, it simplifies the code of tests and it
20 | # makes them more robust.
21 | # In this case we just need to define a different path for the application database.
22 | doctrine:
23 | dbal:
24 | path: "%kernel.root_dir%/data/blog_test.sqlite"
25 |
26 | # this configuration simplifies testing URLs protected by the security mechanism
27 | # See http://symfony.com/doc/current/cookbook/testing/http_authentication.html
28 | security:
29 | firewalls:
30 | secured_area:
31 | http_basic: ~
32 |
--------------------------------------------------------------------------------
/app/config/parameters.yml.dist:
--------------------------------------------------------------------------------
1 | # This file defines the canonical configuration parameters of the application.
2 | # Symfony uses this file as a template to generate the real app/config/parameters.yml
3 | # used by the application.
4 | # See http://symfony.com/doc/current/best_practices/configuration.html#canonical-parameters
5 | parameters:
6 | # this demo application uses an embedded SQLite database to simplify setup.
7 | # in a real Symfony application you probably will use a MySQL or PostgreSQL database
8 | database_driver: pdo_sqlite
9 | database_host: 127.0.0.1
10 | database_port: ~
11 | database_name: symfony
12 | database_user: root
13 | database_password: ~
14 | # the 'database_path' is only used for SQLite type databases
15 | database_path: %kernel.root_dir%/data/blog.sqlite
16 |
17 | # Uncomment these lines to use a MySQL database instead of SQLite:
18 | #
19 | # database_driver: pdo_mysql
20 | # database_host: 127.0.0.1
21 | # database_port: null
22 | # database_name: symfony_demo
23 | # database_user: root
24 | # database_password: null
25 | #
26 | # You can even create the database and load the sample data from the command line:
27 | #
28 | # $ cd your-symfony-project/
29 | # $ php app/console doctrine:database:create
30 | # $ php app/console doctrine:schema:create
31 | # $ php app/console doctrine:fixtures:load
32 |
33 | # If you don't use a real mail server, you can send emails via your Gmail account.
34 | # see http://symfony.com/doc/current/cookbook/email/gmail.html
35 | mailer_transport: smtp
36 | mailer_host: 127.0.0.1
37 | mailer_user: ~
38 | mailer_password: ~
39 |
40 | # The code of the default language used by the application ('en' = English)
41 | locale: en
42 |
43 | # The 'secret' value is a random string of characters, numbers and symbols
44 | # used internally by Symfony in several places (CSRF tokens, URI signing,
45 | # 'Remember Me' functionality, etc.)
46 | # see: http://symfony.com/doc/current/reference/configuration/framework.html#secret
47 | secret: 'secret_value_for_symfony_demo_application'
48 |
--------------------------------------------------------------------------------
/app/config/routing.yml:
--------------------------------------------------------------------------------
1 | # These first lines load the all routes defined as @Route() annotations in any
2 | # controller defined inside the src/AppBundle/Controller/ directory. Controllers
3 | # are loaded recursively, so you can separate them into subdirectories.
4 | # If you don't like to add annotations in your applications, you can also define
5 | # the routes in YAML, XML or PHP files.
6 | # See http://symfony.com/doc/current/book/routing.html
7 | app:
8 | resource: @AppBundle/Controller/
9 | type: annotation
10 | prefix: /{_locale}
11 | requirements:
12 | _locale: %app_locales%
13 | defaults:
14 | _locale: %locale%
15 |
16 | # These lines define a route using YAML configuration. The controller used by
17 | # the route (FrameworkBundle:Template:template) is a convenient shortcut when
18 | # the template can be rendered without executing any logic in your own controller.
19 | # See http://symfony.com/doc/current/cookbook/templating/render_without_controller.html
20 | homepage:
21 | path: /{_locale}
22 | defaults:
23 | _controller: FrameworkBundle:Template:template
24 | template: 'default/homepage.html.twig'
25 | _locale: "%locale%"
26 |
--------------------------------------------------------------------------------
/app/config/routing_dev.yml:
--------------------------------------------------------------------------------
1 | _wdt:
2 | resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
3 | prefix: /_wdt
4 |
5 | _profiler:
6 | resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
7 | prefix: /_profiler
8 |
9 | _main:
10 | resource: routing.yml
11 |
--------------------------------------------------------------------------------
/app/config/security.yml:
--------------------------------------------------------------------------------
1 | security:
2 | encoders:
3 | # Our user class and the algorithm we'll use to encode passwords
4 | # http://symfony.com/doc/current/book/security.html#encoding-the-user-s-password
5 | AppBundle\Entity\User: bcrypt
6 |
7 | providers:
8 | # in this example, users are stored via Doctrine in the database
9 | # To see the users at src/AppBundle/DataFixtures/ORM/LoadFixtures.php
10 | # To load users from somewhere else: http://symfony.com/doc/current/cookbook/security/custom_provider.html
11 | database_users:
12 | entity: { class: AppBundle:User, property: username }
13 |
14 | # http://symfony.com/doc/current/book/security.html#firewalls-authentication
15 | firewalls:
16 | secured_area:
17 | # this firewall applies to all URLs
18 | pattern: ^/
19 |
20 | # but the firewall does not require login on every page
21 | # denying access is done in access_control or in your controllers
22 | anonymous: true
23 |
24 | # This allows the user to login by submitting a username and password
25 | # Reference: http://symfony.com/doc/current/cookbook/security/form_login_setup.html
26 | form_login:
27 | # The route name that the login form submits to
28 | check_path: security_login_check
29 | # The name of the route where the login form lives
30 | # When the user tries to access a protected page, they are redirected here
31 | login_path: security_login_form
32 | # Secure the login form against CSRF
33 | # Reference: http://symfony.com/doc/current/cookbook/security/csrf_in_login_form.html
34 | csrf_provider: security.csrf.token_manager
35 |
36 | logout:
37 | # The route name the user can go to in order to logout
38 | path: security_logout
39 | # The name of the route to redirect to after logging out
40 | target: homepage
41 |
42 | access_control:
43 | # this is a catch-all for the admin area
44 | # additional security lives in the controllers
45 | - { path: ^/admin, roles: ROLE_ADMIN }
46 |
--------------------------------------------------------------------------------
/app/config/services.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | app.notifications.email_sender: anonymous@example.com
3 | app.forecast.class: AppBundle\Utils\Forecast
4 | app.spam_validator.class: AppBundle\Utils\SpamValidator
5 |
6 | services:
7 | # First we define some basic services to make these utilities available in
8 | # the entire application
9 | slugger:
10 | class: AppBundle\Utils\Slugger
11 |
12 | markdown:
13 | class: AppBundle\Utils\Markdown
14 |
15 | # These are the Twig extensions that create new filters and functions for
16 | # using them in the templates
17 | app.twig.app_extension:
18 | public: false
19 | class: AppBundle\Twig\AppExtension
20 | arguments: ["@markdown"]
21 | tags:
22 | - { name: twig.extension }
23 |
24 | app.twig.locale_extension:
25 | public: false
26 | class: AppBundle\Twig\LocaleExtension
27 | arguments: ["%app_locales%"]
28 | tags:
29 | - { name: twig.extension }
30 |
31 | app.twig.stats_extension:
32 | public: false
33 | class: AppBundle\Twig\StatsExtension
34 | arguments: ["@doctrine"]
35 | tags:
36 | - { name: twig.extension }
37 |
38 | app.twig.extension_intl:
39 | public: false
40 | class: Twig_Extensions_Extension_Intl
41 | tags:
42 | - { name: twig.extension }
43 |
44 | app.forecast:
45 | class: %app.forecast.class%
46 | arguments: ["https://forecast-ws.appspot.com"]
47 |
48 | app.server_run_listener:
49 | class: AppBundle\EventListener\ServerRunListener
50 | tags:
51 | - { name: 'kernel.event_listener', event: console.command, method: listenForServerRunCommand }
52 |
53 | app.spam_validator:
54 | class: %app.spam_validator.class%
55 |
56 | app.comment_listener:
57 | class: AppBundle\EventListener\CommentListener
58 | arguments: ["@app.spam_validator"]
59 | tags:
60 | - { name: doctrine.event_listener, event: postPersist }
61 |
62 | # Uncomment the following lines to define a service for the Post Doctrine repository.
63 | # It's not mandatory to create these services, but if you use repositories a lot,
64 | # these services simplify your code:
65 | #
66 | # post_repository:
67 | # class: Doctrine\ORM\EntityRepository
68 | # factory: ["@doctrine.orm.entity_manager", getRepository]
69 | # arguments: [AppBundle\Entity\Post]
70 | #
71 | # // traditional code inside a controller
72 | # $em = $this->getDoctrine()->getManager();
73 | # $posts = $em->getRepository('AppBundle:Post')->findAll();
74 | #
75 | # // same code using repository services
76 | # $posts = $this->get('post_repository')->findAll();
77 |
--------------------------------------------------------------------------------
/app/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');
21 | $debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod';
22 |
23 | if ($debug) {
24 | Debug::enable();
25 | }
26 |
27 | $kernel = new AppKernel($env, $debug);
28 | $application = new Application($kernel);
29 | $application->run($input);
30 |
--------------------------------------------------------------------------------
/app/data/blog.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/app/data/blog.sqlite
--------------------------------------------------------------------------------
/app/data/blog_test.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/app/data/blog_test.sqlite
--------------------------------------------------------------------------------
/app/logs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/app/logs/.gitkeep
--------------------------------------------------------------------------------
/app/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
17 |
18 | ../src/*Bundle/Tests
19 | ../src/*/*Bundle/Tests
20 | ../src/*/Bundle/*Bundle/Tests
21 |
22 |
23 |
24 |
29 |
30 |
31 |
32 | ../src
33 |
34 | ../src/*Bundle/Resources
35 | ../src/*Bundle/Tests
36 | ../src/*/*Bundle/Resources
37 | ../src/*/*Bundle/Tests
38 | ../src/*/Bundle/*Bundle/Resources
39 | ../src/*/Bundle/*Bundle/Tests
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "symfony/symfony-demo",
3 | "license": "MIT",
4 | "type": "project",
5 | "description": "Symfony Demo Application",
6 | "autoload": {
7 | "psr-4": { "": "src/" },
8 | "classmap": [ "app/AppKernel.php", "app/AppCache.php" ]
9 | },
10 | "repositories": [
11 | {
12 | "type": "vcs",
13 | "url": "https://github.com/sensiolabs-de/orm"
14 | }
15 | ],
16 | "require": {
17 | "php" : ">=7.3",
18 | "ext-pdo_sqlite" : "*",
19 | "doctrine/doctrine-bundle" : "^1.10",
20 | "doctrine/doctrine-fixtures-bundle" : "^2.4",
21 | "doctrine/orm" : "^2.5@dev",
22 | "erusev/parsedown" : "^1.5",
23 | "ezyang/htmlpurifier" : "^4.7",
24 | "incenteev/composer-parameter-handler" : "~2.1",
25 | "ircmaxell/password-compat" : "~1.0",
26 | "leafo/scssphp" : "^0.8.4",
27 | "patchwork/jsqueeze" : "~1.0",
28 | "sensio/distribution-bundle" : "^5.0",
29 | "sensio/framework-extra-bundle" : "^3.0",
30 | "symfony/assetic-bundle" : "^2.8",
31 | "symfony/monolog-bundle" : "^3.0.2",
32 | "symfony/swiftmailer-bundle" : "~2.3",
33 | "symfony/symfony" : "~2.8",
34 | "twig/extensions" : "^1.5",
35 | "fzaninotto/faker": "^1.5",
36 | "white-october/pagerfanta-bundle" : "^1.0"
37 | },
38 | "require-dev": {
39 | "sensio/generator-bundle": "~3.0"
40 | },
41 | "scripts": {
42 | "post-install-cmd": [
43 | "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
44 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
45 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
46 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
47 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
48 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
49 | ],
50 | "post-update-cmd": [
51 | "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
52 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
53 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
54 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
55 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
56 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
57 | ]
58 | },
59 | "config": {
60 | "bin-dir": "bin",
61 | "platform": {
62 | "php": "7.3"
63 | }
64 | },
65 | "extra": {
66 | "symfony-app-dir": "app",
67 | "symfony-web-dir": "web",
68 | "symfony-assets-install": "relative",
69 | "incenteev-parameters": {
70 | "file": "app/config/parameters.yml",
71 | "env-map": {
72 | "database_url": "DATABASE_URL",
73 | "secret": "SYMFONY_SECRET"
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | blackfire:
5 | image: blackfire/blackfire:latest
6 | environment:
7 | - BLACKFIRE_SERVER_ID
8 | - BLACKFIRE_SERVER_TOKEN
9 | app:
10 | build: docker/php
11 | volumes:
12 | - .:/app
13 | ports:
14 | - "8000:8000"
15 | links:
16 | - blackfire
17 |
--------------------------------------------------------------------------------
/docker/php/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:7.4-cli
2 |
3 | # Install Blackfire.io
4 | RUN export VERSION=`php -r "echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION;"` \
5 | && curl -A "Docker" -o /tmp/blackfire-probe.tar.gz -D - -L -s https://blackfire.io/api/v1/releases/probe/php/linux/amd64/${VERSION} \
6 | && tar zxpf /tmp/blackfire-probe.tar.gz -C /tmp \
7 | && mv /tmp/blackfire-*.so `php -r "echo ini_get('extension_dir');"`/blackfire.so \
8 | && echo "extension=blackfire.so\nblackfire.agent_socket=\${BLACKFIRE_PORT}" > $PHP_INI_DIR/conf.d/blackfire.ini \
9 | && rm -Rf /tmp/*
10 |
11 | # Install composer
12 | RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \
13 | php -r "if (hash_file('sha384', 'composer-setup.php') === 'c5b9b6d368201a9db6f74e2611495f369991b72d9c8cbd3ffbc63edff210eb73d46ffbfce88669ad33695ef77dc76976') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" && \
14 | php composer-setup.php && \
15 | php -r "unlink('composer-setup.php');" && \
16 | mv composer.phar /usr/local/bin/composer
17 |
18 | # Enable OPCache
19 | RUN docker-php-ext-install opcache && \
20 | pecl install apcu-5.1.18 && \
21 | docker-php-ext-enable apcu
22 |
23 | COPY php.ini /usr/local/etc/php/conf.d/php.ini
24 |
25 | WORKDIR /app
26 |
27 | CMD app/console server:run 0.0.0.0:8000 --env=prod
28 |
--------------------------------------------------------------------------------
/docker/php/php.ini:
--------------------------------------------------------------------------------
1 | date.timezone = Europe/London
2 | short_open_tag = Off
3 | blackfire.agent_socket = tcp://blackfire:8707
4 |
--------------------------------------------------------------------------------
/src/.htaccess:
--------------------------------------------------------------------------------
1 |
2 | Require all denied
3 |
4 |
5 | Order deny,allow
6 | Deny from all
7 |
8 |
--------------------------------------------------------------------------------
/src/AppBundle/AppBundle.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle;
13 |
14 | use Symfony\Component\HttpKernel\Bundle\Bundle;
15 |
16 | /**
17 | * This class is the one that transforms the src/AppBundle/ directory into a real
18 | * Symfony bundle. There are two types of bundles:
19 | *
20 | * * Reusable Bundles: they are meant to be shared between different applications.
21 | * A lot of them are even publicly available in sites like packagist.org.
22 | * See http://symfony.com/doc/current/cookbook/bundles/best_practices.html
23 | * * Application bundles: they are never shared, not even with other of your
24 | * applications. This allows them to be less strict in some conventions and
25 | * their code is usually simpler.
26 | * See http://symfony.com/doc/current/best_practices/business-logic.html
27 | *
28 | * The AppBundle is an application bundle that is already created when you install
29 | * Symfony. Using AppBundle to start developing your Symfony application is
30 | * considered a good practice, but you can also split your application code into
31 | * as many bundles as you want.
32 | *
33 | * @author Ryan Weaver
34 | * @author Javier Eguiluz
35 | */
36 | class AppBundle extends Bundle
37 | {
38 | // At first it's common to leave this class empty, but when the application grows,
39 | // you may need to add some initialization code in the boot() method.
40 | //
41 | // Checkout the Symfony\Component\HttpKernel\Bundle\Bundle class to see all
42 | // the available methods for bundles.
43 | }
44 |
--------------------------------------------------------------------------------
/src/AppBundle/Command/GenerateContentCommand.php:
--------------------------------------------------------------------------------
1 | setName('app:generate-content')
25 | ->setDescription('Generate some random content')
26 | ->addArgument('max-results', InputArgument::OPTIONAL, 'Limits the number of post generated', 50)
27 | ;
28 | }
29 |
30 | protected function initialize(InputInterface $input, OutputInterface $output)
31 | {
32 | $this->em = $this->getContainer()->get('doctrine')->getManager();
33 | }
34 |
35 | protected function execute(InputInterface $input, OutputInterface $output)
36 | {
37 | $maxResults = $input->getArgument('max-results');
38 |
39 | $emails = $this->em->getRepository('AppBundle:User')
40 | ->createQueryBuilder('u')
41 | ->select('u.email')
42 | ->getQuery()
43 | ->getScalarResult();
44 |
45 | array_walk($emails, function (&$result) {
46 | $result = $result['email'];
47 | });
48 |
49 | $generator = Faker\Factory::create('en_GB');
50 |
51 | for ($i = 0; $i < 15; ++$i) {
52 | $emails[] = $generator->email;
53 | }
54 |
55 | $populator = new Faker\ORM\Doctrine\Populator($generator, $this->em);
56 | $populator->addEntity(Post::class, $maxResults, [
57 | 'authorEmail' => function () use ($generator, $emails) { return $generator->randomElement($emails); },
58 | 'slug' => function () use ($generator) { return $generator->slug(4); },
59 | ]);
60 | $populator->addEntity(Comment::class, $maxResults * 10);
61 | $populator->execute();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/AppBundle/Composer/ScriptHandler.php:
--------------------------------------------------------------------------------
1 | getIO()->write(sprintf('Installing XHProf GUI into %s ', $targetDir));
33 |
34 | $fs->remove($targetDir);
35 |
36 | if ($symlink) {
37 | if ($options['symfony-assets-install'] == 'relative') {
38 | $relativeOriginDir = $fs->makePathRelative($originDir, realpath($webDir));
39 | } else {
40 | $relativeOriginDir = $originDir;
41 | }
42 |
43 | try {
44 | $fs->symlink($relativeOriginDir, $targetDir);
45 | if (!file_exists($targetDir)) {
46 | throw new IOException('Symbolic link is broken');
47 | }
48 | $event->getIO()->write('XHProf GUI was installed using symbolic links.');
49 | } catch (IOException $e) {
50 | $event->getIO()->write('It looks like your system doesn\'t support symbolic links, please change your options accordingly.');
51 | }
52 | } else {
53 | $fs->mkdir($targetDir, 0755);
54 | // We use a custom iterator to ignore VCS files
55 | $fs->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir));
56 |
57 | $patcher = new XhprofPatcher($fs->makePathRelative(realpath($originDir.'/../uprofiler_lib'), realpath($targetDir)));
58 | $patcher->patch($targetDir);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/AppBundle/Composer/XhprofPatcher.php:
--------------------------------------------------------------------------------
1 | originalDirectory = $originalDirectory;
15 | }
16 |
17 | public function patch($directory)
18 | {
19 | $files = Finder::create()->ignoreDotFiles(false)->files()->name('*.php')->in($directory);
20 |
21 | foreach ($files as $file) {
22 | $this->patchFile($file);
23 | }
24 | }
25 |
26 | private function patchFile($file)
27 | {
28 | $content = file_get_contents($file);
29 | $src = file($file);
30 | $this->setCode(token_get_all($content), 0);
31 | while ($token = $this->next()) {
32 | if (T_VARIABLE !== $token[0] || '$GLOBALS' !== $token[1]) {
33 | continue;
34 | }
35 |
36 | // [
37 | $_ = $this->next();
38 | if ('[' !== $_) {
39 | continue;
40 | }
41 |
42 | $_ = $this->next();
43 | if (T_CONSTANT_ENCAPSED_STRING !== $_[0] || "'UPROFILER_LIB_ROOT'" != $_[1]) {
44 | continue;
45 | }
46 |
47 | // ]
48 | $_ = $this->next();
49 | if (']' !== $_) {
50 | continue;
51 | }
52 |
53 | // =
54 | $_ = $this->next();
55 | if ('=' !== $_) {
56 | continue;
57 | }
58 |
59 | //this is an assignation, replace the line.
60 | $lines = array_merge(
61 | array_slice($src, 0, $token[2] - 1),
62 | // Appends a separator comma to the current last position of the array
63 | array(sprintf("\$GLOBALS['UPROFILER_LIB_ROOT'] = '%s';\n", $this->originalDirectory)),
64 | array_slice($src, $token[2])
65 | );
66 |
67 | file_put_contents($file, implode('', $lines));
68 |
69 | return true;
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/AppBundle/Controller/Admin/DashboardController.php:
--------------------------------------------------------------------------------
1 | getDoctrine()->getManager();
25 | $commentsCount = $postsCount = 0;
26 | foreach ($em->getRepository('AppBundle:Post')->findAll() as $post) {
27 | ++$postsCount;
28 | $commentsCount += count($post->getComments());
29 | }
30 |
31 | return $this->render('admin/index.html.twig', array(
32 | 'posts_count' => $postsCount,
33 | 'comments_count' => $commentsCount,
34 | ));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/AppBundle/Controller/ForecastController.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Controller;
13 |
14 | use Symfony\Bundle\FrameworkBundle\Controller\Controller;
15 |
16 | /**
17 | * Controller used to get the forecast informations.
18 | *
19 | *
20 | * @author Tugdual Saunier
21 | */
22 | class ForecastController extends Controller
23 | {
24 | public function infoAction()
25 | {
26 | return $this->render(
27 | 'forecast/info.html.twig',
28 | array(
29 | 'forecast' => $this->get('app.forecast')->fetch(),
30 | )
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/AppBundle/Controller/SecurityController.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Controller;
13 |
14 | use Symfony\Bundle\FrameworkBundle\Controller\Controller;
15 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
16 |
17 | /**
18 | * Controller used to manage the application security.
19 | * See http://symfony.com/doc/current/cookbook/security/form_login_setup.html.
20 | *
21 | * @author Ryan Weaver
22 | * @author Javier Eguiluz
23 | */
24 | class SecurityController extends Controller
25 | {
26 | /**
27 | * @Route("/login", name="security_login_form")
28 | */
29 | public function loginAction()
30 | {
31 | $helper = $this->get('security.authentication_utils');
32 |
33 | return $this->render('security/login.html.twig', array(
34 | // last username entered by the user (if any)
35 | 'last_username' => $helper->getLastUsername(),
36 | // last authentication error (if any)
37 | 'error' => $helper->getLastAuthenticationError(),
38 | ));
39 | }
40 |
41 | /**
42 | * This is the route the login form submits to.
43 | *
44 | * But, this will never be executed. Symfony will intercept this first
45 | * and handle the login automatically. See form_login in app/config/security.yml
46 | *
47 | * @Route("/login_check", name="security_login_check")
48 | */
49 | public function loginCheckAction()
50 | {
51 | throw new \Exception('This should never be reached!');
52 | }
53 |
54 | /**
55 | * This is the route the user can use to logout.
56 | *
57 | * But, this will never be executed. Symfony will intercept this first
58 | * and handle the logout automatically. See logout in app/config/security.yml
59 | *
60 | * @Route("/logout", name="security_logout")
61 | */
62 | public function logoutAction()
63 | {
64 | throw new \Exception('This should never be reached!');
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/AppBundle/Entity/Comment.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Entity;
13 |
14 | use Doctrine\ORM\Mapping as ORM;
15 | use Symfony\Component\Validator\Constraints as Assert;
16 |
17 | /**
18 | * @ORM\Entity(repositoryClass="AppBundle\Repository\CommentRepository")
19 | *
20 | * Defines the properties of the Comment entity to represent the blog comments.
21 | * See http://symfony.com/doc/current/book/doctrine.html#creating-an-entity-class
22 | *
23 | * Tip: if you have an existing database, you can generate these entity class automatically.
24 | * See http://symfony.com/doc/current/cookbook/doctrine/reverse_engineering.html
25 | *
26 | * @author Ryan Weaver
27 | * @author Javier Eguiluz
28 | */
29 | class Comment
30 | {
31 | /**
32 | * @ORM\Id
33 | * @ORM\GeneratedValue
34 | * @ORM\Column(type="integer")
35 | */
36 | private $id;
37 |
38 | /**
39 | * @ORM\ManyToOne(targetEntity="Post", inversedBy="comments")
40 | * @ORM\JoinColumn(nullable=false)
41 | */
42 | private $post;
43 |
44 | /**
45 | * @ORM\Column(type="text")
46 | * @Assert\NotBlank(message="comment.blank")
47 | * @Assert\Length(
48 | * min = "5",
49 | * minMessage = "comment.too_short",
50 | * max = "10000",
51 | * maxMessage = "comment.too_long"
52 | * )
53 | */
54 | private $content;
55 |
56 | /**
57 | * @ORM\Column(type="string")
58 | * @Assert\Email()
59 | */
60 | private $authorEmail;
61 |
62 | /**
63 | * @ORM\Column(type="datetime")
64 | * @Assert\DateTime()
65 | */
66 | private $publishedAt;
67 |
68 | public function __construct()
69 | {
70 | $this->publishedAt = new \DateTime();
71 | }
72 |
73 | /**
74 | * @Assert\IsTrue(message = "comment.is_spam")
75 | */
76 | public function isLegitComment()
77 | {
78 | $containsInvalidCharacters = false !== strpos($this->content, '@');
79 |
80 | return !$containsInvalidCharacters;
81 | }
82 |
83 | public function getId()
84 | {
85 | return $this->id;
86 | }
87 |
88 | public function getContent()
89 | {
90 | return $this->content;
91 | }
92 | public function setContent($content)
93 | {
94 | $this->content = $content;
95 | }
96 |
97 | public function getAuthorEmail()
98 | {
99 | return $this->authorEmail;
100 | }
101 | public function setAuthorEmail($authorEmail)
102 | {
103 | $this->authorEmail = $authorEmail;
104 | }
105 |
106 | public function getPublishedAt()
107 | {
108 | return $this->publishedAt;
109 | }
110 | public function setPublishedAt($publishedAt)
111 | {
112 | $this->publishedAt = $publishedAt;
113 | }
114 |
115 | public function getPost()
116 | {
117 | return $this->post;
118 | }
119 | public function setPost(Post $post = null)
120 | {
121 | $this->post = $post;
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/AppBundle/Entity/User.php:
--------------------------------------------------------------------------------
1 |
18 | * @author Javier Eguiluz
19 | */
20 | class User implements UserInterface
21 | {
22 | /**
23 | * @ORM\Id
24 | * @ORM\GeneratedValue
25 | * @ORM\Column(type="integer")
26 | */
27 | private $id;
28 |
29 | /**
30 | * @ORM\Column(type="string", unique=true)
31 | */
32 | private $username;
33 |
34 | /**
35 | * @ORM\Column(type="string", unique=true)
36 | */
37 | private $email;
38 |
39 | /**
40 | * @ORM\Column(type="string")
41 | */
42 | private $password;
43 |
44 | /**
45 | * @ORM\Column(type="json_array")
46 | */
47 | private $roles = array();
48 |
49 | public function getId()
50 | {
51 | return $this->id;
52 | }
53 |
54 | public function getUsername()
55 | {
56 | return $this->username;
57 | }
58 | public function setUsername($username)
59 | {
60 | $this->username = $username;
61 | }
62 |
63 | public function getEmail()
64 | {
65 | return $this->email;
66 | }
67 | public function setEmail($email)
68 | {
69 | $this->email = $email;
70 | }
71 |
72 | public function getPassword()
73 | {
74 | return $this->password;
75 | }
76 | public function setPassword($password)
77 | {
78 | $this->password = $password;
79 | }
80 |
81 | /**
82 | * Returns the roles or permissions granted to the user for security.
83 | */
84 | public function getRoles()
85 | {
86 | $roles = $this->roles;
87 |
88 | // guarantees that a user always has at least one role for security
89 | if (empty($roles)) {
90 | $roles[] = 'ROLE_USER';
91 | }
92 |
93 | return array_unique($roles);
94 | }
95 |
96 | public function setRoles($roles)
97 | {
98 | $this->roles = $roles;
99 | }
100 |
101 | /**
102 | * Returns the salt that was originally used to encode the password.
103 | */
104 | public function getSalt()
105 | {
106 | // See "Do you need to use a Salt?" at http://symfony.com/doc/current/cookbook/security/entity_provider.html
107 | // we're using bcrypt in security.yml to encode the password, so
108 | // the salt value is built-in and you don't have to generate one
109 |
110 | return;
111 | }
112 |
113 | /**
114 | * Removes sensitive data from the user.
115 | */
116 | public function eraseCredentials()
117 | {
118 | // if you had a plainPassword property, you'd nullify it here
119 | // $this->plainPassword = null;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/AppBundle/EventListener/CommentListener.php:
--------------------------------------------------------------------------------
1 | spamValidator = $spamValidator;
23 | }
24 |
25 | /**
26 | * @param LifecycleEventArgs $args
27 | */
28 | public function postPersist(LifecycleEventArgs $args)
29 | {
30 | $entity = $args->getEntity();
31 | if (!$entity instanceof Comment) {
32 | return;
33 | }
34 |
35 | if (!$this->spamValidator->validate($entity->getContent())) {
36 | throw new \InvalidArgumentException('Found a spam !');
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/AppBundle/EventListener/ServerRunListener.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class ServerRunListener
16 | {
17 | public function listenForServerRunCommand(ConsoleCommandEvent $event)
18 | {
19 | if (!$event->getCommand() instanceof ServerRunCommand) {
20 | return;
21 | }
22 |
23 | $argv = $_SERVER['argv'];
24 | if (count($argv) < 3) {
25 | return;
26 | }
27 | // strip the application name
28 | array_shift($argv);
29 | // strip the command name
30 | array_shift($argv);
31 |
32 | $address = $argv[0];
33 | if (0 !== strpos($address, '0.0.0.0')) {
34 | return;
35 | }
36 |
37 | $address = str_replace('0.0.0.0', $this->getLocalIp(), $address);
38 | $output = $event->getOutput();
39 | $output->writeln(sprintf('If you are in a container you would probably prefer to use: http://%s ', $address));
40 |
41 | if (function_exists('uprofiler_enable')) {
42 | $output->writeln(sprintf('XHProf UI: http://%s/xhprof ', $address));
43 | }
44 | $output->writeln('');
45 | }
46 |
47 | private function getLocalIp()
48 | {
49 | return gethostbyname(gethostname());
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/AppBundle/Form/CommentType.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Form;
13 |
14 | use Symfony\Component\Form\AbstractType;
15 | use Symfony\Component\Form\FormBuilderInterface;
16 | use Symfony\Component\OptionsResolver\OptionsResolver;
17 |
18 | /**
19 | * Defines the form used to create and manipulate blog comments. Although in this
20 | * case the form is trivial and we could build it inside the controller, a good
21 | * practice is to always define your forms as classes.
22 | * See http://symfony.com/doc/current/book/forms.html#creating-form-classes.
23 | *
24 | * @author Ryan Weaver
25 | * @author Javier Eguiluz
26 | */
27 | class CommentType extends AbstractType
28 | {
29 | /**
30 | * @param FormBuilderInterface $builder
31 | * @param array $options
32 | */
33 | public function buildForm(FormBuilderInterface $builder, array $options)
34 | {
35 | // By default, form fields include the 'required' attribute, which enables
36 | // the client-side form validation. This means that you can't test the
37 | // server-side validation errors from the browser. To temporarily disable
38 | // this validation, set the 'required' attribute to 'false':
39 | //
40 | // $builder->add('content', null, array('required' => false));
41 |
42 | $builder
43 | ->add('content')
44 | ;
45 | }
46 |
47 | /**
48 | * @param OptionsResolver $resolver
49 | */
50 | public function configureOptions(OptionsResolver $resolver)
51 | {
52 | $resolver->setDefaults(array(
53 | 'data_class' => 'AppBundle\Entity\Comment',
54 | ));
55 | }
56 |
57 | /**
58 | * @return string
59 | */
60 | public function getName()
61 | {
62 | // Best Practice: use 'app_' as the prefix of your custom form types names
63 | // see http://symfony.com/doc/current/best_practices/forms.html#custom-form-field-types
64 | return 'app_comment';
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/AppBundle/Form/PostType.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Form;
13 |
14 | use Symfony\Component\Form\AbstractType;
15 | use Symfony\Component\Form\FormBuilderInterface;
16 | use Symfony\Component\OptionsResolver\OptionsResolver;
17 |
18 | /**
19 | * Defines the form used to create and manipulate blog posts.
20 | *
21 | * @author Ryan Weaver
22 | * @author Javier Eguiluz
23 | */
24 | class PostType extends AbstractType
25 | {
26 | /**
27 | * @param FormBuilderInterface $builder
28 | * @param array $options
29 | */
30 | public function buildForm(FormBuilderInterface $builder, array $options)
31 | {
32 | // For the full reference of options defined by each form field type
33 | // see http://symfony.com/doc/current/reference/forms/types.html
34 |
35 | // By default, form fields include the 'required' attribute, which enables
36 | // the client-side form validation. This means that you can't test the
37 | // server-side validation errors from the browser. To temporarily disable
38 | // this validation, set the 'required' attribute to 'false':
39 | //
40 | // $builder->add('title', null, array('required' => false, ...));
41 |
42 | $builder
43 | ->add('title', null, array('label' => 'label.title'))
44 | ->add('summary', 'textarea', array('label' => 'label.summary'))
45 | ->add('content', 'textarea', array(
46 | 'attr' => array('rows' => 20),
47 | 'label' => 'label.content',
48 | ))
49 | ->add('authorEmail', 'email', array('label' => 'label.author_email'))
50 | ->add('publishedAt', 'datetime', array(
51 | 'widget' => 'single_text',
52 | 'label' => 'label.published_at',
53 | ))
54 | ;
55 | }
56 |
57 | /**
58 | * @param OptionsResolver $resolver
59 | */
60 | public function configureOptions(OptionsResolver $resolver)
61 | {
62 | $resolver->setDefaults(array(
63 | 'data_class' => 'AppBundle\Entity\Post',
64 | ));
65 | }
66 |
67 | /**
68 | * @return string
69 | */
70 | public function getName()
71 | {
72 | // Best Practice: use 'app_' as the prefix of your custom form types names
73 | // see http://symfony.com/doc/current/best_practices/forms.html#custom-form-field-types
74 | return 'app_post';
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/AppBundle/Mocks/Utils/Forecast.php:
--------------------------------------------------------------------------------
1 | time(),
11 | 'summary' => 'Mostly Cloudy',
12 | 'icon' => 'partly-cloudy-day',
13 | 'sunriseTime' => 0,
14 | 'sunsetTime' => 0,
15 | 'precipIntensity' => 0,
16 | 'precipIntensityMax' => 0,
17 | 'precipIntensityMaxTime' => 0,
18 | 'precipProbability' => 0,
19 | 'precipType' => '',
20 | 'precipAccumulation' => 0,
21 | 'temperature' => 15.960000000000001,
22 | 'temperatureMin' => 0,
23 | 'temperatureMinTime' => 0,
24 | 'temperatureMax' => 0,
25 | 'temperatureMaxTime' => 0,
26 | 'apparentTemperature' => 15.960000000000001,
27 | 'dewPoint' => 11.529999999999999,
28 | 'windSpeed' => 10.93,
29 | 'windBearing' => 239,
30 | 'cloudCover' => 0.68000000000000005,
31 | 'humidity' => 0.75,
32 | 'pressure' => 997.59000000000003,
33 | 'visibility' => 14.789999999999999,
34 | 'ozone' => 323.52999999999997,
35 | 'moonPhase' => 0,
36 | );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/AppBundle/Mocks/Utils/SpamValidator.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Repository;
13 |
14 | use Doctrine\ORM\EntityRepository;
15 | use AppBundle\Entity\Post;
16 |
17 | /**
18 | * This custom Doctrine repository contains some methods which are useful when
19 | * querying for blog post information.
20 | * See http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes.
21 | *
22 | * @author Ryan Weaver
23 | * @author Javier Eguiluz
24 | */
25 | class PostRepository extends EntityRepository
26 | {
27 | public function findLatest($limit = Post::NUM_ITEMS)
28 | {
29 | return $this
30 | ->createQueryBuilder('p')
31 | ->select('p')
32 | ->where('p.publishedAt <= :now')->setParameter('now', new \DateTime())
33 | ->orderBy('p.publishedAt', 'DESC')
34 | ->setMaxResults($limit)
35 | ->getQuery()
36 | ->getResult()
37 | ;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/AppBundle/Repository/UserRepository.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Repository;
13 |
14 | use Doctrine\ORM\EntityRepository;
15 |
16 | /**
17 | * This custom Doctrine repository is empty because so far we don't need any custom
18 | * method to query for application user information. But it's always a good practice
19 | * to define a custom repository that will be used when the application grows.
20 | * See http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes.
21 | *
22 | * @author Ryan Weaver
23 | * @author Javier Eguiluz
24 | */
25 | class UserRepository extends EntityRepository
26 | {
27 | }
28 |
--------------------------------------------------------------------------------
/src/AppBundle/Tests/Controller/Admin/BlogControllerTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Tests\Controller\Admin;
13 |
14 | use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
15 | use Symfony\Component\HttpFoundation\Response;
16 | use AppBundle\Entity\Post;
17 |
18 | /**
19 | * Functional test for the controllers defined inside the BlogController used
20 | * for managing the blog in the backend.
21 | * See http://symfony.com/doc/current/book/testing.html#functional-tests.
22 | *
23 | * Whenever you test resources protected by a firewall, consider using the
24 | * technique explained in:
25 | * http://symfony.com/doc/current/cookbook/testing/http_authentication.html
26 | *
27 | * Execute the application tests using this command (requires PHPUnit to be installed):
28 | *
29 | * $ cd your-symfony-project/
30 | * $ phpunit -c app
31 | */
32 | class BlogControllerTest extends WebTestCase
33 | {
34 | public function testRegularUsersCannotAccessToTheBackend()
35 | {
36 | $client = static::createClient(array(), array(
37 | 'PHP_AUTH_USER' => 'john_user',
38 | 'PHP_AUTH_PW' => 'kitten',
39 | ));
40 |
41 | $client->request('GET', '/en/admin/post/');
42 |
43 | $this->assertEquals(Response::HTTP_FORBIDDEN, $client->getResponse()->getStatusCode());
44 | }
45 |
46 | public function testAdministratorUsersCanAccessToTheBackend()
47 | {
48 | $client = static::createClient(array(), array(
49 | 'PHP_AUTH_USER' => 'anna_admin',
50 | 'PHP_AUTH_PW' => 'kitten',
51 | ));
52 |
53 | $client->request('GET', '/en/admin/post/');
54 |
55 | $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
56 | }
57 |
58 | public function testIndex()
59 | {
60 | $client = static::createClient(array(), array(
61 | 'PHP_AUTH_USER' => 'anna_admin',
62 | 'PHP_AUTH_PW' => 'kitten',
63 | ));
64 |
65 | $crawler = $client->request('GET', '/en/admin/post/');
66 |
67 | $this->assertCount(
68 | Post::NUM_ITEMS,
69 | $crawler->filter('body#admin_post_index #main tbody tr'),
70 | 'The backend homepage displays the right number of posts.'
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/AppBundle/Tests/Controller/BlogControllerTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Tests\Controller;
13 |
14 | use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
15 | use AppBundle\Entity\Post;
16 |
17 | /**
18 | * Functional test for the controllers defined inside BlogController.
19 | * See http://symfony.com/doc/current/book/testing.html#functional-tests.
20 | *
21 | * Execute the application tests using this command (requires PHPUnit to be installed):
22 | *
23 | * $ cd your-symfony-project/
24 | * $ phpunit -c app
25 | */
26 | class BlogControllerTest extends WebTestCase
27 | {
28 | public function testIndex()
29 | {
30 | $client = static::createClient();
31 | $crawler = $client->request('GET', '/en/blog/');
32 |
33 | $this->assertCount(
34 | Post::NUM_ITEMS,
35 | $crawler->filter('article.post'),
36 | 'The homepage displays the right number of posts.'
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/AppBundle/Tests/Controller/DefaultControllerTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Tests\Controller;
13 |
14 | use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
15 |
16 | /**
17 | * Functional test that implements a "smoke test" of all the public and secure
18 | * URLs of the application.
19 | * See http://symfony.com/doc/current/best_practices/tests.html#functional-tests.
20 | *
21 | * Execute the application tests using this command (requires PHPUnit to be installed):
22 | *
23 | * $ cd your-symfony-project/
24 | * $ phpunit -c app
25 | */
26 | class DefaultControllerTest extends WebTestCase
27 | {
28 | /**
29 | * PHPUnit's data providers allow to execute the same tests repeated times
30 | * using a different set of data each time.
31 | * See http://symfony.com/doc/current/cookbook/form/unit_testing.html#testing-against-different-sets-of-data.
32 | *
33 | * @dataProvider getPublicUrls
34 | */
35 | public function testPublicUrls($url)
36 | {
37 | $client = self::createClient();
38 | $client->request('GET', $url);
39 |
40 | $this->assertTrue(
41 | $client->getResponse()->isSuccessful(),
42 | sprintf('The %s public URL loads correctly.', $url)
43 | );
44 | }
45 |
46 | /**
47 | * The application contains a lot of secure URLs which shouldn't be
48 | * publicly accessible. This tests ensures that whenever a user tries to
49 | * access one of those pages, a redirection to the login form is performed.
50 | *
51 | * @dataProvider getSecureUrls
52 | */
53 | public function testSecureUrls($url)
54 | {
55 | $client = self::createClient();
56 | $client->request('GET', $url);
57 |
58 | $this->assertTrue($client->getResponse()->isRedirect());
59 |
60 | $this->assertEquals(
61 | 'http://localhost/en/login',
62 | $client->getResponse()->getTargetUrl(),
63 | sprintf('The %s secure URL redirects to the login form.', $url)
64 | );
65 | }
66 |
67 | public function getPublicUrls()
68 | {
69 | return array(
70 | array('/'),
71 | array('/en/blog/'),
72 | array('/en/blog/posts/morbi-tempus-commodo-mattis'),
73 | array('/en/login'),
74 | );
75 | }
76 |
77 | public function getSecureUrls()
78 | {
79 | return array(
80 | array('/en/admin/post/'),
81 | array('/en/admin/post/new'),
82 | array('/en/admin/post/1'),
83 | array('/en/admin/post/1/edit'),
84 | );
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/AppBundle/Tests/Utils/SluggerTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Tests\Utils;
13 |
14 | use AppBundle\Utils\Slugger;
15 |
16 | /**
17 | * Unit test for the application utils.
18 | * See http://symfony.com/doc/current/book/testing.html#unit-tests.
19 | *
20 | * Execute the application tests using this command (requires PHPUnit to be installed):
21 | *
22 | * $ cd your-symfony-project/
23 | * $ phpunit -c app
24 | */
25 | class SluggerTest extends \PHPUnit_Framework_TestCase
26 | {
27 | /**
28 | * @dataProvider getSlugs
29 | */
30 | public function testSlugify($string, $slug)
31 | {
32 | $slugger = new Slugger();
33 | $result = $slugger->slugify($string);
34 |
35 | $this->assertEquals($slug, $result);
36 | }
37 |
38 | public function getSlugs()
39 | {
40 | return array(
41 | array('Lorem Ipsum' , 'lorem-ipsum'),
42 | array(' Lorem Ipsum ' , 'lorem-ipsum'),
43 | array(' lOrEm iPsUm ' , 'lorem-ipsum'),
44 | array('!Lorem Ipsum!' , 'lorem-ipsum'),
45 | array('lorem-ipsum' , 'lorem-ipsum'),
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/AppBundle/Twig/AppExtension.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Twig;
13 |
14 | use AppBundle\Utils\Markdown;
15 |
16 | /**
17 | * This Twig extension adds a new 'md2html' filter to easily transform Markdown
18 | * contents into HTML contents inside Twig templates.
19 | * See http://symfony.com/doc/current/cookbook/templating/twig_extension.html.
20 | *
21 | * In addition to creating the Twig extension class, before using it you must also
22 | * register it as a service. See app/config/services.yml file for details.
23 | *
24 | * @author Ryan Weaver
25 | * @author Javier Eguiluz
26 | */
27 | class AppExtension extends \Twig_Extension
28 | {
29 | private $parser;
30 |
31 | public function __construct(Markdown $parser)
32 | {
33 | $this->parser = $parser;
34 | }
35 |
36 | public function getFilters()
37 | {
38 | return array(
39 | new \Twig_SimpleFilter('md2html', array($this, 'markdownToHtml'), array('is_safe' => array('html'))),
40 | );
41 | }
42 |
43 | public function markdownToHtml($content)
44 | {
45 | return $this->parser->toHtml($content);
46 | }
47 |
48 | // the name of the Twig extension must be unique in the application. Consider
49 | // using 'app.extension' if you only have one Twig extension in your application.
50 | public function getName()
51 | {
52 | return 'app.extension';
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/AppBundle/Twig/LocaleExtension.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Twig;
13 |
14 | use Symfony\Component\Intl\Intl;
15 |
16 | /**
17 | * This Twig extension takes the list of codes of the locales (languages)
18 | * enabled in the application and returns an array with the name of each
19 | * locale written in its own language (e.g. English, Français, Español, etc.).
20 | *
21 | * @author Julien ITARD
22 | */
23 | class LocaleExtension extends \Twig_Extension
24 | {
25 | private $locales;
26 |
27 | public function __construct($locales)
28 | {
29 | $this->locales = $locales;
30 | }
31 |
32 | public function getFunctions()
33 | {
34 | return array(
35 | new \Twig_SimpleFunction('locales', array($this, 'getLocales')),
36 | );
37 | }
38 |
39 | public function getLocales()
40 | {
41 | $localeCodes = explode('|', $this->locales);
42 |
43 | foreach ($localeCodes as $localeCode) {
44 | $locales[] = array('code' => $localeCode, 'name' => Intl::getLocaleBundle()->getLocaleName($localeCode, $localeCode));
45 | }
46 |
47 | return $locales;
48 | }
49 |
50 | // the name of the Twig extension must be unique in the application
51 | public function getName()
52 | {
53 | return 'app.locale_extension';
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/AppBundle/Twig/StatsExtension.php:
--------------------------------------------------------------------------------
1 | stats = array(
14 | 'posts' => count($doctrine->getRepository('AppBundle:Post')->findAll()),
15 | 'comments' => count($doctrine->getRepository('AppBundle:Comment')->findAll()),
16 | );
17 | }
18 |
19 | public function getFunctions()
20 | {
21 | return array(
22 | new \Twig_SimpleFunction('stats_posts_count', array($this, 'getPostsCountStats'), array('is_safe' => array('html'))),
23 | new \Twig_SimpleFunction('stats_comments_count', array($this, 'getCommentsCountStats'), array('is_safe' => array('html'))),
24 | );
25 | }
26 |
27 | public function getPostsCountStats()
28 | {
29 | return $this->stats['posts'];
30 | }
31 |
32 | public function getCommentsCountStats()
33 | {
34 | return $this->stats['comments'];
35 | }
36 |
37 | public function getName()
38 | {
39 | return 'app.stats_extension';
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/AppBundle/Utils/Forecast.php:
--------------------------------------------------------------------------------
1 | baseUrl = rtrim($baseUrl, '/');
12 | }
13 |
14 | public function fetch()
15 | {
16 | $data = file_get_contents(sprintf('%s/forecast', $this->baseUrl));
17 |
18 | return json_decode($data, true);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/AppBundle/Utils/Markdown.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Utils;
13 |
14 | /**
15 | * This class is a light interface between an external Markdown parser library
16 | * and the application. It's generally recommended to create these light interfaces
17 | * to decouple your application from the implementation details of the third-party library.
18 | *
19 | * @author Ryan Weaver
20 | * @author Javier Eguiluz
21 | */
22 | class Markdown
23 | {
24 | private $parser;
25 |
26 | public function __construct()
27 | {
28 | $this->parser = new \Parsedown();
29 | }
30 |
31 | public function toHtml($text)
32 | {
33 | $html = $this->parser->text($text);
34 |
35 | return $html;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/AppBundle/Utils/Slugger.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace AppBundle\Utils;
13 |
14 | /**
15 | * This class is used to provide an example of integrating simple classes as
16 | * services into a Symfony application.
17 | *
18 | * @author Ryan Weaver
19 | * @author Javier Eguiluz
20 | */
21 | class Slugger
22 | {
23 | public function slugify($string)
24 | {
25 | return trim(preg_replace('/[^a-z0-9]+/', '-', strtolower(strip_tags($string))), '-');
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/AppBundle/Utils/SpamValidator.php:
--------------------------------------------------------------------------------
1 | getContentsScore($contents) > self::MAX_SCORE;
17 | }
18 |
19 | /**
20 | * @param string $contents
21 | *
22 | * @return int
23 | */
24 | private function getContentsScore($contents)
25 | {
26 | $score = strlen($contents);
27 | $score = $this->sanitizeScore($score);
28 |
29 | return $score;
30 | }
31 |
32 | /**
33 | * @param int $score
34 | *
35 | * @return int
36 | */
37 | private function sanitizeScore($score)
38 | {
39 | $final = 0;
40 | for ($i = 0; $i < self::MAX_SCORE; ++$i) {
41 | $final = $score == 0 ? 1 : $score * $this->sanitizeScore($score - 1);
42 | }
43 |
44 | return $final;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/AppBundle/Utils/SpamValidatorInterface.php:
--------------------------------------------------------------------------------
1 |
9 | RewriteEngine On
10 |
11 | # Determine the RewriteBase automatically and set it as environment variable.
12 | # If you are using Apache aliases to do mass virtual hosting or installed the
13 | # project in a subdirectory, the base path will be prepended to allow proper
14 | # resolution of the app.php file and to redirect to the correct URI. It will
15 | # work in environments without path prefix as well, providing a safe, one-size
16 | # fits all solution. But as you do not need it in this case, you can comment
17 | # the following 2 lines to eliminate the overhead.
18 | RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
19 | RewriteRule ^(.*) - [E=BASE:%1]
20 |
21 | # Redirect to URI without front controller to prevent duplicate content
22 | # (with and without `/app.php`). Only do this redirect on the initial
23 | # rewrite by Apache and not on subsequent cycles. Otherwise we would get an
24 | # endless redirect loop (request -> rewrite to front controller ->
25 | # redirect -> request -> ...).
26 | # So in case you get a "too many redirects" error or you always get redirected
27 | # to the start page because your Apache does not expose the REDIRECT_STATUS
28 | # environment variable, you have 2 choices:
29 | # - disable this feature by commenting the following 2 lines or
30 | # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
31 | # following RewriteCond (best solution)
32 | RewriteCond %{ENV:REDIRECT_STATUS} ^$
33 | RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]
34 |
35 | # If the requested filename exists, simply serve it.
36 | # We only want to let Apache serve files and not directories.
37 | RewriteCond %{REQUEST_FILENAME} -f
38 | RewriteRule .? - [L]
39 |
40 | # Rewrite all other queries to the front controller.
41 | RewriteRule .? %{ENV:BASE}/app.php [L]
42 |
43 |
44 |
45 |
46 | # When mod_rewrite is not available, we instruct a temporary redirect of
47 | # the start page to the front controller explicitly so that the website
48 | # and the generated links can still be used.
49 | RedirectMatch 302 ^/$ /app.php/
50 | # RedirectTemp cannot be used instead
51 |
52 |
53 |
--------------------------------------------------------------------------------
/web/app.php:
--------------------------------------------------------------------------------
1 | unregister();
26 | // $apcLoader->register(true);
27 |
28 | require_once __DIR__.'/../app/AppKernel.php';
29 |
30 | $kernel = new AppKernel('prod', false);
31 | $kernel->loadClassCache();
32 |
33 | // If you use HTTP Cache to improve application performance, uncomment the following lines:
34 | // See http://symfony.com/doc/current/book/http_cache.html#symfony-reverse-proxy
35 | //
36 | // require_once __DIR__.'/../app/AppCache.php';
37 | // $kernel = new AppCache($kernel);
38 |
39 | // If you use HTTP Cache and your application relies on the _method request parameter
40 | // to get the intended HTTP method, uncomment this line.
41 | // See http://symfony.com/doc/current/reference/configuration/framework.html#http-method-override
42 | // Request::enableHttpMethodParameterOverride();
43 |
44 | $request = Request::createFromGlobals();
45 | $response = $kernel->handle($request);
46 | $response->send();
47 |
48 | $kernel->terminate($request, $response);
49 |
--------------------------------------------------------------------------------
/web/app_dev.php:
--------------------------------------------------------------------------------
1 | loadClassCache();
35 | $request = Request::createFromGlobals();
36 | $response = $kernel->handle($request);
37 | $response->send();
38 | $kernel->terminate($request, $response);
39 |
--------------------------------------------------------------------------------
/web/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/apple-touch-icon.png
--------------------------------------------------------------------------------
/web/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/favicon.ico
--------------------------------------------------------------------------------
/web/fonts/font-awesome/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/fonts/font-awesome/FontAwesome.otf
--------------------------------------------------------------------------------
/web/fonts/font-awesome/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/fonts/font-awesome/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/web/fonts/font-awesome/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/fonts/font-awesome/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/web/fonts/font-awesome/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/fonts/font-awesome/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/web/fonts/font-awesome/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/fonts/font-awesome/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/web/fonts/lato/Lato-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/fonts/lato/Lato-Bold.woff
--------------------------------------------------------------------------------
/web/fonts/lato/Lato-BoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/fonts/lato/Lato-BoldItalic.woff
--------------------------------------------------------------------------------
/web/fonts/lato/Lato-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/fonts/lato/Lato-Italic.woff
--------------------------------------------------------------------------------
/web/fonts/lato/Lato-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blackfireio/blackfire-workshop/7e3b193c83a3cfaa5fd14d0e71241053257488b9/web/fonts/lato/Lato-Regular.woff
--------------------------------------------------------------------------------
/web/robots.txt:
--------------------------------------------------------------------------------
1 | # www.robotstxt.org/
2 | # www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449
3 |
4 | User-agent: *
5 |
--------------------------------------------------------------------------------