forge 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.document +5 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +24 -0
  5. data/Gemfile.lock +81 -0
  6. data/LICENSE +20 -0
  7. data/README.md +24 -0
  8. data/Rakefile +53 -0
  9. data/VERSION +1 -0
  10. data/bin/forge +12 -0
  11. data/features/create.feature +34 -0
  12. data/features/link.feature +14 -0
  13. data/features/step_definitions/forge_steps.rb +38 -0
  14. data/features/support/env.rb +17 -0
  15. data/forge.gemspec +135 -0
  16. data/layouts/config/config.json.erb +13 -0
  17. data/layouts/config/stylesheet_header.erb +11 -0
  18. data/layouts/default/functions/functions.php.erb +21 -0
  19. data/layouts/default/stylesheets/_reset.scss +5 -0
  20. data/layouts/default/stylesheets/_typography.scss +5 -0
  21. data/layouts/default/stylesheets/style.css.scss.erb +28 -0
  22. data/layouts/default/templates/404.php.erb +10 -0
  23. data/layouts/default/templates/archive.php.erb +11 -0
  24. data/layouts/default/templates/attachment.php.erb +34 -0
  25. data/layouts/default/templates/comments.php +2 -0
  26. data/layouts/default/templates/footer.php +9 -0
  27. data/layouts/default/templates/header.php.erb +30 -0
  28. data/layouts/default/templates/index.php +6 -0
  29. data/layouts/default/templates/page.php +18 -0
  30. data/layouts/default/templates/partials/loop.php.erb +30 -0
  31. data/layouts/default/templates/search.php.erb +14 -0
  32. data/layouts/default/templates/sidebar.php +9 -0
  33. data/layouts/default/templates/single.php.erb +32 -0
  34. data/layouts/lib/forge-settings/README.md +43 -0
  35. data/layouts/lib/forge-settings/classes/settings.php +11 -0
  36. data/layouts/lib/forge-settings/classes/settings/collection.php +190 -0
  37. data/layouts/lib/forge-settings/classes/settings/option.php +125 -0
  38. data/layouts/lib/forge-settings/classes/settings/option/select.php +30 -0
  39. data/layouts/lib/forge-settings/classes/settings/option/text.php +15 -0
  40. data/layouts/lib/forge-settings/classes/settings/section.php +56 -0
  41. data/lib/forge.rb +11 -0
  42. data/lib/forge/builder.rb +165 -0
  43. data/lib/forge/cli.rb +86 -0
  44. data/lib/forge/config.rb +63 -0
  45. data/lib/forge/error.rb +8 -0
  46. data/lib/forge/generator.rb +128 -0
  47. data/lib/forge/guard.rb +57 -0
  48. data/lib/forge/project.rb +91 -0
  49. data/lib/forge/version.rb +3 -0
  50. data/lib/guard/forge/assets.rb +31 -0
  51. data/lib/guard/forge/config.rb +31 -0
  52. data/lib/guard/forge/functions.rb +31 -0
  53. data/lib/guard/forge/templates.rb +28 -0
  54. data/spec/lib/forge/config_spec.rb +79 -0
  55. data/spec/lib/forge/project_spec.rb +34 -0
  56. data/spec/spec_helper.rb +13 -0
  57. metadata +263 -0
