Projects by WooThemes - Version 1.0.0

Version Description

  • Initial release. Woo!

=

Download this release

Release Info

Developer jameskoster
Plugin Icon wp plugin Projects by WooThemes
Version 1.0.0
Comparing to
See all releases

Version 1.0.0

Files changed (48) hide show
  1. assets/css/admin.css +1 -0
  2. assets/css/admin.less +95 -0
  3. assets/css/mixins.less +197 -0
  4. assets/css/woo-projects-handheld.css +1 -0
  5. assets/css/woo-projects-handheld.less +51 -0
  6. assets/css/woo-projects.css +1 -0
  7. assets/css/woo-projects.less +360 -0
  8. assets/images/placeholder.png +0 -0
  9. assets/js/script.js +50 -0
  10. assets/js/script.min.js +1 -0
  11. classes/class-projects-admin.php +563 -0
  12. classes/class-projects-frontend.php +38 -0
  13. classes/class-projects-settings.php +163 -0
  14. classes/class-projects-shortcodes.php +112 -0
  15. classes/class-projects-taxonomy.php +119 -0
  16. classes/class-projects-template-loader.php +64 -0
  17. classes/class-projects.php +378 -0
  18. classes/class-widget-project-categories.php +180 -0
  19. classes/class-widget-projects.php +215 -0
  20. lang/woothemes-features-en_GB.po +276 -0
  21. lang/woothemes-features-xx_XX.pot +21 -0
  22. projects-core-functions.php +438 -0
  23. projects-hooks.php +107 -0
  24. projects-template.php +474 -0
  25. projects.php +28 -0
  26. readme.txt +50 -0
  27. templates/archive-project.php +96 -0
  28. templates/content-project-category.php +67 -0
  29. templates/content-project-widget.php +26 -0
  30. templates/content-project.php +61 -0
  31. templates/content-single-project.php +66 -0
  32. templates/layout/sidebar.php +12 -0
  33. templates/layout/wrapper-end.php +29 -0
  34. templates/layout/wrapper-start.php +30 -0
  35. templates/loop/loop-end.php +10 -0
  36. templates/loop/loop-start.php +10 -0
  37. templates/loop/no-projects-found.php +14 -0
  38. templates/loop/pagination.php +31 -0
  39. templates/loop/short-description.php +17 -0
  40. templates/single-project.php +49 -0
  41. templates/single-project/description.php +18 -0
  42. templates/single-project/meta.php +56 -0
  43. templates/single-project/pagination.php +19 -0
  44. templates/single-project/project-feature.php +37 -0
  45. templates/single-project/project-gallery.php +55 -0
  46. templates/single-project/short-description.php +18 -0
  47. templates/single-project/title.php +13 -0
  48. templates/taxonomy-project-category.php +14 -0
assets/css/admin.css ADDED
@@ -0,0 +1 @@
 