@@ -0,0 +1,13 @@
1
+ {
2
+ // The name of the theme
3
+ "name": "<%= config[:name] %>",
4
+
5
+ // The website for the theme
6
+ "uri": "<%= config[:uri] %>",
7
+
8
+ // The author's name
9
+ "author": "<%= config[:author] %>",
10
+
11
+ // The author's website
12
+ "author_uri": "<%= config[:author_uri] %>"
13
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Theme Name: <%= config["name"] %>
3
+ * Theme URI: <%= config["uri"] %>
4
+ * Author: <%= config["author"] %>
5
+ * Author URI: <%= config["author_uri"] %>
6
+ * Description: <%= config["description"] if config["description"] %>
7
+ * Version: <%= config["version_number"] if config["version_number"] %>
8
+ * License: <%= config["license_name"] if config["license_name"] %>
9
+ * License URI: <%= config["license_uri"] if config["license_uri"] %>
10
+ * Tags: <%= config["tags"] if config["tags"] %>
11
+ */
@@ -0,0 +1,21 @@
1
+ <?php
2
+
3
+ add_action( 'after_setup_theme', '<%= theme_id %>_setup' );
4
+
5
+ if ( ! function_exists( '<%= theme_id %>_setup' ) ) :
6
+
7
+ /**
8
+ * Set up your theme here
9
+ */
10
+ function <%= theme_id %>_setup() {
11
+ add_theme_support( 'post-thumbnails' );
12
+
13
+ if ( ! is_admin() ) {
14
+ wp_enqueue_style(
15
+ '<%= theme_id %>-style',
16
+ get_bloginfo( 'stylesheet_url' )
17
+ );
18
+ }
19
+ }
20
+
21
+ endif; // <%= theme_id %>_setup
@@ -0,0 +1,5 @@
1
+ /* _reset.scss
2
+ * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
3
+
4
+ @import "blueprint/reset";
5
+ @inclue blueprint-reset;
@@ -0,0 +1,5 @@
1
+ /* _typography.scss
2
+ * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
3
+
4
+ @import "blueprint/typography";
5
+ @include blueprint-typography;
@@ -0,0 +1,28 @@
1
+ // This is your main stylesheet file, you can use SASS in here to include css partials
2
+
3
+ @import "reset";
4
+ @import "typography";
5
+
6
+ @import "blueprint/grid";
7
+
8
+ .clear {
9
+ clear: both;
10
+ }
11
+
12
+ #container {
13
+ @include container;
14
+ @include prepend(1);
15
+ border-left: 1px solid;
16
+ border-right: 1px solid;
17
+ }
18
+
19
+ #content {
20
+ @include column(15);
21
+ @include border(#555, 2px);
22
+ }
23
+
24
+ #sidebar {
25
+ @include column(7);
26
+ @include prepend(1);
27
+ @include last;
28
+ }
@@ -0,0 +1,10 @@
1
+ <?php get_header(); ?>
2
+ <div id="content" class="clear">
3
+ <h1 class="page-title"><?php _e( '404: Page Not Found', '<%= theme_id %>' ); ?></h1>
4
+ <div class="entry entry-page clear">
5
+ <p><?php _e( 'We are terribly sorry, but the URL you typed no longer exists. It might have been moved or deleted. Try searching the site:', '<%= theme_id %>' ); ?></p>
6
+ <?php get_search_form(); ?>
7
+ </div>
8
+ </div><!--end content-->
9
+ <?php get_sidebar(); ?>
10
+ <?php get_footer(); ?>
@@ -0,0 +1,11 @@
1
+ <?php get_header(); ?>
2
+ <div id="content" class="clear">
3
+ <?php if ( have_posts() ) : ?>
4
+ <h1 class="small-header"><?php _e( 'Blog Archives', '<%= theme_id %>' ); ?></h1>
5
+ <?php get_template_part( 'loop' ); ?>
6
+ <?php else : ?>
7
+ <p><?php _e( 'No posts found.', '<%= theme_id %>' ); ?></p>
8
+ <?php endif; ?>
9
+ </div><!--end content-->
10
+ <?php get_sidebar(); ?>
11
+ <?php get_footer(); ?>
@@ -0,0 +1,34 @@
1
+ <?php get_header(); ?>
2
+ <div id="content" class="clear">
3
+ <?php the_post(); ?>
4
+ <h1 class="page-title"><?php the_title(); ?></h1>
5
+ <div class="entry entry-page clear">
6
+ <a href="<?php echo wp_get_attachment_url( $post->ID ); ?>" title="<?php the_title_attribute(); ?>" rel="attachment">
7
+ <?php
8
+ if ( wp_attachment_is_image ( $post->ID ) ) {
9
+ $img_src = wp_get_attachment_image_src( $post->ID, 'large' );
10
+ $alt_text = get_post_meta( $post->ID, '_wp_attachment_image_alt', true );
11
+ ?>
12
+ <img src="<?php echo esc_url( $img_src[0] ); ?>" alt="<?php esc_attr_e( $alt_text ); ?>">
13
+ <?php
14
+ } else {
15
+ echo basename( $post->guid );
16
+ }
17
+ ?>
18
+ </a>
19
+ <?php if ( $post->post_content ) : ?>
20
+ <div class="description">
21
+ <?php the_content(); ?>
22
+ </div>
23
+ <?php endif; ?>
24
+ <div class="pagination clear">
25
+ <div class="alignleft"><?php previous_image_link( 0, __( '&larr; Previous image', '<%= theme_id %>' ) ); ?></div>
26
+ <div class="alignright"><?php next_image_link( 0, __( 'Next image &rarr;', '<%= theme_id %>' ) ); ?></div>
27
+ </div>
28
+ <div>
29
+ <a href="<?php echo get_permalink( $post->post_parent ); ?>"><?php _e( 'Return to gallery', '<%= theme_id %>' ); ?></a>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ <?php get_sidebar(); ?>
34
+ <?php get_footer(); ?>
@@ -0,0 +1,2 @@
1
+ <?php
2
+ // Default comments file goes here
@@ -0,0 +1,9 @@
1
+ <div id="copyright" class="clear">
2
+ <p>
3
+ <a href="http://wordpress.org/" rel="generator">Proudly powered by WordPress</a>
4
+ </p>
5
+ </div><!--end copyright-->
6
+ </div><!--end container-->
7
+ <?php wp_footer(); ?>
8
+ </body>
9
+ </html>
@@ -0,0 +1,30 @@
1
+ <html <?php language_attributes( 'html' ) ?>>
2
+ <head>
3
+ <title><?php wp_title(); ?></title>
4
+ <!-- Basic Meta Data -->
5
+ <meta charset="<?php bloginfo( 'charset' ); ?>" />
6
+
7
+ <!-- WordPress -->
8
+ <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
9
+ <?php wp_head(); ?>
10
+ </head>
11
+ <body <?php body_class(); ?>>
12
+ <div id="container" class="clear">
13
+ <div id="header" class="clear">
14
+ <div id="title">
15
+ <?php if ( is_front_page() ) echo( '<h1>' ); ?>
16
+ <a href="<?php echo home_url(); ?>"><?php bloginfo( 'name' ); ?></a>
17
+ <?php if ( is_front_page() ) echo( '</h1>' ); ?>
18
+ </div>
19
+ <?php
20
+ wp_nav_menu(
21
+ array(
22
+ 'theme_location' => 'nav-1',
23
+ 'container_id' => 'navigation',
24
+ 'container_class' => 'clear',
25
+ 'menu_class' => 'nav',
26
+ 'depth' => '2'
27
+ )
28
+ );
29
+ ?>
30
+ </div><!--end header-->
@@ -0,0 +1,6 @@
1
+ <?php get_header(); ?>
2
+ <div id="content" class="clear">
3
+ <?php get_template_part( 'loop' ); ?>
4
+ </div><!--end content-->
5
+ <?php get_sidebar(); ?>
6
+ <?php get_footer(); ?>
@@ -0,0 +1,18 @@
1
+ <?php get_header(); ?>
2
+ <div id="content" class="clear">
3
+ <?php the_post(); ?>
4
+ <div id="page-<?php the_ID(); ?>" class="page clear">
5
+ <?php if ( has_post_thumbnail() ) { ?>
6
+ <div class="entry-page-image">
7
+ <?php the_post_thumbnail(); ?>
8
+ </div>
9
+ <?php } ?>
10
+ <h1><?php the_title(); ?></h1>
11
+ <div class="entry entry-page clear">
12
+ <?php the_content(); ?>
13
+ </div>
14
+ </div>
15
+ <?php comments_template( '', true ); ?>
16
+ </div><!--end content-->
17
+ <?php get_sidebar(); ?>
18
+ <?php get_footer(); ?>
@@ -0,0 +1,30 @@
1
+ <?php if (have_posts()) : ?>
2
+ <?php while ( have_posts() ) : the_post(); ?>
3
+ <div id="post-<?php the_ID(); ?>" <?php post_class( 'clear' ); ?>>
4
+ <div class="post-header clear">
5
+ <h2 class="post-title">
6
+ <a href="<?php the_permalink(); ?>" rel="bookmark" title="<?php esc_attr( sprintf( __( 'Permanent Link to %s', '<%= theme_id %>' ), the_title_attribute( 'echo=false' ) ) ); ?>"><?php the_title(); ?></a>
7
+ </h2>
8
+ <p><?php the_time( __( 'F jS, Y', '<%= theme_id %>' ) ); ?></p>
9
+ <p><?php the_author(); ?></p>
10
+ <?php if ( has_post_thumbnail() ) { ?>
11
+ <a href="<?php the_permalink(); ?>">
12
+ <?php the_post_thumbnail(); ?>
13
+ </a>
14
+ <?php } ?>
15
+ </div><!--end post-header-->
16
+ <div class="entry entry-post clear">
17
+ <?php the_content( __( 'Read more', '<%= theme_id %>' )); ?>
18
+ <?php edit_post_link( __( 'Edit this', '<%= theme_id %>' ), '<p>', '</p>' ); ?>
19
+ </div><!--end entry-->
20
+ <div class="post-footer clear">
21
+ <p><?php comments_popup_link( __( 'Leave a comment', '<%= theme_id %>' ), __( '1 Comment', '<%= theme_id %>' ), __( '% Comments', '<%= theme_id %>' ), NULL, NULL ); ?></p>
22
+ </div><!--end post-footer-->
23
+ </div><!--end post-->
24
+ <?php endwhile; /* rewind or continue if all posts have been fetched */ ?>
25
+ <div class="pagination index">
26
+ <div class="alignleft"><?php previous_posts_link( __( '&larr; Newer entries', '<%= theme_id %>' )); ?></div>
27
+ <div class="alignright"><?php next_posts_link( __( 'Older entries &rarr;', '<%= theme_id %>' )); ?></div>
28
+ </div><!--end pagination-->
29
+ <?php else : ?>
30
+ <?php endif; ?>
@@ -0,0 +1,14 @@
1
+ <?php get_header(); ?>
2
+ <h1><?php printf( __( "Search results for '%s'", "<%= theme_id %>" ), get_search_query() ); ?></h1>
3
+ <div id="content" class="clear">
4
+ <?php if ( have_posts() ) : ?>
5
+ <?php get_template_part( 'loop' ); ?>
6
+ <?php else : ?>
7
+ <div>
8
+ <p><?php printf( __( 'Sorry, your search for "%s" did not turn up any results. Please try again.', '<%= theme_id %>' ), get_search_query());?></p>
9
+ <?php get_search_form(); ?>
10
+ </div><!--end entry-->
11
+ <?php endif; ?>
12
+ </div><!--end content-->
13
+ <?php get_sidebar(); ?>
14
+ <?php get_footer(); ?>
@@ -0,0 +1,9 @@
1
+ <div id="sidebar">
2
+ <ul>
3
+ <?php
4
+ if ( ! dynamic_sidebar( 'sidebar' ) ) {
5
+ the_widget( 'WP_Widget_Recent_Posts', array( 'number' => 5 ), array( 'widget_id' => NULL ) );
6
+ }
7
+ ?>
8
+ </ul>
9
+ </div><!--end sidebar-->
@@ -0,0 +1,32 @@
1
+ <?php get_header(); ?>
2
+ <div id="content" class="clear">
3
+ <?php if ( have_posts() ) : ?>
4
+ <?php while ( have_posts() ) : the_post(); ?>
5
+ <div id="post-<?php the_ID(); ?>" <?php post_class( 'single' ); ?>>
6
+ <h1><?php the_title(); ?></h1>
7
+ <div>
8
+ <?php printf( __( 'by %s on', '<%= theme_id %>' ), get_the_author() ); ?> <?php the_date(); ?>
9
+ </div>
10
+ <div class="entry single clear">
11
+ <?php if ( has_post_thumbnail() ) {
12
+ the_post_thumbnail();
13
+ } ?>
14
+ <?php the_content(); ?>
15
+ <?php edit_post_link( __( 'Edit this', '<%= theme_id %>' ), '<p>', '</p>' ); ?>
16
+ <?php wp_link_pages(); ?>
17
+ </div><!--end entry-->
18
+ <div class="post-footer clear">
19
+ <div class="tags">
20
+ <?php the_tags( __( 'Tags: ', '<%= theme_id %>' ), ', ', '' ); ?>
21
+ </div>
22
+ <div class="cats">
23
+ <?php printf( __( 'From: %s', '<%= theme_id %>' ), get_the_category_list( ', ' ) ); ?>
24
+ </div>
25
+ </div><!--end post footer-->
26
+ </div><!--end post-->
27
+ <?php endwhile; /* rewind or continue if all posts have been fetched */ ?>
28
+ <?php comments_template( '', true ); ?>
29
+ <?php endif; ?>
30
+ </div><!--end content-->
31
+ <?php get_sidebar(); ?>
32
+ <?php get_footer(); ?>
@@ -0,0 +1,43 @@
1
+ ## Easy WordPress Theme Options
2
+
3
+ The goal of this library is to abstract away as much of the WordPress settings API as possible, and make setting up options a breeze!
4
+
5
+ ## Setup
6
+
7
+ * Clone this repository
8
+ * Symlink the 'classes' folder from this library into your functions folder in your theme
9
+ * In your functions.php file, use this code to setup your theme's options:
10
+
11
+ <?php
12
+
13
+ add_action( 'after_setup_theme', 'react_options' );
14
+
15
+ function react_options() {
16
+ require( dirname( __FILE__ ) . '/functions/settings/settings.php' );
17
+
18
+ global $react_options;
19
+
20
+ $react_options = new Settings_Collection( 'react', 'theme_react_options' );
21
+
22
+ $react_options->add_section( 'first_section', 'Text for First Section' );
23
+ $react_options->add_section( 'second_section', 'Text for Second Section' );
24
+
25
+ $react_options->add_option( 'my_first_option', 'text', 'first_section' )
26
+ ->default_value( 'The default text' )
27
+ ->tab( 'general')
28
+ ->label( 'Enable Featured Slider' );
29
+
30
+ $react_options->add_option( 'select_this', 'select', 'second_section' )
31
+ ->valid_values( array(
32
+ 'one' => 'ONE',
33
+ 'two' => 'TWO',
34
+ 'three' => 'THREE' ) )
35
+ ->default_value( 'two' )
36
+ ->label( 'Select Your Character' );
37
+
38
+ /* More options go here... */
39
+
40
+ $react_options->initialize();
41
+ }
42
+
43
+ Bam! You have theme options!
@@ -0,0 +1,11 @@
1
+ <?php
2
+
3
+ require( dirname( __FILE__ ) . '/settings/collection.php' );
4
+ require( dirname( __FILE__ ) . '/settings/option.php' );
5
+ require( dirname( __FILE__ ) . '/settings/section.php' );
6
+ require( dirname( __FILE__ ) . '/settings/option/text.php' );
7
+ require( dirname( __FILE__ ) . '/settings/option/select.php' );
8
+
9
+ class Settings {
10
+
11
+ }
@@ -0,0 +1,190 @@
1
+ <?php
2
+
3
+ class Settings_Collection {
4
+ protected $_sections, $_options, $_name, $_slug;
5
+
6
+ public function __construct( $slug, $name ) {
7
+ $this->sections( array() );
8
+ $this->options( array() );
9
+ $this->slug( $slug );
10
+ $this->name( $name );
11
+ $this->register_hooks();
12
+ }
13
+
14
+ /***** Attribute accessors *****/
15
+ public function sections( $sections = NULL ) {
16
+ if ( NULL === $sections )
17
+ return $this->_sections;
18
+
19
+ $this->_sections = $sections;
20
+
21
+ return $this;
22
+ }
23
+
24
+ public function options( $options = NULL ) {
25
+ if ( NULL === $options )
26
+ return $this->_options;
27
+
28
+ $this->_options = $options;
29
+
30
+ return $this;
31
+ }
32
+
33
+ public function slug( $slug = NULL ) {
34
+ if ( NULL === $slug )
35
+ return $this->_slug;
36
+
37
+ $this->_slug = $slug;
38
+
39
+ return $this;
40
+ }
41
+
42
+ public function name( $name = NULL ) {
43
+ if ( NULL === $name )
44
+ return $this->_name;
45
+
46
+ $this->_name = $name;
47
+
48
+ return $this;
49
+ }
50
+
51
+ /***** WordPress setup *****/
52
+
53
+ public function register_hooks() {
54
+ // Load the Admin Options page
55
+ add_action( 'admin_menu', array( &$this, 'add_options_page' ) );
56
+ // Register the sections and options
57
+ add_action( 'admin_init', array( &$this, 'register' ) );
58
+ }
59
+
60
+ public function initialize() {
61
+ $option_values = get_option( $this->name() );
62
+
63
+ if ( false === $option_values || empty( $option_values ) ) {
64
+ $option_values = $this->defaults();
65
+ }
66
+ update_option( $this->name(), $option_values );
67
+
68
+ foreach ( $option_values as $name => $value ) {
69
+ foreach ( $this->_options as $option ) {
70
+ if ( $option->name() == $name ){
71
+ $option->value($value);
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+ public function add_options_page() {
78
+ add_theme_page(
79
+ 'Theme Options',
80
+ 'Theme Options',
81
+ 'edit_theme_options',
82
+ $this->slug() . '-settings',
83
+ array( &$this, 'echo_form_html' ) );
84
+ }
85
+
86
+ public function register() {
87
+ register_setting( $this->name(), $this->name(), array( &$this, 'validate' ) );
88
+ $this->register_sections();
89
+ $this->register_options();
90
+ }
91
+
92
+ protected function register_options() {
93
+ foreach( $this->options() as $option ) {
94
+ $option->register();
95
+ }
96
+ }
97
+
98
+ protected function register_sections() {
99
+ foreach( $this->sections() as $section ) {
100
+ $section->register();
101
+ }
102
+ }
103
+
104
+ public function validate( $inputs ) {
105
+ $validated_input = array();
106
+
107
+ foreach ( $inputs as $key => $value ) {
108
+ $option = $this->_options[$key];
109
+ $validated_input[$key] = $option->validate( $value );
110
+ }
111
+
112
+ return $validated_input;
113
+ }
114
+
115
+ /**
116
+ *
117
+ */
118
+ public function add_section( $id, $title, $description = NULL ) {
119
+ $this->_sections[] = new Settings_Section( $id, $title, $description, $this->name() );
120
+ }
121
+
122
+ /**
123
+ * Adds an option with the given name and type to this collection
124
+ * Sets the option's parent_name to this collection's name, and returns the option
125
+ *
126
+ * @param $name - unique (within the collection ) name for this option
127
+ * @param $type - type of option (text/select/checkbox/etc)
128
+ * @param $section - name of the section this option goes in
129
+ *
130
+ * @return Settings_Option
131
+ */
132
+ public function add_option( $name, $type, $section = NULL ) {
133
+ $option_class = 'Settings_Option_' . ucfirst( $type );
134
+
135
+ $option = new $option_class;
136
+ $option->name( $name );
137
+ $option->parent_name( $this->name() );
138
+ $option->section( $section );
139
+
140
+ $this->_options[$name] = $option;
141
+
142
+ return $option;
143
+ }
144
+
145
+ public function get_value( $option_name ) {
146
+ $options = $this->options();
147
+ $option = $options[$option_name];
148
+ return $option->value();
149
+ }
150
+
151
+ /**
152
+ * Returns the default values of all options in this collection as a hash
153
+ *
154
+ * @return array
155
+ */
156
+ public function defaults() {
157
+ $defaults = array();
158
+
159
+ $options = $this->options();
160
+
161
+ foreach( $options as $option ) {
162
+ $defaults[ $option->name() ] = $option->default_value();
163
+ }
164
+
165
+ return $defaults;
166
+ }
167
+
168
+ /***** HTML Output *****/
169
+
170
+ public function echo_form_html() { ?>
171
+ <div class="wrap">
172
+ <?php echo $this->settings_updated_html(); ?>
173
+ <form action="options.php" method="post">
174
+ <?php
175
+ settings_fields( $this->name() );
176
+ do_settings_sections( $this->name() );
177
+ ?>
178
+ <input type="submit" class="button-primary" value="<?php esc_attr_e('Save Settings'); ?>" />
179
+ <input type="submit" class="button-secondary" value="<?php esc_attr_e('Reset Defaults'); ?>" />
180
+ </form>
181
+ </div>
182
+ <?php }
183
+
184
+ public function settings_updated_html() {
185
+ if ( isset( $_GET['settings-updated'] ) )
186
+ return "<div class='updated'><p>Theme settings updated successfully.</p></div>";
187
+ }
188
+ }
189
+
190
+ class SectionNotFoundException extends Exception { }