1
+ @-webkit-keyframes spin-360{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-ms-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);zoom:1}50%{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);zoom:1}to{-webkit-transform:rotate(0);-moz-transform:rotate(0);-ms-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);zoom:1}}#adminmenu #menu-posts-project .menu-icon-project div.wp-menu-image:before{content:"\f322"}#project-images .inside{margin:0;padding:0}#project-images .inside .add_project_images{padding:0 12px}#project-images .inside #project_images_container{padding:0 0 0 9px}#project-images .inside #project_images_container ul{margin:0;padding:0}#project-images .inside #project_images_container ul:after{content:"\0020";display:block;height:0;overflow:hidden;clear:both}#project-images .inside #project_images_container ul li.image,#project-images .inside #project_images_container ul li.add,#project-images .inside #project_images_container ul li.projects-metabox-sortable-placeholder{width:80px;float:left;cursor:move;margin:9px 9px 0 0;background:#f7f7f7;position:relative;background:#fff;-webkit-border-radius:2px;border-radius:2px;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#project-images .inside #project_images_container ul li.image img,#project-images .inside #project_images_container ul li.add img,#project-images .inside #project_images_container ul li.projects-metabox-sortable-placeholder img{width:100%;height:auto;display:block;-webkit-transition:all ease-in-out .2s;-moz-transition:all ease-in-out .2s;-ms-transition:all ease-in-out .2s;-o-transition:all ease-in-out .2s;transition:all ease-in-out .2s;-webkit-border-radius:2px;border-radius:2px;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box}#project-images .inside #project_images_container ul li.image:hover img,#project-images .inside #project_images_container ul li.add:hover img,#project-images .inside #project_images_container ul li.projects-metabox-sortable-placeholder:hover img{opacity:.75;filter:alpha(opacity=@opacity * 100)}#project-images .inside #project_images_container ul li.projects-metabox-sortable-placeholder{border:4px dashed #ddd;background:#f7f7f7}#project-images .inside #project_images_container ul ul.actions{position:absolute;top:4px;right:4px;-webkit-transition:all ease-in-out .2s;-moz-transition:all ease-in-out .2s;-ms-transition:all ease-in-out .2s;-o-transition:all ease-in-out .2s;transition:all ease-in-out .2s;opacity:0;filter:alpha(opacity=@opacity * 100)}#project-images .inside #project_images_container ul ul.actions li{-webkit-border-radius:100%;border-radius:100%;float:right;margin:0 0 0 2px}#project-images .inside #project_images_container ul ul.actions li a{width:20px;margin:0;height:20px;font-size:16px;display:block;overflow:hidden;color:#fff;background:#000;font-weight:300;line-height:20px;text-align:center;-webkit-border-radius:2px;border-radius:2px;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box;text-decoration:none;-webkit-transition:all ease-in-out .2s;-moz-transition:all ease-in-out .2s;-ms-transition:all ease-in-out .2s;-o-transition:all ease-in-out .2s;transition:all ease-in-out .2s}#project-images .inside #project_images_container ul ul.actions li a.delete{background:#f63121}#project-images .inside #project_images_container ul ul.actions li a.delete:hover{background:#fff;color:#f63121}#project-images .inside #project_images_container ul li:hover ul.actions{opacity:1;filter:alpha(opacity=@opacity * 100)}
assets/css/admin.less ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Imports
2
+ @import url(mixins.less);
3
+
4
+ // Icons
5
+ #adminmenu #menu-posts-project .menu-icon-project div.wp-menu-image:before {
6
+ content: "\f322";
7
+ }
8
+
9
+ // Project Gallery
10
+ #project-images {
11
+ .inside {
12
+ margin: 0;
13
+ padding: 0;
14
+ .add_project_images {
15
+ padding: 0 12px;
16
+ }
17
+ #project_images_container {
18
+ padding: 0 0 0 9px;
19
+ ul {
20
+ margin: 0;
21
+ padding: 0;
22
+ .clearfix;
23
+ li.image, li.add, li.projects-metabox-sortable-placeholder {
24
+ width: 80px;
25
+ float: left;
26
+ cursor: move;
27
+ margin: 9px 9px 0 0;
28
+ background: #f7f7f7;
29
+ .border_radius(2px);
30
+ position: relative;
31
+ background: #fff;
32
+ .border_radius(2px);
33
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
34
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
35
+ box-sizing: border-box; /* Opera/IE 8+ */
36
+ img {
37
+ width: 100%;
38
+ height: auto;
39
+ display: block;
40
+ .transition;
41
+ .border_radius(2px);
42
+ }
43
+ &:hover {
44
+ img {
45
+ .opacity(0.75);
46
+ }
47
+ }
48
+ }
49
+ li.projects-metabox-sortable-placeholder {
50
+ border: 4px dashed #dddddd;
51
+ background: #f7f7f7;
52
+ }
53
+ ul.actions {
54
+ position: absolute;
55
+ top:4px;
56
+ right: 4px;
57
+ .transition;
58
+ .opacity(0);
59
+ li {
60
+ -webkit-border-radius: 100%;
61
+ border-radius: 100%;
62
+ float: right;
63
+ margin: 0 0 0 2px;
64
+ a {
65
+ width: 20px;
66
+ margin: 0;
67
+ height: 20px;
68
+ font-size: 16px;
69
+ display: block;
70
+ overflow: hidden;
71
+ color: #fff;
72
+ background:#000;
73
+ font-weight: 300;
74
+ line-height: 20px;
75
+ text-align: center;
76
+ .border_radius(2px);
77
+ text-decoration: none;
78
+ .transition;
79
+ &.delete {
80
+ background: @error;
81
+ &:hover {
82
+ background: #fff;
83
+ color: @error;
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ li:hover ul.actions {
90
+ .opacity(1);
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
assets/css/mixins.less ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Vars
2
+ // Colors
3
+ @color_links: #52a8e8; // Links / Main theme colour
4
+ @color_body: #555; // Body Copy
5
+ @border_main: #e6e6e6; // The 1px grey rules used throughout the WF
6
+ @bg_light: #fafafa;
7
+ @bg_dark: #d3d3d3;
8
+ @success: #89b93f;
9
+ @info: #3c8bae;
10
+ @error: #f63121;
11
+
12
+ // Fonts
13
+ @sans: sans-serif;
14
+ @serif: Georgia, serif;
15
+
16
+ // Google fonts - These are also defined in Theme Setup (theme-actions.php)
17
+ @sans_google: "Droid Sans", sans-serif;
18
+ @serif_google: "Droid Serif", sans-serif;
19
+
20
+ // Paths
21
+ @imagepath: 'images';
22
+ @fontpath: 'includes/fonts/';
23
+
24
+ // Functions
25
+ .iconbefore( @glyph: "\f179" ) {
26
+ font-family: 'dashicons';
27
+ vertical-align: top;
28
+ margin-right: .618em;
29
+ content: @glyph;
30
+ }
31
+
32
+ .iconafter( @glyph: "\f179" ) {
33
+ font-family: 'dashicons';
34
+ vertical-align: top;
35
+ margin-left: .618em;
36
+ content: @glyph;
37
+ }
38
+
39
+ .ir() {
40
+ display: block;
41
+ text-indent: -999px;
42
+ position: relative;
43
+ height:1em;
44
+ width:1em;
45
+ }
46
+
47
+ .icon( @glyph: "\f179" ) {
48
+ font-family: 'dashicons';
49
+ speak: none;
50
+ font-weight: normal;
51
+ font-variant: normal;
52
+ text-transform: none;
53
+ line-height: 1;
54
+ -webkit-font-smoothing: antialiased;
55
+ margin:0;
56
+ text-indent: 0;
57
+ position: absolute;
58
+ top:0;
59
+ left:0;
60
+ width:100%;
61
+ height: 100%;
62
+ text-align: center;
63
+ content: @glyph;
64
+ }
65
+
66
+ // Mixins
67
+ .clearfix() {
68
+ &:after {
69
+ content: "\0020";
70
+ display: block;
71
+ height: 0;
72
+ overflow: hidden;
73
+ clear: both;
74
+ }
75
+ }
76
+ .border_radius(@radius:10px) {
77
+ -webkit-border-radius:@radius;
78
+ border-radius:@radius;
79
+ -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box;
80
+ }
81
+
82
+ .border_radius_right(@radius:10px) {
83
+ -webkit-border-top-right-radius: @radius;
84
+ -webkit-border-bottom-right-radius: @radius;
85
+ border-top-right-radius: @radius;
86
+ border-bottom-right-radius: @radius;
87
+ -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box;
88
+ }
89
+
90
+ .border_radius_left(@radius:10px) {
91
+ -webkit-border-top-left-radius: @radius;
92
+ -webkit-border-bottom-left-radius: @radius;
93
+ border-top-left-radius: @radius;
94
+ border-bottom-left-radius: @radius;
95
+ -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box;
96
+ }
97
+
98
+ .border_radius_bottom(@radius:10px) {
99
+ -webkit-border-bottom-left-radius: @radius;
100
+ -webkit-border-bottom-right-radius: @radius;
101
+ border-bottom-left-radius: @radius;
102
+ border-bottom-right-radius: @radius;
103
+ -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box;
104
+ }
105
+
106
+ .border_radius_top(@radius:10px) {
107
+ -webkit-border-top-left-radius: @radius;
108
+ -webkit-border-top-right-radius: @radius;
109
+ border-top-left-radius: @radius;
110
+ border-top-right-radius: @radius;
111
+ -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box;
112
+ }
113
+
114
+ .border_radius_reset() {
115
+ -webkit-border-radius: none;
116
+ -moz-border-radius: none;
117
+ border-radius: none;
118
+ }
119
+
120
+ .box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
121
+ box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
122
+ -webkit-box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
123
+ }
124
+
125
+ .inset_box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
126
+ box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
127
+ -webkit-box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
128
+ }
129
+
130
+ .box_shadow_reset() {
131
+ -webkit-box-shadow: none;
132
+ -moz-box-shadow: none;
133
+ box-shadow: none;
134
+ }
135
+
136
+ .text_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_color:#fff) {
137
+ text-shadow:@shadow_x @shadow_y @shadow_rad @shadow_color;
138
+ }
139
+
140
+ .vertical_gradient(@from: #000, @to: #FFF) {
141
+ background-color: @from;
142
+ background-image: -webkit-gradient(linear, left top, left bottom, from(@from), to(@to)); /* Saf4+, Chrome */
143
+ background-image: -webkit-linear-gradient(top, @from, @to); /* Chrome 10+, Saf5.1+, iOS 5+ */
144
+ background-image: -moz-linear-gradient(top, @from, @to); /* FF3.6+ */
145
+ background-image: -ms-linear-gradient(top, @from, @to); /* IE10 */
146
+ background-image: -o-linear-gradient(top, @from, @to); /* Opera 11.10+ */
147
+ background-image: linear-gradient(to bottom, @from, @to);
148
+ }
149
+
150
+ .transition(@selector:all, @animation:ease-in-out, @duration:.2s) {
151
+ -webkit-transition:@selector @animation @duration;
152
+ -moz-transition:@selector @animation @duration;
153
+ -ms-transition:@selector @animation @duration;
154
+ -o-transition:@selector @animation @duration;
155
+ transition:@selector @animation @duration;
156
+ }
157
+
158
+ .opacity(@opacity:0.75) {
159
+ opacity: @opacity;
160
+ filter:~"alpha(opacity=@opacity * 100)";
161
+ }
162
+
163
+ .rotate(@degree:1deg) {
164
+ -webkit-transform: rotate(@degree); /* Saf3.1+, Chrome */
165
+ -moz-transform: rotate(@degree); /* FF3.5+ */
166
+ -ms-transform: rotate(@degree); /* IE9 */
167
+ -o-transform: rotate(@degree); /* Opera 10.5 */
168
+ transform: rotate(@degree);
169
+ zoom: 1;
170
+ }
171
+
172
+ .scale(@ratio:1.5) {
173
+ -webkit-transform:scale(@ratio);
174
+ -moz-transform:scale(@ratio);
175
+ -ms-transform:scale(@ratio);
176
+ -o-transform:scale(@ratio);
177
+ transform:scale(@ratio);
178
+ }
179
+
180
+ .radial_gradient(@from: #000, @to: #FFF) {
181
+ background: @from;
182
+ background: -webkit-gradient(radial, 50% 10%, 0, 50% 10%, 1000, from(@from), to(@to));
183
+ background: -moz-radial-gradient(center top, @from 0%, @to 100%);
184
+ }
185
+
186
+ .borderbox () {
187
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
188
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
189
+ box-sizing: border-box; /* Opera/IE 8+ */
190
+ }
191
+
192
+ // Animations
193
+ @-webkit-keyframes spin-360 {
194
+ from { .rotate(0); }
195
+ 50% { .rotate(180deg); }
196
+ to { .rotate(0); }
197
+ }
assets/css/woo-projects-handheld.css ADDED
@@ -0,0 +1 @@
 
1
+ @-webkit-keyframes spin-360{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-ms-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);zoom:1}50%{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);zoom:1}to{-webkit-transform:rotate(0);-moz-transform:rotate(0);-ms-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);zoom:1}}@media only screen and (max-width:768px){.projects ul.projects li.project,.projects-page ul.projects li.project{width:48%;float:left;clear:both}.projects ul.projects li.project:nth-child(2n),.projects-page ul.projects li.project:nth-child(2n){margin-right:0;float:right;clear:none!important}.single-project.has-gallery .gallery,.single-project.has-gallery .summary{width:100%;float:none;padding:0}.single-project.has-gallery .summary>div{font-size:1em}.single-project.no-gallery .project_title,.single-project.no-gallery .single-project-description,.single-project.no-gallery .project-meta{width:100%!important;float:none}}
assets/css/woo-projects-handheld.less ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Imports
2
+ @import url(mixins.less);
3
+
4
+ // Styles for handheld devices
5
+
6
+ @media only screen and ( max-width: 768px ) {
7
+
8
+
9
+
10
+ .projects, .projects-page {
11
+ ul.projects {
12
+ li.project {
13
+ width:48%;
14
+ float: left;
15
+ clear:both;
16
+ &:nth-child(2n) {
17
+ margin-right:0;
18
+ float: right;
19
+ clear: none !important;
20
+ }
21
+ }
22
+ }
23
+ }
24
+
25
+ .single-project {
26
+ &.has-gallery {
27
+ .gallery,
28
+ .summary {
29
+ width: 100%;
30
+ float: none;
31
+ padding: 0;
32
+ }
33
+
34
+ .summary {
35
+ > div {
36
+ font-size: 1em;
37
+ }
38
+ }
39
+ }
40
+
41
+ &.no-gallery {
42
+ .project_title,
43
+ .single-project-description,
44
+ .project-meta {
45
+ width: 100% !important;
46
+ float: none;
47
+ }
48
+ }
49
+ }
50
+
51
+ }
assets/css/woo-projects.css ADDED
@@ -0,0 +1 @@
 
1
+ @-webkit-keyframes spin-360{from{-webkit-transform:rotate(0);-moz-transform:rotate(0);-ms-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);zoom:1}50%{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);zoom:1}to{-webkit-transform:rotate(0);-moz-transform:rotate(0);-ms-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);zoom:1}}.projects ul.projects,.projects-page ul.projects{list-style:none;margin:0;margin-left:0!important;padding:0!important;*zoom:1}.projects ul.projects:before,.projects-page ul.projects:before,.projects ul.projects:after,.projects-page ul.projects:after{content:" ";display:table}.projects ul.projects:after,.projects-page ul.projects:after{clear:both}.projects ul.projects li.project,.projects-page ul.projects li.project{margin:0 0 2.618em;padding:0;width:48%;float:left;margin-right:3.8%}.projects ul.projects li.project .project-thumbnail,.projects-page ul.projects li.project .project-thumbnail{margin:0 0 1em}.projects ul.projects li.project a,.projects-page ul.projects li.project a{text-decoration:none}.projects ul.projects li.project h3,.projects-page ul.projects li.project h3{margin-bottom:.618em}.projects ul.projects li.project img,.projects-page ul.projects li.project img{max-width:100%;height:auto;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;-webkit-border-radius:0;border-radius:0;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box;padding:0;border:0;margin:0 auto;display:block}.projects ul.projects li.project.first,.projects-page ul.projects li.project.first{clear:both}.projects ul.projects li.project.last,.projects-page ul.projects li.project.last{margin-right:0}.projects ul.project-categories,.projects-page ul.project-categories{margin-left:0!important;padding:0!important;list-style:none}.projects ul.project-categories:after,.projects-page ul.project-categories:after{content:"\0020";display:block;height:0;overflow:hidden;clear:both}.projects ul.project-categories li,.projects-page ul.project-categories li{display:inline-block;margin-right:.5em;list-style:none;margin-left:0!important}.projects ul.project-categories li:after,.projects-page ul.project-categories li:after{content:"|";display:inline-block;padding-left:.5em}.projects ul.project-categories li:last-child:after,.projects-page ul.project-categories li:last-child:after{display:none}.projects .projects-pagination,.projects-page .projects-pagination{text-align:center}.projects .projects-pagination li,.projects-page .projects-pagination li{display:inline-block;margin:0 .236em}.single-project .project{margin-bottom:1.618em}.single-project .project:after{content:"\0020";display:block;height:0;overflow:hidden;clear:both}.single-project .project .single-project-short-description{margin-bottom:1.618em}.single-project .project .summary .single-project-categories li:before{font-family:dashicons;vertical-align:top;margin-right:.618em;content:"\f318"}.single-project .project .summary .client-name:before{font-family:dashicons;vertical-align:top;margin-right:.618em;content:"\f338"}.single-project .project .summary .project-url:before{font-family:dashicons;vertical-align:top;margin-right:.618em;content:"\f319"}.single-project .project .summary .single-project-categories,.single-project .project .summary .url,.single-project .project .summary .client{margin-bottom:1.618em}.single-project .project .summary .project-meta ul,.single-project .project .summary .project-meta li{list-style:none}.single-project .single-featured{margin-bottom:1.618em}.single-project.has-gallery .gallery{width:62%;float:left}.single-project.has-gallery .gallery a{display:block}.single-project.has-gallery .gallery img{-webkit-border-radius:0;border-radius:0;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box;max-width:100%;height:auto;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;display:block}.single-project.has-gallery .summary{width:38%;float:right;padding:0 0 0 2.618em;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.single-project.has-gallery .summary>div{font-size:.857em}.single-project.no-gallery .summary:after{content:"\0020";display:block;height:0;overflow:hidden;clear:both}.single-project.no-gallery .summary .project_title,.single-project.no-gallery .summary .single-project-description{width:62%;float:left}.single-project.no-gallery .summary .project-meta{width:34%;float:right}.single-project .projects-single-pagination:after{content:"\0020";display:block;height:0;overflow:hidden;clear:both}.single-project .projects-single-pagination .previous a,.single-project .projects-single-pagination .next a{text-decoration:none}.single-project .projects-single-pagination .previous{float:right}.single-project .projects-single-pagination .previous a:after{font-family:dashicons;vertical-align:top;margin-left:.618em;content:"\f344"}.single-project .projects-single-pagination .next{float:left}.single-project .projects-single-pagination .next a:before{font-family:dashicons;vertical-align:top;margin-right:.618em;content:"\f340"}.projects_list_widget li{margin-bottom:1.618em}.projects_list_widget li a{display:block}.projects_list_widget li a:after{content:"\0020";display:block;height:0;overflow:hidden;clear:both}.projects_list_widget li img{float:right;max-width:60px;height:auto}.projects_list_widget li .project-title{float:left}.widget_projects_categories ul.children{margin-left:2.618em;list-style-type:disc}.single-project .twentythirteen .entry-summary{padding:0}.single-project .twentythirteen ul.single-project-categories{padding-left:0}.single-project.has-gallery .twentythirteen .summary{width:36%}.single-project.has-gallery .twentythirteen .gallery{width:61%}.single-project.has-gallery .tfp .gallery{width:50%}.single-project.has-gallery .tfp .entry-summary{width:50%;padding-left:2.618em!important}.twentyfourteen .tfp{padding:12px 10px 0;max-width:474px;margin:0 auto}.twentyfourteen .tfp .project .entry-summary{padding:0;margin:0 0 1.618em!important}.twentyfourteen .tfp div.project.hentry.has-post-thumbnail{margin-top:0}.twentyfourteen .tfp .project .images img{margin-bottom:1em}@media screen and (min-width:673px){.twentyfourteen .tfp{padding-right:30px;padding-left:30px}}@media screen and (min-width:1040px){.twentyfourteen .tfp{padding-right:15px;padding-left:15px}}@media screen and (min-width:1110px){.twentyfourteen .tfp{padding-right:30px;padding-left:30px}}@media screen and (min-width:1218px){.twentyfourteen .tfp{margin-right:54px}.full-width .twentyfourteen .tfp{margin-right:auto}}
assets/css/woo-projects.less ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Imports
2
+ @import url(mixins.less);
3
+
4
+ /**
5
+ * Layout Styles
6
+ */
7
+ .projects,
8
+ .projects-page {
9
+ ul.projects {
10
+ list-style: none;
11
+ margin: 0;
12
+ margin-left: 0 !important;
13
+ padding: 0 !important;
14
+ *zoom: 1;
15
+
16
+ &:before, &:after {
17
+ content: " ";
18
+ display: table;
19
+ }
20
+
21
+ &:after {
22
+ clear: both;
23
+ }
24
+
25
+ li.project {
26
+ margin: 0 0 2.618em;
27
+ padding: 0;
28
+ width: 48%;
29
+ float: left;
30
+ margin-right: 3.8%;
31
+
32
+ .project-thumbnail {
33
+ margin: 0 0 1em;
34
+ }
35
+
36
+ a {
37
+ text-decoration: none;
38
+ }
39
+
40
+ h3 {
41
+ margin-bottom: .618em;
42
+ }
43
+
44
+ img {
45
+ max-width: 100%;
46
+ height: auto;
47
+ -webkit-box-shadow: none;
48
+ -moz-box-shadow: none;
49
+ box-shadow: none;
50
+ .border_radius(0);
51
+ padding: 0;
52
+ border: 0;
53
+ margin: 0 auto;
54
+ display: block;
55
+ }
56
+
57
+ &.first {
58
+ clear: both;
59
+ }
60
+
61
+ &.last {
62
+ margin-right: 0;
63
+ }
64
+ }
65
+ }
66
+
67
+ ul.project-categories {
68
+ margin-left: 0 !important;
69
+ padding: 0 !important;
70
+ .clearfix;
71
+ list-style: none;
72
+
73
+ li {
74
+ display: inline-block;
75
+ margin-right: .5em;
76
+ list-style: none;
77
+ margin-left: 0 !important;
78
+
79
+ &:after {
80
+ content: "|";
81
+ display: inline-block;
82
+ padding-left: .5em;
83
+ }
84
+
85
+ &:last-child {
86
+ &:after {
87
+ display: none;
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ .projects-pagination {
94
+ text-align: center;
95
+
96
+ li {
97
+ display: inline-block;
98
+ margin:0 .236em;
99
+ }
100
+ }
101
+ }
102
+
103
+ .single-project {
104
+ .project {
105
+ .clearfix;
106
+ margin-bottom: 1.618em;
107
+
108
+ .single-project-short-description {
109
+ margin-bottom: 1.618em;
110
+ }
111
+
112
+ .summary {
113
+ .single-project-categories {
114
+ li:before {
115
+ .iconbefore( "\f318" );
116
+ }
117
+ }
118
+
119
+ .client-name {
120
+ &:before {
121
+ .iconbefore( "\f338" );
122
+ }
123
+ }
124
+
125
+ .project-url {
126
+ &:before {
127
+ .iconbefore( "\f319" );
128
+ }
129
+ }
130
+
131
+ .single-project-categories,
132
+ .url,
133
+ .client {
134
+ margin-bottom: 1.618em;
135
+ }
136
+
137
+ .project-meta {
138
+ ul,
139
+ li {
140
+ list-style: none;
141
+ }
142
+ }
143
+ }
144
+ }
145
+
146
+ .single-featured {
147
+ margin-bottom: 1.618em;
148
+ }
149
+
150
+ &.has-gallery {
151
+ .gallery {
152
+ width: 62%;
153
+ float: left;
154
+ a {
155
+ display: block;
156
+ }
157
+
158
+ img {
159
+ .border_radius(0);
160
+ max-width: 100%;
161
+ height: auto;
162
+ -webkit-box-shadow: none;
163
+ -moz-box-shadow: none;
164
+ box-shadow: none;
165
+ display: block;
166
+ }
167
+ }
168
+ .summary {
169
+ width: 38%;
170
+ float: right;
171
+ padding: 0 0 0 2.618em;
172
+ .borderbox;
173
+ > div {
174
+ font-size: .857em;
175
+ }
176
+ }
177
+ }
178
+
179
+ &.no-gallery {
180
+ .summary {
181
+ .clearfix;
182
+
183
+ .project_title,
184
+ .single-project-description {
185
+ width: 62%;
186
+ float: left;
187
+ }
188
+
189
+ .project-meta {
190
+ width: 34%;
191
+ float: right;
192
+ }
193
+ }
194
+ }
195
+
196
+ .projects-single-pagination {
197
+ .clearfix;
198
+
199
+ .previous,
200
+ .next {
201
+ a {
202
+ text-decoration: none;
203
+ }
204
+ }
205
+
206
+ .previous {
207
+ float: right;
208
+
209
+ a:after {
210
+ .iconafter( "\f344" );
211
+ }
212
+ }
213
+
214
+ .next {
215
+ float: left;
216
+
217
+ a:before {
218
+ .iconbefore( "\f340" );
219
+ }
220
+ }
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Widgets
226
+ */
227
+ .projects_list_widget {
228
+ li {
229
+ margin-bottom: 1.618em;
230
+
231
+ a {
232
+ display: block;
233
+ .clearfix;
234
+ }
235
+
236
+ img {
237
+ float: right;
238
+ max-width: 60px;
239
+ height: auto;
240
+ }
241
+
242
+ .project-title {
243
+ float: left;
244
+ }
245
+ }
246
+ }
247
+
248
+ .widget_projects_categories {
249
+ ul.children {
250
+ margin-left: 2.618em;
251
+ list-style-type: disc;
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Twenty Thirteen Specific
257
+ */
258
+ .single-project {
259
+ .twentythirteen {
260
+ .entry-summary {
261
+ padding: 0;
262
+ }
263
+
264
+ ul.single-project-categories {
265
+ padding-left: 0;
266
+ }
267
+ }
268
+
269
+ &.has-gallery {
270
+ .twentythirteen {
271
+ .summary {
272
+ width: 36%;
273
+ }
274
+
275
+ .gallery {
276
+ width: 61%;
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ /**
283
+ * Twenty Fourteen Specific
284
+ */
285
+ .single-project.has-gallery {
286
+ .tfp {
287
+ .gallery {
288
+ width: 50%;
289
+ }
290
+
291
+ .entry-summary {
292
+ width: 50%;
293
+ padding-left: 2.618em !important;
294
+ }
295
+ }
296
+ }
297
+
298
+ .twentyfourteen {
299
+ .tfp {
300
+ padding: 12px 10px 0;
301
+ max-width: 474px;
302
+ margin:0 auto;
303
+ .project .entry-summary {
304
+ padding: 0;
305
+ margin: 0 0 1.618em !important;
306
+ }
307
+ div.project.hentry.has-post-thumbnail {
308
+ margin-top:0;
309
+ }
310
+ .project {
311
+ .images {
312
+ img {
313
+ margin-bottom:1em;
314
+ }
315
+ }
316
+ }
317
+ }
318
+ }
319
+
320
+ @media screen and (min-width: 673px) {
321
+ .twentyfourteen {
322
+ .tfp {
323
+ padding-right: 30px;
324
+ padding-left: 30px;
325
+ }
326
+ }
327
+ }
328
+
329
+ @media screen and (min-width: 1040px) {
330
+ .twentyfourteen {
331
+ .tfp {
332
+ padding-right: 15px;
333
+ padding-left: 15px;
334
+ }
335
+ }
336
+ }
337
+
338
+ @media screen and (min-width: 1110px) {
339
+ .twentyfourteen {
340
+ .tfp {
341
+ padding-right: 30px;
342
+ padding-left: 30px;
343
+ }
344
+ }
345
+ }
346
+
347
+ @media screen and (min-width: 1218px) {
348
+ .twentyfourteen {
349
+ .tfp {
350
+ margin-right: 54px;
351
+ }
352
+ }
353
+ .full-width {
354
+ .twentyfourteen {
355
+ .tfp {
356
+ margin-right: auto;
357
+ }
358
+ }
359
+ }
360
+ }
assets/images/placeholder.png ADDED
Binary file
assets/js/script.js ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($){
2
+ jQuery('ul.sorting a').click(function(e) {
3
+ e.preventDefault();
4
+ jQuery(this).css('outline','none');
5
+ jQuery('ul.sorting .current').removeClass('current');
6
+ jQuery(this).parent().addClass('current');
7
+
8
+ // filterVal = slug of active link
9
+ var filterVal = jQuery(this).text().toLowerCase().replace(' ','-');
10
+
11
+ // filterVal default = 'all'
12
+ if( filterVal == 'all' ) {
13
+ jQuery('ul.projects li.hidden').show().removeClass('hidden').addClass('visible');
14
+ } else {
15
+
16
+ // Show / hide based on active link
17
+ jQuery('ul.projects li').each(function() {
18
+
19
+ if( ! jQuery(this).hasClass( filterVal ) ) {
20
+ // If the li doesn't have a class = filterVal, hide it
21
+ jQuery(this).hide().addClass('hidden').removeClass('visible');
22
+ } else {
23
+ // If it does, show it
24
+ jQuery(this).show().removeClass('hidden').addClass('visible');
25
+ }
26
+ });
27
+ }
28
+
29
+ //jQuery('ul.projects').hide().fadeIn(300);
30
+
31
+ return false;
32
+ });
33
+
34
+ jQuery('ul.sorting a').click(function() {
35
+ jQuery('ul.projects').find('li').removeClass('last').removeClass('first');
36
+ });
37
+
38
+ jQuery('ul.sorting a').click(function() {
39
+ jQuery('ul.projects li.visible').each(function(i) {
40
+ i=( i+1 );
41
+ x=( i+2 );
42
+ if ( i%3==0 ) {
43
+ jQuery(this).removeClass('first').addClass('last');
44
+ }
45
+ if ( x%3==0 ) {
46
+ jQuery(this).removeClass('last').addClass('first');
47
+ }
48
+ });
49
+ });
50
+ });
assets/js/script.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(document).ready(function(e){jQuery("ul.sorting a").click(function(e){e.preventDefault();jQuery(this).css("outline","none");jQuery("ul.sorting .current").removeClass("current");jQuery(this).parent().addClass("current");var t=jQuery(this).text().toLowerCase().replace(" ","-");t=="all"?jQuery("ul.projects li.hidden").show().removeClass("hidden").addClass("visible"):jQuery("ul.projects li").each(function(){jQuery(this).hasClass(t)?jQuery(this).show().removeClass("hidden").addClass("visible"):jQuery(this).hide().addClass("hidden").removeClass("visible")});return!1});jQuery("ul.sorting a").click(function(){jQuery("ul.projects").find("li").removeClass("last").removeClass("first")});jQuery("ul.sorting a").click(function(){jQuery("ul.projects li.visible").each(function(e){e+=1;x=e+2;e%3==0&&jQuery(this).removeClass("first").addClass("last");x%3==0&&jQuery(this).removeClass("last").addClass("first")})})});
classes/class-projects-admin.php ADDED
@@ -0,0 +1,563 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
3
+
4
+ /**
5
+ * WooThemes Projects Admin Class
6
+ *
7
+ * All functionality pertaining to the projects admin.
8
+ *
9
+ * @package WordPress
10
+ * @subpackage Projects_Admin
11
+ * @category Plugin
12
+ * @author Matty
13
+ * @since 1.0.0
14
+ */
15
+
16
+ class Projects_Admin {
17
+ private $dir;
18
+ private $assets_dir;
19
+ private $assets_url;
20
+ private $token;
21
+ private $post_type;
22
+ private $file;
23
+
24
+ /**
25
+ * Constructor function.
26
+ *
27
+ * @access public
28
+ * @since 1.0.0
29
+ * @return void
30
+ */
31
+ public function __construct ( $file ) {
32
+ $this->dir = dirname( $file );
33
+ $this->file = $file;
34
+ $this->assets_dir = trailingslashit( $this->dir ) . 'assets';
35
+ $this->assets_url = esc_url( str_replace( WP_PLUGIN_DIR, WP_PLUGIN_URL, $this->assets_dir ) );
36
+ $this->token = 'projects';
37
+ $this->post_type = 'project';
38
+
39
+ global $pagenow;
40
+
41
+ add_action( 'admin_menu', array( $this, 'meta_box_setup' ), 20 );
42
+ add_action( 'save_post', array( $this, 'meta_box_save' ) );
43
+ add_filter( 'enter_title_here', array( $this, 'enter_title_here' ) );
44
+ add_action( 'admin_print_styles', array( $this, 'enqueue_admin_styles' ), 10 );
45
+ add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
46
+ add_action( 'admin_notices', array( $this, 'configuration_admin_notice' ) );
47
+ add_action( 'do_meta_boxes', array( $this, 'featured_image_label' ) );
48
+ add_filter( 'admin_post_thumbnail_html', array( $this, 'featured_image_set_link' ) );
49
+ add_filter( 'admin_post_thumbnail_html', array( $this, 'featured_image_remove_link' ) );
50
+ add_filter( 'media_view_strings', array( $this, 'featured_image_popup_set_link' ) );
51
+
52
+ if ( $pagenow == 'edit.php' && isset( $_GET['post_type'] ) && esc_attr( $_GET['post_type'] ) == $this->post_type ) {
53
+ add_filter( 'manage_edit-' . $this->post_type . '_columns', array( $this, 'register_custom_column_headings' ), 10, 1 );
54
+ add_action( 'manage_posts_custom_column', array( $this, 'register_custom_columns' ), 10, 2 );
55
+ }
56
+ } // End __construct()
57
+
58
+ /**
59
+ * Add custom columns for the "manage" screen of this post type.
60
+ *
61
+ * @access public
62
+ * @param string $column_name
63
+ * @param int $id
64
+ * @since 1.0.0
65
+ * @return void
66
+ */
67
+ public function register_custom_columns ( $column_name, $id ) {
68
+ global $wpdb, $post;
69
+
70
+ $meta = get_post_custom( $id );
71
+
72
+ switch ( $column_name ) {
73
+
74
+ case 'image':
75
+ $value = '';
76
+
77
+ $value = projects_get_image( $id, 40 );
78
+
79
+ echo $value;
80
+ break;
81
+
82
+ default:
83
+ break;
84
+
85
+ }
86
+ } // End register_custom_columns()
87
+
88
+ /**
89
+ * Add custom column headings for the "manage" screen of this post type.
90
+ *
91
+ * @access public
92
+ * @param array $defaults
93
+ * @since 1.0.0
94
+ * @return void
95
+ */
96
+ public function register_custom_column_headings ( $defaults ) {
97
+ $new_columns = array(
98
+ 'image' => __( 'Cover Image', 'projects' )
99
+ );
100
+
101
+ $last_item = '';
102
+
103
+ if ( isset( $defaults['date'] ) ) { unset( $defaults['date'] ); }
104
+
105
+ if ( count( $defaults ) > 2 ) {
106
+ $last_item = array_slice( $defaults, -1 );
107
+
108
+ array_pop( $defaults );
109
+ }
110
+ $defaults = array_merge( $defaults, $new_columns );
111
+
112
+ if ( $last_item != '' ) {
113
+ foreach ( $last_item as $k => $v ) {
114
+ $defaults[$k] = $v;
115
+ break;
116
+ }
117
+ }
118
+
119
+ return $defaults;
120
+ } // End register_custom_column_headings()
121
+
122
+ /**
123
+ * Update messages for the post type admin.
124
+ * @since 1.0.0
125
+ * @param array $messages Array of messages for all post types.
126
+ * @return array Modified array.
127
+ */
128
+ public function updated_messages ( $messages ) {
129
+ global $post, $post_ID;
130
+
131
+ $messages[$this->post_type] = array(
132
+ 0 => '', // Unused. Messages start at index 1.
133
+ 1 => sprintf( __( 'Project updated. %sView project%s', 'projects' ), '<a href="' . esc_url( get_permalink( $post_ID ) ) . '">', '</a>' ),
134
+ 2 => __( 'Custom field updated.', 'projects' ),
135
+ 3 => __( 'Custom field deleted.', 'projects' ),
136
+ 4 => __( 'Project updated.', 'projects' ),
137
+ /* translators: %s: date and time of the revision */
138
+ 5 => isset($_GET['revision']) ? sprintf( __( 'Project restored to revision from %s', 'projects' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
139
+ 6 => sprintf( __( 'Project published. %sView Project%s', 'projects' ), '<a href="' . esc_url( get_permalink( $post_ID ) ) . '">', '</a>' ),
140
+ 7 => __( 'Project saved.' ),
141
+ 8 => sprintf( __( 'Project submitted. %sPreview Project%s', 'projects' ), '<a target="_blank" href="' . esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) . '">', '</a>' ),
142
+ 9 => sprintf( __( 'Project scheduled for: %1$s. %2$sPreview Project%3$s', 'projects' ),
143
+ // translators: Publish box date format, see http://php.net/date
144
+ '<strong>' . date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ) . '</strong>', '<a target="_blank" href="' . esc_url( get_permalink($post_ID) ) . '">', '</a>' ),
145
+ 10 => sprintf( __( 'Project draft updated. %sPreview Project%s', 'projects' ), '<a target="_blank" href="' . esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) . '">', '</a>' ),
146
+ );
147
+
148
+ return $messages;
149
+ } // End updated_messages()
150
+
151
+ /**
152
+ * Setup the meta box.
153
+ *
154
+ * @access public
155
+ * @since 1.1.0
156
+ * @return void
157
+ */
158
+ public function meta_box_setup () {
159
+ // Project Details Meta Box Load
160
+ add_meta_box( 'project-data', __( 'Project Details', 'projects' ), array( $this, 'meta_box_content' ), $this->post_type, 'normal', 'high' );
161
+ // Project Images Meta Bog Load
162
+ add_meta_box( 'project-images', __( 'Project Gallery', 'projects' ), array( $this, 'meta_box_content_project_images' ), 'project', 'side' );
163
+ } // End meta_box_setup()
164
+
165
+ /**
166
+ * The contents of our meta box.
167
+ *
168
+ * @access public
169
+ * @since 1.1.0
170
+ * @return void
171
+ */
172
+ public function meta_box_content () {
173
+ global $post_id;
174
+ $fields = get_post_custom( $post_id );
175
+ $field_data = $this->get_custom_fields_settings();
176
+
177
+ $html = '';
178
+
179
+ $html .= '<input type="hidden" name="woo_' . $this->token . '_noonce" id="woo_' . $this->token . '_noonce" value="' . wp_create_nonce( plugin_basename( $this->dir ) ) . '" />';
180
+
181
+ if ( 0 < count( $field_data ) ) {
182
+ $html .= '<table class="form-table">' . "\n";
183
+ $html .= '<tbody>' . "\n";
184
+
185
+ foreach ( $field_data as $k => $v ) {
186
+ $data = $v['default'];
187
+ if ( isset( $fields['_' . $k] ) && isset( $fields['_' . $k][0] ) ) {
188
+ $data = $fields['_' . $k][0];
189
+ }
190
+
191
+ $html .= '<tr valign="top"><th scope="row"><label for="' . esc_attr( $k ) . '">' . $v['name'] . '</label></th><td><input name="' . esc_attr( $k ) . '" type="text" id="' . esc_attr( $k ) . '" class="regular-text" value="' . esc_attr( $data ) . '" />' . "\n";
192
+ $html .= '<p class="description">' . $v['description'] . '</p>' . "\n";
193
+ $html .= '</td><tr/>' . "\n";
194
+ }
195
+
196
+ $html .= '</tbody>' . "\n";
197
+ $html .= '</table>' . "\n";
198
+ }
199
+
200
+ echo $html;
201
+ } // End meta_box_content()
202
+
203
+ /**
204
+ * Display the project images meta box.
205
+ *
206
+ * @access public
207
+ * @return void
208
+ */
209
+ public function meta_box_content_project_images () {
210
+ global $post;
211
+ ?>
212
+ <div id="project_images_container">
213
+ <ul class="project_images">
214
+ <?php
215
+ if ( metadata_exists( 'post', $post->ID, '_project_image_gallery' ) ) {
216
+ $project_image_gallery = get_post_meta( $post->ID, '_project_image_gallery', true );
217
+ } else {
218
+ // Backwards compat
219
+ $attachment_ids = get_posts( 'post_parent=' . $post->ID . '&numberposts=-1&post_type=attachment&orderby=menu_order&order=ASC&post_mime_type=image&fields=ids' );
220
+ $attachment_ids = array_diff( $attachment_ids, array( get_post_thumbnail_id() ) );
221
+ $project_image_gallery = implode( ',', $attachment_ids );
222
+ }
223
+
224
+ $attachments = array_filter( explode( ',', $project_image_gallery ) );
225
+
226
+ if ( $attachments )
227
+ foreach ( $attachments as $attachment_id ) {
228
+ echo '<li class="image" data-attachment_id="' . $attachment_id . '">
229
+ ' . wp_get_attachment_image( $attachment_id, 'thumbnail' ) . '
230
+ <ul class="actions">
231
+ <li><a href="#" class="delete" title="' . __( 'Delete image', 'projects' ) . '">&times;</a></li>
232
+ </ul>
233
+ </li>';
234
+ }
235
+ ?>
236
+ </ul>
237
+
238
+ <input type="hidden" id="project_image_gallery" name="project_image_gallery" value="<?php echo esc_attr( $project_image_gallery ); ?>" />
239
+
240
+ </div>
241
+ <p class="add_project_images hide-if-no-js">
242
+ <a href="#"><?php _e( 'Add project gallery images', 'projects' ); ?></a>
243
+ </p>
244
+ <script type="text/javascript">
245
+ jQuery(document).ready(function($){
246
+
247
+ // Uploading files
248
+ var project_gallery_frame;
249
+ var $image_gallery_ids = $( '#project_image_gallery' );
250
+ var $project_images = $( '#project_images_container ul.project_images' );
251
+
252
+ jQuery( '.add_project_images' ).on( 'click', 'a', function( event ) {
253
+
254
+ var $el = $(this);
255
+ var attachment_ids = $image_gallery_ids.val();
256
+
257
+ event.preventDefault();
258
+
259
+ // If the media frame already exists, reopen it.
260
+ if ( project_gallery_frame ) {
261
+ project_gallery_frame.open();
262
+ return;
263
+ }
264
+
265
+ // Create the media frame.
266
+ project_gallery_frame = wp.media.frames.downloadable_file = wp.media({
267
+ // Set the title of the modal.
268
+ title: '<?php _e( 'Add Images to Project Gallery', 'projects' ); ?>',
269
+ button: {
270
+ text: '<?php _e( 'Add to gallery', 'projects' ); ?>',
271
+ },
272
+ multiple: true
273
+ });
274
+
275
+ // When an image is selected, run a callback.
276
+ project_gallery_frame.on( 'select', function() {
277
+
278
+ var selection = project_gallery_frame.state().get( 'selection' );
279
+
280
+ selection.map( function( attachment ) {
281
+
282
+ attachment = attachment.toJSON();
283
+
284
+ if ( attachment.id ) {
285
+ attachment_ids = attachment_ids ? attachment_ids + "," + attachment.id : attachment.id;
286
+
287
+ $project_images.append('\
288
+ <li class="image" data-attachment_id="' + attachment.id + '">\
289
+ <img src="' + attachment.url + '" />\
290
+ <ul class="actions">\
291
+ <li><a href="#" class="delete" title="<?php _e( 'Delete image', 'projects' ); ?>">&times;</a></li>\
292
+ </ul>\
293
+ </li>');
294
+ }
295
+
296
+ } );
297
+
298
+ $image_gallery_ids.val( attachment_ids );
299
+ });
300
+
301
+ // Finally, open the modal.
302
+ project_gallery_frame.open();
303
+ });
304
+
305
+ // Image ordering
306
+ $project_images.sortable({
307
+ items: 'li.image',
308
+ cursor: 'move',
309
+ scrollSensitivity:40,
310
+ forcePlaceholderSize: true,
311
+ forceHelperSize: false,
312
+ helper: 'clone',
313
+ opacity: 0.65,
314
+ placeholder: 'projects-metabox-sortable-placeholder',
315
+ start:function(event,ui){
316
+ ui.item.css( 'background-color','#f6f6f6' );
317
+ },
318
+ stop:function(event,ui){
319
+ ui.item.removeAttr( 'style' );
320
+ },
321
+ update: function(event, ui) {
322
+ var attachment_ids = '';
323
+
324
+ $( '#project_images_container ul li.image' ).css( 'cursor','default' ).each(function() {
325
+ var attachment_id = jQuery(this).attr( 'data-attachment_id' );
326
+ attachment_ids = attachment_ids + attachment_id + ',';
327
+ });
328
+
329
+ $image_gallery_ids.val( attachment_ids );
330
+ }
331
+ });
332
+
333
+ // Remove images
334
+ $( '#project_images_container' ).on( 'click', 'a.delete', function() {
335
+
336
+ $(this).closest( 'li.image' ).remove();
337
+
338
+ var attachment_ids = '';
339
+
340
+ $( '#project_images_container ul li.image' ).css( 'cursor','default' ).each(function() {
341
+ var attachment_id = jQuery(this).attr( 'data-attachment_id' );
342
+ attachment_ids = attachment_ids + attachment_id + ',';
343
+ });
344
+
345
+ $image_gallery_ids.val( attachment_ids );
346
+
347
+ return false;
348
+ } );
349
+
350
+ });
351
+ </script>
352
+ <?php
353
+ } // End meta_box_content_project_images()
354
+
355
+ /**
356
+ * Save meta box fields.
357
+ *
358
+ * @access public
359
+ * @since 1.1.0
360
+ * @param int $post_id
361
+ * @return void
362
+ */
363
+ public function meta_box_save ( $post_id ) {
364
+ global $post, $messages;
365
+
366
+ // Verify
367
+ if ( ( get_post_type() != $this->post_type ) || ! wp_verify_nonce( $_POST['woo_' . $this->token . '_noonce'], plugin_basename( $this->dir ) ) ) {
368
+ return $post_id;
369
+ }
370
+
371
+ if ( 'page' == $_POST['post_type'] ) {
372
+ if ( ! current_user_can( 'edit_page', $post_id ) ) {
373
+ return $post_id;
374
+ }
375
+ } else {
376
+ if ( ! current_user_can( 'edit_post', $post_id ) ) {
377
+ return $post_id;
378
+ }
379
+ }
380
+
381
+ $field_data = $this->get_custom_fields_settings();
382
+ $fields = array_keys( $field_data );
383
+
384
+ foreach ( $fields as $f ) {
385
+
386
+ ${$f} = strip_tags(trim($_POST[$f]));
387
+
388
+ // Escape the URLs.
389
+ if ( 'url' == $field_data[$f]['type'] ) {
390
+ ${$f} = esc_url( ${$f} );
391
+ }
392
+
393
+ if ( get_post_meta( $post_id, '_' . $f ) == '' ) {
394
+ add_post_meta( $post_id, '_' . $f, ${$f}, true );
395
+ } elseif( ${$f} != get_post_meta( $post_id, '_' . $f, true ) ) {
396
+ update_post_meta( $post_id, '_' . $f, ${$f} );
397
+ } elseif ( ${$f} == '' ) {
398
+ delete_post_meta( $post_id, '_' . $f, get_post_meta( $post_id, '_' . $f, true ) );
399
+ }
400
+ }
401
+
402
+ // Save the project gallery image IDs.
403
+ $attachment_ids = array_filter( explode( ',', sanitize_text_field( $_POST['project_image_gallery'] ) ) );
404
+ update_post_meta( $post_id, '_project_image_gallery', implode( ',', $attachment_ids ) );
405
+ } // End meta_box_save()
406
+
407
+ /**
408
+ * Get the settings for the custom fields.
409
+ * @since 1.1.0
410
+ * @return array
411
+ */
412
+ public function get_custom_fields_settings () {
413
+ $fields = array();
414
+
415
+ $fields['client'] = array(
416
+ 'name' => __( 'Client', 'projects' ),
417
+ 'description' => __( 'Enter the client name for this project.', 'projects' ),
418
+ 'type' => 'text',
419
+ 'default' => '',
420
+ 'section' => 'info'
421
+ );
422
+
423
+ $fields['url'] = array(
424
+ 'name' => __( 'URL', 'projects' ),
425
+ 'description' => __( 'Enter a URL that applies to this project.', 'projects' ),
426
+ 'type' => 'url',
427
+ 'default' => '',
428
+ 'section' => 'info'
429
+ );
430
+
431
+ return apply_filters( 'projects_custom_fields', $fields );
432
+ } // End get_custom_fields_settings()
433
+
434
+ /**
435
+ * Customise the "Enter title here" text.
436
+ *
437
+ * @access public
438
+ * @since 1.0.0
439
+ * @param string $title
440
+ * @return void
441
+ */
442
+ public function enter_title_here ( $title ) {
443
+ if ( get_post_type() == $this->post_type ) {
444
+ $title = __( 'Enter the project title here', 'projects' );
445
+ }
446
+ return $title;
447
+ } // End enter_title_here()
448
+
449
+ /**
450
+ * Enqueue post type admin CSS.
451
+ *
452
+ * @access public
453
+ * @since 1.0.0
454
+ * @return void
455
+ */
456
+ public function enqueue_admin_styles () {
457
+ wp_register_style( 'projects-admin', $this->assets_url . '/css/admin.css', array(), '1.0.0' );
458
+ wp_enqueue_style( 'projects-admin' );
459
+ } // End enqueue_admin_styles()
460
+
461
+ /**
462
+ * Display an admin notice, if not on the settings screen and if projects page isn't set.
463
+ * @access public
464
+ * @since 1.0.0
465
+ * @return void
466
+ */
467
+ public function configuration_admin_notice () {
468
+ if ( ( isset( $_GET['page'] ) && 'projects-settings-page' == $_GET['page'] ) ) return;
469
+
470
+ $projects_page = projects_get_page_id( 'projects' );
471
+
472
+ if ( -1 == $projects_page ) {
473
+ $url = add_query_arg( 'post_type', 'project', admin_url( 'edit.php' ) );
474
+ $url = add_query_arg( 'page', 'projects-settings-page', $url );
475
+ echo '<div class="updated fade"><p>' . sprintf( __( '%sProjects by WooThemes is almost ready.%s To get started, %sconfigure your projects page%s.', 'projects' ), '<strong>', '</strong>', '<a href="' . esc_url( $url ) . '">', '</a>' ) . '</p></div>' . "\n";
476
+ }
477
+ } // End configuration_admin_notice()
478
+
479
+ /**
480
+ * Replace the featured image meta box
481
+ * Functionality is identical, this is purely to change the label.
482
+ * @access public
483
+ * @since 1.0.0
484
+ * @return void
485
+ */
486
+ public function featured_image_label() {
487
+ remove_meta_box( 'postimagediv', 'project', 'side' );
488
+ add_meta_box( 'postimagediv', __( 'Project Cover Image', 'projects' ), 'post_thumbnail_meta_box', 'project', 'side' );
489
+ }
490
+
491
+ /**
492
+ * Tweak the 'Set featured image' string to say 'Set cover image'.
493
+ * @access public
494
+ * @since 1.0.0
495
+ * @return void
496
+ */
497
+ public function featured_image_set_link( $content ) {
498
+ $post_type = $this->get_current_post_type();
499
+
500
+ if ( 'project' == $post_type ) {
501
+ $content = str_replace( __( 'Set featured image' ), __( 'Set cover image', 'projects' ), $content );
502
+ }
503
+
504
+ return $content;
505
+ }
506
+
507
+ /**
508
+ * Tweak the 'Remove featured image' string to say 'Remove cover image'.
509
+ * @access public
510
+ * @since 1.0.0
511
+ * @return void
512
+ */
513
+ public function featured_image_remove_link( $content ) {
514
+ $post_type = $this->get_current_post_type();
515
+
516
+ if ( 'project' == $post_type ) {
517
+ $content = str_replace( __( 'Remove featured image' ), __( 'Remove cover image', 'projects' ), $content );
518
+ }
519
+
520
+ return $content;
521
+ }
522
+
523
+ /**
524
+ * Tweak the featured image strings in the media popup
525
+ * @access public
526
+ * @since 1.0.0
527
+ * @return void
528
+ */
529
+ public function featured_image_popup_set_link( $strings ) {
530
+ $post_type = $this->get_current_post_type();
531
+ if ( 'project' == $post_type ) {
532
+ $strings['setFeaturedImageTitle'] = __( 'Set Cover Image', 'projects' );
533
+ $strings['setFeaturedImage'] = __( 'Set cover image', 'projects' );
534
+ }
535
+ return $strings;
536
+ }
537
+
538
+ /**
539
+ * Determine what post type the current admin page is related to
540
+ * @access public
541
+ * @since 1.0.0
542
+ * @return string
543
+ */
544
+ public function get_current_post_type() {
545
+ global $post, $typenow, $current_screen;
546
+
547
+ if ( $post && $post->post_type )
548
+ return $post->post_type;
549
+
550
+ elseif ( $typenow )
551
+ return $typenow;
552
+
553
+ elseif ( $current_screen && $current_screen->post_type )
554
+ return $current_screen->post_type;
555
+
556
+ elseif ( isset( $_REQUEST['post_type'] ) )
557
+ return sanitize_key( $_REQUEST['post_type'] );
558
+
559
+ return null;
560
+ }
561
+
562
+ } // End Class
563
+ ?>
classes/class-projects-frontend.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
3
+
4
+ /**
5
+ * WooThemes Projects Frontend Class
6
+ *
7
+ * All functionality pertaining to the projects frontend.
8
+ *
9
+ * @package WordPress
10
+ * @subpackage Projects_Frontend
11
+ * @category Plugin
12
+ * @author Matty
13
+ * @since 1.0.0
14
+ */
15
+
16
+ class Projects_Frontend {
17
+ /**
18
+ * Instance of Projects_Template_Loader.
19
+ * @access public
20
+ * @since 1.0.0
21
+ * @var object
22
+ */
23
+ public $template_loader;
24
+
25
+ /**
26
+ * Constructor function.
27
+ *
28
+ * @access public
29
+ * @since 1.0.0
30
+ * @return void
31
+ */
32
+ public function __construct () {
33
+ require_once( 'class-projects-template-loader.php' );
34
+ $this->template_loader = new Projects_Template_Loader();
35
+ add_filter( 'template_include', array( $this->template_loader, 'template_loader' ) );
36
+ } // End __construct()
37
+ } // End Class
38
+ ?>
classes/class-projects-settings.php ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
3
+
4
+ /**
5
+ * WooThemes Projects Settings Class
6
+ *
7
+ * All functionality pertaining to the projects settings.
8
+ *
9
+ * @package WordPress
10
+ * @subpackage Projects
11
+ * @category Plugin
12
+ * @author Matty
13
+ * @since 1.0.0
14
+ */
15
+ class Projects_Settings {
16
+ /**
17
+ * Constructor function.
18
+ *
19
+ * @access public
20
+ * @since 1.0.0
21
+ * @return void
22
+ */
23
+ public function __construct() {
24
+
25
+ add_action( 'admin_menu', array( $this, 'projects_add_settings_page' ) );
26
+ add_action( 'admin_init', array( $this, 'projects_options_init' ) );
27
+
28
+ } // End __construct()
29
+
30
+ public function projects_add_settings_page() {
31
+ add_submenu_page( 'edit.php?post_type=project', 'Settings', 'Settings', 'publish_posts', 'projects-settings-page', array( $this, 'projects_settings_page' ) );
32
+ }
33
+
34
+ public function projects_settings_page() {
35
+ ?>
36
+ <div class="wrap">
37
+
38
+ <h2><?php _e( 'Projects Settings', 'projects' ); ?></h2>
39
+
40
+ <form action="options.php" method="post">
41
+
42
+ <?php settings_fields( 'projects_main_settings' ); ?>
43
+
44
+ <?php do_settings_sections( 'projects' ); ?>
45
+
46
+ <p class="submit">
47
+ <input type="submit" class="button-primary" value="<?php _e( 'Save Changes' ) ?>" />
48
+ </p>
49
+
50
+ </form>
51
+
52
+ </div>
53
+ <?php
54
+ }
55
+
56
+ public function projects_options_init(){
57
+ register_setting( 'projects_main_settings', 'projects', array( $this, 'projects_main_settings_validate' ) );
58
+ add_settings_section( 'projects_page_settings_description', 'Pages', array( $this, 'projects_page_settings' ), 'projects' );
59
+ add_settings_section( 'projects_image_settings_description', 'Images', array( $this, 'projects_images_settings' ), 'projects' );
60
+ }
61
+
62
+ public function projects_page_settings() {
63
+ ?>
64
+ <p><?php _e( 'Setup core projects pages.', 'projects' ); ?></p>
65
+ <?php
66
+ $options = get_option( 'projects' );
67
+ $args = array(
68
+ 'name' => 'projects[projects_page_id]',
69
+ 'selected' => absint( $options['projects_page_id'] ),
70
+ 'sort_column' => 'menu_order',
71
+ 'sort_order' => 'ASC',
72
+ 'show_option_none' => ' ',
73
+ );
74
+ ?>
75
+ <table class="form-table">
76
+ <tr valign="top">
77
+ <th scope="row"><?php _e( 'Projects Page', 'projects' ); ?></th>
78
+ <td>
79
+ <?php wp_dropdown_pages( $args ); ?>
80
+ <p class="description">
81
+ <?php _e( 'This sets the base page of your projects. This is where your projects archive will be.', 'projects' ); ?>
82
+ </p>
83
+ </td>
84
+ </tr>
85
+ </table>
86
+ <?php
87
+ }
88
+
89
+ public function projects_images_settings() {
90
+ ?>
91
+ <p><?php _e ( 'These settings affect the actual dimensions of images in your projects – the display on the front-end will still be affected by CSS styles. After changing these settings you may need to' , 'projects' ); ?> <a href="http://wordpress.org/extend/plugins/regenerate-thumbnails/"><?php _e( 'regenerate your thumbnails', 'projects' ); ?></a>.</p>
92
+ <?php
93
+
94
+ $options = get_option( 'projects' );
95
+
96
+ $defaults = apply_filters( 'projects_default_image_size', array(
97
+ 'project-archive' => array(
98
+ 'width' => 300,
99
+ 'height' => 300
100
+ ),
101
+ 'project-single' => array(
102
+ 'width' => 1024,
103
+ 'height' => 1024
104
+ ),
105
+ 'project-thumbnail' => array(
106
+ 'width' => 100,
107
+ 'height' => 100
108
+ )
109
+ ) );
110
+
111
+ // Parse incomming $options into an array and merge it with $defaults
112
+ $options = wp_parse_args( $options, $defaults );
113
+
114
+ ?>
115
+ <table class="form-table">
116
+ <tr valign="top">
117
+ <th scope="row">
118
+ <?php _e( 'Archive Images', 'projects' ); ?>
119
+ </th>
120
+ <td>
121
+ <?php _e( 'Width:', 'projects' ); ?> <input type="text" size="3" name="projects[project-archive][width]" value="<?php echo $options['project-archive']['width']; ?>" /> <?php _e( 'Height:', 'projects' ); ?> <input type="text" size="3" name="projects[project-archive][height]" value="<?php echo $options['project-archive']['height']; ?>" />
122
+ </td>
123
+ </tr>
124
+ <tr valign="top">
125
+ <th scope="row">
126
+ <?php _e( 'Single Images', 'projects' ); ?>
127
+ </th>
128
+ <td>
129
+ <?php _e( 'Width:', 'projects' ); ?> <input type="text" size="3" name="projects[project-single][width]" value="<?php echo $options['project-single']['width']; ?>" /> <?php _e( 'Height:', 'projects' ); ?> <input type="text" size="3" name="projects[project-single][height]" value="<?php echo $options['project-single']['height']; ?>" />
130
+ </td>
131
+ </tr>
132
+ <tr valign="top">
133
+ <th scope="row">
134
+ <?php _e( 'Thumbnails', 'projects' ); ?>
135
+ </th>
136
+ <td>
137
+ <?php _e( 'Width:', 'projects' ); ?> <input type="text" size="3" name="projects[project-thumbnail][width]" value="<?php echo $options['project-thumbnail']['width']; ?>" /> <?php _e( 'Height:', 'projects' ); ?> <input type="text" size="3" name="projects[project-thumbnail][height]" value="<?php echo $options['project-thumbnail']['height']; ?>" />
138
+ </td>
139
+ </tr>
140
+ </table>
141
+ <?php
142
+ }
143
+
144
+ public function projects_main_settings_validate( $input ) {
145
+
146
+ $input['projects_page_id'] = absint( $input['projects_page_id'] );
147
+
148
+ $input['project-archive']['width'] = absint( $input['project-archive']['width'] );
149
+ $input['project-archive']['height'] = absint( $input['project-archive']['height'] );
150
+
151
+ $input['project-single']['width'] = absint( $input['project-single']['width'] );
152
+ $input['project-single']['height'] = absint( $input['project-single']['height'] );
153
+
154
+ $input['project-thumbnail']['width'] = absint( $input['project-thumbnail']['width'] );
155
+ $input['project-thumbnail']['height'] = absint( $input['project-thumbnail']['height'] );
156
+
157
+ return $input;
158
+ }
159
+
160
+
161
+ } // End Class
162
+
163
+ new Projects_Settings();
classes/class-projects-shortcodes.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Projects_Shortcodes class.
4
+ *
5
+ * @class Projects_Shortcodes
6
+ * @version 1.0.0
7
+ * @package WordPress
8
+ * @subpackage Projects/Classes
9
+ * @category Class
10
+ * @author WooThemes
11
+ */
12
+ class Projects_Shortcodes {
13
+
14
+ public function __construct() {
15
+ // Regular shortcodes
16
+ add_shortcode( 'projects', array( $this, 'projects' ) );
17
+ }
18
+
19
+ /**
20
+ * Shortcode Wrapper
21
+ *
22
+ * @param mixed $function
23
+ * @param array $atts (default: array())
24
+ * @return string
25
+ */
26
+ public static function shortcode_wrapper(
27
+ $function,
28
+ $atts = array(),
29
+ $wrapper = array(
30
+ 'class' => 'projects',
31
+ 'before' => null,
32
+ 'after' => null
33
+ )
34
+ ){
35
+ ob_start();
36
+
37
+ $before = empty( $wrapper['before'] ) ? '<div class="' . $wrapper['class'] . '">' : $wrapper['before'];
38
+ $after = empty( $wrapper['after'] ) ? '</div>' : $wrapper['after'];
39
+
40
+ echo $before;
41
+ call_user_func( $function, $atts );
42
+ echo $after;
43
+
44
+ return ob_get_clean();
45
+ }
46
+
47
+ /**
48
+ * Recent Products shortcode
49
+ *
50
+ * @access public
51
+ * @param array $atts
52
+ * @return string
53
+ */
54
+ public function projects( $atts ) {
55
+
56
+ global $projects_loop;
57
+
58
+ extract( shortcode_atts( array(
59
+ 'limit' => '12',
60
+ 'columns' => '2',
61
+ 'orderby' => 'date',
62
+ 'order' => 'desc',
63
+ 'exclude_categories' => null,
64
+ ), $atts ) );
65
+
66
+ $args = array(
67
+ 'post_type' => 'project',
68
+ 'post_status' => 'publish',
69
+ 'ignore_sticky_posts' => 1,
70
+ 'posts_per_page' => $limit,
71
+ 'orderby' => $orderby,
72
+ 'order' => $order,
73
+ 'tax_query' => array(
74
+ array(
75
+ 'taxonomy' => 'project-category',
76
+ 'field' => 'id',
77
+ 'terms' => explode( ',', $exclude_categories ),
78
+ 'operator' => 'NOT IN'
79
+ )
80
+ )
81
+ );
82
+
83
+ ob_start();
84
+
85
+ $projects = new WP_Query( apply_filters( 'projects_query', $args, $atts ) );
86
+
87
+ $projects_loop['columns'] = $columns;
88
+
89
+ if ( $projects->have_posts() ) : ?>
90
+
91
+ <?php projects_project_loop_start(); ?>
92
+
93
+ <?php while ( $projects->have_posts() ) : $projects->the_post(); ?>
94
+
95
+ <?php projects_get_template_part( 'content', 'project' ); ?>
96
+
97
+ <?php endwhile; // end of the loop. ?>
98
+
99
+ <?php projects_project_loop_end(); ?>
100
+
101
+ <?php endif;
102
+
103
+ wp_reset_postdata();
104
+
105
+ return '<div class="projects columns-' . $columns . '">' . ob_get_clean() . '</div>';
106
+
107
+ }
108
+
109
+ }
110
+
111
+
112
+ new Projects_Shortcodes();
classes/class-projects-taxonomy.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
3
+
4
+ /**
5
+ * WooThemes Projects Taxonomy Class
6
+ *
7
+ * Re-usable class for registering project taxonomies.
8
+ *
9
+ * @package WordPress
10
+ * @subpackage WooThemes_Projects
11
+ * @category Plugin
12
+ * @author Matty
13
+ * @since 1.0.0
14
+ */
15
+ class Projects_Taxonomy {
16
+ /**
17
+ * The post type to register the taxonomy for.
18
+ * @access private
19
+ * @since 1.0.0
20
+ * @var string
21
+ */
22
+ private $post_type;
23
+
24
+ /**
25
+ * The key of the taxonomy.
26
+ * @access private
27
+ * @since 1.0.0
28
+ * @var string
29
+ */
30
+ private $token;
31
+
32
+ /**
33
+ * The singular name for the taxonomy.
34
+ * @access private
35
+ * @since 1.0.0
36
+ * @var string
37
+ */
38
+ private $singular;
39
+
40
+ /**
41
+ * The plural name for the taxonomy.
42
+ * @access private
43
+ * @since 1.0.0
44
+ * @var string
45
+ */
46
+ private $plural;
47
+
48
+ /**
49
+ * The arguments to use when registering the taxonomy.
50
+ * @access private
51
+ * @since 1.0.0
52
+ * @var string
53
+ */
54
+ private $args;
55
+
56
+ /**
57
+ * Class constructor.
58
+ * @access public
59
+ * @since 1.0.0
60
+ * @param string $token The taxonomy key.
61
+ * @param string $singular Singular name.
62
+ * @param string $plural Plural name.
63
+ * @param array $args Array of argument overrides.
64
+ */
65
+ public function __construct ( $token = 'project-category', $singular = '', $plural = '', $args = array() ) {
66
+ $this->post_type = 'project';
67
+ $this->token = esc_attr( $token );
68
+ $this->singular = esc_html( $singular );
69
+ $this->plural = esc_html( $plural );
70
+
71
+ if ( '' == $this->singular ) $this->singular = __( 'Category', 'projects' );
72
+ if ( '' == $this->plural ) $this->plural = __( 'Categories', 'projects' );
73
+
74
+ $this->args = wp_parse_args( $args, $this->_get_default_args() );
75
+ } // End __construct()
76
+
77
+ /**
78
+ * Return an array of default arguments.
79
+ * @access private
80
+ * @since 1.0.0
81
+ * @return array Default arguments.
82
+ */
83
+ private function _get_default_args () {
84
+ return array( 'labels' => $this->_get_default_labels(), 'public' => true, 'hierarchical' => true, 'show_ui' => true, 'show_admin_column' => true, 'query_var' => true, 'show_in_nav_menus' => false, 'show_tagcloud' => false );
85
+ } // End _get_default_args()
86
+
87
+ /**
88
+ * Return an array of default labels.
89
+ * @access private
90
+ * @since 1.3.0
91
+ * @return array Default labels.
92
+ */
93
+ private function _get_default_labels () {
94
+ return array(
95
+ 'name' => sprintf( _x( '%s', 'taxonomy general name', 'projects' ), $this->plural ),
96
+ 'singular_name' => sprintf( _x( '%s', 'taxonomy singular name', 'projects' ), $this->singular ),
97
+ 'search_items' => sprintf( __( 'Search %s', 'projects' ), $this->plural ),
98
+ 'all_items' => sprintf( __( 'All %s', 'projects' ), $this->plural ),
99
+ 'parent_item' => sprintf( __( 'Parent %s', 'projects' ), $this->singular ),
100
+ 'parent_item_colon' => sprintf( __( 'Parent %s:', 'projects' ), $this->singular ),
101
+ 'edit_item' => sprintf( __( 'Edit %s', 'projects' ), $this->singular ),
102
+ 'update_item' => sprintf( __( 'Update %s', 'projects' ), $this->singular ),
103
+ 'add_new_item' => sprintf( __( 'Add New %s', 'projects' ), $this->singular ),
104
+ 'new_item_name' => sprintf( __( 'New %s Name', 'projects' ), $this->singular ),
105
+ 'menu_name' => sprintf( __( '%s', 'projects' ), $this->plural )
106
+ );
107
+ } // End _get_default_labels()
108
+
109
+ /**
110
+ * Register the taxonomy.
111
+ * @access public
112
+ * @since 1.0.0
113
+ * @return void
114
+ */
115
+ public function register () {
116
+ register_taxonomy( esc_attr( $this->token ), esc_attr( $this->post_type ), (array)$this->args );
117
+ } // End register()
118
+ } // End Class
119
+ ?>
classes/class-projects-template-loader.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Projects_Template_Loader {
3
+ public $template_url;
4
+
5
+ /**
6
+ * Constructor function.
7
+ * @access public
8
+ * @since 1.0.0
9
+ * @return void
10
+ */
11
+ public function __construct() {
12
+ $this->template_url = apply_filters( 'projects_template_url', 'projects/' );
13
+ } // End __construct()
14
+
15
+ /**
16
+ * Load a template.
17
+ *
18
+ * Handles template usage so that we can use our own templates instead of the themes.
19
+ *
20
+ * Templates are in the 'templates' folder. projects looks for theme
21
+ * overrides in /theme/projects/ by default
22
+ *
23
+ * @access public
24
+ * @param mixed $template
25
+ * @return string
26
+ */
27
+ public function template_loader ( $template ) {
28
+ global $projects, $post;
29
+
30
+ $find = array( 'projects.php' );
31
+ $file = '';
32
+
33
+ if ( is_single() && 'project' == get_post_type() ) {
34
+
35
+ $file = 'single-project.php';
36
+ $find[] = $file;
37
+ $find[] = $this->template_url . $file;
38
+
39
+ } elseif ( is_tax( 'project-category' ) ) {
40
+
41
+ $term = get_queried_object();
42
+
43
+ $file = 'taxonomy-' . $term->taxonomy . '.php';
44
+ $find[] = 'taxonomy-' . $term->taxonomy . '-' . $term->slug . '.php';
45
+ $find[] = $this->template_url . 'taxonomy-' . $term->taxonomy . '-' . $term->slug . '.php';
46
+ $find[] = $file;
47
+ $find[] = $this->template_url . $file;
48
+
49
+ } elseif ( is_post_type_archive( 'project' ) || is_page( projects_get_page_id( 'projects' ) ) ) {
50
+
51
+ $file = 'archive-project.php';
52
+ $find[] = $file;
53
+ $find[] = $this->template_url . $file;
54
+
55
+ }
56
+
57
+ if ( $file ) {
58
+ $template = locate_template( $find );
59
+ if ( ! $template ) $template = $projects->plugin_path() . '/templates/' . $file;
60
+ }
61
+
62
+ return $template;
63
+ } // End template_loader()
64
+ } // End Class
classes/class-projects.php ADDED
@@ -0,0 +1,378 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
3
+
4
+ /**
5
+ * WooThemes Projects Class
6
+ *
7
+ * All functionality pertaining to the projects.
8
+ *
9
+ * @package WordPress
10
+ * @subpackage Projects
11
+ * @category Plugin
12
+ * @author Matty
13
+ * @since 1.0.0
14
+ */
15
+ class Projects {
16
+ private $dir;
17
+ private $assets_dir;
18
+ private $assets_url;
19
+ private $token;
20
+ private $post_type;
21
+ private $file;
22
+ public $taxonomy_category;
23
+
24
+ public $template_url;
25
+
26
+ public $admin;
27
+ public $frontend;
28
+
29
+ /**
30
+ * @var string
31
+ */
32
+ public $version = '1.0.0';
33
+
34
+ /**
35
+ * Constructor function.
36
+ *
37
+ * @access public
38
+ * @since 1.0.0
39
+ * @return void
40
+ */
41
+ public function __construct( $file ) {
42
+ $this->dir = dirname( $file );
43
+ $this->file = $file;
44
+ $this->assets_dir = trailingslashit( $this->dir ) . 'assets';
45
+ $this->assets_url = esc_url( str_replace( WP_PLUGIN_DIR, WP_PLUGIN_URL, $this->assets_dir ) );
46
+ $this->token = 'projects';
47
+ $this->post_type = 'project';
48
+
49
+ // Variables
50
+ $this->template_url = apply_filters( 'projects_template_url', 'projects/' );
51
+
52
+ $this->load_plugin_textdomain();
53
+ add_action( 'init', array( $this, 'load_localisation' ), 0 );
54
+
55
+ // Define constants
56
+ $this->define_constants();
57
+
58
+ // Run this on activation.
59
+ register_activation_hook( $this->file, array( $this, 'activation' ) );
60
+
61
+ // Run this on deactivation.
62
+ register_deactivation_hook( $this->file, array( $this, 'deactivation' ) );
63
+
64
+ add_action( 'init', array( $this, 'register_rewrite_tags' ) );
65
+ add_action( 'init', array( $this, 'register_post_type' ) );
66
+ add_action( 'init', array( $this, 'register_taxonomy' ) );
67
+
68
+ add_action( 'after_setup_theme', array( $this, 'ensure_post_thumbnails_support' ) );
69
+ add_action( 'after_setup_theme', array( $this, 'register_image_sizes' ) );
70
+
71
+ if ( is_admin() ) {
72
+ require_once( 'class-projects-admin.php' );
73
+ $this->admin = new Projects_Admin( $file );
74
+ } else {
75
+ require_once( 'class-projects-frontend.php' );
76
+ $this->frontend = new Projects_Frontend( $file );
77
+ }
78
+ } // End __construct()
79
+
80
+ /**
81
+ * Register custom rewrite tags.
82
+ * @access public
83
+ * @since 1.0.0
84
+ * @return void
85
+ */
86
+ public function register_rewrite_tags () {
87
+ add_rewrite_tag( '%project_category%','([^&]+)' );
88
+ } // End register_rewrite_tags()
89
+
90
+ /**
91
+ * Define Projects Constants
92
+ */
93
+ private function define_constants() {
94
+ define( 'PROJECTS_PLUGIN_FILE', __FILE__ );
95
+ define( 'PROJECTS_VERSION', $this->version );
96
+ }
97
+
98
+ /**
99
+ * Register the post type.
100
+ *
101
+ * @access public
102
+ * @return void
103
+ */
104
+ public function register_post_type () {
105
+ $labels = array(
106
+ 'name' => _x( 'Projects', 'post type general name', 'projects' ),
107
+ 'singular_name' => _x( 'Project', 'post type singular name', 'projects' ),
108
+ 'add_new' => _x( 'Add New', $this->post_type, 'projects' ),
109
+ 'add_new_item' => sprintf( __( 'Add New %s', 'projects' ), __( 'Project', 'projects' ) ),
110
+ 'edit_item' => sprintf( __( 'Edit %s', 'projects' ), __( 'Project', 'projects' ) ),
111
+ 'new_item' => sprintf( __( 'New %s', 'projects' ), __( 'Project', 'projects' ) ),
112
+ 'all_items' => sprintf( _x( 'All %s', $this->post_type, 'projects' ), __( 'Projects', 'projects' ) ),
113
+ 'view_item' => sprintf( __( 'View %s', 'projects' ), __( 'Project', 'projects' ) ),
114
+ 'search_items' => sprintf( __( 'Search %a', 'projects' ), __( 'Projects', 'projects' ) ),
115
+ 'not_found' => sprintf( __( 'No %s Found', 'projects' ), __( 'Projects', 'projects' ) ),
116
+ 'not_found_in_trash' => sprintf( __( 'No %s Found In Trash', 'projects' ), __( 'Projects', 'projects' ) ),
117
+ 'parent_item_colon' => '',
118
+ 'menu_name' => __( 'Projects', 'projects' )
119
+
120
+ );
121
+ $args = array(
122
+ 'labels' => $labels,
123
+ 'public' => true,
124
+ 'publicly_queryable' => true,
125
+ 'show_ui' => true,
126
+ 'show_in_menu' => true,
127
+ 'query_var' => true,
128
+ 'rewrite' => array(
129
+ 'slug' => 'projects/%project_category%',
130
+ 'with_front' => false
131
+ ),
132
+ 'capability_type' => 'post',
133
+ 'has_archive' => 'projects',
134
+ 'hierarchical' => false,
135
+ 'supports' => array(
136
+ 'title',
137
+ 'editor',
138
+ 'thumbnail',
139
+ 'excerpt'
140
+ ),
141
+ 'menu_position' => 5,
142
+ 'menu_icon' => ''
143
+ );
144
+ register_post_type( $this->post_type, $args );
145
+ } // End register_post_type()
146
+
147
+ /**
148
+ * Register the "project-category" taxonomy.
149
+ * @access public
150
+ * @since 1.3.0
151
+ * @return void
152
+ */
153
+ public function register_taxonomy () {
154
+ $this->taxonomy_category = new Projects_Taxonomy(); // Leave arguments empty, to use the default arguments.
155
+ $this->taxonomy_category->register();
156
+ } // End register_taxonomy()
157
+
158
+ /**
159
+ * Register image sizes.
160
+ * @since 1.0.0
161
+ * @return void
162
+ */
163
+ public function register_image_sizes () {
164
+ if ( function_exists( 'add_image_size' ) ) {
165
+
166
+ $options = get_option( 'projects' );
167
+
168
+ $defaults = apply_filters( 'projects_default_image_size', array(
169
+ 'project-archive' => array(
170
+ 'width' => 300,
171
+ 'height' => 300
172
+ ),
173
+ 'project-single' => array(
174
+ 'width' => 1024,
175
+ 'height' => 1024
176
+ ),
177
+ 'project-thumbnail' => array(
178
+ 'width' => 100,
179
+ 'height' => 100
180
+ )
181
+ ) );
182
+
183
+ // Parse incomming $options into an array and merge it with $defaults
184
+ $options = wp_parse_args( $options, $defaults );
185
+
186
+ // Register each image size
187
+ foreach ( $options as $image_size => $size ) {
188
+ add_image_size( $image_size, $size['width'], $size['height'] );
189
+ }
190
+
191
+ }
192
+ } // End register_image_sizes()
193
+
194
+ /**
195
+ * Get projects.
196
+ * @param string/array $args Arguments to be passed to the query.
197
+ * @since 1.0.0
198
+ * @return array/boolean Array if true, boolean if false.
199
+ */
200
+ public function get_projects ( $args = '' ) {
201
+ $defaults = array(
202
+ 'limit' => 5,
203
+ 'orderby' => 'menu_order',
204
+ 'order' => 'DESC',
205
+ 'id' => 0
206
+ );
207
+
208
+ $args = wp_parse_args( $args, $defaults );
209
+
210
+ // Allow child themes/plugins to filter here.
211
+ $args = apply_filters( 'projects_get_projects_args', $args );
212
+
213
+ // The Query Arguments.
214
+ $query_args = array();
215
+ $query_args['post_type'] = 'project';
216
+ $query_args['numberposts'] = $args['limit'];
217
+ $query_args['orderby'] = $args['orderby'];
218
+ $query_args['order'] = $args['order'];
219
+
220
+ if ( is_numeric( $args['id'] ) && ( intval( $args['id'] ) > 0 ) ) {
221
+ $query_args['p'] = intval( $args['id'] );
222
+ }
223
+
224
+ // Whitelist checks.
225
+ if ( ! in_array( $query_args['orderby'], array( 'none', 'ID', 'author', 'title', 'date', 'modified', 'parent', 'rand', 'comment_count', 'menu_order', 'meta_value', 'meta_value_num' ) ) ) {
226
+ $query_args['orderby'] = 'date';
227
+ }
228
+
229
+ if ( ! in_array( $query_args['order'], array( 'ASC', 'DESC' ) ) ) {
230
+ $query_args['order'] = 'DESC';
231
+ }
232
+
233
+ if ( ! in_array( $query_args['post_type'], get_post_types() ) ) {
234
+ $query_args['post_type'] = 'project';
235
+ }
236
+
237
+ // The Query.
238
+ $query = get_posts( $query_args );
239
+
240
+ // The Display.
241
+ if ( ! is_wp_error( $query ) && is_array( $query ) && count( $query ) > 0 ) {
242
+ foreach ( $query as $k => $v ) {
243
+ $meta = get_post_custom( $v->ID );
244
+
245
+ // Get the image.
246
+ $query[$k]->image = projects_get_image( $v->ID, $args['size'] );
247
+
248
+ // Get the URL.
249
+ if ( isset( $meta['_url'][0] ) && '' != $meta['_url'][0] ) {
250
+ $query[$k]->url = esc_url( $meta['_url'][0] );
251
+ } else {
252
+ $query[$k]->url = get_permalink( $v->ID );
253
+ }
254
+ }
255
+ } else {
256
+ $query = false;
257
+ }
258
+
259
+ return $query;
260
+ } // End get_projects()
261
+
262
+ /**
263
+ * Load the plugin's localisation file.
264
+ * @access public
265
+ * @since 1.0.0
266
+ * @return void
267
+ */
268
+ public function load_localisation () {
269
+ load_plugin_textdomain( 'projects', false, dirname( plugin_basename( $this->file ) ) . '/lang/' );
270
+ } // End load_localisation()
271
+
272
+ /**
273
+ * Load the plugin textdomain from the main WordPress "languages" folder.
274
+ * @since 1.0.0
275
+ * @return void
276
+ */
277
+ public function load_plugin_textdomain () {
278
+ $domain = 'projects';
279
+ // The "plugin_locale" filter is also used in load_plugin_textdomain()
280
+ $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
281
+
282
+ load_textdomain( $domain, WP_LANG_DIR . '/' . $domain . '/' . $domain . '-' . $locale . '.mo' );
283
+ load_plugin_textdomain( $domain, FALSE, dirname( plugin_basename( $this->file ) ) . '/lang/' );
284
+ } // End load_plugin_textdomain()
285
+
286
+ /**
287
+ * Run on activation.
288
+ * @access public
289
+ * @since 1.0.0
290
+ * @return void
291
+ */
292
+ public function activation () {
293
+ $this->register_plugin_version();
294
+
295
+ // Flush rewrite rules
296
+ flush_rewrite_rules();
297
+ } // End activation()
298
+
299
+ /**
300
+ * Run on deactivation.
301
+ * @access public
302
+ * @since 1.0.0
303
+ * @return void
304
+ */
305
+ public function deactivation () {
306
+ // Flush rewrite rules
307
+ flush_rewrite_rules();
308
+ } // End deactivation()
309
+
310
+ /**
311
+ * Register the plugin's version.
312
+ * @access public
313
+ * @since 1.0.0
314
+ * @return void
315
+ */
316
+ private function register_plugin_version () {
317
+ if ( $this->version != '' ) {
318
+ update_option( 'projects' . '-version', $this->version );
319
+ }
320
+ } // End register_plugin_version()
321
+
322
+ /**
323
+ * Ensure that "post-thumbnails" support is available for those themes that don't register it.
324
+ * @since 1.0.0
325
+ * @return void
326
+ */
327
+ public function ensure_post_thumbnails_support () {
328
+ if ( ! current_theme_supports( 'post-thumbnails' ) ) { add_theme_support( 'post-thumbnails' ); }
329
+ } // End ensure_post_thumbnails_support()
330
+
331
+ /**
332
+ * Get the plugin url.
333
+ * @access public
334
+ * @since 1.0.0
335
+ * @return string
336
+ */
337
+ public function plugin_url () {
338
+ return untrailingslashit( plugins_url( '/', $this->file ) );
339
+ } // End plugin_url()
340
+
341
+
342
+ /**
343
+ * Get the plugin path.
344
+ * @access public
345
+ * @since 1.0.0
346
+ * @return string
347
+ */
348
+ public function plugin_path () {
349
+ return untrailingslashit( plugin_dir_path( $this->file ) );
350
+ } // End plugin_path()
351
+
352
+
353
+ /**
354
+ * Get an image size.
355
+ *
356
+ * Variable is filtered by projects_get_image_size_{image_size}
357
+ *
358
+ * @access public
359
+ * @since 1.0.0
360
+ * @param mixed $image_size
361
+ * @return string
362
+ */
363
+ public function get_image_size ( $image_size ) {
364
+ // Only return sizes we define in settings
365
+ if ( ! in_array( $image_size, array( 'project-thumbnail', 'project-archive', 'project-single' ) ) )
366
+ return apply_filters( 'projects_get_image_size_' . $image_size, '' );
367
+
368
+ // Get image size from options
369
+ $options = get_option( 'projects', array() );
370
+ $size = $options[ $image_size ];
371
+
372
+ $size['width'] = isset( $size['width'] ) ? $size['width'] : '300';
373
+ $size['height'] = isset( $size['height'] ) ? $size['height'] : '300';
374
+ $size['crop'] = isset( $size['crop'] ) ? $size['crop'] : 1;
375
+
376
+ return apply_filters( 'projects_get_image_size_' . $image_size, $size );
377
+ } // End get_image_size()
378
+ } // End Class
classes/class-widget-project-categories.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
3
+
4
+ /**
5
+ * WooThemes Project Categories Widget
6
+ *
7
+ * A WooThemes standardized project categories widget.
8
+ *
9
+ * @package WordPress
10
+ * @subpackage Projects
11
+ * @category Widgets
12
+ * @author WooThemes
13
+ * @since 1.0.0
14
+ *
15
+ * TABLE OF CONTENTS
16
+ *
17
+ * protected $projects_widget_cssclass
18
+ * protected $projects_widget_description
19
+ * protected $projects_widget_idbase
20
+ * protected $projects_widget_title
21
+ *
22
+ * - __construct()
23
+ * - widget()
24
+ * - update()
25
+ * - form()
26
+ * - get_orderby_options()
27
+ */
28
+ class Woothemes_Widget_Project_Categories extends WP_Widget {
29
+ protected $projects_widget_cssclass;
30
+ protected $projects_widget_description;
31
+ protected $projects_widget_idbase;
32
+ protected $projects_widget_title;
33
+
34
+ /**
35
+ * Constructor function.
36
+ * @since 1.0.0
37
+ * @return void
38
+ */
39
+ public function __construct() {
40
+ /* Widget variable settings. */
41
+ $this->projects_widget_cssclass = 'widget_projects_categories';
42
+ $this->projects_widget_description = __( 'Project Categories', 'projects' );
43
+ $this->projects_widget_idbase = 'woothemes-project-categories';
44
+ $this->projects_widget_title = __( 'Project Categories', 'projects' );
45
+
46
+ /* Widget settings. */
47
+ $widget_ops = array(
48
+ 'classname' => $this->projects_widget_cssclass,
49
+ 'description' => $this->projects_widget_description
50
+ );
51
+
52
+ /* Widget control settings. */
53
+ $control_ops = array(
54
+ 'id_base' => $this->projects_widget_idbase
55
+ );
56
+
57
+ /* Create the widget. */
58
+ $this->WP_Widget( $this->projects_widget_idbase, $this->projects_widget_title, $widget_ops, $control_ops );
59
+ } // End __construct()
60
+
61
+ /**
62
+ * Display the widget on the frontend.
63
+ * @since 1.0.0
64
+ * @param array $args Widget arguments.
65
+ * @param array $instance Widget settings for this instance.
66
+ * @return void
67
+ */
68
+ public function widget( $args, $instance ) {
69
+ extract( $args, EXTR_SKIP );
70
+
71
+ /* Our variables from the widget settings. */
72
+ $title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
73
+
74
+ $args = array();
75
+
76
+ /* Display the widget title if one was input (before and after defined by themes). */
77
+ if ( $title ) { $args['title'] = $title; }
78
+
79
+ /* Widget content. */
80
+ // Add actions for plugins/themes to hook onto.
81
+ do_action( $this->projects_widget_cssclass . '_top' );
82
+
83
+ // Checkbox values.
84
+ if ( isset( $instance['count'] ) ) { $args['count'] = $instance['count']; }
85
+ if ( isset( $instance['hierarchical'] ) ) { $args['hierarchical'] = $instance['hierarchical']; }
86
+
87
+ echo $before_widget;
88
+
89
+ if ( $title ) {
90
+ echo $before_title . $title . $after_title;
91
+ }
92
+
93
+ // Display the project categories
94
+ $project_taxonomies = get_object_taxonomies( 'project' );
95
+
96
+ if ( count( $project_taxonomies ) > 0) {
97
+ foreach ( $project_taxonomies as $project_tax ) {
98
+ $args = array(
99
+ 'orderby' => 'name',
100
+ 'show_count' => $instance['count'],
101
+ 'pad_counts' => 0,
102
+ 'hierarchical' => $instance['hierarchical'],
103
+ 'taxonomy' => $project_tax,
104
+ 'title_li' => ''
105
+ );
106
+
107
+ wp_list_categories( $args );
108
+ }
109
+ }
110
+
111
+ echo $after_widget;
112
+
113
+ // Add actions for plugins/themes to hook onto.
114
+ do_action( $this->projects_widget_cssclass . '_bottom' );
115
+
116
+ } // End widget()
117
+
118
+ /**
119
+ * Method to update the settings from the form() method.
120
+ * @since 1.0.0
121
+ * @param array $new_instance New settings.
122
+ * @param array $old_instance Previous settings.
123
+ * @return array Updated settings.
124
+ */
125
+ public function update ( $new_instance, $old_instance ) {
126
+ $instance = $old_instance;
127
+
128
+ /* Strip tags for title and name to remove HTML (important for text inputs). */
129
+ $instance['title'] = strip_tags( $new_instance['title'] );
130
+
131
+ /* Escape checkbox values */
132
+ $instance['count'] = esc_attr( $new_instance['count'] );
133
+ $instance['hierarchical'] = esc_attr( $new_instance['hierarchical'] );
134
+
135
+ return $instance;
136
+ } // End update()
137
+
138
+ /**
139
+ * The form on the widget control in the widget administration area.
140
+ * Make use of the get_field_id() and get_field_name() function when creating your form elements. This handles the confusing stuff.
141
+ * @since 1.0.0
142
+ * @param array $instance The settings for this instance.
143
+ * @return void
144
+ */
145
+ public function form( $instance ) {
146
+
147
+ /* Set up some default widget settings. */
148
+ /* Make sure all keys are added here, even with empty string values. */
149
+ $defaults = array(
150
+ 'title' => __( 'Project Categories', 'projects' ),
151
+ 'count' => 1,
152
+ 'hierarchical' => 1,
153
+ );
154
+
155
+ $instance = wp_parse_args( (array) $instance, $defaults );
156
+ ?>
157
+ <!-- Widget Title: Text Input -->
158
+ <p>
159
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title (optional):', 'projects' ); ?></label>
160
+ <input type="text" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" />
161
+ </p>
162
+
163
+ <!-- Widget Show Count: Checkbox Input -->
164
+ <p>
165
+ <input id="<?php echo $this->get_field_id( 'count' ); ?>" name="<?php echo $this->get_field_name( 'count' ); ?>" type="checkbox" value="1" <?php checked( '1', $instance['count'] ); ?> />
166
+ <label for="<?php echo $this->get_field_id( 'count' ); ?>"><?php _e( 'Show Count:', 'projects' ); ?></label>
167
+ </p>
168
+
169
+ <!-- Widget Hierarchical: Checkbox Input -->
170
+ <p>
171
+ <input id="<?php echo $this->get_field_id( 'hierarchical' ); ?>" name="<?php echo $this->get_field_name( 'hierarchical' ); ?>" type="checkbox" value="1" <?php checked( '1', $instance['hierarchical'] ); ?> />
172
+ <label for="<?php echo $this->get_field_id( 'hierarchical' ); ?>"><?php _e( 'Show Hierarchy:', 'projects' ); ?></label>
173
+ </p>
174
+ <?php
175
+ } // End form()
176
+
177
+ } // End Class
178
+
179
+ /* Register the widget. */
180
+ add_action( 'widgets_init', create_function( '', 'return register_widget( "Woothemes_Widget_Project_Categories" );' ), 1 );
classes/class-widget-projects.php ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
3
+
4
+ /**
5
+ * WooThemes Projects Widget
6
+ *
7
+ * A WooThemes standardized projects widget.
8
+ *
9
+ * @package WordPress
10
+ * @subpackage Projects
11
+ * @category Widgets
12
+ * @author WooThemes
13
+ * @since 1.0.0
14
+ *
15
+ * TABLE OF CONTENTS
16
+ *
17
+ * protected $projects_widget_cssclass
18
+ * protected $projects_widget_description
19
+ * protected $projects_widget_idbase
20
+ * protected $projects_widget_title
21
+ *
22
+ * - __construct()
23
+ * - widget()
24
+ * - update()
25
+ * - form()
26
+ */
27
+ class Woothemes_Widget_Projects extends WP_Widget {
28
+ protected $projects_widget_cssclass;
29
+ protected $projects_widget_description;
30
+ protected $projects_widget_idbase;
31
+ protected $projects_widget_title;
32
+
33
+ /**
34
+ * Constructor function.
35
+ * @since 1.0.0
36
+ * @return void
37
+ */
38
+ public function __construct() {
39
+ /* Widget variable settings. */
40
+ $this->projects_widget_cssclass = 'widget_projects_items';
41
+ $this->projects_widget_description = __( 'Recent projects listed on your site.', 'projects' );
42
+ $this->projects_widget_idbase = 'projects';
43
+ $this->projects_widget_title = __( 'Recent Projects', 'projects' );
44
+
45
+ // Cache
46
+ add_action( 'save_post', array($this, 'flush_widget_cache') );
47
+ add_action( 'deleted_post', array($this, 'flush_widget_cache') );
48
+ add_action( 'switch_theme', array($this, 'flush_widget_cache') );
49
+
50
+ /* Widget settings. */
51
+ $widget_ops = array(
52
+ 'classname' => $this->projects_widget_cssclass,
53
+ 'description' => $this->projects_widget_description
54
+ );
55
+
56
+ /* Widget control settings. */
57
+ $control_ops = array(
58
+ 'id_base' => $this->projects_widget_idbase
59
+ );
60
+
61
+ /* Create the widget. */
62
+ $this->WP_Widget( $this->projects_widget_idbase, $this->projects_widget_title, $widget_ops, $control_ops );
63
+ } // End __construct()
64
+
65
+ /**
66
+ * Display the widget on the frontend.
67
+ * @since 1.0.0
68
+ * @param array $args Widget arguments.
69
+ * @param array $instance Widget settings for this instance.
70
+ * @return void
71
+ */
72
+ public function widget( $args, $instance ) {
73
+
74
+ $cache = wp_cache_get('widget_projects_items', 'widget');
75
+
76
+ if ( !is_array($cache) )
77
+ $cache = array();
78
+
79
+ if ( ! isset( $args['widget_id'] ) )
80
+ $args['widget_id'] = $this->id;
81
+
82
+ if ( isset( $cache[ $args['widget_id'] ] ) ) {
83
+ echo $cache[ $args['widget_id'] ];
84
+ return;
85
+ }
86
+
87
+ ob_start();
88
+
89
+ extract( $args, EXTR_SKIP );
90
+
91
+ /* Our variables from the widget settings. */
92
+ $title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
93
+
94
+ $args = array();
95
+
96
+ /* Display the widget title if one was input (before and after defined by themes). */
97
+ if ( $title ) { $args['title'] = $title; }
98
+
99
+ /* Widget content. */
100
+ // Add actions for plugins/themes to hook onto.
101
+ do_action( $this->projects_widget_cssclass . '_top' );
102
+
103
+ // Integer values.
104
+ if ( isset( $instance['limit'] ) && ( 0 < count( $instance['limit'] ) ) ) { $args['limit'] = intval( $instance['limit'] ); }
105
+
106
+ // Display the projects.
107
+
108
+ $args = array(
109
+ 'post_type' => 'project',
110
+ 'post_status' => 'publish',
111
+ 'ignore_sticky_posts' => 1,
112
+ 'posts_per_page' => $args['limit'],
113
+ 'orderby' => 'date',
114
+ 'order' => 'DESC'
115
+ );
116
+
117
+ $r = new WP_Query( $args );
118
+
119
+ if ( $r->have_posts() ) {
120
+
121
+ echo $before_widget;
122
+
123
+ if ( $title )
124
+ echo $before_title . $title . $after_title;
125
+
126
+ echo '<ul class="projects_list_widget">';
127
+
128
+ while ( $r->have_posts()) {
129
+ $r->the_post();
130
+ projects_get_template_part( 'content', 'project-widget' );
131
+ }
132
+
133
+ echo '</ul>';
134
+
135
+ echo $after_widget;
136
+ }
137
+
138
+ // Add actions for plugins/themes to hook onto.
139
+ do_action( $this->projects_widget_cssclass . '_bottom' );
140
+
141
+ $cache[ $widget_id ] = ob_get_flush();
142
+
143
+ wp_cache_set('widget_projects_items', $cache, 'widget');
144
+
145
+ } // End widget()
146
+
147
+ /**
148
+ * Method to update the settings from the form() method.
149
+ * @since 1.0.0
150
+ * @param array $new_instance New settings.
151
+ * @param array $old_instance Previous settings.
152
+ * @return array Updated settings.
153
+ */
154
+ public function update ( $new_instance, $old_instance ) {
155
+ $instance = $old_instance;
156
+
157
+ /* Strip tags for title and name to remove HTML (important for text inputs). */
158
+ $instance['title'] = strip_tags( $new_instance['title'] );
159
+
160
+ /* Make sure the integer values are definitely integers. */
161
+ $instance['limit'] = intval( $new_instance['limit'] );
162
+
163
+ /* Flush cache. */
164
+ $this->flush_widget_cache();
165
+ $alloptions = wp_cache_get( 'alloptions', 'options' );
166
+ if ( isset($alloptions['widget_projects_items']) )
167
+ delete_option('widget_projects_items');
168
+
169
+ return $instance;
170
+ } // End update()
171
+
172
+ /**
173
+ * The form on the widget control in the widget administration area.
174
+ * Make use of the get_field_id() and get_field_name() function when creating your form elements. This handles the confusing stuff.
175
+ * @since 1.0.0
176
+ * @param array $instance The settings for this instance.
177
+ * @return void
178
+ */
179
+ public function form( $instance ) {
180
+
181
+ /* Set up some default widget settings. */
182
+ /* Make sure all keys are added here, even with empty string values. */
183
+ $defaults = array(
184
+ 'title' => __( 'Recent Projects', 'projects' ),
185
+ 'limit' => 5,
186
+ );
187
+
188
+ $instance = wp_parse_args( (array) $instance, $defaults );
189
+ ?>
190
+ <!-- Widget Title: Text Input -->
191
+ <p>
192
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title (optional):', 'projects' ); ?></label>
193
+ <input type="text" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" />
194
+ </p>
195
+ <!-- Widget Limit: Text Input -->
196
+ <p>
197
+ <label for="<?php echo $this->get_field_id( 'limit' ); ?>"><?php _e( 'Limit:', 'projects' ); ?></label>
198
+ <input type="text" name="<?php echo $this->get_field_name( 'limit' ); ?>" value="<?php echo $instance['limit']; ?>" class="widefat" id="<?php echo $this->get_field_id( 'limit' ); ?>" />
199
+ </p>
200
+ <?php
201
+ } // End form()
202
+
203
+ /**
204
+ * Flush widget cache
205
+ * @since 1.0.0
206
+ * @return void
207
+ */
208
+ public function flush_widget_cache() {
209
+ wp_cache_delete('widget_projects_items', 'widget');
210
+ }
211
+
212
+ } // End Class
213
+
214
+ /* Register the widget. */
215
+ add_action( 'widgets_init', create_function( '', 'return register_widget( "Woothemes_Widget_Projects" );' ), 1 );
lang/woothemes-features-en_GB.po ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Features v1.1.0\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: \n"
6
+ "PO-Revision-Date: 2012-11-08 08:28:45+0000\n"
7
+ "Last-Translator: Matt <matt@woothemes.com>\n"
8
+ "Language-Team: \n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
13
+ "X-Poedit-Language: English\n"
14
+ "X-Poedit-Country: UNITED KINGDOM\n"
15
+ "X-Poedit-SourceCharset: utf-8\n"
16
+ "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
17
+ "X-Poedit-Basepath: ../\n"
18
+ "X-Poedit-Bookmarks: \n"
19
+ "X-Poedit-SearchPath-0: .\n"
20
+ "X-Textdomain-Support: yes"
21
+
22
+ #: classes/class-woothemes-features.php:76
23
+ #@ woothemes-features
24
+ msgctxt "post type general name"
25
+ msgid "Features"
26
+ msgstr ""
27
+
28
+ #: classes/class-woothemes-features.php:77
29
+ #@ woothemes-features
30
+ msgctxt "post type singular name"
31
+ msgid "Feature"
32
+ msgstr ""
33
+
34
+ #: classes/class-woothemes-features.php:78
35
+ #@ woothemes-features
36
+ msgctxt "feature"
37
+ msgid "Add New"
38
+ msgstr ""
39
+
40
+ #: classes/class-woothemes-features.php:79
41
+ #, php-format
42
+ #@ woothemes-features
43
+ msgid "Add New %s"
44
+ msgstr ""
45
+
46
+ #: classes/class-woothemes-features.php:79
47
+ #: classes/class-woothemes-features.php:80
48
+ #: classes/class-woothemes-features.php:81
49
+ #@ woothemes-features
50
+ msgid "Feature"
51
+ msgstr ""
52
+
53
+ #: classes/class-woothemes-features.php:80
54
+ #, php-format
55
+ #@ woothemes-features
56
+ msgid "Edit %s"
57
+ msgstr ""
58
+
59
+ #: classes/class-woothemes-features.php:81
60
+ #, php-format
61
+ #@ woothemes-features
62
+ msgid "New %s"
63
+ msgstr ""
64
+
65
+ #: classes/class-woothemes-features.php:82
66
+ #, php-format
67
+ #@ woothemes-features
68
+ msgid "All %s"
69
+ msgstr ""
70
+
71
+ #: classes/class-woothemes-features.php:82
72
+ #: classes/class-woothemes-features.php:84
73
+ #: classes/class-woothemes-features.php:85
74
+ #: classes/class-woothemes-features.php:86
75
+ #: classes/class-woothemes-features.php:88
76
+ #: classes/class-woothemes-widget-features.php:44
77
+ #@ woothemes-features
78
+ msgid "Features"
79
+ msgstr ""
80
+
81
+ #: classes/class-woothemes-features.php:83
82
+ #, php-format
83
+ #@ woothemes-features
84
+ msgid "View %s"
85
+ msgstr ""
86
+
87
+ #: classes/class-woothemes-features.php:83
88
+ #@ woothemes-features
89
+ msgid "Testimonial"
90
+ msgstr ""
91
+
92
+ #: classes/class-woothemes-features.php:84
93
+ #, php-format
94
+ #@ woothemes-features
95
+ msgid "Search %a"
96
+ msgstr ""
97
+
98
+ #: classes/class-woothemes-features.php:85
99
+ #, php-format
100
+ #@ woothemes-features
101
+ msgid "No %s Found"
102
+ msgstr ""
103
+
104
+ #: classes/class-woothemes-features.php:86
105
+ #, php-format
106
+ #@ woothemes-features
107
+ msgid "No %s Found In Trash"
108
+ msgstr ""
109
+
110
+ #: classes/class-woothemes-features.php:148
111
+ #@ woothemes-features
112
+ msgid "Image"
113
+ msgstr ""
114
+
115
+ #: classes/class-woothemes-features.php:182
116
+ #, php-format
117
+ #@ woothemes-features
118
+ msgid "Feature updated. %sView feature%s"
119
+ msgstr ""
120
+
121
+ #: classes/class-woothemes-features.php:183
122
+ #@ woothemes-features
123
+ msgid "Custom field updated."
124
+ msgstr ""
125
+
126
+ #: classes/class-woothemes-features.php:184
127
+ #@ woothemes-features
128
+ msgid "Custom field deleted."
129
+ msgstr ""
130
+
131
+ #: classes/class-woothemes-features.php:185
132
+ #@ woothemes-features
133
+ msgid "Feature updated."
134
+ msgstr ""
135
+
136
+ #. translators: %s: date and time of the revision
137
+ #: classes/class-woothemes-features.php:187
138
+ #, php-format
139
+ #@ woothemes-features
140
+ msgid "Feature restored to revision from %s"
141
+ msgstr ""
142
+
143
+ #: classes/class-woothemes-features.php:188
144
+ #, php-format
145
+ #@ woothemes-features
146
+ msgid "Feature published. %sView feature%s"
147
+ msgstr ""
148
+
149
+ #: classes/class-woothemes-features.php:189
150
+ #@ default
151
+ msgid "Feature saved."
152
+ msgstr ""
153
+
154
+ #: classes/class-woothemes-features.php:190
155
+ #, php-format
156
+ #@ woothemes-features
157
+ msgid "Feature submitted. %sPreview feature%s"
158
+ msgstr ""
159
+
160
+ #: classes/class-woothemes-features.php:191
161
+ #, php-format
162
+ #@ woothemes-features
163
+ msgid "Feature scheduled for: %1$s. %2$sPreview feature%3$s"
164
+ msgstr ""
165
+
166
+ #: classes/class-woothemes-features.php:193
167
+ #@ default
168
+ msgid "M j, Y @ G:i"
169
+ msgstr ""
170
+
171
+ #: classes/class-woothemes-features.php:194
172
+ #, php-format
173
+ #@ woothemes-features
174
+ msgid "Feature draft updated. %sPreview feature%s"
175
+ msgstr ""
176
+
177
+ #: classes/class-woothemes-features.php:307
178
+ #@ woothemes-features
179
+ msgid "Enter the feature title here"
180
+ msgstr ""
181
+
182
+ #: classes/class-woothemes-widget-features.php:42
183
+ #@ woothemes-features
184
+ msgid "Recent features listed on your site."
185
+ msgstr ""
186
+
187
+ #: classes/class-woothemes-widget-features.php:152
188
+ #@ woothemes-features
189
+ msgid "Title (optional):"
190
+ msgstr ""
191
+
192
+ #: classes/class-woothemes-widget-features.php:157
193
+ #@ woothemes-features
194
+ msgid "Limit:"
195
+ msgstr ""
196
+
197
+ #: classes/class-woothemes-widget-features.php:162
198
+ #@ woothemes-features
199
+ msgid "Image Size (in pixels):"
200
+ msgstr ""
201
+
202
+ #: classes/class-woothemes-widget-features.php:172
203
+ #@ woothemes-features
204
+ msgid "Order By:"
205
+ msgstr ""
206
+
207
+ #: classes/class-woothemes-widget-features.php:181
208
+ #@ woothemes-features
209
+ msgid "Order Direction:"
210
+ msgstr ""
211
+
212
+ #: classes/class-woothemes-widget-features.php:190
213
+ #@ woothemes-features
214
+ msgid "Specific ID (optional):"
215
+ msgstr ""
216
+
217
+ #: classes/class-woothemes-widget-features.php:193
218
+ #@ woothemes-features
219
+ msgid "Display a specific testimonial, rather than a list."
220
+ msgstr ""
221
+
222
+ #: classes/class-woothemes-widget-features.php:204
223
+ #@ woothemes-features
224
+ msgid "No Order"
225
+ msgstr ""
226
+
227
+ #: classes/class-woothemes-widget-features.php:205
228
+ #@ woothemes-features
229
+ msgid "Entry ID"
230
+ msgstr ""
231
+
232
+ #: classes/class-woothemes-widget-features.php:206
233
+ #@ woothemes-features
234
+ msgid "Title"
235
+ msgstr ""
236
+
237
+ #: classes/class-woothemes-widget-features.php:207
238
+ #@ woothemes-features
239
+ msgid "Date Added"
240
+ msgstr ""
241
+
242
+ #: classes/class-woothemes-widget-features.php:208
243
+ #@ woothemes-features
244
+ msgid "Specified Order Setting"
245
+ msgstr ""
246
+
247
+ #: classes/class-woothemes-widget-features.php:219
248
+ #@ woothemes-features
249
+ msgid "Ascending"
250
+ msgstr ""
251
+
252
+ #: classes/class-woothemes-widget-features.php:220
253
+ #@ woothemes-features
254
+ msgid "Descending"
255
+ msgstr ""
256
+
257
+ #: classes/class-woothemes-features.php:208
258
+ #@ woothemes-features
259
+ msgid "Feature Details"
260
+ msgstr ""
261
+
262
+ #: classes/class-woothemes-features.php:333
263
+ #@ woothemes-features
264
+ msgid "URL"
265
+ msgstr ""
266
+
267
+ #: classes/class-woothemes-features.php:334
268
+ #@ woothemes-features
269
+ msgid "Enter a URL that applies to this feature (for example: http://woothemes.com/)."
270
+ msgstr ""
271
+
272
+ #: classes/class-woothemes-widget-features.php:167
273
+ #@ woothemes-features
274
+ msgid "Items Per Row:"
275
+ msgstr ""
276
+
lang/woothemes-features-xx_XX.pot ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: PlaceHolder\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: \n"
6
+ "PO-Revision-Date: 2012-10-17 12:43:24+0000\n"
7
+ "Last-Translator: none\n"
8
+ "Language-Team: \n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
13
+ "X-Poedit-Language: English\n"
14
+ "X-Poedit-Country: UNITED STATES\n"
15
+ "X-Poedit-SourceCharset: utf-8\n"
16
+ "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
17
+ "X-Poedit-Basepath: ../\n"
18
+ "X-Poedit-Bookmarks: \n"
19
+ "X-Poedit-SearchPath-0: .\n"
20
+ "X-Textdomain-Support: yes"
21
+
projects-core-functions.php ADDED
@@ -0,0 +1,438 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WooThemes Projects Core Functions
4
+ *
5
+ * Functions available on both the front-end and admin.
6
+ *
7
+ * @author WooThemes
8
+ * @category Core
9
+ * @package Projects/Functions
10
+ * @version 1.0.0
11
+ */
12
+
13
+ if ( ! function_exists( 'projects_get_page_id' ) ) {
14
+
15
+ /**
16
+ * WooThemes Projects page IDs
17
+ *
18
+ * retrieve page ids - used for projects
19
+ *
20
+ * returns -1 if no page is found
21
+ *
22
+ * @access public
23
+ * @param string $page
24
+ * @return int
25
+ */
26
+ function projects_get_page_id ( $page ) {
27
+ $options = get_option( 'projects' );
28
+ $page = apply_filters( 'projects_get_' . $page . '_page_id', $options[ $page . '_page_id' ] );
29
+
30
+ return $page ? $page : -1;
31
+ } // End projects_get_page_id()
32
+ }
33
+
34
+ if ( ! function_exists( 'projects_get_image' ) ) {
35
+
36
+ /**
37
+ * Get the image for the given ID.
38
+ * @param int $id Post ID.
39
+ * @param string/array/int $size Image dimension. (default: "projects-thumbnail")
40
+ * @since 1.0.0
41
+ * @return string <img> tag.
42
+ */
43
+ function projects_get_image ( $id, $size = 'projects-thumbnail' ) {
44
+ $response = '';
45
+
46
+ if ( has_post_thumbnail( $id ) ) {
47
+ // If not a string or an array, and not an integer, default to 150x9999.
48
+ if ( is_int( $size ) || ( 0 < intval( $size ) ) ) {
49
+ $size = array( intval( $size ), intval( $size ) );
50
+ } elseif ( ! is_string( $size ) && ! is_array( $size ) ) {
51
+ $size = array( 150, 9999 );
52
+ }
53
+ $response = get_the_post_thumbnail( intval( $id ), $size );
54
+ }
55
+
56
+ return $response;
57
+ } // End projects_get_image()
58
+
59
+ }
60
+
61
+ /**
62
+ * is_projects - Returns true if on a page which uses WooThemes Projects templates
63
+ *
64
+ * @access public
65
+ * @return bool
66
+ */
67
+ function is_projects () {
68
+ return ( is_projects_archive() || is_project_category() || is_project() ) ? true : false;
69
+ } // End is_projects()
70
+
71
+ if ( ! function_exists( 'is_projects_archive' ) ) {
72
+
73
+ /**
74
+ * is_projects_archive - Returns true when viewing the project type archive.
75
+ *
76
+ * @access public
77
+ * @return bool
78
+ */
79
+ function is_projects_archive() {
80
+ return ( is_post_type_archive( 'project' ) || is_project_taxonomy() || is_page( projects_get_page_id( 'projects' ) ) ) ? true : false;
81
+ } // End is_projects_archive()
82
+ }
83
+
84
+ if ( ! function_exists( 'is_project_taxonomy' ) ) {
85
+
86
+ /**
87
+ * is_project_taxonomy - Returns true when viewing a project taxonomy archive.
88
+ *
89
+ * @access public
90
+ * @return bool
91
+ */
92
+ function is_project_taxonomy() {
93
+ return is_tax( get_object_taxonomies( 'project' ) );
94
+ } // End is_project_taxonomy()
95
+ }
96
+
97
+ if ( ! function_exists( 'is_project_category' ) ) {
98
+
99
+ /**
100
+ * is_project_category - Returns true when viewing a project category.
101
+ *
102
+ * @access public
103
+ * @param string $term (default: '') The term slug your checking for. Leave blank to return true on any.
104
+ * @return bool
105
+ */
106
+ function is_project_category( $term = '' ) {
107
+ return is_tax( 'project-category', $term );
108
+ } // End is_project_category()
109
+ }
110
+
111
+ if ( ! function_exists( 'is_project' ) ) {
112
+
113
+ /**
114
+ * is_project - Returns true when viewing a single project.
115
+ *
116
+ * @access public
117
+ * @return bool
118
+ */
119
+ function is_project() {
120
+ return is_singular( array( 'project' ) );
121
+ } // End is_project()
122
+ }
123
+
124
+ if ( ! function_exists( 'is_ajax' ) ) {
125
+
126
+ /**
127
+ * is_ajax - Returns true when the page is loaded via ajax.
128
+ *
129
+ * @access public
130
+ * @return bool
131
+ */
132
+ function is_ajax() {
133
+ if ( defined('DOING_AJAX') )
134
+ return true;
135
+
136
+ return ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest' ) ? true : false;
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Get template part (for templates like the projects-loop).
142
+ *
143
+ * @access public
144
+ * @param mixed $slug
145
+ * @param string $name (default: '')
146
+ * @return void
147
+ */
148
+ function projects_get_template_part( $slug, $name = '' ) {
149
+ global $projects;
150
+ $template = '';
151
+
152
+ // Look in yourtheme/slug-name.php and yourtheme/projects/slug-name.php
153
+ if ( $name )
154
+ $template = locate_template( array ( "{$slug}-{$name}.php", "{$projects->template_url}{$slug}-{$name}.php" ) );
155
+
156
+ // Get default slug-name.php
157
+ if ( !$template && $name && file_exists( $projects->plugin_path() . "/templates/{$slug}-{$name}.php" ) )
158
+ $template = $projects->plugin_path() . "/templates/{$slug}-{$name}.php";
159
+
160
+ // If template file doesn't exist, look in yourtheme/slug.php and yourtheme/projects/slug.php
161
+ if ( !$template )
162
+ $template = locate_template( array ( "{$slug}.php", "{$projects->template_url}{$slug}.php" ) );
163
+
164
+ if ( $template )
165
+ load_template( $template, false );
166
+ } // End projects_get_template_part()
167
+
168
+
169
+ /**
170
+ * Get other templates and including the file.
171
+ *
172
+ * @access public
173
+ * @param mixed $template_name
174
+ * @param array $args (default: array())
175
+ * @param string $template_path (default: '')
176
+ * @param string $default_path (default: '')
177
+ * @return void
178
+ */
179
+ function projects_get_template ( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
180
+ global $projects;
181
+
182
+ if ( $args && is_array($args) )
183
+ extract( $args );
184
+
185
+ $located = projects_locate_template( $template_name, $template_path, $default_path );
186
+
187
+ do_action( 'projects_before_template_part', $template_name, $template_path, $located, $args );
188
+
189
+ include( $located );
190
+
191
+ do_action( 'projects_after_template_part', $template_name, $template_path, $located, $args );
192
+ } // End projects_get_template()
193
+
194
+
195
+ /**
196
+ * Locate a template and return the path for inclusion.
197
+ *
198
+ * This is the load order:
199
+ *
200
+ * yourtheme / $template_path / $template_name
201
+ * yourtheme / $template_name
202
+ * $default_path / $template_name
203
+ *
204
+ * @access public
205
+ * @param mixed $template_name
206
+ * @param string $template_path (default: '')
207
+ * @param string $default_path (default: '')
208
+ * @return string
209
+ */
210
+ function projects_locate_template( $template_name, $template_path = '', $default_path = '' ) {
211
+ global $projects;
212
+
213
+ if ( ! $template_path ) $template_path = $projects->template_url;
214
+ if ( ! $default_path ) $default_path = $projects->plugin_path() . '/templates/';
215
+
216
+ // Look within passed path within the theme - this is priority
217
+ $template = locate_template(
218
+ array(
219
+ trailingslashit( $template_path ) . $template_name,
220
+ $template_name
221
+ )
222
+ );
223
+
224
+ // Get default template
225
+ if ( ! $template )
226
+ $template = $default_path . $template_name;
227
+
228
+ // Return what we found
229
+ return apply_filters( 'projects_locate_template', $template, $template_name, $template_path );
230
+ } // End projects_locate_template()
231
+
232
+ /**
233
+ * Filter to allow project-category in the permalinks for projects.
234
+ *
235
+ * @access public
236
+ * @param string $permalink The existing permalink URL.
237
+ * @param object $post
238
+ * @return string
239
+ */
240
+ function projects_project_post_type_link( $permalink, $post ) {
241
+ // Abort if post is not a project
242
+ if ( $post->post_type !== 'project' )
243
+ return $permalink;
244
+
245
+ // Abort early if the placeholder rewrite tag isn't in the generated URL
246
+ if ( false === strpos( $permalink, '%' ) )
247
+ return $permalink;
248
+
249
+ // Get the custom taxonomy terms in use by this post
250
+ $terms = get_the_terms( $post->ID, 'project-category' );
251
+
252
+ if ( empty( $terms ) ) {
253
+ // If no terms are assigned to this post, use a string instead (can't leave the placeholder there)
254
+ $project_cat = _x( 'uncategorized', 'slug', 'projects' );
255
+ } else {
256
+ // Replace the placeholder rewrite tag with the first term's slug
257
+ $first_term = array_shift( $terms );
258
+ $project_cat = $first_term->slug;
259
+ }
260
+
261
+ $find = array(
262
+ '%year%',
263
+ '%monthnum%',
264
+ '%day%',
265
+ '%hour%',
266
+ '%minute%',
267
+ '%second%',
268
+ '%post_id%',
269
+ '%category%',
270
+ '%project_category%'
271
+ );
272
+
273
+ $replace = array(
274
+ date_i18n( 'Y', strtotime( $post->post_date ) ),
275
+ date_i18n( 'm', strtotime( $post->post_date ) ),
276
+ date_i18n( 'd', strtotime( $post->post_date ) ),
277
+ date_i18n( 'H', strtotime( $post->post_date ) ),
278
+ date_i18n( 'i', strtotime( $post->post_date ) ),
279
+ date_i18n( 's', strtotime( $post->post_date ) ),
280
+ $post->ID,
281
+ $project_cat,
282
+ $project_cat
283
+ );
284
+
285
+ $replace = array_map( 'sanitize_title', $replace );
286
+
287
+ $permalink = str_replace( $find, $replace, $permalink );
288
+
289
+ return $permalink;
290
+ } // End projects_project_post_type_link()
291
+
292
+ add_filter( 'post_type_link', 'projects_project_post_type_link', 10, 2 );
293
+
294
+ /**
295
+ * projects_get_gallery_attachment_ids function.
296
+ *
297
+ * @access public
298
+ * @return array
299
+ */
300
+ function projects_get_gallery_attachment_ids ( $post_id = 0 ) {
301
+ global $post;
302
+ if ( 0 == $post_id ) $post_id = get_the_ID();
303
+ $project_image_gallery = get_post_meta( $post_id, '_project_image_gallery', true );
304
+ if ( '' == $project_image_gallery ) {
305
+ // Backwards compat
306
+ $attachment_ids = get_posts( 'post_parent=' . intval( $post_id ) . '&numberposts=-1&post_type=attachment&orderby=menu_order&order=ASC&post_mime_type=image&fields=ids' );
307
+ $attachment_ids = array_diff( $attachment_ids, array( get_post_thumbnail_id() ) );
308
+ $project_image_gallery = implode( ',', $attachment_ids );
309
+ }
310
+ return array_filter( (array) explode( ',', $project_image_gallery ) );
311
+ } // End projects_get_gallery_attachment_ids()
312
+
313
+
314
+ /**
315
+ * Add body classes for Projects pages
316
+ *
317
+ * @param array $classes
318
+ * @return array
319
+ */
320
+ function woo_projects_body_class( $classes ) {
321
+ $classes = (array) $classes;
322
+
323
+ if ( is_projects() ) {
324
+ $classes[] = 'projects';
325
+ $classes[] = 'projects-page';
326
+ }
327
+
328
+ if ( is_project() ) {
329
+
330
+ $attachments = count( projects_get_gallery_attachment_ids() );
331
+
332
+ if ( $attachments > 0 ) {
333
+ $classes[] = 'has-gallery';
334
+ } else {
335
+ $classes[] = 'no-gallery';
336
+ }
337
+
338
+ if ( !has_post_thumbnail() ) {
339
+ $classes[] = 'no-cover-image';
340
+ }
341
+
342
+ }
343
+
344
+ return array_unique( $classes );
345
+ }
346
+
347
+
348
+ /**
349
+ * Find a category image.
350
+ * @since 1.0.0
351
+ * @return string
352
+ */
353
+ function projects_category_image ( $cat_id = 0 ) {
354
+
355
+ global $post;
356
+
357
+ if ( 0 == $cat_id ) return;
358
+
359
+ $image = '';
360
+
361
+ if ( false === ( $image = get_transient( 'projects_category_image_' . $cat_id ) ) ) {
362
+
363
+ $cat = get_term( $cat_id, 'project-category' );
364
+
365
+ $query_args = array(
366
+ 'post_type' => 'project',
367
+ 'posts_per_page' => -1,
368
+ 'no_found_rows' => 1,
369
+ 'tax_query' => array(
370
+ array(
371
+ 'taxonomy' => 'project-category',
372
+ 'field' => 'id',
373
+ 'terms' => array( $cat->term_id )
374
+ )
375
+ )
376
+ );
377
+
378
+ $query = new WP_Query( $query_args );
379
+
380
+ while ( $query->have_posts() && $image == '' ) : $query->the_post();
381
+
382
+ $image = projects_get_image( get_the_ID() );
383
+
384
+ if ( $image ) {
385
+ $image = '<a href="' . get_term_link( $cat ) . '" title="' . $cat->name . '">' . $image . '</a>';
386
+ set_transient( 'projects_category_image_' . $cat->term_id, $image, 60 * 60 ); // 1 Hour.
387
+ }
388
+
389
+ endwhile;
390
+
391
+ wp_reset_postdata();
392
+
393
+ } // get transient
394
+
395
+ return $image;
396
+
397
+ } // End projects_category_image()
398
+
399
+ /**
400
+ * When a post is saved, flush the transient used to store the category images.
401
+ * @since 1.0.0
402
+ * @return void
403
+ */
404
+ function projects_category_image_flush_transient ( $post_id ) {
405
+ if ( get_post_type( $post_id ) != 'project' ) return; // we only want projects
406
+ $categories = get_the_terms( $post_id, 'project-category' );
407
+ if ( $categories ) {
408
+ foreach ($categories as $category ) {
409
+ delete_transient( 'projects_category_image_' . $category->term_id );
410
+ }
411
+ }
412
+ } // End projects_category_image_flush_transient()
413
+ add_action( 'save_post', 'projects_category_image_flush_transient' );
414
+
415
+ /**
416
+ * Enqueue styles
417
+ */
418
+ function projects_script() {
419
+
420
+ // Register projects CSS
421
+ wp_register_style( 'projects-styles', plugins_url( '/assets/css/woo-projects.css', __FILE__ ), array(), PROJECTS_VERSION );
422
+ wp_register_style( 'projects-handheld', plugins_url( '/assets/css/woo-projects-handheld.css', __FILE__ ), array(), PROJECTS_VERSION );
423
+
424
+ if ( apply_filters( 'projects_enqueue_styles', true ) ) {
425
+
426
+ // Load Main styles
427
+ wp_enqueue_style( 'projects-styles' );
428
+
429
+ // Load styles applied to handheld devices
430
+ wp_enqueue_style( 'projects-handheld' );
431
+
432
+ // Load Dashicons
433
+ if ( is_project() ) {
434
+ wp_enqueue_style( 'dashicons' );
435
+ }
436
+ }
437
+
438
+ }
projects-hooks.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WooThemes Projects Hooks
4
+ *
5
+ * Action/filter hooks used for WooThemes Projects functions/templates
6
+ *
7
+ * @author WooThemes
8
+ * @category Core
9
+ * @package Projects/Templates
10
+ * @version 1.0.0
11
+ */
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
+
15
+ /** Template Hooks ********************************************************/
16
+
17
+ if ( ! is_admin() || defined('DOING_AJAX') ) {
18
+
19
+ add_filter( 'body_class', 'woo_projects_body_class' );
20
+ add_action( 'wp_enqueue_scripts', 'projects_script' );
21
+ add_action( 'template_redirect', 'projects_template_redirect' );
22
+ add_filter( 'wp_nav_menu_objects', 'projects_nav_menu_item_classes', 2, 20 );
23
+
24
+ /**
25
+ * Content Wrappers
26
+ *
27
+ * @see projects_output_content_wrapper()
28
+ * @see projects_output_content_wrapper_end()
29
+ */
30
+ add_action( 'projects_before_main_content', 'projects_output_content_wrapper', 10 );
31
+ add_action( 'projects_after_main_content', 'projects_output_content_wrapper_end', 10 );
32
+
33
+ /**
34
+ * Sidebar
35
+ *
36
+ * @see projects_get_sidebar()
37
+ */
38
+ add_action( 'projects_sidebar', 'projects_get_sidebar', 10 );
39
+
40
+ /**
41
+ * Archive descriptions
42
+ *
43
+ * @see projects_taxonomy_archive_description()
44
+ * @see projects_project_archive_description()
45
+ */
46
+ add_action( 'projects_archive_description', 'projects_taxonomy_archive_description', 10 );
47
+ add_action( 'projects_archive_description', 'projects_project_archive_description', 10 );
48
+
49
+ /**
50
+ * Project Loop Items
51
+ *
52
+ * @see projects_template_loop_project_thumbnail()
53
+ * @see projects_template_short_description()
54
+ */
55
+ add_action( 'projects_loop_item', 'projects_template_loop_project_thumbnail', 10 );
56
+ add_action( 'projects_loop_item', 'projects_template_loop_project_title', 20 );
57
+ add_action( 'projects_after_loop_item', 'projects_template_short_description', 10 );
58
+
59
+ /**
60
+ * Before Single Projects Summary Div
61
+ *
62
+ * @see projects_template_single_title()
63
+ * @see projects_template_single_short_description()
64
+ * @see projects_template_single_feature()
65
+ * @see projects_template_single_gallery()
66
+ */
67
+ add_action( 'projects_before_single_project_summary', 'projects_template_single_title', 10 );
68
+ add_action( 'projects_before_single_project_summary', 'projects_template_single_short_description', 20 );
69
+ add_action( 'projects_before_single_project_summary', 'projects_template_single_feature', 30 );
70
+ add_action( 'projects_before_single_project_summary', 'projects_template_single_gallery', 40 );
71
+
72
+ /**
73
+ * Project Summary Box
74
+ *
75
+ * @see projects_template_single_description()
76
+ * @see projects_template_single_meta()
77
+ */
78
+ add_action( 'projects_single_project_summary', 'projects_template_single_description', 10 );
79
+ add_action( 'projects_single_project_summary', 'projects_template_single_meta', 20 );
80
+
81
+ /**
82
+ * After Single Project
83
+ *
84
+ * @see projects_single_pagination()
85
+ */
86
+ add_action( 'projects_after_single_project', 'projects_single_pagination', 5 );
87
+
88
+ /**
89
+ * Pagination after projects loops
90
+ *
91
+ * @see projects_pagination()
92
+ */
93
+ add_action( 'projects_after_loop', 'projects_pagination', 10 );
94
+ }
95
+
96
+ /** Store Event Hooks *****************************************************/
97
+
98
+ /**
99
+ * Filters
100
+ */
101
+ add_filter( 'projects_short_description', 'wptexturize' );
102
+ add_filter( 'projects_short_description', 'convert_smilies' );
103
+ add_filter( 'projects_short_description', 'convert_chars' );
104
+ add_filter( 'projects_short_description', 'wpautop' );
105
+ add_filter( 'projects_short_description', 'shortcode_unautop' );
106
+ add_filter( 'projects_short_description', 'prepend_attachment' );
107
+ add_filter( 'projects_short_description', 'do_shortcode', 11 ); // AFTER wpautop()
projects-template.php ADDED
@@ -0,0 +1,474 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WooThemes Projects Template Functions
4
+ *
5
+ * Functions used in the template files to output content - in most cases hooked in via the template actions. All functions are pluggable.
6
+ *
7
+ * @author WooThemes
8
+ * @category Core
9
+ * @package Projects/Templates
10
+ * @version 1.0.0
11
+ */
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
+
15
+ /** Global ****************************************************************/
16
+
17
+ /**
18
+ * Handle redirects before content is output - hooked into template_redirect so is_page works.
19
+ *
20
+ * @return void
21
+ */
22
+ function projects_template_redirect() {
23
+ global $wp_query, $wp;
24
+
25
+ // Redirect project base page to post type archive url
26
+ if ( is_page( projects_get_page_id( 'projects' ) ) ) {
27
+ wp_safe_redirect( get_post_type_archive_link( 'project' ) );
28
+ exit;
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Fix active class in nav for shop page.
34
+ *
35
+ * @param array $menu_items
36
+ * @param array $args
37
+ * @return array
38
+ */
39
+ function projects_nav_menu_item_classes( $menu_items, $args ) {
40
+
41
+ if ( ! is_projects() ) return $menu_items;
42
+
43
+ $projects_page = (int) projects_get_page_id( 'projects' );
44
+ $page_for_posts = (int) get_option( 'page_for_posts' );
45
+
46
+ foreach ( (array) $menu_items as $key => $menu_item ) {
47
+
48
+ $classes = (array) $menu_item->classes;
49
+
50
+ // Unset active class for blog page
51
+ if ( $page_for_posts == $menu_item->object_id ) {
52
+ $menu_items[$key]->current = false;
53
+
54
+ if ( in_array( 'current_page_parent', $classes ) )
55
+ unset( $classes[ array_search('current_page_parent', $classes) ] );
56
+
57
+ if ( in_array( 'current-menu-item', $classes ) )
58
+ unset( $classes[ array_search('current-menu-item', $classes) ] );
59
+
60
+ // Set active state if this is the shop page link
61
+ } elseif ( is_projects() && $projects_page == $menu_item->object_id ) {
62
+ $menu_items[$key]->current = true;
63
+ $classes[] = 'current-menu-item';
64
+ $classes[] = 'current_page_item';
65
+
66
+ // Set parent state if this is a product page
67
+ } elseif ( is_singular( 'project' ) && $projects_page == $menu_item->object_id ) {
68
+ $classes[] = 'current_page_parent';
69
+ }
70
+
71
+ $menu_items[$key]->classes = array_unique( $classes );
72
+
73
+ }
74
+
75
+ return $menu_items;
76
+ }
77
+
78
+ if ( ! function_exists( 'projects_output_content_wrapper' ) ) {
79
+
80
+ /**
81
+ * Output the start of the page wrapper.
82
+ *
83
+ * @access public
84
+ * @return void
85
+ */
86
+ function projects_output_content_wrapper() {
87
+ projects_get_template( 'layout/wrapper-start.php' );
88
+ }
89
+ }
90
+ if ( ! function_exists( 'projects_output_content_wrapper_end' ) ) {
91
+
92
+ /**
93
+ * Output the end of the page wrapper.
94
+ *
95
+ * @access public
96
+ * @return void
97
+ */
98
+ function projects_output_content_wrapper_end() {
99
+ projects_get_template( 'layout/wrapper-end.php' );
100
+ }
101
+ }
102
+
103
+ if ( ! function_exists( 'projects_get_sidebar' ) ) {
104
+
105
+ /**
106
+ * Get the projects sidebar template.
107
+ *
108
+ * @access public
109
+ * @return void
110
+ */
111
+ function projects_get_sidebar() {
112
+ projects_get_template( 'layout/sidebar.php' );
113
+ }
114
+ }
115
+
116
+ /** Loop ******************************************************************/
117
+
118
+ if ( ! function_exists( 'projects_page_title' ) ) {
119
+
120
+ /**
121
+ * projects_page_title function.
122
+ *
123
+ * @access public
124
+ * @return void
125
+ */
126
+ function projects_page_title() {
127
+
128
+ if ( is_search() ) {
129
+ $page_title = sprintf( __( 'Search Results: &ldquo;%s&rdquo;', 'projects' ), get_search_query() );
130
+
131
+ if ( get_query_var( 'paged' ) )
132
+ $page_title .= sprintf( __( '&nbsp;&ndash; Page %s', 'projects' ), get_query_var( 'paged' ) );
133
+
134
+ } elseif ( is_tax() ) {
135
+
136
+ $page_title = single_term_title( '', false );
137
+
138
+ } else {
139
+
140
+ $projects_page_id = projects_get_page_id( 'projects' );
141
+ $page_title = get_the_title( $projects_page_id );
142
+
143
+ }
144
+
145
+ echo apply_filters( 'projects_page_title', $page_title );
146
+ }
147
+ }
148
+
149
+ if ( ! function_exists( 'projects_project_loop_start' ) ) {
150
+
151
+ /**
152
+ * Output the start of a project loop. By default this is a UL
153
+ *
154
+ * @access public
155
+ * @return void
156
+ */
157
+ function projects_project_loop_start( $echo = true ) {
158
+ ob_start();
159
+ projects_get_template( 'loop/loop-start.php' );
160
+ if ( $echo )
161
+ echo ob_get_clean();
162
+ else
163
+ return ob_get_clean();
164
+ }
165
+ }
166
+ if ( ! function_exists( 'projects_project_loop_end' ) ) {
167
+
168
+ /**
169
+ * Output the end of a project loop. By default this is a UL
170
+ *
171
+ * @access public
172
+ * @return void
173
+ */
174
+ function projects_project_loop_end( $echo = true ) {
175
+ ob_start();
176
+
177
+ projects_get_template( 'loop/loop-end.php' );
178
+
179
+ if ( $echo )
180
+ echo ob_get_clean();
181
+ else
182
+ return ob_get_clean();
183
+ }
184
+ }
185
+ if ( ! function_exists( 'projects_taxonomy_archive_description' ) ) {
186
+
187
+ /**
188
+ * Show an archive description on taxonomy archives
189
+ *
190
+ * @access public
191
+ * @subpackage Archives
192
+ * @return void
193
+ */
194
+ function projects_taxonomy_archive_description() {
195
+ if ( is_tax( array( 'project-category', 'project-tag' ) ) && get_query_var( 'paged' ) == 0 ) {
196
+ $description = apply_filters( 'the_content', term_description() );
197
+ if ( $description ) {
198
+ echo '<div class="term-description">' . $description . '</div>';
199
+ }
200
+ }
201
+ }
202
+ }
203
+ if ( ! function_exists( 'projects_project_archive_description' ) ) {
204
+
205
+ /**
206
+ * Show a projects page description on project archives
207
+ *
208
+ * @access public
209
+ * @subpackage Archives
210
+ * @return void
211
+ */
212
+ function projects_project_archive_description() {
213
+ if ( is_post_type_archive( 'project' ) && get_query_var( 'paged' ) == 0 || is_page( projects_get_page_id( 'projects' ) ) ) {
214
+ $projects_page = get_post( projects_get_page_id( 'projects' ) );
215
+ $description = apply_filters( 'the_content', $projects_page->post_content );
216
+ if ( $description ) {
217
+ echo '<div class="page-description">' . $description . '</div>';
218
+ }
219
+ }
220
+ }
221
+ }
222
+
223
+ if ( ! function_exists( 'projects_template_loop_project_thumbnail' ) ) {
224
+
225
+ /**
226
+ * Get the project thumbnail for the loop.
227
+ *
228
+ * @access public
229
+ * @subpackage Loop
230
+ * @return void
231
+ */
232
+ function projects_template_loop_project_thumbnail() {
233
+ echo '<figure class="project-thumbnail">' . projects_get_project_thumbnail() . '</figure>';
234
+ }
235
+ }
236
+
237
+ if ( ! function_exists( 'projects_template_loop_project_title' ) ) {
238
+
239
+ /**
240
+ * Display the project title in the loop.
241
+ *
242
+ * @access public
243
+ * @subpackage Loop
244
+ * @return void
245
+ */
246
+ function projects_template_loop_project_title() {
247
+ echo '<h3>' . get_the_title() . '</h3>';
248
+ }
249
+ }
250
+
251
+ if ( ! function_exists( 'projects_reset_loop' ) ) {
252
+
253
+ /**
254
+ * Reset the loop's index and columns when we're done outputting a project loop.
255
+ *
256
+ * @access public
257
+ * @subpackage Loop
258
+ * @return void
259
+ */
260
+ function projects_reset_loop() {
261
+ global $projects_loop;
262
+ // Reset loop/columns globals when starting a new loop
263
+ $projects_loop['loop'] = $projects_loop['column'] = '';
264
+ }
265
+ }
266
+
267
+ add_filter( 'loop_end', 'projects_reset_loop' );
268
+
269
+
270
+ if ( ! function_exists( 'projects_get_project_thumbnail' ) ) {
271
+
272
+ /**
273
+ * Get the project thumbnail, or the placeholder if not set.
274
+ *
275
+ * @access public
276
+ * @subpackage Loop
277
+ * @param string $size (default: 'project-archive')
278
+ * @param int $placeholder_width (default: 0)
279
+ * @param int $placeholder_height (default: 0)
280
+ * @return string
281
+ */
282
+ function projects_get_project_thumbnail( $size = 'project-archive' ) {
283
+ global $post;
284
+
285
+ if ( has_post_thumbnail() )
286
+ return get_the_post_thumbnail( $post->ID, $size );
287
+ }
288
+ }
289
+
290
+ if ( ! function_exists( 'projects_pagination' ) ) {
291
+
292
+ /**
293
+ * Output the pagination.
294
+ *
295
+ * @access public
296
+ * @subpackage Loop
297
+ * @return void
298
+ */
299
+ function projects_pagination() {
300
+ projects_get_template( 'loop/pagination.php' );
301
+ }
302
+ }
303
+
304
+ if ( ! function_exists( 'projects_template_short_description' ) ) {
305
+
306
+ /**
307
+ * Output the project short description.
308
+ *
309
+ * @access public
310
+ * @subpackage Project
311
+ * @return void
312
+ */
313
+ function projects_template_short_description() {
314
+ projects_get_template( 'loop/short-description.php' );
315
+ }
316
+ }
317
+
318
+ /** Single Project ********************************************************/
319
+
320
+ if ( ! function_exists( 'projects_template_single_feature' ) ) {
321
+
322
+ /**
323
+ * Output the project feature before the single project summary.
324
+ *
325
+ * @access public
326
+ * @subpackage Project
327
+ * @return void
328
+ */
329
+ function projects_template_single_feature() {
330
+ projects_get_template( 'single-project/project-feature.php' );
331
+ }
332
+ }
333
+
334
+ if ( ! function_exists( 'projects_template_single_gallery' ) ) {
335
+
336
+ /**
337
+ * Output the project gallery before the single project summary.
338
+ *
339
+ * @access public
340
+ * @subpackage Project
341
+ * @return void
342
+ */
343
+ function projects_template_single_gallery() {
344
+ projects_get_template( 'single-project/project-gallery.php' );
345
+ }
346
+ }
347
+
348
+ if ( ! function_exists( 'projects_template_single_title' ) ) {
349
+
350
+ /**
351
+ * Output the project title.
352
+ *
353
+ * @access public
354
+ * @subpackage Project
355
+ * @return void
356
+ */
357
+ function projects_template_single_title() {
358
+ projects_get_template( 'single-project/title.php' );
359
+ }
360
+ }
361
+
362
+ if ( ! function_exists( 'projects_template_single_short_description' ) ) {
363
+
364
+ /**
365
+ * Output the project short description (excerpt).
366
+ *
367
+ * @access public
368
+ * @subpackage Project
369
+ * @return void
370
+ */
371
+ function projects_template_single_short_description() {
372
+ projects_get_template( 'single-project/short-description.php' );
373
+ }
374
+ }
375
+
376
+ if ( ! function_exists( 'projects_template_single_description' ) ) {
377
+
378
+ /**
379
+ * Output the project description.
380
+ *
381
+ * @access public
382
+ * @subpackage Project
383
+ * @return void
384
+ */
385
+ function projects_template_single_description() {
386
+ projects_get_template( 'single-project/description.php' );
387
+ }
388
+ }
389
+
390
+ if ( ! function_exists( 'projects_template_single_meta' ) ) {
391
+
392
+ /**
393
+ * Output the project meta.
394
+ *
395
+ * @access public
396
+ * @subpackage Project
397
+ * @return void
398
+ */
399
+ function projects_template_single_meta() {
400
+ projects_get_template( 'single-project/meta.php' );
401
+ }
402
+ }
403
+
404
+ if ( ! function_exists( 'projects_single_pagination' ) ) {
405
+
406
+ /**
407
+ * Output the project pagination.
408
+ *
409
+ * @access public
410
+ * @subpackage Project
411
+ * @return void
412
+ */
413
+ function projects_single_pagination() {
414
+ projects_get_template( 'single-project/pagination.php' );
415
+ }
416
+ }
417
+
418
+ if ( ! function_exists( 'projects_content' ) ) {
419
+
420
+ /**
421
+ * Output Projects content.
422
+ *
423
+ * This function is only used in the optional 'projects.php' template
424
+ * which people can add to their themes to add basic projects support
425
+ * without hooks or modifying core templates.
426
+ *
427
+ * @access public
428
+ * @return void
429
+ */
430
+ function projects_content() {
431
+
432
+ if ( is_singular( 'project' ) ) {
433
+
434
+ while ( have_posts() ) : the_post();
435
+
436
+ projects_get_template_part( 'content', 'single-project' );
437
+
438
+ endwhile;
439
+
440
+ } else { ?>
441
+
442
+ <?php if ( apply_filters( 'projects_show_page_title', true ) ) : ?>
443
+
444
+ <h1 class="page-title"><?php projects_page_title(); ?></h1>
445
+
446
+ <?php endif; ?>
447
+
448
+ <?php do_action( 'projects_archive_description' ); ?>
449
+
450
+ <?php if ( have_posts() ) : ?>
451
+
452
+ <?php do_action( 'projects_before_loop' ); ?>
453
+
454
+ <?php projects_project_loop_start(); ?>
455
+
456
+ <?php while ( have_posts() ) : the_post(); ?>
457
+
458
+ <?php projects_get_template_part( 'content', 'project' ); ?>
459
+
460
+ <?php endwhile; // end of the loop. ?>
461
+
462
+ <?php projects_project_loop_end(); ?>
463
+
464
+ <?php do_action( 'projects_after_loop' ); ?>
465
+
466
+ <?php else : ?>
467
+
468
+ <?php projects_get_template( 'loop/no-products-found.php' ); ?>
469
+
470
+ <?php endif;
471
+
472
+ }
473
+ }
474
+ }
projects.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin Name: Projects
4
+ * Plugin URI: http://woothemes.com/
5
+ * Description: Hi, I'm your project showcase plugin for WordPress. Show off your recent work using our shortcode, widget or template tag.
6
+ * Author: WooThemes
7
+ * Version: 1.0.0
8
+ * Author URI: http://woothemes.com/
9
+ *
10
+ * @package WordPress
11
+ * @subpackage Projects
12
+ * @author Matty
13
+ * @since 1.0.0
14
+ */
15
+
16
+ require_once( 'classes/class-projects.php' );
17
+ require_once( 'classes/class-projects-taxonomy.php' );
18
+ require_once( 'classes/class-projects-shortcodes.php' );
19
+ require_once( 'classes/class-projects-settings.php' );
20
+ require_once( 'classes/class-widget-projects.php' );
21
+ require_once( 'classes/class-widget-project-categories.php' );
22
+
23
+ require_once( 'projects-template.php' );
24
+ require_once( 'projects-core-functions.php' );
25
+ require_once( 'projects-hooks.php' );
26
+
27
+ global $projects;
28
+ $projects = new Projects( __FILE__ );
readme.txt ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Projects by WooThemes ===
2
+ Contributors: woothemes, mattyza, jameskoster, tiagonoronha
3
+ Donate link: http://woothemes.com/
4
+ Tags: portfolio, projects, widget, shortcode, template-tag, services
5
+ Requires at least: 3.8
6
+ Tested up to: 3.8.1
7
+ Stable tag: 1.0.0
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Hi, I'm your projects showcase plugin for WordPress. Use me to show off a portfolio of your latest work.
12
+
13
+ == Description ==
14
+
15
+ "Projects" by WooThemes is a clean and easy-to-use project showcase management system for WordPress. Load in your recent projects, and display them on a specified page using our template system, or via a shortcode, widget or template tag.
16
+
17
+ == Usage ==
18
+
19
+ Once installed you can begin adding projects right away via the 'Projects' item in the main menu. The interface for adding projects is very similar to adding posts so you should feel right at home. But before you do that you should go ahead and create a page for your projects (via the Pages menu item) and specify that page as your projects base page in the projects settings.
20
+
21
+ == Installation ==
22
+
23
+ Installing "Projects" can be done either by searching for "Projects by WooThemes" via the "Plugins > Add New" screen in your WordPress dashboard, or by using the following steps:
24
+
25
+ 1. Download the plugin via WordPress.org.
26
+ 2. Upload the ZIP file through the "Plugins > Add New > Upload" screen in your WordPress dashboard.
27
+ 3. Activate the plugin through the 'Plugins' menu in WordPress
28
+
29
+ == Frequently Asked Questions ==
30
+
31
+ = How do I contribute? =
32
+
33
+ We encourage everyone to contribute their ideas, thoughts and code snippets. This can be done by forking the [repository over at GitHub](http://github.com/woothemes/projects/).
34
+
35
+ == Screenshots ==
36
+
37
+ 1. The projects base page
38
+ 2. A single project page
39
+ 3. The projects management screen within the WordPress dashboard.
40
+
41
+ == Upgrade Notice ==
42
+
43
+ = 1.0.0 =
44
+ * Initial release. Woo!
45
+
46
+ == Changelog ==
47
+
48
+ = 1.0.0 =
49
+ * 2014-12-17
50
+ * Initial release. Woo!
templates/archive-project.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Template for displaying project archives, including the main showcase page which is a post type archive.
4
+ *
5
+ * Override this template by copying it to yourtheme/projects/archive-project.php
6
+ *
7
+ * @author WooThemes
8
+ * @package Projects/Templates
9
+ * @version 1.0.0
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+
14
+ global $projects_loop;
15
+
16
+ // Store column count for displaying the grid
17
+ if ( empty( $projects_loop['columns'] ) )
18
+ $projects_loop['columns'] = apply_filters( 'projects_loop_columns', 2 );
19
+
20
+ get_header( 'projects' ); ?>
21
+
22
+ <?php
23
+ /**
24
+ * projects_before_main_content hook
25
+ *
26
+ * @hooked projects_output_content_wrapper - 10 (outputs opening divs for the content)
27
+ */
28
+ do_action( 'projects_before_main_content' );
29
+ ?>
30
+
31
+ <?php if ( apply_filters( 'projects_show_page_title', true ) ) : ?>
32
+
33
+ <h1 class="page-title"><?php projects_page_title(); ?></h1>
34
+
35
+ <?php endif; ?>
36
+
37
+ <?php do_action( 'projects_archive_description' ); ?>
38
+
39
+ <?php if ( have_posts() ) : ?>
40
+
41
+ <?php
42
+ /**
43
+ * projects_before_loop hook
44
+ *
45
+ */
46
+ do_action( 'projects_before_loop' );
47
+ ?>
48
+
49
+ <div class="projects columns-<?php echo $projects_loop['columns']; ?>">
50
+
51
+ <?php projects_project_loop_start(); ?>
52
+
53
+ <?php while ( have_posts() ) : the_post(); ?>
54
+
55
+ <?php projects_get_template_part( 'content', 'project' ); ?>
56
+
57
+ <?php endwhile; // end of the loop. ?>
58
+
59
+ <?php projects_project_loop_end(); ?>
60
+
61
+ </div><!-- .projects -->
62
+
63
+ <?php
64
+ /**
65
+ * projects_after_loop hook
66
+ *
67
+ * @hooked projects_pagination - 10
68
+ */
69
+ do_action( 'projects_after_loop' );
70
+ ?>
71
+
72
+ <?php else : ?>
73
+
74
+ <?php projects_get_template( 'loop/no-projects-found.php' ); ?>
75
+
76
+ <?php endif; ?>
77
+
78
+ <?php
79
+ /**
80
+ * projects_after_main_content hook
81
+ *
82
+ * @hooked projects_output_content_wrapper_end - 10 (outputs closing divs for the content)
83
+ */
84
+ do_action( 'projects_after_main_content' );
85
+ ?>
86
+
87
+ <?php
88
+ /**
89
+ * projects_sidebar hook
90
+ *
91
+ * @hooked projects_get_sidebar - 10
92
+ */
93
+ do_action( 'projects_sidebar' );
94
+ ?>
95
+
96
+ <?php get_footer( 'projects' ); ?>
templates/content-project-category.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The template for displaying project category thumbnails within loops.
4
+ *
5
+ * Override this template by copying it to yourtheme/projects/content-project_cat.php
6
+ *
7
+ * @author WooThemes
8
+ * @package Projects/Templates
9
+ * @version 1.0.0
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+
14
+ global $projects_loop;
15
+
16
+ // Store loop count we're currently on
17
+ if ( empty( $projects_loop['loop'] ) )
18
+ $projects_loop['loop'] = 0;
19
+
20
+ // Store column count for displaying the grid
21
+ if ( empty( $projects_loop['columns'] ) )
22
+ $projects_loop['columns'] = apply_filters( 'projects_loop_columns', 2 );
23
+
24
+ // Increase loop count
25
+ $projects_loop['loop']++;
26
+ ?>
27
+ <li class="project-category project<?php
28
+ if ( ( $projects_loop['loop'] - 1 ) % $projects_loop['columns'] == 0 || $projects_loop['columns'] == 1)
29
+ echo ' first';
30
+ if ( $projects_loop['loop'] % $projects_loop['columns'] == 0 )
31
+ echo ' last';
32
+ ?>">
33
+
34
+ <?php do_action( 'projects_before_subcategory', $category ); ?>
35
+
36
+ <a href="<?php echo get_term_link( $category->slug, 'project_cat' ); ?>">
37
+
38
+ <?php
39
+ /**
40
+ * projects_before_subcategory_title hook
41
+ *
42
+ * @hooked projects_subcategory_thumbnail - 10
43
+ */
44
+ do_action( 'projects_before_subcategory_title', $category );
45
+ ?>
46
+
47
+ <h3>
48
+ <?php
49
+ echo $category->name;
50
+
51
+ if ( $category->count > 0 )
52
+ echo apply_filters( 'projects_subcategory_count_html', ' <mark class="count">(' . $category->count . ')</mark>', $category );
53
+ ?>
54
+ </h3>
55
+
56
+ <?php
57
+ /**
58
+ * projects_after_subcategory_title hook
59
+ */
60
+ do_action( 'projects_after_subcategory_title', $category );
61
+ ?>
62
+
63
+ </a>
64
+
65
+ <?php do_action( 'projects_after_subcategory', $category ); ?>
66
+
67
+ </li>
templates/content-project-widget.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The template for displaying project content within widgets.
4
+ *
5
+ * Override this template by copying it to yourtheme/projects/content-project-widget.php
6
+ *
7
+ * @author WooThemes
8
+ * @package Projects/Templates
9
+ * @version 1.0.0
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+
14
+ global $post, $project;
15
+ ?>
16
+ <li>
17
+
18
+ <a href="<?php the_permalink(); ?>" class="project-permalink">
19
+
20
+ <?php echo projects_get_project_thumbnail( 'project-thumbnail' ); ?>
21
+
22
+ <span class="project-title"><?php the_title(); ?></span>
23
+
24
+ </a>
25
+
26
+ </li>
templates/content-project.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The template for displaying project content within loops.
4
+ *
5
+ * Override this template by copying it to yourtheme/projects/content-project.php
6
+ *
7
+ * @author WooThemes
8
+ * @package Projects/Templates
9
+ * @version 1.0.0
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+
14
+ global $project, $projects_loop;
15
+
16
+ // Store loop count we're currently on
17
+ if ( empty( $projects_loop['loop'] ) )
18
+ $projects_loop['loop'] = 0;
19
+
20
+ // Store column count for displaying the grid
21
+ if ( empty( $projects_loop['columns'] ) )
22
+ $projects_loop['columns'] = apply_filters( 'projects_loop_columns', 2 );
23
+
24
+ // Increase loop count
25
+ $projects_loop['loop']++;
26
+
27
+ // Extra post classes
28
+ $classes = array();
29
+ if ( 0 == ( $projects_loop['loop'] - 1 ) % $projects_loop['columns'] || 1 == $projects_loop['columns'] )
30
+ $classes[] = 'first';
31
+ if ( 0 == $projects_loop['loop'] % $projects_loop['columns'] )
32
+ $classes[] = 'last';
33
+ ?>
34
+ <li <?php post_class( $classes ); ?>>
35
+
36
+ <?php do_action( 'projects_before_loop_item' ); ?>
37
+
38
+ <a href="<?php the_permalink(); ?>" class="project-permalink">
39
+
40
+ <?php
41
+ /**
42
+ * projects_loop_item hook
43
+ *
44
+ * @hooked projects_template_loop_project_thumbnail - 10
45
+ * @hooked projects_template_loop_project_title - 20
46
+ */
47
+ do_action( 'projects_loop_item' );
48
+ ?>
49
+
50
+ </a>
51
+
52
+ <?php
53
+ /**
54
+ * projects_after_loop_item hook
55
+ *
56
+ * @hooked projects_template_short_description - 10
57
+ */
58
+ do_action( 'projects_after_loop_item' );
59
+ ?>
60
+
61
+ </li>
templates/content-single-project.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The template for displaying project content in the single-project.php template
4
+ *
5
+ * Override this template by copying it to yourtheme/projects/content-single-project.php
6
+ *
7
+ * @author WooThemes
8
+ * @package Projects/Templates
9
+ * @version 1.0.0
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+ ?>
14
+
15
+ <?php
16
+ /**
17
+ * projects_before_single_project hook
18
+ *
19
+ */
20
+ do_action( 'projects_before_single_project' );
21
+ ?>
22
+
23
+ <div id="project-<?php the_ID(); ?>" <?php post_class(); ?>>
24
+
25
+ <?php
26
+ /**
27
+ * projects_show_project_images hook
28
+ * @hooked projects_template_single_title - 10
29
+ * @hooked projects_template_single_short_description - 20
30
+ * @hooked projects_template_single_feature - 30
31
+ * @hooked projects_template_single_gallery - 40
32
+ */
33
+ do_action( 'projects_before_single_project_summary' );
34
+ ?>
35
+
36
+ <div class="summary entry-summary">
37
+
38
+ <?php
39
+ /**
40
+ * projects_single_project_summary hook
41
+ *
42
+ * @hooked projects_template_single_description - 10
43
+ * @hooked projects_template_single_meta - 20
44
+ */
45
+ do_action( 'projects_single_project_summary' );
46
+ ?>
47
+
48
+ </div><!-- .summary -->
49
+
50
+ <?php
51
+ /**
52
+ * projects_after_single_project_summary hook
53
+ *
54
+ */
55
+ do_action( 'projects_after_single_project_summary' );
56
+ ?>
57
+
58
+ </div><!-- #project-<?php the_ID(); ?> -->
59
+
60
+ <?php
61
+ /**
62
+ * projects_after_single_project hook
63
+ *
64
+ * @hooked projects_single_pagination - 10
65
+ */
66
+ do_action( 'projects_after_single_project' );
templates/layout/sidebar.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Sidebar
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ get_sidebar( 'projects' ); ?>
templates/layout/wrapper-end.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Content wrappers
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ $template = get_option( 'template' );
11
+
12
+ switch( $template ) {
13
+ case 'twentyeleven' :
14
+ echo '</div></div>';
15
+ break;
16
+ case 'twentytwelve' :
17
+ echo '</div></div>';
18
+ break;
19
+ case 'twentythirteen' :
20
+ echo '</div></div>';
21
+ break;
22
+ case 'twentyfourteen' :
23
+ echo '</div></div></div>';
24
+ get_sidebar( 'content' );
25
+ break;
26
+ default :
27
+ echo '</div></div>';
28
+ break;
29
+ }
templates/layout/wrapper-start.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Content wrappers
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ $template = get_option( 'template' );
13
+
14
+ switch( $template ) {
15
+ case 'twentyeleven' :
16
+ echo '<div id="primary"><div id="content" role="main">';
17
+ break;
18
+ case 'twentytwelve' :
19
+ echo '<div id="primary" class="site-content"><div id="content" role="main">';
20
+ break;
21
+ case 'twentythirteen' :
22
+ echo '<div id="primary" class="site-content"><div id="content" role="main" class="entry-content twentythirteen">';
23
+ break;
24
+ case 'twentyfourteen' :
25
+ echo '<div id="primary" class="content-area"><div id="content" role="main" class="site-content twentyfourteen"><div class="tfp">';
26
+ break;
27
+ default :
28
+ echo '<div id="container"><div id="content" role="main">';
29
+ break;
30
+ }
templates/loop/loop-end.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Project Loop End
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+ ?>
10
+ </ul>
templates/loop/loop-start.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Project Loop Start
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+ ?>
10
+ <ul class="projects">
templates/loop/no-projects-found.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Displayed when no projects are found matching the current query.
4
+ *
5
+ * Override this template by copying it to yourtheme/projects/loop/no-projects-found.php
6
+ *
7
+ * @author WooThemes
8
+ * @package Projects/Templates
9
+ * @version 1.0.0
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+ ?>
14
+ <p class="projects-info"><?php _e( 'No projects found which match your selection.', 'projects' ); ?></p>
templates/loop/pagination.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Pagination - Show numbered pagination for catalog pages.
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ global $wp_query;
13
+
14
+ if ( $wp_query->max_num_pages <= 1 )
15
+ return;
16
+ ?>
17
+ <nav class="projects-pagination">
18
+ <?php
19
+ echo paginate_links( apply_filters( 'projects_pagination_args', array(
20
+ 'base' => str_replace( 999999999, '%#%', get_pagenum_link( 999999999 ) ),
21
+ 'format' => '',
22
+ 'current' => max( 1, get_query_var('paged') ),
23
+ 'total' => $wp_query->max_num_pages,
24
+ 'prev_text' => '&larr;',
25
+ 'next_text' => '&rarr;',
26
+ 'type' => 'list',
27
+ 'end_size' => 3,
28
+ 'mid_size' => 3
29
+ ) ) );
30
+ ?>
31
+ </nav>
templates/loop/short-description.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Single project description
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ global $post;
13
+
14
+ ?>
15
+ <div itemprop="description" class="short-description">
16
+ <?php the_excerpt(); ?>
17
+ </div>
templates/single-project.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Template for displaying all single projects.
4
+ *
5
+ * Override this template by copying it to yourtheme/projects/single-project.php
6
+ *
7
+ * @author WooThemes
8
+ * @package Projects/Templates
9
+ * @version 1.0.0
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+
14
+ get_header( 'projects' ); ?>
15
+
16
+ <?php
17
+ /**
18
+ * projects_before_main_content hook
19
+ *
20
+ * @hooked projects_output_content_wrapper - 10 (outputs opening divs for the content)
21
+ */
22
+ do_action( 'projects_before_main_content' );
23
+ ?>
24
+
25
+ <?php while ( have_posts() ) : the_post(); ?>
26
+
27
+ <?php projects_get_template_part( 'content', 'single-project' ); ?>
28
+
29
+ <?php endwhile; // end of the loop. ?>
30
+
31
+ <?php
32
+ /**
33
+ * projects_after_main_content hook
34
+ *
35
+ * @hooked projects_output_content_wrapper_end - 10 (outputs closing divs for the content)
36
+ */
37
+ do_action( 'projects_after_main_content' );
38
+ ?>
39
+
40
+ <?php
41
+ /**
42
+ * projects_sidebar hook
43
+ *
44
+ * @hooked projects_get_sidebar - 10
45
+ */
46
+ do_action( 'projects_sidebar' );
47
+ ?>
48
+
49
+ <?php get_footer( 'projects' ); ?>
templates/single-project/description.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Single project description
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ global $post;
13
+
14
+ if ( ! $post->post_content ) return;
15
+ ?>
16
+ <div class="single-project-description" itemprop="description">
17
+ <?php echo apply_filters( 'projects_description', wpautop( $post->post_content ) ) ?>
18
+ </div>
templates/single-project/meta.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Single Project Meta
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ global $post;
13
+ ?>
14
+ <div class="project-meta">
15
+
16
+ <?php
17
+ // Categories
18
+ $terms_as_text = get_the_term_list( $post->ID, 'project-category', '<li>', '</li><li>', '</li>' );
19
+
20
+ // Meta
21
+ $client = esc_attr( get_post_meta( $post->ID, '_client', true ) );
22
+ $url = esc_url( get_post_meta( $post->ID, '_url', true ) );
23
+
24
+ /**
25
+ * Display categories if they're set
26
+ */
27
+ if ( $terms_as_text ) {
28
+ echo '<div class="categories">';
29
+ echo '<h3>' . __( 'Categories', 'projects' ) . '</h3>';
30
+ echo '<ul class="single-project-categories">';
31
+ echo $terms_as_text;
32
+ echo '</ul>';
33
+ echo '</div>';
34
+ }
35
+
36
+ /**
37
+ * Display client if set
38
+ */
39
+ if ( $client ) {
40
+ echo '<div class="client">';
41
+ echo '<h3>' . __( 'Client', 'projects' ) . '</h3>';
42
+ echo '<span class="client-name">' . $client . '</span>';
43
+ echo '</div>';
44
+ }
45
+
46
+ /**
47
+ * Display link if set
48
+ */
49
+ if ( $url ) {
50
+ echo '<div class="url">';
51
+ echo '<h3>' . __( 'Link', 'projects' ) . '</h3>';
52
+ echo '<span class="project-url"><a href="' . $url . '">' . apply_filters( 'projects_visit_project_link', __( 'Visit project', 'projects' ) ) . '</a></span>';
53
+ echo '</div>';
54
+ }
55
+ ?>
56
+ </div>
templates/single-project/pagination.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Single project pagination
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+ ?>
12
+ <nav class="projects-single-pagination">
13
+ <div class="next">
14
+ <?php next_post_link( '%link' ); ?>
15
+ </div>
16
+ <div class="previous">
17
+ <?php previous_post_link( '%link' ); ?>
18
+ </div>
19
+ </nav>
templates/single-project/project-feature.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Single Project Image
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ global $post;
13
+
14
+ ?>
15
+ <div class="single-featured">
16
+
17
+ <?php
18
+ if ( has_post_thumbnail() ) {
19
+
20
+ $image = get_the_post_thumbnail( $post->ID, 'project-single' );
21
+ $image_title = esc_attr( get_the_title( get_post_thumbnail_id() ) );
22
+ $image_link = wp_get_attachment_url( get_post_thumbnail_id() );
23
+ $attachment_count = count( projects_get_gallery_attachment_ids() );
24
+
25
+ if ( $attachment_count > 0 ) {
26
+ $gallery = '[project-gallery]';
27
+ } else {
28
+ $gallery = '';
29
+ }
30
+
31
+ echo $image;
32
+
33
+ }
34
+
35
+ ?>
36
+
37
+ </div>
templates/single-project/project-gallery.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Single Project Image
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ global $post, $projects, $project;
13
+
14
+ ?>
15
+ <div class="gallery">
16
+
17
+ <?php
18
+
19
+ $attachment_ids = projects_get_gallery_attachment_ids();
20
+
21
+ if ( $attachment_ids ) { ?>
22
+
23
+ <?php
24
+
25
+ $loop = 0;
26
+ $columns = apply_filters( 'projects_project_gallery_columns', 3 );
27
+
28
+ foreach ( $attachment_ids as $attachment_id ) {
29
+
30
+ $classes = array( 'zoom' );
31
+
32
+ if ( $loop == 0 || $loop % $columns == 0 )
33
+ $classes[] = 'first';
34
+
35
+ if ( ( $loop + 1 ) % $columns == 0 )
36
+ $classes[] = 'last';
37
+
38
+ $image_link = wp_get_attachment_url( $attachment_id );
39
+
40
+ if ( ! $image_link )
41
+ continue;
42
+
43
+ $image = wp_get_attachment_image( $attachment_id, apply_filters( 'single_project_small_thumbnail_size', 'project-single' ) );
44
+ $image_class = esc_attr( implode( ' ', $classes ) );
45
+ $image_title = esc_attr( get_the_title( $attachment_id ) );
46
+
47
+ echo $image;
48
+
49
+ $loop++;
50
+
51
+ } // endforeach ?>
52
+
53
+ <?php } // endif ?>
54
+
55
+ </div>
templates/single-project/short-description.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Single project description
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ global $post;
13
+
14
+ if ( ! $post->post_excerpt ) return;
15
+ ?>
16
+ <div class="single-project-short-description" itemprop="description">
17
+ <?php echo apply_filters( 'projects_short_description', wpautop( $post->post_excerpt ) ) ?>
18
+ </div>
templates/single-project/title.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Single Project title
4
+ *
5
+ * @author WooThemes
6
+ * @package Projects/Templates
7
+ * @version 1.0.0
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ ?>
13
+ <h1 itemprop="name" class="project_title entry-title"><?php the_title(); ?></h1>
templates/taxonomy-project-category.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Template for displaying projects in a project category. Simply includes the archive template.
4
+ *
5
+ * Override this template by copying it to yourtheme/projects/taxonomy-project-category.php
6
+ *
7
+ * @author WooThemes
8
+ * @package Projects/Templates
9
+ * @version 1.0.0
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+
14
+ projects_get_template( 'archive-project.php' );