├── .bowerrc
├── templates
├── play-button-shortcode-not-found.php
├── series-search-results.php
├── sermon-search-results.php
├── search-query-error.php
├── play-button-shortcode.php
├── related-links.php
├── nav.php
├── sermons-list.php
├── admin-column.css
├── play-button-shortcode-modal-videos.php
├── sermon-speaker-info.php
├── series-list.php
├── play-button-shortcode-style.css
├── list-item.php
├── searchform.php
├── searchform-xhtml.php
└── list-item-style.css
├── gc-sermons.zip
├── includes
├── README.md
├── shortcodes
│ ├── shortcodes-series
│ │ ├── class-shortcode.php
│ │ ├── class-admin.php
│ │ └── class-run.php
│ ├── shortcodes-recent-series
│ │ ├── class-shortcode.php
│ │ ├── class-run.php
│ │ └── class-admin.php
│ ├── shortcodes-play-button
│ │ ├── class-shortcode.php
│ │ ├── class-admin.php
│ │ └── class-run.php
│ ├── shortcodes-sermons
│ │ ├── class-shortcode.php
│ │ ├── class-admin.php
│ │ └── class-run.php
│ ├── shortcodes-recent-speaker
│ │ ├── class-shortcode.php
│ │ ├── class-run.php
│ │ └── class-admin.php
│ ├── shortcodes-search
│ │ ├── class-shortcode.php
│ │ ├── class-sermons-search-run.php
│ │ ├── class-admin.php
│ │ ├── class-series-search-run.php
│ │ └── class-run.php
│ ├── class-shortcodes-base.php
│ ├── class-shortcodes-recent-admin-base.php
│ ├── class-shortcodes-admin-base.php
│ ├── class-shortcodes-run-base.php
│ ├── class-shortcodes.php
│ ├── shortcodes-audio-player
│ │ └── class-shortcode.php
│ ├── shortcodes-video-player
│ │ └── class-shortcode.php
│ └── shortcodes-related-links
│ │ └── class-shortcode.php
├── taxonomies
│ ├── class-topic.php
│ ├── class-tag.php
│ ├── class-scripture.php
│ ├── class-taxonomies.php
│ ├── class-series.php
│ ├── class-speaker.php
│ └── class-taxonomies-base.php
├── class-async.php
├── post-types
│ └── class-post-types-base.php
├── class-style-loader.php
├── class-template-loader.php
└── class-sermon-post.php
├── tests
├── test-pbs-run.php
├── test-base.php
├── test-taxonomies.php
├── test-shortcodes.php
├── test-play-button-shortcode.php
├── test-sermons.php
├── test-async.php
├── test-speaker.php
├── test-sermon-series.php
├── bootstrap.php
└── test-sermon-post.php
├── bower.json
├── phpunit.xml
├── .travis.yml
├── .yo-rc.json
├── package.json
├── readme.txt
├── Dockunit.json
├── assets
└── js
│ ├── gc-sermons-admin.js
│ ├── gc-sermon-videos.js
│ └── vendor
│ └── jquery.fitvids.js
├── README.md
├── .gitignore
├── composer.json
├── Gruntfile.js
├── bin
└── install-wp-tests.sh
├── CHANGELOG.md
├── gc-sermons.php
└── functions.php
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "assets/bower"
3 | }
--------------------------------------------------------------------------------
/templates/play-button-shortcode-not-found.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/gc-sermons.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jtsternberg/GC-Sermons/HEAD/gc-sermons.zip
--------------------------------------------------------------------------------
/includes/README.md:
--------------------------------------------------------------------------------
1 | # GC Sermons Includes #
2 | http://dsgnwrks.pro
3 | Copyright (c) 2016 jtsternberg
4 | Licensed under the GPLv2 license.
5 |
6 | Additional PHP functionality goes here.
7 |
--------------------------------------------------------------------------------
/tests/test-pbs-run.php:
--------------------------------------------------------------------------------
1 | assertTrue( class_exists( 'GCSS_Play_Button_Run') );
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/templates/series-search-results.php:
--------------------------------------------------------------------------------
1 |
2 |
output( 'search_notice' ); ?>
3 |
4 | output( 'results' ); ?>
5 |
6 |
--------------------------------------------------------------------------------
/templates/sermon-search-results.php:
--------------------------------------------------------------------------------
1 |
2 |
output( 'search_notice' ); ?>
3 |
4 | output( 'results' ); ?>
5 |
6 |
--------------------------------------------------------------------------------
/templates/search-query-error.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/templates/play-button-shortcode.php:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/tests/test-base.php:
--------------------------------------------------------------------------------
1 | assertTrue( class_exists( 'GC_Sermons_Plugin') );
7 | }
8 |
9 | function test_get_instance() {
10 | $this->assertTrue( gc_sermons() instanceof GC_Sermons_Plugin );
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/related-links.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
--------------------------------------------------------------------------------
/tests/test-taxonomies.php:
--------------------------------------------------------------------------------
1 | assertTrue( class_exists( 'GCS_Taxonomies') );
7 | }
8 |
9 | function test_class_access() {
10 | $this->assertTrue( gc_sermons()->taxonomies instanceof GCS_Taxonomies );
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/test-shortcodes.php:
--------------------------------------------------------------------------------
1 | assertTrue( class_exists( 'GCS_Shortcodes') );
7 | }
8 |
9 | function test_class_access() {
10 | gc_sermons()->hooks();
11 | $this->assertTrue( gc_sermons()->shortcodes instanceof GCS_Shortcodes );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gc-sermons",
3 | "description": "Manage sermons and sermon content in WordPress",
4 | "license": "GPLv2",
5 | "authors": [
6 | "jtsternberg"
7 | ],
8 | "private": true,
9 | "ignore": [
10 | "**/.*",
11 | "node_modules",
12 | "bower_components",
13 | "test",
14 | "tests"
15 | ],
16 | "dependencies": {
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 | ./tests/
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/templates/nav.php:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/tests/test-play-button-shortcode.php:
--------------------------------------------------------------------------------
1 | assertTrue( class_exists( 'GCS_Shortcodes_Play_Button') );
7 | }
8 |
9 | // function test_class_access() {
10 | // $this->assertTrue( gc_sermons()->play_button instanceof GCS_Shortcodes_Play_Button );
11 | // }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/sermons-list.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | get( 'sermons' ) as $year => $sermon ) : ?>
4 |
5 |
6 |
7 |
8 | args ); ?>
9 |
10 |
--------------------------------------------------------------------------------
/tests/test-sermons.php:
--------------------------------------------------------------------------------
1 | assertTrue( class_exists( 'GCS_Sermons') );
7 | }
8 |
9 | function test_class_access() {
10 | $this->assertTrue( gc_sermons()->sermons instanceof GCS_Sermons );
11 | }
12 |
13 | function test_cpt_exists() {
14 | $this->assertTrue( post_type_exists( 'gc-sermons' ) );
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/test-async.php:
--------------------------------------------------------------------------------
1 | assertTrue( true );
8 | }
9 |
10 | function test_class_exists() {
11 | $this->assertTrue( class_exists( 'GCS_Async') );
12 | }
13 |
14 | function test_class_access() {
15 | $this->assertTrue( gc_sermons()->async instanceof GCS_Async );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/test-speaker.php:
--------------------------------------------------------------------------------
1 | assertTrue( class_exists( 'GCS_Speaker') );
7 | }
8 |
9 | function test_class_access() {
10 | $this->assertTrue( gc_sermons()->speaker instanceof GCS_Speaker );
11 | }
12 |
13 | function test_taxonomy_exists() {
14 | $this->assertTrue( taxonomy_exists( 'gcs-speaker' ) );
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/test-sermon-series.php:
--------------------------------------------------------------------------------
1 | assertTrue( class_exists( 'GCS_Series') );
7 | }
8 |
9 | function test_class_access() {
10 | $this->assertTrue( gc_sermons()->series instanceof GCS_Series );
11 | }
12 |
13 | function test_taxonomy_exists() {
14 | $this->assertTrue( taxonomy_exists( 'gc-sermon-series' ) );
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | notifications:
4 | email:
5 | on_success: never
6 | on_failure: change
7 |
8 | php:
9 | - 5.3
10 | - 5.5
11 |
12 | env:
13 | - WP_VERSION=latest WP_MULTISITE=0
14 |
15 | matrix:
16 | include:
17 | - php: 5.3
18 | env: WP_VERSION=latest WP_MULTISITE=1
19 |
20 | before_script:
21 | - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
22 |
23 | script: phpunit
24 |
--------------------------------------------------------------------------------
/templates/admin-column.css:
--------------------------------------------------------------------------------
1 | #tax-series {
2 | width: 150px;
3 | }
4 |
5 | .sermon-series.with-image a {
6 | display: block;
7 | position: relative;
8 | text-align: center;
9 | }
10 |
11 | .sermon-series.with-image a:hover img {
12 | opacity: .05;
13 | }
14 |
15 | .sermon-series.with-image a:hover:after {
16 | content: attr(title);
17 | position: absolute;
18 | top: 0;
19 | left: 0;
20 | padding: 8px 10%;
21 | z-index: 98;
22 | width: 80%;
23 | min-height: 40px;
24 | }
25 |
--------------------------------------------------------------------------------
/templates/play-button-shortcode-modal-videos.php:
--------------------------------------------------------------------------------
1 |
2 | get( 'videos' ) as $sermon_id => $player ) : ?>
3 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-plugin-wp": {
3 | "name": "GC Sermons",
4 | "homepage": "http://dsgnwrks.pro",
5 | "description": "Manage sermons and sermon content in WordPress",
6 | "version": "0.2.1",
7 | "author": "jtsternberg",
8 | "authoremail": "justin@dsgnwrks.pro",
9 | "authorurl": "http://dsgnwrks.pro",
10 | "license": "GPLv2",
11 | "slug": "gc-sermons",
12 | "classname": "GC_Sermons",
13 | "classprefix": "GCS_",
14 | "prefix": "gc_sermons",
15 | "year": 2016
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/templates/sermon-speaker-info.php:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-series/class-shortcode.php:
--------------------------------------------------------------------------------
1 | run = new GCSS_Series_Run( $plugin->sermons, $plugin->series );
18 | $this->admin = new GCSS_Series_Admin( $this->run );
19 |
20 | parent::hooks();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/templates/series-list.php:
--------------------------------------------------------------------------------
1 |
2 | get( 'terms' ) as $year => $terms ) : ?>
3 | get( 'remove_dates' ) ) : ?>
4 |
5 |
6 |
11 |
12 |
13 | args ); ?>
14 |
15 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-recent-series/class-shortcode.php:
--------------------------------------------------------------------------------
1 | run = new GCSS_Recent_Series_Run( $plugin->sermons );
18 | $this->admin = new GCSS_Recent_Series_Admin( $this->run );
19 |
20 | parent::hooks();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gc-sermons",
3 | "title": "GC Sermons",
4 | "version": "0.2.1",
5 | "description": "Manage sermons and sermon content in WordPress",
6 | "author": {
7 | "name": "jtsternberg",
8 | "url": "http://dsgnwrks.pro"
9 | },
10 | "license": "GPLv2",
11 | "devDependencies": {
12 | "grunt": "latest",
13 | "grunt-contrib-watch": "latest",
14 | "grunt-wp-i18n": "latest",
15 | "grunt-contrib-compress": "~0.11.0",
16 | "grunt-githooks": "~0.3.1",
17 | "grunt-text-replace": "latest",
18 | "load-grunt-tasks": "latest"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-play-button/class-shortcode.php:
--------------------------------------------------------------------------------
1 | run = new GCSS_Play_Button_Run( $plugin->sermons );
19 | $this->admin = new GCSS_Play_Button_Admin( $this->run );
20 |
21 | parent::hooks();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-sermons/class-shortcode.php:
--------------------------------------------------------------------------------
1 | run = new GCSS_Sermons_Run( $plugin->sermons, $plugin->taxonomies );
18 | $this->admin = new GCSS_Sermons_Admin( $this->run, $plugin->taxonomies );
19 |
20 | parent::hooks();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-recent-speaker/class-shortcode.php:
--------------------------------------------------------------------------------
1 | run = new GCSS_Recent_Speaker_Run( $plugin->sermons );
18 | $this->admin = new GCSS_Recent_Speaker_Admin( $this->run );
19 |
20 | parent::hooks();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | run = new GCS_Shortcodes_Sermon_Search_Run( $plugin->sermons, $plugin->taxonomies );
18 | $this->admin = new GCS_Shortcodes_Sermon_Search_Admin( $this->run, $plugin->taxonomies );
19 |
20 | parent::hooks();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/tests/test-sermon-post.php:
--------------------------------------------------------------------------------
1 | assertTrue( class_exists( 'GCS_Sermon_Post') );
7 | }
8 |
9 | function test_class_access() {
10 | $sermons = gc_sermons()->sermons;
11 | $this->assertFalse( $sermons->most_recent() );
12 | $this->assertEquals( 'gc-sermons', $sermons->post_type() );
13 |
14 | // Create a post
15 | $this->factory->post->create( array(
16 | 'post_type' => $sermons->post_type(),
17 | ) );
18 |
19 | $sermons->flush = true;
20 |
21 | // And check if we found an instance
22 | $this->assertTrue( $sermons->most_recent() instanceof GCS_Sermon_Post );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/templates/play-button-shortcode-style.css:
--------------------------------------------------------------------------------
1 | .gc-sermons-play-button {
2 | padding: 1em;
3 | }
4 |
5 | .gc-sermons-play-button.icon-size-large {
6 | font-size: 2em;
7 | }
8 |
9 | .gc-sermons-play-button.icon-size-medium {
10 | font-size: 1em;
11 | }
12 |
13 | .gc-sermons-play-button.icon-size-small {
14 | font-size: .5em;
15 | }
16 |
17 | #gc-video-overlay {
18 | display: block;
19 | width: 100%;
20 | position: fixed;
21 | left: 0;
22 | top: 0;
23 | height: 100%;
24 | background: rgba(0,0,0,.62);
25 | z-index: 9999998;
26 | }
27 |
28 | .gc-sermons-modal {
29 | position: absolute;
30 | display: block;
31 | top: 50%;
32 | left: 0;
33 | width: 90%;
34 | margin-left: 5%;
35 | }
36 |
37 | .gcinvisible {
38 | visibility: hidden;
39 | }
40 |
--------------------------------------------------------------------------------
/includes/shortcodes/class-shortcodes-base.php:
--------------------------------------------------------------------------------
1 | hooks();
33 | }
34 |
35 | public function hooks() {
36 | $this->run->hooks();
37 | $this->admin->hooks();
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/templates/list-item.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | maybe_output( 'image', '', 'do_image' ); ?>
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | output( 'name' ); ?>
13 | |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | maybe_output( 'description', '', 'do_description' ); ?>
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | === GC Sermons ===
2 | Contributors: jtsternberg
3 | Donate link: http://dsgnwrks.pro
4 | Tags:
5 | Requires at least: 4.4
6 | Tested up to: 4.9.8
7 | Stable tag: 0.2.1
8 | License: GPLv2
9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html
10 |
11 |
12 | == Description ==
13 |
14 | Manage sermons and sermon content in WordPress
15 |
16 | == Installation ==
17 |
18 | = Manual Installation =
19 |
20 | 1. Upload the entire `/gc-sermons` directory to the `/wp-content/plugins/` directory.
21 | 2. Activate GC Sermons through the 'Plugins' menu in WordPress.
22 |
23 | == Frequently Asked Questions ==
24 |
25 |
26 | == Screenshots ==
27 |
28 |
29 | == Changelog ==
30 |
31 | = 0.1.0 =
32 | * First release
33 |
34 | == Upgrade Notice ==
35 |
36 | = 0.1.0 =
37 | First Release
38 |
--------------------------------------------------------------------------------
/includes/taxonomies/class-topic.php:
--------------------------------------------------------------------------------
1 | array( __( 'Topic', 'gc-sermons' ), __( 'Topics', 'gc-sermons' ), 'gcs-topic' ),
28 | 'args' => array(
29 | 'rewrite' => array( 'slug' => 'sermon-topic' ),
30 | ),
31 | ) );
32 | }
33 |
34 | /**
35 | * Initiate our hooks
36 | *
37 | * @since 0.1.0
38 | * @return void
39 | */
40 | public function hooks() {
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/includes/taxonomies/class-tag.php:
--------------------------------------------------------------------------------
1 | array( __( 'Tag', 'gc-sermons' ), __( 'Tags', 'gc-sermons' ), 'gcs-tag' ),
28 | 'args' => array(
29 | 'hierarchical' => false,
30 | 'rewrite' => array( 'slug' => 'sermon-tag' ),
31 | ),
32 | ) );
33 | }
34 |
35 | /**
36 | * Initiate our hooks
37 | *
38 | * @since 0.1.0
39 | * @return void
40 | */
41 | public function hooks() {
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-recent-speaker/class-run.php:
--------------------------------------------------------------------------------
1 | 0, // 'Blank, "recent", or "0" will play the most recent video.
24 | 'recent' => 'recent', // Options: 'recent', 'audio', 'video'
25 | 'remove_thumbnail' => false,
26 | 'thumbnail_size' => 'medium',
27 | );
28 |
29 | /**
30 | * Shortcode Output
31 | */
32 | public function shortcode() {
33 | $content = gc_get_sermon_speaker_info( $this->get_sermon(), ! $this->bool_att( 'remove_thumbnail' ) );
34 |
35 | return $content;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/Dockunit.json:
--------------------------------------------------------------------------------
1 | {
2 | "containers": [
3 | {
4 | "prettyName": "PHP 5.2 FPM WordPress 4.1",
5 | "image": "dockunit/prebuilt-images:php-mysql-phpunit-5.2-fpm",
6 | "beforeScripts": [
7 | "service mysql start",
8 | "bash bin/install-wp-tests.sh wordpress_test root '' localhost 4.1"
9 | ],
10 | "testCommand": "phpunit"
11 | },
12 | {
13 | "prettyName": "PHP 5.6 FPM WordPress 4.0",
14 | "image": "dockunit/prebuilt-images:php-mysql-phpunit-5.6-fpm",
15 | "beforeScripts": [
16 | "service mysql start",
17 | "bash bin/install-wp-tests.sh wordpress_test2 root '' localhost 4.0"
18 | ],
19 | "testCommand": "phpunit"
20 | },
21 | {
22 | "prettyName": "PHP 7.0 RC-1",
23 | "image": "dockunit/prebuilt-images:php-mysql-phpunit-7.0-rc-1-fpm",
24 | "beforeScripts": [
25 | "service mysql start",
26 | "bash bin/install-wp-tests.sh wordpress_test3 root '' localhost 3.9"
27 | ],
28 | "testCommand": "phpunit"
29 | }
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/assets/js/gc-sermons-admin.js:
--------------------------------------------------------------------------------
1 | window.GCSermonsAdmin = window.GCSermonsAdmin || {};
2 |
3 | ( function( window, document, $, app, undefined ) {
4 | 'use strict';
5 |
6 | var methodBackup = null;
7 |
8 | app.cache = function() {
9 | app.$ = {};
10 | };
11 |
12 | app.init = function() {
13 | app.cache();
14 |
15 | $( document.body )
16 | .on( 'keyup change', '.check-if-recent input[type="text"]', app.maybeToggle )
17 | .on( 'shortcode_button:open', app.showNotRecent );
18 | };
19 |
20 | app.maybeToggle = function( evt ) {
21 | var $this = $( evt.target );
22 | var value = $this.val();
23 | if ( ! value || '0' === value || 0 === value || 'recent' === value ) {
24 | $this.parents( '.cmb2-metabox' ).find( '.hide-if-not-recent' ).show();
25 | } else {
26 | $this.parents( '.cmb2-metabox' ).find( '.hide-if-not-recent' ).hide();
27 | }
28 | };
29 |
30 | app.showNotRecent = function() {
31 | $( '.scb-form-wrap .hide-if-not-recent' ).show();
32 | };
33 |
34 | $( app.init );
35 |
36 | } )( window, document, jQuery, window.GCSermonsAdmin );
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GC Sermons - BETA #
2 | **Contributors:** jtsternberg
3 | **Donate link:** http://dsgnwrks.pro
4 | **Tags:**
5 | **Requires at least:** 4.4
6 | **Tested up to:** 4.9.8
7 | **Stable tag:** 0.2.1
8 | **License:** GPLv2
9 | **License URI:** http://www.gnu.org/licenses/gpl-2.0.html
10 |
11 | ## Description ##
12 |
13 | Manage sermons and sermon content in WordPress. The [GC Staff](https://github.com/jtsternberg/GC-Staff) plugin is recommended to complement this plugin for church sites.
14 |
15 | **Please note:** you will need to run `composer install` in order to fetch the dependenceis for this plugin/library, **or** you can [download the zip here](https://github.com/jtsternberg/GC-Sermons/blob/master/gc-sermons.zip?raw=true).
16 |
17 | **Also please note:** This plugin is still in beta, and in active development, and _things may change_. If you have any questions, [let me know](http://twitter.com/jtsternberg).
18 |
19 | ### Documentation
20 |
21 | [Check out the wiki](https://github.com/jtsternberg/GC-Sermons/wiki) for usage.
22 |
--------------------------------------------------------------------------------
/includes/taxonomies/class-scripture.php:
--------------------------------------------------------------------------------
1 | array( __( 'Scripture Reference', 'gc-sermons' ), __( 'Scripture References', 'gc-sermons' ), 'gcs-scripture' ),
32 | 'args' => array(
33 | 'rewrite' => array( 'slug' => 'scripture-reference' ),
34 | ),
35 | ) );
36 | }
37 |
38 | /**
39 | * Initiate our hooks
40 | *
41 | * @since 0.1.3
42 | * @return void
43 | */
44 | public function hooks() {
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-recent-series/class-run.php:
--------------------------------------------------------------------------------
1 | 0, // 'Blank, "recent", or "0" will play the most recent video.
24 | 'recent' => 'recent', // Options: 'recent', 'audio', 'video'
25 | 'remove_thumbnail' => true,
26 | 'thumbnail_size' => 'medium',
27 |
28 | // No admin
29 | 'remove_description' => true,
30 | 'wrap_classes' => '',
31 | );
32 |
33 | /**
34 | * Shortcode Output
35 | */
36 | public function shortcode() {
37 | $args = array();
38 | foreach ( $this->atts_defaults as $key => $default_value ) {
39 | $args[ $key ] = is_bool( $this->atts_defaults[ $key ] )
40 | ? $this->bool_att( $key, $default_value )
41 | : $this->att( $key, $default_value );
42 | }
43 |
44 | $args['wrap_classes'] .= ' gc-recent-series';
45 |
46 | return gc_get_sermon_series_info( $this->get_sermon(), $args );
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/includes/class-async.php:
--------------------------------------------------------------------------------
1 | plugin = $plugin;
32 | parent::__construct();
33 | }
34 |
35 | /**
36 | * Prepare data for the asynchronous request
37 | *
38 | * @throws Exception If for any reason the request should not happen
39 | *
40 | * @param array $data An array of data sent to the hook
41 | *
42 | * @return array
43 | */
44 | protected function prepare_data( $data ) {
45 | $object_id = $data[0];
46 | $taxonomy = $data[3];
47 |
48 | if ( $this->plugin->sermons->post_type() !== get_post_type( $object_id ) ) {
49 | throw new Exception( 'We only want async tasks for sermons' );
50 | }
51 |
52 | return compact( 'object_id', 'taxonomy' );
53 | }
54 |
55 | /**
56 | * Run the async task action
57 | */
58 | protected function run_action() {
59 | if ( isset( $_POST['object_id'], $_POST['taxonomy'] ) ) {
60 | do_action( 'wp_async_set_sermon_terms', $_POST['object_id'], $_POST['taxonomy'] );
61 | }
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### OSX ###
2 | .DS_Store
3 | .AppleDouble
4 | .LSOverride
5 |
6 | # Icon must end with two \r
7 | Icon
8 |
9 |
10 | # Thumbnails
11 | ._*
12 |
13 | # Files that might appear on external disk
14 | .Spotlight-V100
15 | .Trashes
16 |
17 | # Directories potentially created on remote AFP share
18 | .AppleDB
19 | .AppleDesktop
20 | Network Trash Folder
21 | Temporary Items
22 | .apdisk
23 |
24 |
25 | ### Bower ###
26 | bower_components
27 | .bower-cache
28 | .bower-registry
29 | .bower-tmp
30 |
31 |
32 | ### Node ###
33 | # Logs
34 | logs
35 | *.log
36 |
37 | # Runtime data
38 | pids
39 | *.pid
40 | *.seed
41 |
42 | # Directory for instrumented libs generated by jscoverage/JSCover
43 | lib-cov
44 |
45 | # Coverage directory used by tools like istanbul
46 | coverage
47 |
48 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
49 | .grunt
50 |
51 | # node-waf configuration
52 | .lock-wscript
53 |
54 | # Compiled binary addons (http://nodejs.org/api/addons.html)
55 | build/Release
56 |
57 | # Dependency directory
58 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
59 | node_modules
60 |
61 |
62 | ### Composer ###
63 | composer.phar
64 | /vendor
65 |
66 |
67 | # Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
68 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
69 | # composer.lock
70 |
71 | ### Sass ###
72 | .sass-cache
73 |
74 | dandelion.yml
75 | phploy.ini
76 | .revision
--------------------------------------------------------------------------------
/includes/taxonomies/class-taxonomies.php:
--------------------------------------------------------------------------------
1 | series = new GCS_Series( $sermons );
54 | $this->speaker = new GCS_Speaker( $sermons );
55 | $this->topic = new GCS_Topic( $sermons );
56 | $this->tag = new GCS_Tag( $sermons );
57 | $this->scripture = new GCS_Scripture( $sermons );
58 | }
59 |
60 | /**
61 | * Magic getter for our object. Allows getting but not setting.
62 | *
63 | * @param string $field
64 | * @throws Exception Throws an exception if the field is invalid.
65 | * @return mixed
66 | */
67 | public function __get( $field ) {
68 | switch ( $field ) {
69 | case 'series':
70 | case 'speaker':
71 | case 'topic':
72 | case 'tag':
73 | case 'scripture':
74 | return $this->{$field};
75 | default:
76 | throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field );
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/templates/searchform.php:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/templates/searchform-xhtml.php:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/includes/shortcodes/class-shortcodes-recent-admin-base.php:
--------------------------------------------------------------------------------
1 | shortcode}", array( $this, 'enqueue_js' ) );
22 |
23 | // Do this super late.
24 | add_filter( "{$this->shortcode}_shortcode_fields", array( $this, 'maybe_remove_recent_attribute' ), 100000 );
25 | }
26 |
27 | public function enqueue_js() {
28 | wp_enqueue_script(
29 | 'gc-sermons-admin',
30 | GC_Sermons_Plugin::$url . 'assets/js/gc-sermons-admin.js',
31 | array( 'jquery' ),
32 | GC_Sermons_Plugin::VERSION,
33 | true
34 | );
35 | }
36 |
37 | /**
38 | * Removes 'recent' shortcode attribute when it isn't applicable.
39 | *
40 | * @since 0.1.3
41 | *
42 | * @param array $updated Array of shortcode attributes.
43 | *
44 | * @return array Modified array of shortcode attributes.
45 | */
46 | public function maybe_remove_recent_attribute( $updated ) {
47 |
48 | // If recent is set, but shouldn't be, let's remove it.
49 | if ( isset( $updated['recent'], $updated['sermon_id'] ) ) {
50 | if ( $updated['sermon_id'] && '0' !== $updated['sermon_id'] && 0 !== $updated['sermon_id'] && 'recent' !== $updated['sermon_id'] ) {
51 | unset( $updated['recent'] );
52 | }
53 | }
54 |
55 | return $updated;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/includes/shortcodes/class-shortcodes-admin-base.php:
--------------------------------------------------------------------------------
1 | run = $run;
34 |
35 | parent::__construct(
36 | $this->run->shortcode,
37 | GC_Sermons_Plugin::VERSION,
38 | $this->run->atts_defaults
39 | );
40 |
41 | // Do this super late.
42 | add_filter( "{$this->shortcode}_shortcode_fields", array( $this, 'maybe_remove_prefixes' ), 99999 );
43 | }
44 |
45 | /**
46 | * If the shortcode has a prefix property, we remove it from the shortcode attributes.
47 | *
48 | * @since 0.1.3
49 | *
50 | * @param array $updated Array of shortcode attributes.
51 | *
52 | * @return array Modified array of shortcode attributes.
53 | */
54 | public function maybe_remove_prefixes( $updated ) {
55 | if ( $this->prefix ) {
56 | $prefix_length = strlen( $this->prefix );
57 | $new_updated = array();
58 |
59 | foreach ( $updated as $key => $value) {
60 |
61 | if ( $this->prefix === substr( $key, 0, $prefix_length ) ) {
62 | $key = substr( $key, $prefix_length );
63 | }
64 |
65 | $new_updated[ $key ] = $value;
66 | }
67 |
68 | $updated = $new_updated;
69 | }
70 |
71 | return $updated;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/assets/js/gc-sermon-videos.js:
--------------------------------------------------------------------------------
1 | window.GCVideoModal = window.GCVideoModal || {};
2 |
3 | /**
4 | * @todo Play video when opening
5 | * @todo Test with local video
6 | * @todo Add a close icon
7 | */
8 | ( function( window, document, $, app, undefined ) {
9 | 'use strict';
10 |
11 | app.cache = function() {
12 | app.$ = {};
13 | app.$.overlay = $( document.getElementById( 'gc-video-overlay' ) );
14 | app.$.body = $( document.body );
15 | app.$.modals = $( '.gc-sermons-modal' );
16 | };
17 |
18 | app.init = function() {
19 | app.cache();
20 | if ( 'function' === typeof $.fn.prettyPhoto ) {
21 | $( '.gc-sermons-play-button' ).prettyPhoto({
22 | default_width : 1100,
23 | default_height : 619,
24 | theme : 'dark_square',
25 | });
26 |
27 | return;
28 | }
29 |
30 | $( document ).on( 'keydown', function( evt ) {
31 | var escapeKey = 27;
32 | if ( escapeKey === evt.keyCode ) {
33 | evt.preventDefault();
34 | app.closeModals();
35 | }
36 | } );
37 |
38 | app.$.body
39 | .on( 'click', '.gc-sermons-play-button', app.clickOpenModal )
40 | .on( 'click', '#gc-video-overlay', app.closeModals );
41 | };
42 |
43 | app.clickOpenModal = function( evt ) {
44 | evt.preventDefault();
45 | var sermonId = $( this ).data( 'sermonid' );
46 |
47 | app.showVideo( sermonId );
48 | };
49 |
50 | app.showVideo = function( sermonId ) {
51 | app.$.overlay.fadeIn( 'fast' );
52 |
53 | var $video = app.$.modals.filter( '#gc-sermons-video-'+ sermonId ).removeClass( 'gcinvisible' );
54 |
55 | $video.find( '.gc-sermons-video-container' ).html( $video.find( '.tmpl-videoModal' ).html() ).fitVids();
56 |
57 | $video.css({ 'margin-top' : - Math.floor( parseInt( $video.outerHeight() * 0.6 ) ) });
58 | };
59 |
60 | app.closeModals = function() {
61 | app.$.overlay.fadeOut();
62 | app.$.modals.addClass( 'gcinvisible' ).find( '.gc-sermons-video-container' ).empty();
63 | };
64 |
65 | $( app.init );
66 |
67 | } )( window, document, jQuery, window.GCVideoModal );
68 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jtsternberg/gc-sermons",
3 | "type": "wordpress-plugin",
4 | "description": "Manage sermons and sermon content in WordPress",
5 | "keywords": ["wordpress", "plugin", "generator-plugin-wp", "sermons"],
6 | "homepage": "https://github.com/jtsternberg/GC-Sermons",
7 | "license": "GPL-2.0-or-later",
8 | "authors": [
9 | {
10 | "name": "jtsternberg",
11 | "email": "justin@dsgnwrks.pro",
12 | "homepage": "http://dsgnwrks.pro",
13 | "role": "Developer"
14 | }
15 | ],
16 | "minimum-stability": "dev",
17 | "autoload": {
18 | "classmap": [
19 | "gc-sermons.php",
20 | "includes/",
21 | "vendor/webdevstudios/cpt-core/CPT_Core.php",
22 | "vendor/webdevstudios/taxonomy_core/Taxonomy_Core.php"
23 | ],
24 | "files": [
25 | "vendor/webdevstudios/cmb2-user-select/cmb2-user-select.php",
26 | "vendor/webdevstudios/cmb2-post-search-field/cmb2_post_search_field.php",
27 | "vendor/jtsternberg/cmb2-related-links/cmb2-related-links.php",
28 | "vendor/jtsternberg/cmb2-term-select/cmb2-term-select.php",
29 | "vendor/webdevstudios/wds-shortcodes/wds-shortcodes.php",
30 | "vendor/tgmpa/tgm-plugin-activation/class-tgm-plugin-activation.php"
31 | ]
32 | },
33 | "require": {
34 | "php": ">=5.2",
35 | "xrstf/composer-php52": "1.*",
36 | "techcrunch/wp-async-task": "dev-master",
37 | "tgmpa/tgm-plugin-activation": "^2.5.2",
38 | "webdevstudios/cpt-core": "dev-master",
39 | "webdevstudios/taxonomy_core": "^0.2.4",
40 | "webdevstudios/cmb2-post-search-field": "^v0.2.5",
41 | "jtsternberg/cmb2-related-links": "^v0.1.1",
42 | "jtsternberg/cmb2-term-select": "^v0.1.0",
43 | "webdevstudios/wds-shortcodes": "^v1.0.7",
44 | "webdevstudios/cmb2-user-select": "^v0.2.0"
45 | },
46 | "scripts": {
47 | "post-install-cmd": [
48 | "xrstf\\Composer52\\Generator::onPostInstallCmd"
49 | ],
50 | "post-update-cmd": [
51 | "xrstf\\Composer52\\Generator::onPostInstallCmd"
52 | ],
53 | "post-autoload-dump": [
54 | "xrstf\\Composer52\\Generator::onPostInstallCmd"
55 | ]
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/includes/taxonomies/class-series.php:
--------------------------------------------------------------------------------
1 | 'medium',
33 | );
34 |
35 | /**
36 | * Constructor
37 | * Register Taxonomy. See documentation in Taxonomy_Core, and in wp-includes/taxonomy.php
38 | *
39 | * @since 0.1.0
40 | * @param object $sermons GCS_Sermons object.
41 | * @return void
42 | */
43 | public function __construct( $sermons ) {
44 | parent::__construct( $sermons, array(
45 | 'labels' => array( __( 'Sermon Series', 'gc-sermons' ), __( 'Sermon Series', 'gc-sermons' ), 'gc-sermon-series' ),
46 | 'args' => array(
47 | 'hierarchical' => false,
48 | 'show_admin_column' => false,
49 | 'rewrite' => array( 'slug' => 'sermon-series' ),
50 | ),
51 | ) );
52 | }
53 |
54 | /**
55 | * Initiate our hooks
56 | *
57 | * @since 0.1.0
58 | * @return void
59 | */
60 | public function hooks() {
61 | add_action( 'cmb2_admin_init', array( $this, 'fields' ) );
62 | }
63 |
64 | /**
65 | * Add custom fields to the CPT
66 | *
67 | * @since 0.1.0
68 | * @return void
69 | */
70 | public function fields() {
71 | $cmb = $this->new_cmb2( array(
72 | 'id' => 'gc_sermon_series_metabox',
73 | 'taxonomies' => array( $this->taxonomy() ),
74 | 'object_types' => array( 'term' ),
75 | 'fields' => array(
76 | $this->image_meta_key => array(
77 | 'name' => __( 'Sermon Series Image', 'gc-sermons' ),
78 | 'desc' => __( 'Select the series\' branding image', 'gc-sermons' ),
79 | 'id' => $this->image_meta_key,
80 | 'type' => 'file'
81 | ),
82 | ),
83 | ) );
84 |
85 | $this->add_image_column( __( 'Series Image', 'gc-sermons' ) );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/includes/shortcodes/class-shortcodes-run-base.php:
--------------------------------------------------------------------------------
1 | sermons = $sermons;
27 | parent::__construct();
28 | }
29 |
30 | protected function get_sermon() {
31 | $sermon_id = $this->att( 'sermon_id' );
32 |
33 | if ( ! $sermon_id || 'recent' === $sermon_id || '0' === $sermon_id || 0 === $sermon_id ) {
34 |
35 | $this->shortcode_object->set_att( 'sermon', $this->most_recent_sermon() );
36 |
37 | } elseif ( 'this' === $sermon_id ) {
38 |
39 | $this->shortcode_object->set_att( 'sermon', gc_get_sermon_post( get_queried_object_id() ) );
40 |
41 | } elseif ( is_numeric( $sermon_id ) ) {
42 |
43 | $this->shortcode_object->set_att( 'sermon', gc_get_sermon_post( $sermon_id ) );
44 |
45 | }
46 |
47 | return $this->att( 'sermon' );
48 | }
49 |
50 | protected function most_recent_sermon() {
51 | switch ( $this->att( 'recent', 'recent' ) ) {
52 | case 'audio':
53 | return $this->sermons->most_recent_with_audio();
54 |
55 | case 'video':
56 | return $this->sermons->most_recent_with_video();
57 | }
58 |
59 | return $this->sermons->most_recent();
60 | }
61 |
62 | public function get_inline_styles() {
63 | $style = '';
64 | $has_icon_font_size = false;
65 |
66 | if ( $this->att( 'icon_color' ) || $this->att( 'icon_size' ) ) {
67 | $style = ' style="';
68 | // Get/check our text_color attribute
69 | if ( $this->att( 'icon_color' ) ) {
70 | $text_color = sanitize_text_field( $this->att( 'icon_color' ) );
71 | $style .= 'color: ' . $text_color .';';
72 | }
73 | if ( is_numeric( $this->att( 'icon_size' ) ) ) {
74 | $has_icon_font_size = absint( $this->att( 'icon_size' ) );
75 | $style .= 'font-size: ' . $has_icon_font_size .'em;';
76 | }
77 | $style .= '"';
78 | }
79 |
80 | return array( $style, $has_icon_font_size );
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-play-button/class-admin.php:
--------------------------------------------------------------------------------
1 | __( 'GC Sermon Play', 'gc-sermons' ),
26 | 'button_tooltip' => __( 'GC Sermon Play Button', 'gc-sermons' ),
27 | 'icon' => 'dashicons-controls-play',
28 | 'mceView' => true, // The future
29 | );
30 | }
31 |
32 | /**
33 | * Adds fields to the button modal using CMB2
34 | *
35 | * @param $fields
36 | * @param $button_data
37 | *
38 | * @return array
39 | */
40 | function fields( $fields, $button_data ) {
41 | $fields[] = array(
42 | 'name' => __( 'Sermon to play', 'gc-sermons' ),
43 | 'desc' => __( 'Blank, "recent", or "0" will play the most recent video. Otherwise enter a post ID. Click the magnifying glass to search for a Sermon post.', 'gc-sermons' ),
44 | 'id' => $this->prefix . 'sermon_id',
45 | 'type' => 'post_search_text',
46 | 'post_type' => $this->run->sermons->post_type(),
47 | 'select_type' => 'radio',
48 | 'select_behavior' => 'replace',
49 | );
50 |
51 | $fields[] = array(
52 | 'name' => __( 'Icon Color', 'gc-sermons' ),
53 | 'type' => 'colorpicker',
54 | 'id' => $this->prefix . 'icon_color',
55 | 'default' => $this->atts_defaults['icon_color'],
56 | );
57 |
58 | $fields[] = array(
59 | 'name' => __( 'Icon Size', 'gc-sermons' ),
60 | 'desc' => __( 'Select a font-size (in ems, or enter either "medium", "large", or "small".', 'gc-sermons' ),
61 | 'type' => 'text',
62 | 'id' => $this->prefix . 'icon_size',
63 | 'default' => $this->atts_defaults['icon_size'],
64 | );
65 |
66 | $fields[] = array(
67 | 'name' => __( 'Extra CSS Classes', 'gc-sermons' ),
68 | 'desc' => __( 'Enter classes separated by spaces (e.g. "class1 class2")', 'gc-sermons' ),
69 | 'type' => 'text',
70 | 'id' => $this->prefix . 'icon_class',
71 | 'default' => $this->atts_defaults['icon_class'],
72 | );
73 |
74 | return $fields;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-recent-speaker/class-admin.php:
--------------------------------------------------------------------------------
1 | __( 'GC Recent Speaker', 'gc-sermons' ),
26 | 'button_tooltip' => __( 'GC Recent Speaker', 'gc-sermons' ),
27 | 'icon' => 'dashicons-businessman',
28 | // 'mceView' => true, // The future
29 | );
30 | }
31 |
32 | /**
33 | * Adds fields to the button modal using CMB2
34 | *
35 | * @param $fields
36 | * @param $button_data
37 | *
38 | * @return array
39 | */
40 | function fields( $fields, $button_data ) {
41 |
42 | $fields[] = array(
43 | 'name' => __( 'Sermon ID', 'gc-sermons' ),
44 | 'desc' => __( 'Blank, "recent", or "0" will get the most recent sermon\'s speaker info. Otherwise enter a post ID. Click the magnifying glass to search for a Sermon post.', 'gc-sermons' ),
45 | 'id' => $this->prefix . 'sermon_id',
46 | 'type' => 'post_search_text',
47 | 'post_type' => $this->run->sermons->post_type(),
48 | 'select_type' => 'radio',
49 | 'select_behavior' => 'replace',
50 | 'row_classes' => 'check-if-recent',
51 | );
52 |
53 | $fields[] = array(
54 | 'name' => __( 'Filter Most Recent Sermon By:', 'gc-sermons' ),
55 | 'desc' => __( 'If setting "Sermon ID" above to blank, "recent", or "0", this setting determines which type of most recent sermon to get the speaker info for.', 'gc-sermons' ),
56 | 'type' => 'select',
57 | 'id' => $this->prefix . 'recent',
58 | 'default' => $this->atts_defaults['recent'],
59 | 'row_classes' => 'hide-if-not-recent',
60 | 'options' => array(
61 | 'recent' => __( 'Most Recent', 'gc-sermons' ),
62 | 'audio' => __( 'Most Recent with Audio', 'gc-sermons' ),
63 | 'video' => __( 'Most Recent with Video', 'gc-sermons' ),
64 | ),
65 | );
66 |
67 | $fields[] = array(
68 | 'name' => __( 'Remove Thumbnail', 'gc-sermons' ),
69 | 'type' => 'checkbox',
70 | 'id' => $this->prefix . 'remove_thumbnail',
71 | 'default' => false,
72 | );
73 |
74 | $fields[] = array(
75 | 'name' => __( 'Thumbnail Size (if included)', 'gc-sermons' ),
76 | 'type' => 'text',
77 | 'id' => $this->prefix . 'thumbnail_size',
78 | 'default' => $this->atts_defaults['thumbnail_size'],
79 | );
80 |
81 |
82 | return $fields;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/includes/shortcodes/class-shortcodes.php:
--------------------------------------------------------------------------------
1 | play_button = new GCS_Shortcodes_Play_Button( $plugin );
83 | $this->sermons = new GCS_Shortcodes_Sermons( $plugin );
84 | $this->recent_series = new GCS_Shortcodes_Recent_Series( $plugin );
85 | $this->recent_speaker = new GCS_Shortcodes_Recent_Speaker( $plugin );
86 | $this->series = new GCS_Shortcodes_Series( $plugin );
87 | $this->related_links = new GCS_Shortcodes_Related_Links( $plugin );
88 | $this->video_player = new GCS_Shortcodes_Video_Player( $plugin );
89 | $this->audio_player = new GCS_Shortcodes_Audio_Player( $plugin );
90 | $this->search = new GCS_Shortcodes_Sermon_Search( $plugin );
91 | }
92 |
93 | /**
94 | * Magic getter for our object. Allows getting but not setting.
95 | *
96 | * @param string $field
97 | * @throws Exception Throws an exception if the field is invalid.
98 | * @return mixed
99 | */
100 | public function __get( $field ) {
101 | return $this->{$field};
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-recent-series/class-admin.php:
--------------------------------------------------------------------------------
1 | __( 'GC Recent Series', 'gc-sermons' ),
26 | 'button_tooltip' => __( 'GC Recent Series', 'gc-sermons' ),
27 | 'icon' => 'dashicons-images-alt',
28 | // 'mceView' => true, // The future
29 | );
30 | }
31 |
32 | /**
33 | * Adds fields to the button modal using CMB2
34 | *
35 | * @param $fields
36 | * @param $button_data
37 | *
38 | * @return array
39 | */
40 | function fields( $fields, $button_data ) {
41 |
42 | $fields[] = array(
43 | 'name' => __( 'Sermon ID', 'gc-sermons' ),
44 | 'desc' => __( 'Blank, "recent", or "0" will get the most recent sermon\'s series info. Otherwise enter a post ID. Click the magnifying glass to search for a Sermon post.', 'gc-sermons' ),
45 | 'id' => $this->prefix . 'sermon_id',
46 | 'type' => 'post_search_text',
47 | 'post_type' => $this->run->sermons->post_type(),
48 | 'select_type' => 'radio',
49 | 'select_behavior' => 'replace',
50 | 'row_classes' => 'check-if-recent',
51 | );
52 |
53 | $fields[] = array(
54 | 'name' => __( 'Filter Most Recent Sermon By:', 'gc-sermons' ),
55 | 'desc' => __( 'If setting "Sermon ID" above to blank, "recent", or "0", this setting determines which type of most recent sermon to get the series info for.', 'gc-sermons' ),
56 | 'type' => 'select',
57 | 'id' => $this->prefix . 'recent',
58 | 'default' => $this->atts_defaults['recent'],
59 | 'row_classes' => 'hide-if-not-recent',
60 | 'options' => array(
61 | 'recent' => __( 'Most Recent', 'gc-sermons' ),
62 | 'audio' => __( 'Most Recent with Audio', 'gc-sermons' ),
63 | 'video' => __( 'Most Recent with Video', 'gc-sermons' ),
64 | ),
65 | );
66 |
67 | $fields[] = array(
68 | 'name' => __( 'Remove Thumbnail', 'gc-sermons' ),
69 | 'type' => 'checkbox',
70 | 'id' => $this->prefix . 'remove_thumbnail',
71 | 'default' => false,
72 | );
73 |
74 | $fields[] = array(
75 | 'name' => __( 'Thumbnail Size (if included)', 'gc-sermons' ),
76 | 'type' => 'text',
77 | 'id' => $this->prefix . 'thumbnail_size',
78 | 'default' => $this->atts_defaults['thumbnail_size'],
79 | );
80 |
81 | return $fields;
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-search/class-sermons-search-run.php:
--------------------------------------------------------------------------------
1 | search_query = $search_query;
49 | $this->current_page = absint( gc__get_arg( 'results-page', 1 ) );
50 |
51 | parent::__construct( $sermons, $taxonomies );
52 | }
53 |
54 | public function get_search_results( $atts = array(), $content = '' ) {
55 | add_filter( 'gcs_get_sermons_args', array( $this, 'filter_sermon_args' ) );
56 |
57 | $this->results = parent::shortcode_callback( $atts, $content );
58 |
59 | remove_filter( 'gcs_get_sermons_args', array( $this, 'filter_sermon_args' ) );
60 |
61 | return $this->results;
62 | }
63 |
64 | public function filter_sermon_args( $args ) {
65 | $args['s'] = sanitize_text_field( $this->search_query );
66 | return $args;
67 | }
68 |
69 | /**
70 | * Make this method applicable.
71 | *
72 | * @since [since]
73 | *
74 | * @return [type] [description]
75 | */
76 | public function get_initial_query_args() {
77 | $posts_per_page = (int) $this->att( 'per_page', get_option( 'posts_per_page' ) );
78 | $paged = $this->current_page;
79 | $offset = ( ( $paged - 1 ) * $posts_per_page ) + $this->att( 'list_offset', 0 );
80 |
81 | return compact( 'posts_per_page', 'paged', 'offset' );
82 | }
83 |
84 | protected function get_pagination( $total_pages ) {
85 | $this->total_pages = $total_pages;
86 | $nav = array( 'prev_link' => '', 'next_link' => '' );
87 |
88 | if ( ! $this->bool_att( 'remove_pagination' ) ) {
89 | $nav['prev_link'] = gc_search_get_previous_results_link();
90 | $nav['next_link'] = gc_search_get_next_results_link( $total_pages );
91 | }
92 |
93 | return $nav;
94 | }
95 |
96 | protected function get_wrap_classes() {
97 | return parent::get_wrap_classes() . ' gc-sermons-search-wrap';
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-audio-player/class-shortcode.php:
--------------------------------------------------------------------------------
1 | run = new GCS_Shortcodes_Audio_Player_Run( $plugin->sermons );
18 | $this->admin = new GCS_Shortcodes_Audio_Player_Admin( $this->run );
19 |
20 | parent::hooks();
21 | }
22 |
23 | }
24 |
25 | /**
26 | * GC Sermons Audio Player Shortcode
27 | *
28 | * @version 0.1.3
29 | * @package GC Sermons
30 | */
31 | class GCS_Shortcodes_Audio_Player_Run extends GCS_Shortcodes_Run_Base {
32 |
33 | /**
34 | * The Shortcode Tag
35 | * @var string
36 | * @since 0.1.0
37 | */
38 | public $shortcode = 'gc_audio_player';
39 |
40 | /**
41 | * Default attributes applied to the shortcode.
42 | * @var array
43 | * @since 0.1.0
44 | */
45 | public $atts_defaults = array(
46 | 'sermon_id' => 0, // 'Blank, "recent", or "0" will play the most recent audio.
47 | );
48 |
49 | /**
50 | * Shortcode Output
51 | */
52 | public function shortcode() {
53 | return gc_get_sermon_audio_player( $this->get_sermon() );
54 | }
55 |
56 | }
57 |
58 |
59 | /**
60 | * GC Sermons Audio Player Shortcode - Admin
61 | * @version 0.1.3
62 | * @package GC Sermons
63 | */
64 | class GCS_Shortcodes_Audio_Player_Admin extends GCSS_Recent_Admin_Base {
65 |
66 | /**
67 | * Shortcode prefix for field ids.
68 | *
69 | * @var string
70 | * @since 0.1.3
71 | */
72 | protected $prefix = 'gc_audplayer_';
73 |
74 | /**
75 | * Sets up the button
76 | *
77 | * @return array
78 | */
79 | function js_button_data() {
80 | return array(
81 | 'qt_button_text' => __( 'GC Sermon Audio Player', 'gc-sermons' ),
82 | 'button_tooltip' => __( 'GC Sermon Audio Player', 'gc-sermons' ),
83 | 'icon' => 'dashicons-format-audio',
84 | // 'mceView' => true, // The future
85 | );
86 | }
87 |
88 | /**
89 | * Adds fields to the button modal using CMB2
90 | *
91 | * @param $fields
92 | * @param $button_data
93 | *
94 | * @return array
95 | */
96 | function fields( $fields, $button_data ) {
97 |
98 | $fields[] = array(
99 | 'name' => __( 'Sermon ID', 'gc-sermons' ),
100 | 'desc' => __( 'Blank, "recent", or "0" will get the most recent sermon\'s audio player. Otherwise enter a post ID. Click the magnifying glass to search for a Sermon post.', 'gc-sermons' ),
101 | 'id' => $this->prefix . 'sermon_id',
102 | 'type' => 'post_search_text',
103 | 'post_type' => $this->run->sermons->post_type(),
104 | 'select_type' => 'radio',
105 | 'select_behavior' => 'replace',
106 | 'row_classes' => 'check-if-recent',
107 | );
108 |
109 | return $fields;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-video-player/class-shortcode.php:
--------------------------------------------------------------------------------
1 | run = new GCS_Shortcodes_Video_Player_Run( $plugin->sermons );
19 | $this->admin = new GCS_Shortcodes_Video_Player_Admin( $this->run );
20 |
21 | parent::hooks();
22 | }
23 |
24 | }
25 |
26 | /**
27 | * GC Sermons Video Player Shortcode
28 | *
29 | * @version 0.1.3
30 | * @package GC Sermons
31 | */
32 | class GCS_Shortcodes_Video_Player_Run extends GCS_Shortcodes_Run_Base {
33 |
34 | /**
35 | * The Shortcode Tag
36 | * @var string
37 | * @since 0.1.0
38 | */
39 | public $shortcode = 'gc_video_player';
40 |
41 | /**
42 | * Default attributes applied to the shortcode.
43 | * @var array
44 | * @since 0.1.0
45 | */
46 | public $atts_defaults = array(
47 | 'sermon_id' => 0, // 'Blank, "recent", or "0" will play the most recent video.
48 | );
49 |
50 | /**
51 | * Shortcode Output
52 | */
53 | public function shortcode() {
54 | return gc_get_sermon_video_player( $this->get_sermon() );
55 | }
56 |
57 | }
58 |
59 | /**
60 | * GC Sermons Video Player Shortcode - Admin
61 | * @version 0.1.3
62 | * @package GC Sermons
63 | */
64 | class GCS_Shortcodes_Video_Player_Admin extends GCSS_Recent_Admin_Base {
65 |
66 | /**
67 | * Shortcode prefix for field ids.
68 | *
69 | * @var string
70 | * @since 0.1.3
71 | */
72 | protected $prefix = 'gc_vidplayer_';
73 |
74 | /**
75 | * Sets up the button
76 | *
77 | * @return array
78 | */
79 | function js_button_data() {
80 | return array(
81 | 'qt_button_text' => __( 'GC Sermon Video Player', 'gc-sermons' ),
82 | 'button_tooltip' => __( 'GC Sermon Video Player', 'gc-sermons' ),
83 | 'icon' => 'dashicons-format-video',
84 | // 'mceView' => true, // The future
85 | );
86 | }
87 |
88 | /**
89 | * Adds fields to the button modal using CMB2
90 | *
91 | * @param $fields
92 | * @param $button_data
93 | *
94 | * @return array
95 | */
96 | function fields( $fields, $button_data ) {
97 |
98 | $fields[] = array(
99 | 'name' => __( 'Sermon ID', 'gc-sermons' ),
100 | 'desc' => __( 'Blank, "recent", or "0" will get the most recent sermon\'s video player. Otherwise enter a post ID. Click the magnifying glass to search for a Sermon post.', 'gc-sermons' ),
101 | 'id' => $this->prefix . 'sermon_id',
102 | 'type' => 'post_search_text',
103 | 'post_type' => $this->run->sermons->post_type(),
104 | 'select_type' => 'radio',
105 | 'select_behavior' => 'replace',
106 | 'row_classes' => 'check-if-recent',
107 | );
108 |
109 | return $fields;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/includes/post-types/class-post-types-base.php:
--------------------------------------------------------------------------------
1 | plugin = $plugin;
37 |
38 | // Register this cpt
39 | // First parameter should be an array with Singular, Plural, and Registered name.
40 | parent::__construct(
41 | $args['labels'],
42 | $args['args']
43 | );
44 |
45 | $this->hooks();
46 | add_action( 'plugins_loaded', array( $this, 'filter_values' ), 4 );
47 | }
48 |
49 | public function filter_values() {
50 | if ( $this->overrides_processed ) {
51 | return;
52 | }
53 |
54 | $args = array(
55 | 'singular' => $this->singular,
56 | 'plural' => $this->plural,
57 | 'post_type' => $this->post_type,
58 | 'arg_overrides' => $this->arg_overrides,
59 | );
60 |
61 | $filtered_args = apply_filters( 'gcs_post_types_'. $this->id, $args, $this );
62 |
63 | if ( $filtered_args !== $args ) {
64 | foreach ( $args as $arg => $val ) {
65 | if ( isset( $filtered_args[ $arg ] ) ) {
66 | $this->{$arg} = $filtered_args[ $arg ];
67 | }
68 | }
69 | }
70 |
71 | $this->overrides_processed = true;
72 | }
73 |
74 | /**
75 | * Provides access to protected class properties.
76 | * @since 0.2.0
77 | * @param boolean $key Specific CPT parameter to return
78 | * @return mixed Specific CPT parameter or array of singular, plural and registered name
79 | */
80 | public function post_type( $key = 'post_type' ) {
81 | if ( ! $this->overrides_processed ) {
82 | $this->filter_values();
83 | }
84 |
85 | return parent::post_type( $key );
86 | }
87 |
88 | /**
89 | * Initiate our hooks
90 | *
91 | * @since 0.1.0
92 | * @return void
93 | */
94 | abstract function hooks();
95 |
96 | /**
97 | * Wrapper for new_cmb2_box
98 | *
99 | * @since 0.1.1
100 | *
101 | * @param array $args Array of CMB2 args
102 | *
103 | * @return CMB2
104 | */
105 | public function new_cmb2( $args ) {
106 | $cmb_id = $args['id'];
107 | return new_cmb2_box( apply_filters( "gcs_cmb2_box_args_{$this->id}_{$cmb_id}", $args ) );
108 | }
109 |
110 | /**
111 | * Magic getter for our object. Allows getting but not setting.
112 | *
113 | * @param string $field
114 | * @throws Exception Throws an exception if the field is invalid.
115 | * @return mixed
116 | */
117 | public function __get( $field ) {
118 | switch ( $field ) {
119 | case 'id':
120 | case 'arg_overrides':
121 | case 'cpt_args':
122 | return $this->{$field};
123 | default:
124 | throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field );
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-series/class-admin.php:
--------------------------------------------------------------------------------
1 | __( 'GC Series', 'gc-sermons' ),
26 | 'button_tooltip' => __( 'GC Series', 'gc-sermons' ),
27 | 'icon' => 'dashicons-images-alt',
28 | // 'mceView' => true, // The future
29 | );
30 | }
31 |
32 | /**
33 | * Adds fields to the button modal using CMB2
34 | *
35 | * @param $fields
36 | * @param $button_data
37 | *
38 | * @return array
39 | */
40 | function fields( $fields, $button_data ) {
41 |
42 | $fields[] = array(
43 | 'name' => __( 'Number of Series to Show Per-Page', 'gc-sermons' ),
44 | 'type' => 'text_small',
45 | 'id' => $this->prefix . 'per_page',
46 | 'default' => get_option( 'posts_per_page', $this->atts_defaults['per_page'] ),
47 | );
48 |
49 | $fields[] = array(
50 | 'name' => __( 'Remove Year Date Separators', 'gc-sermons' ),
51 | 'type' => 'checkbox',
52 | 'id' => $this->prefix . 'remove_dates',
53 | 'default' => false,
54 | );
55 |
56 | $fields[] = array(
57 | 'name' => __( 'Remove Pagination', 'gc-sermons' ),
58 | 'type' => 'checkbox',
59 | 'id' => $this->prefix . 'remove_pagination',
60 | 'default' => false,
61 | );
62 |
63 | $fields[] = array(
64 | 'name' => __( 'Remove Thumbnail', 'gc-sermons' ),
65 | 'type' => 'checkbox',
66 | 'id' => $this->prefix . 'remove_thumbnail',
67 | 'default' => false,
68 | );
69 |
70 | $fields[] = array(
71 | 'name' => __( 'Thumbnail Size (if included)', 'gc-sermons' ),
72 | 'type' => 'text',
73 | 'id' => $this->prefix . 'thumbnail_size',
74 | 'default' => $this->atts_defaults['thumbnail_size'],
75 | );
76 |
77 | $fields[] = array(
78 | 'name' => __( 'Max number of columns', 'gc-sermons' ),
79 | 'desc' => __( 'Will vary on device screen width', 'gc-sermons' ),
80 | 'type' => 'radio_inline',
81 | 'options' => array( 1 => 1, 2 => 2, 3 => 3, 4 => 4 ),
82 | 'id' => $this->prefix . 'number_columns',
83 | 'default' => $this->atts_defaults['number_columns'],
84 | );
85 |
86 | $fields[] = array(
87 | 'name' => __( 'Offset', 'gc-sermons' ),
88 | 'desc' => __( 'Changes which series starts the list', 'gc-sermons' ),
89 | 'type' => 'text_small',
90 | 'id' => $this->prefix . 'list_offset',
91 | 'sanitization_cb' => 'absint',
92 | 'default' => $this->atts_defaults['list_offset'],
93 | );
94 |
95 | $fields[] = array(
96 | 'name' => __( 'Extra Wrap CSS Classes', 'gc-sermons' ),
97 | 'desc' => __( 'Enter classes separated by spaces (e.g. "class1 class2")', 'gc-sermons' ),
98 | 'type' => 'text',
99 | 'id' => $this->prefix . 'wrap_classes',
100 | 'default' => $this->atts_defaults['wrap_classes'],
101 | );
102 |
103 | return $fields;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/assets/js/vendor/jquery.fitvids.js:
--------------------------------------------------------------------------------
1 | /*jshint browser:true */
2 | /*!
3 | * FitVids 1.1
4 | *
5 | * Copyright 2013, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com
6 | * Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/
7 | * Released under the WTFPL license - http://sam.zoy.org/wtfpl/
8 | *
9 | */
10 |
11 | ;(function( $ ){
12 |
13 | 'use strict';
14 |
15 | $.fn.fitVids = function( options ) {
16 | var settings = {
17 | customSelector: null,
18 | ignore: null
19 | };
20 |
21 | if(!document.getElementById('fit-vids-style')) {
22 | // appendStyles: https://github.com/toddmotto/fluidvids/blob/master/dist/fluidvids.js
23 | var head = document.head || document.getElementsByTagName('head')[0];
24 | var css = '.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}';
25 | var div = document.createElement("div");
26 | div.innerHTML = 'x
';
27 | head.appendChild(div.childNodes[1]);
28 | }
29 |
30 | if ( options ) {
31 | $.extend( settings, options );
32 | }
33 |
34 | return this.each(function(){
35 | var selectors = [
36 | 'iframe[src*="player.vimeo.com"]',
37 | 'iframe[src*="youtube.com"]',
38 | 'iframe[src*="youtube-nocookie.com"]',
39 | 'iframe[src*="kickstarter.com"][src*="video.html"]',
40 | 'object',
41 | 'embed'
42 | ];
43 |
44 | if (settings.customSelector) {
45 | selectors.push(settings.customSelector);
46 | }
47 |
48 | var ignoreList = '.fitvidsignore';
49 |
50 | if(settings.ignore) {
51 | ignoreList = ignoreList + ', ' + settings.ignore;
52 | }
53 |
54 | var $allVideos = $(this).find(selectors.join(','));
55 | $allVideos = $allVideos.not('object object'); // SwfObj conflict patch
56 | $allVideos = $allVideos.not(ignoreList); // Disable FitVids on this video.
57 |
58 | $allVideos.each(function(){
59 | var $this = $(this);
60 | if($this.parents(ignoreList).length > 0) {
61 | return; // Disable FitVids on this video.
62 | }
63 | if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; }
64 | if ((!$this.css('height') && !$this.css('width')) && (isNaN($this.attr('height')) || isNaN($this.attr('width'))))
65 | {
66 | $this.attr('height', 9);
67 | $this.attr('width', 16);
68 | }
69 | var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(),
70 | width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(),
71 | aspectRatio = height / width;
72 | if(!$this.attr('name')){
73 | var videoName = 'fitvid' + $.fn.fitVids._count;
74 | $this.attr('name', videoName);
75 | $.fn.fitVids._count++;
76 | }
77 | $this.wrap('').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+'%');
78 | $this.removeAttr('height').removeAttr('width');
79 | });
80 | });
81 | };
82 |
83 | // Internal counter for unique video names.
84 | $.fn.fitVids._count = 0;
85 |
86 | // Works with either jQuery or Zepto
87 | })( window.jQuery || window.Zepto );
88 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-related-links/class-shortcode.php:
--------------------------------------------------------------------------------
1 | run = new GCSS_Related_Links_Run( $plugin->sermons );
18 | $this->admin = new GCSS_Related_Links_Admin( $this->run );
19 |
20 | parent::hooks();
21 | }
22 |
23 | }
24 |
25 | /**
26 | * GC Sermons Related Links Shortcode
27 | *
28 | * @version 0.1.3
29 | * @package GC Sermons
30 | */
31 | class GCSS_Related_Links_Run extends GCS_Shortcodes_Run_Base {
32 |
33 | /**
34 | * The Shortcode Tag
35 | * @var string
36 | * @since 0.1.0
37 | */
38 | public $shortcode = 'gc_related_links';
39 |
40 | /**
41 | * Default attributes applied to the shortcode.
42 | * @var array
43 | * @since 0.1.0
44 | */
45 | public $atts_defaults = array(
46 | 'sermon_id' => 0, // 'Blank, "recent", or "0" will play the most recent video.
47 | 'recent' => 'recent', // Options: 'recent', 'audio', 'video'
48 | );
49 |
50 | /**
51 | * Shortcode Output
52 | */
53 | public function shortcode() {
54 | return gc_get_sermon_related_links( $this->get_sermon() );
55 | }
56 |
57 | }
58 |
59 | /**
60 | * GC Sermons Related Links Shortcode - Admin
61 | * @version 0.1.3
62 | * @package GC Sermons
63 | */
64 | class GCSS_Related_Links_Admin extends GCSS_Recent_Admin_Base {
65 |
66 | /**
67 | * Shortcode prefix for field ids.
68 | *
69 | * @var string
70 | * @since 0.1.3
71 | */
72 | protected $prefix = 're_links_';
73 |
74 | /**
75 | * Sets up the button
76 | *
77 | * @return array
78 | */
79 | function js_button_data() {
80 | return array(
81 | 'qt_button_text' => __( 'GC Sermon Links', 'gc-sermons' ),
82 | 'button_tooltip' => __( 'GC Sermon Related Links', 'gc-sermons' ),
83 | 'icon' => 'dashicons-admin-links',
84 | // 'mceView' => true, // The future
85 | );
86 | }
87 |
88 | /**
89 | * Adds fields to the button modal using CMB2
90 | *
91 | * @param $fields
92 | * @param $button_data
93 | *
94 | * @return array
95 | */
96 | function fields( $fields, $button_data ) {
97 |
98 | $fields[] = array(
99 | 'name' => __( 'Sermon ID', 'gc-sermons' ),
100 | 'desc' => __( 'Blank, "recent", or "0" will get the most recent sermon\'s speaker info. Otherwise enter a post ID. Click the magnifying glass to search for a Sermon post.', 'gc-sermons' ),
101 | 'id' => $this->prefix . 'sermon_id',
102 | 'type' => 'post_search_text',
103 | 'post_type' => $this->run->sermons->post_type(),
104 | 'select_type' => 'radio',
105 | 'select_behavior' => 'replace',
106 | 'row_classes' => 'check-if-recent',
107 | );
108 |
109 | $fields[] = array(
110 | 'name' => __( 'Filter Most Recent Sermon By:', 'gc-sermons' ),
111 | 'desc' => __( 'If setting "Sermon ID" above to blank, "recent", or "0", this setting determines which type of most recent sermon to get the related links info for.', 'gc-sermons' ),
112 | 'type' => 'select',
113 | 'id' => $this->prefix . 'recent',
114 | 'default' => $this->atts_defaults['recent'],
115 | 'row_classes' => 'hide-if-not-recent',
116 | 'options' => array(
117 | 'recent' => __( 'Most Recent', 'gc-sermons' ),
118 | 'audio' => __( 'Most Recent with Audio', 'gc-sermons' ),
119 | 'video' => __( 'Most Recent with Video', 'gc-sermons' ),
120 | ),
121 | );
122 |
123 | return $fields;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-search/class-admin.php:
--------------------------------------------------------------------------------
1 | taxonomies = $taxonomies;
34 | parent::__construct( $run );
35 | }
36 |
37 | /**
38 | * Sets up the button
39 | *
40 | * @return array
41 | */
42 | function js_button_data() {
43 | return array(
44 | 'qt_button_text' => __( 'GC Sermons Search', 'gc-sermons' ),
45 | 'button_tooltip' => __( 'GC Sermons Search', 'gc-sermons' ),
46 | 'icon' => 'dashicons-search',
47 | // 'mceView' => true, // The future
48 | );
49 | }
50 |
51 | /**
52 | * Adds fields to the button modal using CMB2
53 | *
54 | * @param $fields
55 | * @param $button_data
56 | *
57 | * @return array
58 | */
59 | function fields( $fields, $button_data ) {
60 |
61 | $fields[] = array(
62 | 'name' => __( 'Search:', 'gc-sermons' ),
63 | 'desc' => sprintf( __( 'Select whether form allows searching %s, %s, or both.', 'gc-sermons' ), $this->run->sermons->post_type( 'plural' ), $this->taxonomies->series->taxonomy( 'plural' ) ),
64 | 'id' => $this->prefix . 'search',
65 | 'type' => 'select',
66 | 'default' => $this->atts_defaults['search'],
67 | 'options' => array(
68 | 'sermons' => $this->run->sermons->post_type( 'plural' ),
69 | 'series' => $this->taxonomies->series->taxonomy( 'plural' ),
70 | '' => __( 'Both', 'gc-sermons' ),
71 | ),
72 | );
73 |
74 | $fields[] = array(
75 | 'name' => __( 'Number of results to show per-page', 'gc-sermons' ),
76 | 'type' => 'text_small',
77 | 'id' => $this->prefix . 'per_page',
78 | 'default' => get_option( 'posts_per_page', $this->atts_defaults['per_page'] ),
79 | );
80 |
81 | $fields[] = array(
82 | 'name' => __( 'Content', 'gc-sermons' ),
83 | 'type' => 'radio',
84 | 'id' => $this->prefix . 'content',
85 | 'default' => $this->atts_defaults['content'],
86 | 'options' => array(
87 | '' => __( 'None', 'gc-sermons' ),
88 | 'content' => __( 'Sermon Post Content', 'gc-sermons' ),
89 | 'excerpt' => __( 'Sermon Post Excerpt', 'gc-sermons' ),
90 | ),
91 | );
92 |
93 | $fields[] = array(
94 | 'name' => __( 'Remove Thumbnails', 'gc-sermons' ),
95 | 'type' => 'checkbox',
96 | 'id' => $this->prefix . 'remove_thumbnail',
97 | 'default' => false,
98 | );
99 |
100 | $fields[] = array(
101 | 'name' => __( 'Thumbnail Size (if included)', 'gc-sermons' ),
102 | 'type' => 'text',
103 | 'id' => $this->prefix . 'thumbnail_size',
104 | 'default' => $this->atts_defaults['thumbnail_size'],
105 | );
106 |
107 | $fields[] = array(
108 | 'name' => __( 'Max number of columns', 'gc-sermons' ),
109 | 'desc' => __( 'Will vary on device screen width', 'gc-sermons' ),
110 | 'type' => 'radio_inline',
111 | 'options' => array( 1 => 1, 2 => 2, 3 => 3, 4 => 4 ),
112 | 'id' => $this->prefix . 'number_columns',
113 | 'default' => $this->atts_defaults['number_columns'],
114 | );
115 |
116 | return $fields;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-series/class-run.php:
--------------------------------------------------------------------------------
1 | series = $series;
34 | parent::__construct( $sermons );
35 | }
36 |
37 | /**
38 | * Default attributes applied to the shortcode.
39 | * @var array
40 | * @since 0.1.0
41 | */
42 | public $atts_defaults = array(
43 | 'per_page' => 10, // Will use WP's per-page option.
44 | 'remove_dates' => false,
45 | 'remove_thumbnail' => false,
46 | 'thumbnail_size' => 'medium',
47 | 'number_columns' => 2,
48 | 'list_offset' => 0,
49 | 'wrap_classes' => '',
50 | 'remove_pagination' => false,
51 |
52 | // No admin
53 | 'remove_description' => true,
54 | );
55 |
56 | /**
57 | * Shortcode Output
58 | */
59 | public function shortcode() {
60 | $allterms = $this->series->get_many( array( 'orderby' => 'sermon_date' ) );
61 |
62 | if ( empty( $allterms ) ) {
63 | return '';
64 | }
65 |
66 | $args = $this->get_initial_query_args();
67 | $total_pages = ceil( count( $allterms ) / $args['posts_per_page'] );
68 | $allterms = array_splice( $allterms, $args['offset'], $args['posts_per_page'] );
69 |
70 | if ( empty( $allterms ) ) {
71 | return '';
72 | }
73 |
74 | $args = $this->get_pagination( $total_pages );
75 |
76 | $args['terms'] = $this->add_year_index_and_augment_terms( $allterms );
77 | $args['remove_dates'] = $this->bool_att( 'remove_dates' );
78 | $args['wrap_classes'] = $this->get_wrap_classes();
79 |
80 | $content = '';
81 | $content .= GCS_Style_Loader::get_template( 'list-item-style' );
82 | $content .= GCS_Template_Loader::get_template( 'series-list', $args );
83 |
84 | return $content;
85 | }
86 |
87 | public function get_initial_query_args() {
88 | $posts_per_page = (int) $this->att( 'per_page', get_option( 'posts_per_page' ) );
89 | $paged = (int) get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
90 | $offset = ( ( $paged - 1 ) * $posts_per_page ) + $this->att( 'list_offset', 0 );
91 |
92 | return compact( 'posts_per_page', 'paged', 'offset' );
93 | }
94 |
95 | public function get_pagination( $total_pages ) {
96 | $nav = array( 'prev_link' => '', 'next_link' => '' );
97 |
98 | if ( ! $this->bool_att( 'remove_pagination' ) ) {
99 | $nav['prev_link'] = get_previous_posts_link( __( '← Newer', 'gc-sermons' ), $total_pages );
100 | $nav['next_link'] = get_next_posts_link( __( 'Older →', 'gc-sermons' ), $total_pages );
101 | }
102 |
103 | return $nav;
104 | }
105 |
106 | public function get_wrap_classes() {
107 | $columns = absint( $this->att( 'number_columns' ) );
108 | $columns = $columns < 1 ? 1 : $columns;
109 |
110 | return $this->att( 'wrap_classes' ) . ' gc-' . $columns . '-cols gc-series-wrap';
111 | }
112 |
113 | public function add_year_index_and_augment_terms( $allterms ) {
114 | $terms = array();
115 |
116 | $do_date = ! $this->bool_att( 'remove_dates' );
117 | $do_thumb = ! $this->bool_att( 'remove_thumbnail' );
118 | $do_desc = ! $this->bool_att( 'remove_description' );
119 |
120 | foreach ( $allterms as $key => $term ) {
121 | $term = $this->get_term_data( $term );
122 |
123 | $term->do_image = $do_thumb && $term->image;
124 | $term->do_description = $do_desc && $term->description;
125 | $term->url = $term->term_link;
126 |
127 | $terms[ $do_date ? $term->year : 0 ][] = $term;
128 | }
129 |
130 | return $terms;
131 | }
132 |
133 | public function get_term_data( $term ) {
134 | return $this->series->get( $term, array( 'image_size' => $this->att( 'thumbnail_size' ) ) );
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function( grunt ) {
2 |
3 | require('load-grunt-tasks')(grunt);
4 |
5 | var pkg = grunt.file.readJSON( 'package.json' );
6 |
7 | var bannerTemplate = '/**\n' +
8 | ' * <%= pkg.title %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
9 | ' * <%= pkg.author.url %>\n' +
10 | ' *\n' +
11 | ' * Copyright (c) <%= grunt.template.today("yyyy") %>;\n' +
12 | ' * Licensed GPLv2+\n' +
13 | ' */\n';
14 |
15 | var compactBannerTemplate = '/** ' +
16 | '<%= pkg.title %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> | <%= pkg.author.url %> | Copyright (c) <%= grunt.template.today("yyyy") %>; | Licensed GPLv2+' +
17 | ' **/\n';
18 |
19 | // Project configuration
20 | grunt.initConfig( {
21 |
22 | pkg: pkg,
23 |
24 |
25 | watch: {
26 | styles: {
27 | files: ['assets/**/*.css','assets/**/*.scss'],
28 | tasks: ['styles'],
29 | options: {
30 | spawn: false,
31 | livereload: true,
32 | debounceDelay: 500
33 | }
34 | },
35 | scripts: {
36 | files: ['assets/**/*.js'],
37 | tasks: ['scripts'],
38 | options: {
39 | spawn: false,
40 | livereload: true,
41 | debounceDelay: 500
42 | }
43 | },
44 | php: {
45 | files: ['**/*.php', '!vendor/**.*.php'],
46 | tasks: ['php'],
47 | options: {
48 | spawn: false,
49 | debounceDelay: 500
50 | }
51 | }
52 | },
53 |
54 | makepot: {
55 | dist: {
56 | options: {
57 | domainPath: '/languages/',
58 | potFilename: pkg.name + '.pot',
59 | type: 'wp-plugin'
60 | }
61 | }
62 | },
63 |
64 | addtextdomain: {
65 | dist: {
66 | options: {
67 | textdomain: pkg.name
68 | },
69 | target: {
70 | files: {
71 | src: ['**/*.php']
72 | }
73 | }
74 | }
75 | },
76 |
77 | githooks: {
78 | all: {
79 | // create zip and deploy changes to ftp
80 | 'pre-push': 'compress'
81 | }
82 | },
83 |
84 | replace: {
85 | version_php: {
86 | src: [
87 | '**/*.php',
88 | '!vendor/**',
89 | ],
90 | overwrite: true,
91 | replacements: [ {
92 | from: /Version:(\s*?)[a-zA-Z0-9\.\-\+]+$/m,
93 | to: 'Version:$1' + pkg.version
94 | }, {
95 | from: /@version(\s*?)[a-zA-Z0-9\.\-\+]+$/m,
96 | to: '@version$1' + pkg.version
97 | }, {
98 | from: /@since(.*?)NEXT/mg,
99 | to: '@since$1' + pkg.version
100 | }, {
101 | from: /VERSION(\s*?)=(\s*?['"])[a-zA-Z0-9\.\-\+]+/mg,
102 | to: 'VERSION$1=$2' + pkg.version
103 | } ]
104 | },
105 | version_readme: {
106 | src: ['README.md', 'readme.txt'],
107 | overwrite: true,
108 | replacements: [ {
109 | from: /^\*\*Stable tag:\*\*(\s*?)[a-zA-Z0-9.-]+(\s*?)$/mi,
110 | to: '**Stable tag:**$1<%= pkg.version %>$2'
111 | } ]
112 | },
113 | },
114 |
115 | compress: {
116 | main: {
117 | options: {
118 | mode: 'zip',
119 | archive: 'gc-sermons.zip'
120 | },
121 | files: [ {
122 | expand: true,
123 | src: [
124 | '**',
125 | '!**/**dandelion**.yml',
126 | '!**/**.xml',
127 | '!**/Dockunit.json',
128 | '!**/package.json',
129 | '!**/node_modules/**',
130 | '!**/bin/**',
131 | '!**/tests/**',
132 | '!**/sass/**',
133 | '!**.zip',
134 | '!**/**.orig',
135 | '!**/**.map',
136 | '!**/**Gruntfile.js',
137 | '!**/**composer.json',
138 | '!**/**composer.lock',
139 | '!**/**bower.json',
140 | '!vendor/tgmpa/tgm-plugin-activation/plugins/**',
141 | '!vendor/jtsternberg/shortcode-button/**'
142 | ],
143 | dest: '/gc-sermons'
144 | } ]
145 | }
146 | },
147 |
148 | githooks: {
149 | all: {
150 | // create zip and deploy changes to ftp
151 | 'pre-push': 'compress'
152 | }
153 | }
154 |
155 | } );
156 |
157 | // Default task.
158 | grunt.registerTask( 'scripts', [] );
159 | grunt.registerTask( 'styles', [] );
160 | grunt.registerTask( 'php', [ 'addtextdomain', 'makepot' ] );
161 | grunt.registerTask( 'default', ['styles', 'scripts', 'php', 'compress'] );
162 |
163 | grunt.registerTask( 'version', [ 'styles', 'scripts', 'php', 'replace:version_php', 'replace:version_readme', 'compress' ] );
164 |
165 | grunt.util.linefeed = '\n';
166 | };
167 |
--------------------------------------------------------------------------------
/bin/install-wp-tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [ $# -lt 3 ]; then
4 | echo "usage: $0 [db-host] [wp-version]"
5 | exit 1
6 | fi
7 |
8 | DB_NAME=$1
9 | DB_USER=$2
10 | DB_PASS=$3
11 | DB_HOST=${4-localhost}
12 | WP_VERSION=${5-latest}
13 |
14 | WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
15 | WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
16 |
17 | download() {
18 | if [ `which curl` ]; then
19 | curl -s "$1" > "$2";
20 | elif [ `which wget` ]; then
21 | wget -nv -O "$2" "$1"
22 | fi
23 | }
24 |
25 | if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then
26 | WP_TESTS_TAG="tags/$WP_VERSION"
27 | else
28 | # http serves a single offer, whereas https serves multiple. we only want one
29 | download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
30 | grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
31 | LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
32 | if [[ -z "$LATEST_VERSION" ]]; then
33 | echo "Latest WordPress version could not be found"
34 | exit 1
35 | fi
36 | WP_TESTS_TAG="tags/$LATEST_VERSION"
37 | fi
38 |
39 | set -ex
40 |
41 | install_wp() {
42 |
43 | if [ -d $WP_CORE_DIR ]; then
44 | return;
45 | fi
46 |
47 | mkdir -p $WP_CORE_DIR
48 |
49 | if [ $WP_VERSION == 'latest' ]; then
50 | local ARCHIVE_NAME='latest'
51 | else
52 | local ARCHIVE_NAME="wordpress-$WP_VERSION"
53 | fi
54 |
55 | download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz
56 | tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
57 |
58 | download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
59 | }
60 |
61 | install_test_suite() {
62 | # portable in-place argument for both GNU sed and Mac OSX sed
63 | if [[ $(uname -s) == 'Darwin' ]]; then
64 | local ioption='-i .bak'
65 | else
66 | local ioption='-i'
67 | fi
68 |
69 | # set up testing suite if it doesn't yet exist
70 | if [ ! -d $WP_TESTS_DIR ]; then
71 | # set up testing suite
72 | mkdir -p $WP_TESTS_DIR
73 | svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
74 | fi
75 |
76 | cd $WP_TESTS_DIR
77 |
78 | if [ ! -f wp-tests-config.php ]; then
79 | download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
80 | sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php
81 | sed $ioption "s:define( 'WP_DEBUG', true );:define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true );:" "$WP_TESTS_DIR"/wp-tests-config.php
82 | sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
83 | sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
84 | sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
85 | sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
86 | fi
87 |
88 | }
89 |
90 | install_required_plugins() {
91 | WDS_SHORTCODES="$WP_CORE_DIR/wp-content/plugins/wds-shortcodes"
92 | CMB2="$WP_CORE_DIR/wp-content/plugins/cmb2"
93 |
94 | if [ ! -d WDS_SHORTCODES ]; then
95 | mkdir -p WDS_SHORTCODES
96 | download https://raw.githubusercontent.com/WebDevStudios/WDS-Shortcodes/master/wds-shortcodes.zip /tmp/wds-shortcodes.zip
97 | unzip /tmp/wds-shortcodes.zip -d WDS_SHORTCODES
98 | fi
99 |
100 | if [ ! -d CMB2 ]; then
101 | mkdir -p CMB2
102 | download https://downloads.wordpress.org/plugin/cmb2.zip /tmp/cmb2.zip
103 | unzip /tmp/cmb2.zip -d CMB2
104 | fi
105 | }
106 |
107 | install_db() {
108 | # parse DB_HOST for port or socket references
109 | local PARTS=(${DB_HOST//\:/ })
110 | local DB_HOSTNAME=${PARTS[0]};
111 | local DB_SOCK_OR_PORT=${PARTS[1]};
112 | local EXTRA=""
113 |
114 | if ! [ -z $DB_HOSTNAME ] ; then
115 | if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
116 | EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
117 | elif ! [ -z $DB_SOCK_OR_PORT ] ; then
118 | EXTRA=" --socket=$DB_SOCK_OR_PORT"
119 | elif ! [ -z $DB_HOSTNAME ] ; then
120 | EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
121 | fi
122 | fi
123 |
124 | # create database
125 | mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
126 | }
127 |
128 | install_wp
129 | install_test_suite
130 | install_required_plugins
131 | install_db
132 |
--------------------------------------------------------------------------------
/includes/class-style-loader.php:
--------------------------------------------------------------------------------
1 | force = $force;
54 | parent::__construct( $css_template, $name, $args );
55 | }
56 |
57 | /**
58 | * Loads the view and outputs it
59 | *
60 | * @since 0.1.3
61 | *
62 | * @param boolean $echo Whether to output or return the template
63 | *
64 | * @return string Rendered template
65 | */
66 | public function load( $echo = false ) {
67 | $content = '';
68 |
69 | // If we haven't done the template before (or we're forcing it)...
70 | if ( ! isset( self::$done[ $this->template ] ) || $this->force ) {
71 | // Then get the content.
72 | $content = parent::load( false );
73 | }
74 |
75 | // If we got content...
76 | if ( $content ) {
77 |
78 | $content = $this->format_css_tag( $content );
79 |
80 | // Ok, this one is done, don't load it again.
81 | self::$done[ $this->template ] = $this->template;
82 | }
83 |
84 | if ( ! $echo ) {
85 | return $content;
86 | }
87 |
88 | echo $content;
89 | }
90 |
91 | /**
92 | * Minifies css and wraps in style tag.
93 | *
94 | * @since 0.1.3
95 | *
96 | * @param string $content CSS content to format/wrap.
97 | *
98 | * @return string Formatted CSS in style tag.
99 | */
100 | protected function format_css_tag( $content ) {
101 |
102 | // Remove comments.
103 | $content = preg_replace( '!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $content );
104 |
105 | // Remove space after colons.
106 | $content = str_replace( ': ', ':', $content );
107 | // Remove whitespace.
108 | $content = str_replace( array( "\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $content );
109 |
110 | // Then wrap in a style tag.
111 | $content = "\n\n";
112 |
113 | return $content;
114 | }
115 |
116 | /**
117 | * Get a rendered HTML view with the given arguments and return the view's contents.
118 | *
119 | * @since 0.1.3
120 | *
121 | * @param string $template The template file name, relative to the includes/templates/ folder
122 | * - without .php extension
123 | * @param string $name The name of the specialised template. If array, will take the place of the $args.
124 | * @param array $args An array of arguments to extract as variables into the template
125 | *
126 | * @return string Rendered template output
127 | */
128 | public static function get_template( $template, $name = null, array $args = array() ) {
129 | $view = new self( $template, $name, $args );
130 | return $view->load();
131 | }
132 |
133 | /**
134 | * Render an HTML view with the given arguments and output the view's contents.
135 | *
136 | * @since 0.1.3
137 | *
138 | * @param string $template The template file name, relative to the includes/templates/ folder
139 | * - without .php extension
140 | * @param string $name The name of the specialised template. If array, will take the place of the $args.
141 | * @param array $args An array of arguments to extract as variables into the template
142 | *
143 | * @return void
144 | */
145 | public static function output_template( $template, $name = null, array $args = array() ) {
146 | $view = new self( $template, $name, $args );
147 | $view->load( 1 );
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-play-button/class-run.php:
--------------------------------------------------------------------------------
1 | 0,
27 | 'icon_color' => '#000000',
28 | 'icon_size' => 'large',
29 | 'icon_class' => 'fa-youtube-play',
30 |
31 | // no admin
32 | 'do_scripts' => true,
33 | );
34 |
35 | /**
36 | * Shortcode Output
37 | */
38 | public function shortcode() {
39 |
40 | $sermon = $this->get_sermon();
41 |
42 | if ( ! $sermon || ! isset( $sermon->ID ) ) {
43 | return apply_filters( 'gcs_sermon_play_button_shortcode_output', GCS_Template_Loader::get_template( 'play-button-shortcode-not-found' ), $this );
44 | }
45 |
46 | if ( $this->att( 'do_scripts' ) ) {
47 | $this->do_scripts();
48 | }
49 |
50 | $output = GCS_Style_Loader::get_template( 'play-button-shortcode-style' );
51 |
52 | list( $style, $has_icon_font_size ) = $this->get_inline_styles();
53 |
54 | $output .= apply_filters( 'gcs_sermon_play_button_shortcode_output', GCS_Template_Loader::get_template(
55 | 'play-button-shortcode',
56 | array(
57 | // Get our extra_class attribute
58 | 'extra_classes' => $this->get_extra_classes( $has_icon_font_size ),
59 | 'sermond_id' => $sermon->ID,
60 | 'style' => $style,
61 | 'video_url' => get_post_meta( $sermon->ID, 'gc_sermon_video_url', 1 ),
62 | )
63 | ), $this );
64 |
65 | return $output;
66 | }
67 |
68 | protected function most_recent_sermon() {
69 | return $this->sermons->most_recent_with_video();
70 | }
71 |
72 | public function get_inline_styles() {
73 | $style = '';
74 | $has_icon_font_size = false;
75 |
76 | if ( $this->att( 'icon_color' ) || $this->att( 'icon_size' ) ) {
77 | $style = ' style="';
78 | // Get/check our text_color attribute
79 | if ( $this->att( 'icon_color' ) ) {
80 | $text_color = sanitize_text_field( $this->att( 'icon_color' ) );
81 | $style .= 'color: ' . $text_color .';';
82 | }
83 | if ( is_numeric( $this->att( 'icon_size' ) ) ) {
84 | $has_icon_font_size = absint( $this->att( 'icon_size' ) );
85 | $style .= 'font-size: ' . $has_icon_font_size .'em;';
86 | }
87 | $style .= '"';
88 | }
89 |
90 | return array( $style, $has_icon_font_size );
91 | }
92 |
93 | public function get_extra_classes( $has_icon_font_size = false ) {
94 | $classes = ' ' . implode( ' ', array_map( 'esc_attr', explode( ' ', $this->att( 'icon_class' ) ) ) );
95 |
96 | if ( ! $has_icon_font_size ) {
97 | $classes .= ' icon-size-' . esc_attr( $this->att( 'icon_size', 'large' ) );
98 | }
99 |
100 | return $classes;
101 | }
102 |
103 | public function do_scripts() {
104 |
105 | // Enqueue whatever version of fontawesome that's registereed (if it is registered)
106 | wp_enqueue_style( 'qode_font_awesome-css' );
107 | wp_enqueue_style( 'font_awesome' );
108 | wp_enqueue_style( 'font-awesome' );
109 | wp_enqueue_style( 'fontawesome' );
110 |
111 | add_action( 'wp_footer', array( $this, 'video_modal' ) );
112 |
113 | wp_enqueue_script(
114 | 'fitvids',
115 | GC_Sermons_Plugin::$url . 'assets/js/vendor/jquery.fitvids.js',
116 | array( 'jquery' ),
117 | '1.1',
118 | true
119 | );
120 |
121 | wp_enqueue_script(
122 | 'gc-sermon-videos',
123 | GC_Sermons_Plugin::$url . 'assets/js/gc-sermon-videos.js',
124 | array( 'fitvids' ),
125 | GC_Sermons_Plugin::VERSION,
126 | true
127 | );
128 | }
129 |
130 | public function video_modal() {
131 | static $done;
132 |
133 | // Get shortcode instances
134 | $shortcodes = WDS_Shortcode_Instances::get( $this->shortcode );
135 |
136 | if ( $done || empty( $shortcodes ) ) {
137 | return;
138 | }
139 |
140 | $videos = array();
141 | foreach ( $shortcodes as $shortcode ) {
142 | // Check for found sermons
143 | if ( ! ( $sermon = $shortcode->att( 'sermon' ) ) ) {
144 | continue;
145 | }
146 |
147 | // Check for video player
148 | if ( ! ( $player = $sermon->get_video_player() ) ) {
149 | return;
150 | }
151 |
152 | // Ok, add the video player
153 | $videos[ $sermon->ID ] = $player;
154 | }
155 |
156 | if ( ! empty( $videos ) ) {
157 | echo new GCS_Template_Loader( 'play-button-shortcode-modal-videos', array(
158 | 'videos' => $videos,
159 | ) );
160 | }
161 |
162 | $done = true;
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-search/class-series-search-run.php:
--------------------------------------------------------------------------------
1 | search_query = $search_query;
42 | $this->current_page = absint( gc__get_arg( 'results-page', 1 ) );
43 |
44 | parent::__construct( $sermons, $series );
45 |
46 | $this->create_shortcode_object(
47 | shortcode_atts( $this->atts_defaults, $atts, $this->shortcode ),
48 | ''
49 | );
50 | }
51 |
52 | public function get_search_results() {
53 | $args = $this->get_initial_query_args();
54 |
55 | $number = $args['number'];
56 | $offset = $args['offset'];
57 |
58 | // We want to get them all. (well, up to 1000).
59 | $args['number'] = 1000;
60 | $args['offset'] = 0;
61 | $args['hide_empty'] = true;
62 | $allterms = $this->series->search( sanitize_text_field( $this->search_query ), $args );
63 | $allterms = $this->orderby_post_date( $allterms );
64 |
65 | if ( empty( $allterms ) ) {
66 | return '';
67 | }
68 |
69 | $count = count( $allterms );
70 | $total_pages = ceil( $count / $number );
71 | $allterms = array_splice( $allterms, $offset, $number );
72 |
73 | if ( $count > 900 ) {
74 | // Whoops, warn!
75 | trigger_error( 'You have more than 900 sermon series terms, and search queries which are requesting greater than 900 sermon series terms. You may want to look into additional performance optimizations.', E_USER_WARNING );
76 | }
77 |
78 | $args = $this->get_pagination( $total_pages );
79 |
80 | $args['terms'] = array( $this->augment_terms( $allterms ) );
81 | $args['remove_dates'] = true;
82 | $args['wrap_classes'] = $this->get_wrap_classes();
83 |
84 | $this->results = '';
85 | $this->results .= GCS_Style_Loader::get_template( 'list-item-style' );
86 | $this->results .= GCS_Template_Loader::get_template( 'series-list', $args );
87 |
88 | return $this->results;
89 | }
90 |
91 | public function get_initial_query_args() {
92 | $number = (int) $this->att( 'per_page', get_option( 'number' ) );
93 | $offset = ( ( $this->current_page - 1 ) * $number ) + $this->att( 'list_offset', 0 );
94 |
95 | return compact( 'number', 'offset' );
96 | }
97 |
98 | public function get_pagination( $total_pages ) {
99 | $nav = array( 'prev_link' => '', 'next_link' => '' );
100 |
101 | if ( ! $this->bool_att( 'remove_pagination' ) ) {
102 | $nav['prev_link'] = gc_search_get_previous_results_link();
103 | $nav['next_link'] = gc_search_get_next_results_link( $total_pages );
104 | }
105 |
106 | return $nav;
107 | }
108 |
109 | public function get_wrap_classes() {
110 | return parent::get_wrap_classes() . ' gc-series-search-wrap';
111 | }
112 |
113 | public function augment_terms( $allterms ) {
114 | $do_thumb = ! $this->bool_att( 'remove_thumbnail' );
115 | $do_desc = ! $this->bool_att( 'remove_description' );
116 |
117 | foreach ( $allterms as $key => $term ) {
118 | $term = $this->get_term_data( $term );
119 |
120 | $term->do_image = $do_thumb && $term->image;
121 | $term->do_description = $do_desc && $term->description;
122 | $term->url = $term->term_link;
123 |
124 | $allterms[ $key ] = $term;
125 | }
126 |
127 | return $allterms;
128 | }
129 |
130 | public function orderby_post_date( $allterms ) {
131 | $ordered = array();
132 | if ( empty( $allterms ) ) {
133 | return $ordered;
134 | }
135 | foreach ( $allterms as $key => $term ) {
136 | $query = new WP_Query( array(
137 | 'post_status' => 'publish',
138 | 'posts_per_page' => 1,
139 | 'no_found_rows' => true,
140 | 'cache_results' => false,
141 | 'suppress_filters' => true,
142 | 'tax_query' => array(
143 | array(
144 | 'taxonomy' => $this->series->taxonomy(),
145 | 'field' => 'slug',
146 | 'terms' => $term->slug,
147 | ),
148 | ),
149 | ) );
150 |
151 | if ( $query->have_posts() ) {
152 | $ordered[ strtotime( $query->post->post_date ) ] = $term;
153 | }
154 |
155 | }
156 |
157 | krsort( $ordered );
158 |
159 | return $ordered;
160 | }
161 |
162 | }
163 |
--------------------------------------------------------------------------------
/templates/list-item-style.css:
--------------------------------------------------------------------------------
1 | .gc-series-wrap h4 {
2 | clear: both;
3 | border-bottom: 1px solid rgba(0,0,0,.5);
4 | padding: .5em;
5 | }
6 |
7 | .gc-sermons-list {
8 | clear: both;
9 | margin-left: 0;
10 | margin-right: 0;
11 | padding-left: 0;
12 | padding-right: 0;
13 | }
14 |
15 | .gc-sermons-list:after {
16 | content: '';
17 | display: block;
18 | clear: both;
19 | }
20 |
21 | .gc-sermons-list:after {
22 | content: '';
23 | display: block;
24 | clear: both;
25 | }
26 |
27 | .gc-item {
28 | position: relative;
29 | display: block;
30 | list-style-type: none;
31 | float: left;
32 | padding: .5em;
33 | }
34 |
35 | .gc-1-cols .gc-item {
36 | float: none;
37 | }
38 |
39 | .gc-2-cols .gc-item {
40 | width: 50%;
41 | }
42 |
43 | .gc-3-cols .gc-item {
44 | width: 33.333333%;
45 | }
46 |
47 | .gc-4-cols .gc-item {
48 | width: 25%;
49 | }
50 |
51 | .gc-4-cols .gc-item h3 {
52 | font-size: 1.5em;
53 | }
54 |
55 | .gc-item, .gc-item * {
56 | -moz-box-sizing: border-box;
57 | -webkit-box-sizing: border-box;
58 | box-sizing: border-box;
59 | }
60 |
61 | .gc-2-cols .gc-item:nth-child(2n+1),
62 | .gc-3-cols .gc-item:nth-child(3n+1),
63 | .gc-4-cols .gc-item:nth-child(4n+1) {
64 | clear: both;
65 | }
66 |
67 | .gc-item img {
68 | max-width: 100%;
69 | height: auto;
70 | }
71 |
72 | .gc-item-link {
73 | display: inline-block;
74 | position: relative;
75 | margin: 0;
76 | width: 100%;
77 | /*overflow: hidden;*/
78 | }
79 |
80 | .gc-no-thumb .gc-item-link {
81 | background-color: rgba(0,0,0,.5);
82 | padding: .9em .5em .95em;
83 | -webkit-transition: background-color .3s ease-in-out;
84 | -moz-transition: background-color .3s ease-in-out;
85 | -o-transition: background-color .3s ease-in-out;
86 | -ms-transition: background-color .3s ease-in-out;
87 | }
88 |
89 | .gc-no-thumb .gc-item-link:hover {
90 | background-color: rgba(0,0,0,.7);
91 | }
92 |
93 | .gc-thumb .gc-item-link:hover .gc-sermons-shader,
94 | .gc-thumb .gc-item-link:hover .gc-sermons-table-wrapper {
95 | opacity: 0;
96 | }
97 |
98 | .gc-sermons-table-wrapper {
99 | overflow: hidden;
100 | }
101 |
102 | .gc-sermons-shader,
103 | .gc-sermons-table-wrapper,
104 | .gc-item-link table {
105 | position: relative;
106 | }
107 |
108 | .gc-thumb .gc-sermons-shader,
109 | .gc-thumb .gc-sermons-table-wrapper,
110 | .gc-thumb table {
111 | position: absolute;
112 | -webkit-transition: opacity .3s ease-in-out;
113 | -moz-transition: opacity .3s ease-in-out;
114 | -o-transition: opacity .3s ease-in-out;
115 | -ms-transition: opacity .3s ease-in-out;
116 | }
117 |
118 | .gc-thumb .gc-sermons-shader,
119 | .gc-thumb .gc-sermons-table-wrapper,
120 | .gc-item-link table {
121 | width: 100%;
122 | height: 100%;
123 | left: 0;
124 | top: 0;
125 | }
126 |
127 | .gc-item-link table {
128 | border: 10px solid transparent;
129 | }
130 |
131 | .gc-item-link img {
132 | display: block;
133 | position: relative;
134 | width: 100%;
135 | }
136 |
137 | .gc-item-link .gc-sermons-shader {
138 | background-color: rgba(0,0,0,.5);
139 | }
140 |
141 | .gc-item-link td {
142 | padding: 0;
143 | vertical-align: middle;
144 | background: none;
145 | }
146 |
147 | .gc-item h3 {
148 | color: #fff;
149 | font-size: 2em;
150 | position: relative;
151 | padding-bottom: 1.5em;
152 | }
153 |
154 | .gc-item h3:after {
155 | position: absolute;
156 | content: '→';
157 | font-family: monospace;
158 | font-size: 2em;
159 | display: block;
160 | line-height: .25em;
161 | text-align: center;
162 | bottom: .5em;
163 | height: 0;
164 | width: 100%;
165 | left: 50%;
166 | margin-left: -50%;
167 | padding: 0;
168 | -webkit-transition: all .1s ease-in-out;
169 | -moz-transition: all .1s ease-in-out;
170 | -o-transition: all .1s ease-in-out;
171 | -ms-transition: all .1s ease-in-out;
172 | }
173 |
174 | .gc-no-thumb .gc-link:hover h3:after {
175 | font-size: 2.5em;
176 | bottom: .46em;
177 | }
178 |
179 | .gc-next-link {
180 | float: right;
181 | }
182 |
183 | .gc-next-link a span, .gc-prev-link a:before {
184 | display: inline-block;
185 | font-family: monospace;
186 | font-size: 2em;
187 | }
188 |
189 | .gc-prev-link a span {
190 | display: none;
191 | }
192 |
193 | .gc-prev-link a:before {
194 | /* Because → looks better w/ monospace font, so flip it. */
195 | content: '→';
196 | -webkit-transform:rotateY(180deg);
197 | -moz-transform:rotateY(180deg);
198 | -o-transform:rotateY(180deg);
199 | -ms-transform:rotateY(180deg);
200 | }
201 |
202 | .gc-prev-next:after {
203 | content: '';
204 | display: block;
205 | clear: both;
206 | }
207 |
208 | @media only screen and (max-width : 1000px) {
209 |
210 | .gc-item h3 {
211 | font-size: 1.5em;
212 | }
213 |
214 | .gc-4-cols .gc-item h3 {
215 | font-size: 1em;
216 | }
217 |
218 | }
219 |
220 | @media only screen and (max-width : 775px) {
221 |
222 | .gc-3-cols .gc-item,
223 | .gc-4-cols .gc-item {
224 | width: 50%;
225 | }
226 |
227 | .gc-3-cols .gc-item:nth-child(3n+1),
228 | .gc-4-cols .gc-item:nth-child(4n+1) {
229 | clear: none;
230 | }
231 |
232 | .gc-3-cols .gc-item:nth-child(2n+1),
233 | .gc-4-cols .gc-item:nth-child(2n+1) {
234 | clear: both;
235 | }
236 |
237 | .gc-4-cols .gc-item h3 {
238 | font-size: 1.5em;
239 | }
240 |
241 | }
242 |
243 | @media only screen and (max-width : 600px) {
244 |
245 | .gc-2-cols .gc-item,
246 | .gc-3-cols .gc-item,
247 | .gc-4-cols .gc-item {
248 | width: 100%;
249 | }
250 |
251 | .gc-item h3 {
252 | font-size: 1.4em;
253 | }
254 |
255 | }
256 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-search/class-run.php:
--------------------------------------------------------------------------------
1 | '',
25 | 'per_page' => 10, // Will use WP's per-page option.
26 | 'content' => 'excerpt',
27 | 'remove_thumbnail' => false,
28 | 'thumbnail_size' => 'medium',
29 | 'number_columns' => 2,
30 |
31 | // No admin UI.
32 |
33 | // Sermon specific
34 | 'list_offset' => 0,
35 | 'wrap_classes' => '',
36 | 'remove_pagination' => false,
37 | 'related_speaker' => 0,
38 | 'related_series' => 0,
39 |
40 | // Series specific
41 | 'remove_description' => true,
42 |
43 | 'sermon_search_args' => array(),
44 | 'series_search_args' => array(),
45 | );
46 |
47 | /**
48 | * GCS_Sermons object
49 | *
50 | * @var GCS_Sermons
51 | * @since 0.1.0
52 | */
53 | public $taxonomies;
54 |
55 | /**
56 | * The current search query.
57 | *
58 | * @var string
59 | */
60 | protected $search_query = '';
61 |
62 | /**
63 | * Constructor
64 | *
65 | * @since 0.1.3
66 | *
67 | * @param GCS_Sermons $sermons
68 | * @param GCS_Taxonomies $taxonomies
69 | */
70 | public function __construct( GCS_Sermons $sermons, GCS_Taxonomies $taxonomies ) {
71 |
72 | $this->taxonomies = $taxonomies;
73 | parent::__construct( $sermons );
74 | }
75 |
76 | /**
77 | * Shortcode Output
78 | */
79 | public function shortcode() {
80 | $this->search_query = gc__get_arg( 'sermon-search', '' );
81 | $show_results = gc__get_arg( 'results-for', '' );
82 |
83 | $series_slug = $this->taxonomies->series->taxonomy();
84 | $cpt_slug = $this->sermons->post_type();
85 |
86 | $to_search = $this->att( 'search' );
87 | $search_both = ! $to_search;
88 |
89 | $format = current_theme_supports( 'html5', 'search-form' ) ? 'html5' : 'xhtml';
90 | $format = apply_filters( 'search_form_format', $format );
91 | $template = 'searchform' . ( 'xhtml' === $format ? '-' . $format : '' );
92 |
93 | $args = array(
94 | 'search_query' => $this->search_query,
95 | 'action_url' => add_query_arg( 'sermon-search', 1 ),
96 | 'sermons_value' => $cpt_slug,
97 | 'sermons_label' => $this->sermons->post_type( 'singular' ),
98 | 'series_value' => $series_slug,
99 | 'series_label' => $this->taxonomies->series->taxonomy( 'singular' ),
100 | 'show_filter' => $search_both,
101 | 'show_results' => $show_results,
102 | );
103 |
104 | $content = GCS_Template_Loader::get_template( $template, $args );
105 |
106 | // If a search was performed, let's get the results.
107 | if ( $this->search_query ) {
108 |
109 | if ( strlen( $this->search_query ) < 3 ) {
110 | // Uh-oh, we need at least 3 characters.
111 | $content .= GCS_Template_Loader::get_template( 'search-query-error' );
112 | } else {
113 |
114 | $show_sermon_results = ! $show_results || $cpt_slug === $show_results;
115 | $show_series_results = ! $show_results || $series_slug === $show_results;
116 |
117 | $search_sermons = $search_both || in_array( $to_search, array( 'sermons' ), 1 );
118 | $search_series = $search_both || in_array( $to_search, array( 'series' ), 1 );
119 |
120 | if ( $search_sermons && $show_sermon_results ) {
121 | $content .= $this->sermon_search_results();
122 | }
123 |
124 | if ( $search_series && $show_series_results ) {
125 | $content .= $this->series_search_results();
126 | }
127 |
128 | }
129 | }
130 |
131 | return $content;
132 | }
133 |
134 | protected function sermon_search_results() {
135 | $atts = $this->atts;
136 | unset( $atts['search'] );
137 | unset( $atts['wrap_classes'] );
138 |
139 | $atts = wp_parse_args( $atts, $this->att( 'sermon_search_args', array() ) );
140 |
141 | $search = new GCSS_Sermons_Search_Run( $this->search_query, $this->sermons, $this->taxonomies );
142 | $search->get_search_results( $atts );
143 |
144 | return GCS_Template_Loader::get_template( 'sermon-search-results', array(
145 | 'wrap_classes' => $this->att( 'wrap_classes' ),
146 | 'results' => empty( $search->results ) ? __( 'No results.', 'gc-sermons' ) : $search->results,
147 | 'search_notice' => sprintf(
148 | __( '%s search results for: %s', 'gc-sermons' ),
149 | $this->sermons->post_type( 'singular' ),
150 | esc_html( $this->search_query )
151 | ),
152 | ) );
153 |
154 | return $search;
155 | }
156 |
157 | protected function series_search_results() {
158 | $atts = $this->atts;
159 | unset( $atts['search'] );
160 | unset( $atts['wrap_classes'] );
161 |
162 | $atts = wp_parse_args( $atts, $this->att( 'series_search_args', array() ) );
163 |
164 | $search = new GCSS_Series_Search_Run( $this->search_query, $atts, $this->sermons, $this->taxonomies->series );
165 | $search->get_search_results();
166 |
167 | return GCS_Template_Loader::get_template( 'series-search-results', array(
168 | 'wrap_classes' => $this->att( 'wrap_classes' ),
169 | 'results' => empty( $search->results ) ? __( 'No results.', 'gc-sermons' ) : $search->results,
170 | 'search_notice' => sprintf(
171 | __( '%s search results for: %s', 'gc-sermons' ),
172 | $this->taxonomies->series->taxonomy( 'singular' ),
173 | esc_html( $this->search_query )
174 | ),
175 | ) );
176 | }
177 |
178 | }
179 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | ## [Unreleased][unreleased]
5 |
6 | ## 0.2.1 - 2018-08-31
7 |
8 | - Fix the `label_coming_soon` method and only check for posts in our post-type
9 | - Use `$this->post_type()`, not (wrong) hard-coded post-type string
10 | - Fix `get_the_id`
11 |
12 | ## 0.2.0 - 2018-08-28
13 |
14 | ### Enhancements
15 |
16 | - Helper functions for getting the GC Sermons augmented taxonomy term objects.
17 | - New helper functions:
18 | - `gc_get_series_object( $term = 0, $args = array() )`
19 | - `gc_get_speaker_object( $term = 0, $args = array() )`
20 | - `gc_get_topic_object( $term = 0, $args = array() )`
21 | - `gc_get_tag_object( $term = 0, $args = array() )`
22 | - `gc_get_scripture_object( $term = 0, $args = array() )`
23 |
24 | ### Bug Fixes
25 |
26 | - Make sure `GCS_Taxonomies_Base::filter_values` runs (so that custom post-type and taxonomy overrides work).
27 | - fix composer.json license value to be compatible with packagist
28 |
29 | ## 0.1.6 - 2016-06-08
30 |
31 | ### Enhancements
32 |
33 | * Move loading of plugin's classes to the `'plugins_loaded'` hook for more flexibility.
34 | * Output "No results" string when Sermon/Series search results are empty.
35 | * Update shortcode-button dependency to fix modal displaying before CSS loads.
36 |
37 | ### Bug Fixes
38 |
39 | * Fix required plugins notices. WDS Shortcodes is now bundled and not required for installation.
40 | * Fix php notice caused by looping an empty array.
41 |
42 | ## 0.1.5 - 2016-06-01
43 |
44 | ### Enhancements
45 |
46 | * Add sermon/series search shortcode.
47 | * Add `GCS_Taxonomies_Base::search()` method for searching for terms in the taxonomies.
48 | * Move some functionality in series shortcode to dedicated methods.
49 | * Add wrapper for `get_terms` to account for changes in WP 4.5 where taxonomy is expected as part of the arguments..
50 | * Update WDS-Shortcodes dependency.
51 |
52 | ### Bug Fixes
53 |
54 | * Fix bug where the no-thumb class may not be added properly when thumbs are disabled in shortcodes.
55 | * Tidy up debug/whitespace stuff.
56 | * Fix bug where last page may not show because of rounding error.
57 | * Update sermons shortcode to account for inception issues.
58 | * Cleanup shortcodes class, fixing bad property names.
59 |
60 | ### Other
61 |
62 | * Move taxonomy-based files to taxonomy includes directory, and post-type-based files to post-type includes directory.
63 | * Pass the series taxonomy object to `GCSS_Series_Run` (dependency injection).
64 |
65 | ## 0.1.4 - 2016-05-30
66 |
67 | ### Enhancements
68 |
69 | - Shortcodes, shortcodes, shortcodes. Also, this changelog.
70 | - Update readme, pointing to the wiki.
71 | - Filter, `gc_do_sermon_series_fallback_image`, to disable image fallback.
72 | - Update the term-image column and add a term-edit link.
73 | - Move shortcode files around, and add video/audio player shortcodes.
74 | - Clean up "recent" shortcodes and nicer UX.
75 | - Update dependencies to fix some JS issues.
76 | - Add speaker/series filters to the sermon shortcode.
77 | - Add a prefix to shortcode fields, and method to de-prefix before inserting shortcode.
78 | - Add a filter on the template content output.
79 | - Update sermons shortcode, and make things more generic to be shared.
80 | - Revamp/cleanup shortcodes and finalize the series shortcodes.
81 | - Update wds-shortcodes dependency to get the bool_att method, for getting boolean values from shortcode values.
82 | - Add `GCS_Template_Loader::maybe_output` for doing condtional output in templates.
83 | - Update Template Loader.
84 | - Clean up some typos.
85 | - Add image column to speakers/series taxonomies.
86 | - Add several shortcodes, series image fallback for sermson, allow future posts, etc.
87 | - Rename file to match file/class nameing convention.
88 | - Enable future posts to be displayed (with "coming soon") text on the front-end.
89 | - Make audio player wrap class consistent.
90 | - Make `GCS_Shortcodes_Play_Button` properties accessible.
91 | - Implement template loader to allow overriding in themes, etc.
92 |
93 | ## 0.1.3 - 2016-06-01
94 |
95 | - Add "Scripture" Taxonomy.
96 | - Fix `"gcs_cmb2_box_args_{$this->id}_{$cmb_id}"` filter.
97 |
98 | ## 0.1.2 - 2016-04-14
99 |
100 | - Move css to separate css templates.
101 | - `most_recent_with_audio` method should search for audio, not video.
102 |
103 | ## 0.1.1 - 2016-04-14
104 |
105 | - Specify rewite slugs for all taxonomies.
106 | - When calling `get_audio_player`, init media.
107 | - Be more discerning when removing metaboxes, and replace the featured image metabox.
108 | - Use `plugins_loaded` hook to filter the post-type/taxonomy values so that the filter happens early (before init).
109 | - Update to series column. Replace with image, if one is set.
110 | - Check if `gc_staff` is loaded, and change speaker connected field and augmented data.
111 | - Fix textdomains.
112 | - Add sermon `get` and `get_many` methods.
113 | - build a series image when we only have a url.
114 | - Only get the user avatar if there is no speaker image set.
115 | - on post save, asynchronously save the sermon series terms in order of recent sermons.
116 | - Allow a `series_image_fallback`.
117 | - New `GCS_Sermon_Post` methods, `permalink`, `title`, `series_image`, `get_others_in_series`, `get_others_by_speaker`.
118 | - Make play button shortcode enqueue scripts/styles and for the video modal to actually work.
119 | - Add `get_video_player` method to sermon post class.
120 | - make `url`, `path`, `dir` publicly accessible variables.
121 | - Add `wds-shortcodes` as dependency.
122 | - Add `GCS_Sermon_Post` method for getting the sermon post meta.
123 | - Add `GCS_Sermon_Post` method for getting the sermon audio player.
124 | - Add methods to `GCS_Sermon_Post` for getting the post's series or speaker's term object.
125 | - Add addional CMB2 field types and add related links, etc to sermon CPT.
126 | - Add several utility methods for getting taxonomy term objects, and augmenting with additional info.
127 | - Update rewrite for sermons.
128 | - Fix a bug with taxonomy `most_recent`.
129 | - Differentiate between taxonomy/post-type slug, and the object identifier (since slug can be changed via filter).
130 | - clean up composer.json.
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-sermons/class-admin.php:
--------------------------------------------------------------------------------
1 | taxonomies = $taxonomies;
35 | parent::__construct( $run );
36 |
37 | add_filter( "{$this->shortcode}_shortcode_fields", array( $this, 'return_taxonomy_term_id_only' ), 10 );
38 | }
39 |
40 | /**
41 | * Sets up the button
42 | *
43 | * @return array
44 | */
45 | function js_button_data() {
46 | return array(
47 | 'qt_button_text' => __( 'GC Sermons', 'gc-sermons' ),
48 | 'button_tooltip' => __( 'GC Sermons', 'gc-sermons' ),
49 | 'icon' => $this->run->sermons->arg_overrides['menu_icon'],
50 | // 'mceView' => true, // The future
51 | );
52 | }
53 |
54 | /**
55 | * Adds fields to the button modal using CMB2
56 | *
57 | * @param $fields
58 | * @param $button_data
59 | *
60 | * @return array
61 | */
62 | function fields( $fields, $button_data ) {
63 |
64 | $fields[] = array(
65 | 'name' => __( 'Number of sermons to show per-page', 'gc-sermons' ),
66 | 'type' => 'text_small',
67 | 'id' => $this->prefix . 'per_page',
68 | 'default' => get_option( 'posts_per_page', $this->atts_defaults['per_page'] ),
69 | );
70 |
71 | $fields[] = array(
72 | 'name' => sprintf( _x( 'Optionally select to limit %1$s by %2$s', 'limit sermons by sermon series.', 'gc-sermons' ), $this->run->sermons->post_type( 'plural' ), $this->taxonomies->series->taxonomy( 'plural' ) ),
73 | 'desc' => sprintf( __( 'Start typing to search. Enter "this" to use this post\'s %s.', 'gc-sermons' ), $this->taxonomies->series->taxonomy( 'singular' ) ),
74 | 'type' => 'term_select',
75 | 'apply_term' => false,
76 | 'id' => $this->prefix . 'related_series',
77 | 'taxonomy' => $this->taxonomies->series->taxonomy(),
78 | 'attributes' => array(
79 | 'data-min-length' => 2,
80 | 'data-delay' => 100,
81 | ),
82 | );
83 |
84 | $fields[] = array(
85 | 'name' => sprintf( _x( 'Optionally select to limit %1$s by %2$s', 'limit sermons by sermon speaker.', 'gc-sermons' ), $this->run->sermons->post_type( 'plural' ), $this->taxonomies->speaker->taxonomy( 'plural' ) ),
86 | 'desc' => sprintf( __( 'Start typing to search. Enter "this" to use this post\'s %s.', 'gc-sermons' ), $this->taxonomies->speaker->taxonomy( 'singular' ) ),
87 | 'type' => 'term_select',
88 | 'apply_term' => false,
89 | 'id' => $this->prefix . 'related_speaker',
90 | 'taxonomy' => $this->taxonomies->speaker->taxonomy(),
91 | 'attributes' => array(
92 | 'data-min-length' => 2,
93 | 'data-delay' => 100,
94 | ),
95 | );
96 |
97 | $fields[] = array(
98 | 'name' => __( 'Remove Pagination', 'gc-sermons' ),
99 | 'type' => 'checkbox',
100 | 'id' => $this->prefix . 'remove_pagination',
101 | 'default' => false,
102 | );
103 |
104 | $fields[] = array(
105 | 'name' => __( 'Content', 'gc-sermons' ),
106 | 'type' => 'radio',
107 | 'id' => $this->prefix . 'content',
108 | 'default' => $this->atts_defaults['content'],
109 | 'options' => array(
110 | '' => __( 'None', 'gc-sermons' ),
111 | 'content' => __( 'Sermon Post Content', 'gc-sermons' ),
112 | 'excerpt' => __( 'Sermon Post Excerpt', 'gc-sermons' ),
113 | ),
114 | );
115 |
116 | $fields[] = array(
117 | 'name' => __( 'Remove Thumbnails', 'gc-sermons' ),
118 | 'type' => 'checkbox',
119 | 'id' => $this->prefix . 'remove_thumbnail',
120 | 'default' => false,
121 | );
122 |
123 | $fields[] = array(
124 | 'name' => __( 'Thumbnail Size (if included)', 'gc-sermons' ),
125 | 'type' => 'text',
126 | 'id' => $this->prefix . 'thumbnail_size',
127 | 'default' => $this->atts_defaults['thumbnail_size'],
128 | );
129 |
130 | $fields[] = array(
131 | 'name' => __( 'Max number of columns', 'gc-sermons' ),
132 | 'desc' => __( 'Will vary on device screen width', 'gc-sermons' ),
133 | 'type' => 'radio_inline',
134 | 'options' => array( 1 => 1, 2 => 2, 3 => 3, 4 => 4 ),
135 | 'id' => $this->prefix . 'number_columns',
136 | 'default' => $this->atts_defaults['number_columns'],
137 | );
138 |
139 | $fields[] = array(
140 | 'name' => __( 'Offset', 'gc-sermons' ),
141 | 'desc' => __( 'Changes which sermon starts the list', 'gc-sermons' ),
142 | 'type' => 'text_small',
143 | 'id' => $this->prefix . 'list_offset',
144 | 'sanitization_cb' => 'absint',
145 | 'default' => $this->atts_defaults['list_offset'],
146 | );
147 |
148 | $fields[] = array(
149 | 'name' => __( 'Extra Wrap CSS Classes', 'gc-sermons' ),
150 | 'desc' => __( 'Enter classes separated by spaces (e.g. "class1 class2")', 'gc-sermons' ),
151 | 'type' => 'text',
152 | 'id' => $this->prefix . 'wrap_classes',
153 | 'default' => $this->atts_defaults['wrap_classes'],
154 | );
155 |
156 | return $fields;
157 | }
158 |
159 | public function return_taxonomy_term_id_only( $updated ) {
160 | $term_id_params = array( 'sermon_related_series', 'sermon_related_speaker' );
161 | foreach ( $term_id_params as $param ) {
162 | if ( isset( $updated[ $param ], $updated[ $param ]['id'] ) ) {
163 | if ( isset( $updated[ $param ]['name'] ) && 'this' === $updated[ $param ]['name'] ) {
164 | $updated[ $param ] = $updated[ $param ]['name'];
165 | } else {
166 | $updated[ $param ] = $updated[ $param ]['id'];
167 | }
168 | }
169 | }
170 |
171 | return $updated;
172 | }
173 |
174 | }
175 |
--------------------------------------------------------------------------------
/includes/shortcodes/shortcodes-sermons/class-run.php:
--------------------------------------------------------------------------------
1 | 10, // Will use WP's per-page option.
24 | 'content' => 'excerpt',
25 | 'remove_thumbnail' => false,
26 | 'thumbnail_size' => 'medium',
27 | 'number_columns' => 2,
28 | 'list_offset' => 0,
29 | 'wrap_classes' => '',
30 | 'remove_pagination' => false,
31 | 'related_speaker' => 0,
32 | 'related_series' => 0,
33 | );
34 |
35 | /**
36 | * GCS_Sermons object
37 | *
38 | * @var GCS_Sermons
39 | * @since 0.1.0
40 | */
41 | public $taxonomies;
42 |
43 | /**
44 | * Keep track of the levels of inception.
45 | *
46 | * @var string
47 | * @since 0.1.5
48 | */
49 | protected static $inception_levels = 0;
50 |
51 | /**
52 | * Constructor
53 | *
54 | * @since 0.1.3
55 | *
56 | * @param GCS_Sermons $sermons
57 | * @param GCS_Taxonomies $taxonomies
58 | */
59 | public function __construct( GCS_Sermons $sermons, GCS_Taxonomies $taxonomies ) {
60 | $this->taxonomies = $taxonomies;
61 | parent::__construct( $sermons );
62 | }
63 |
64 | /**
65 | * Shortcode Output
66 | */
67 | public function shortcode() {
68 | /*
69 | * Because it's possible to trigger inception, we need to keep track which
70 | * level we are in, and reset the shortcode object accordingly.
71 | *
72 | * Clever alert. The ++ happens AFTER the value is read, So $my_level starts at 0.
73 | */
74 | $my_level = self::$inception_levels++;
75 |
76 | $args = $this->map_related_term_args( $this->get_initial_query_args() );
77 |
78 | if ( ! $args ) {
79 | // We failed the related term check.
80 | return '';
81 | }
82 |
83 | if ( ! isset( $args['post__not_in'] ) && is_singular( $this->sermons->post_type() ) ) {
84 | $args['post__not_in'] = array( get_queried_object_id() );
85 | }
86 |
87 | $sermons = $this->sermons->get_many( $args );
88 |
89 | if ( ! $sermons->have_posts() ) {
90 | return '';
91 | }
92 |
93 | $max = $sermons->max_num_pages;
94 | $sermons = $this->map_sermon_args( $sermons, $my_level );
95 |
96 | $content = '';
97 | if ( 0 === $my_level ) {
98 | $content .= GCS_Style_Loader::get_template( 'list-item-style' );
99 | }
100 |
101 | $args = $this->get_pagination( $max );
102 | $args['wrap_classes'] = $this->get_wrap_classes();
103 | $args['sermons'] = $sermons;
104 |
105 | $content .= GCS_Template_Loader::get_template( 'sermons-list', $args );
106 |
107 | return $content;
108 | }
109 |
110 | public function get_initial_query_args() {
111 | $posts_per_page = (int) $this->att( 'per_page', get_option( 'posts_per_page' ) );
112 | $paged = (int) get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
113 | $offset = ( ( $paged - 1 ) * $posts_per_page ) + $this->att( 'list_offset', 0 );
114 |
115 | return compact( 'posts_per_page', 'paged', 'offset' );
116 | }
117 |
118 | protected function map_related_term_args( $args ) {
119 |
120 | $required = false;
121 | $passes = false;
122 | $keys = array(
123 | 'series' => 'related_series',
124 | 'speaker' => 'related_speaker',
125 | );
126 |
127 | foreach ( $keys as $key => $param ) {
128 |
129 | if ( $term_id = absint( $this->att( $param ) ) ) {
130 |
131 | $args['tax_query'][] = array(
132 | 'taxonomy' => $this->taxonomies->{$key}->taxonomy(),
133 | 'field' => 'id',
134 | 'terms' => $term_id,
135 | );
136 |
137 | continue;
138 | }
139 |
140 | if ( 'this' !== $this->att( $param ) ) {
141 | continue;
142 | }
143 |
144 | $required = true;
145 |
146 | try {
147 | $sermon = gc_get_sermon_post( get_queried_object(), true );
148 |
149 | $args['post__not_in'] = array( $sermon->ID );
150 |
151 | $method = 'get_' . $key;
152 | $term = $sermon->$method();
153 |
154 | if ( ! $term ) {
155 | throw new Exception( 'No '. $key . ' term.' );
156 | }
157 |
158 | } catch( Exception $e ) {
159 | continue;
160 | }
161 |
162 | $passes = true;
163 |
164 | $args['tax_query'][] = array(
165 | 'taxonomy' => $this->taxonomies->{$key}->taxonomy(),
166 | 'field' => 'id',
167 | 'terms' => $term->term_id,
168 | );
169 |
170 | }
171 |
172 | if ( $required && ! $passes ) {
173 | // They wanted sermons associated to 'this', but that's not possible.
174 | return false;
175 | }
176 |
177 | return $args;
178 | }
179 |
180 | protected function get_pagination( $total_pages ) {
181 | $nav = array( 'prev_link' => '', 'next_link' => '' );
182 |
183 | if ( ! $this->bool_att( 'remove_pagination' ) ) {
184 | $nav['prev_link'] = get_previous_posts_link( __( '← Newer', 'gc-sermons' ), $total_pages );
185 | $nav['next_link'] = get_next_posts_link( __( 'Older →', 'gc-sermons' ), $total_pages );
186 | }
187 |
188 | return $nav;
189 | }
190 |
191 | protected function get_wrap_classes() {
192 | $columns = absint( $this->att( 'number_columns' ) );
193 | $columns = $columns < 1 ? 1 : $columns;
194 |
195 | return $this->att( 'wrap_classes' ) . ' gc-' . $columns . '-cols gc-sermons-wrap';
196 | }
197 |
198 | protected function map_sermon_args( $all_sermons, $my_level ) {
199 | global $post;
200 | $sermons = array();
201 |
202 | $do_thumb = ! $this->bool_att( 'remove_thumbnail' );
203 | $do_content = $this->bool_att( 'content' );
204 | $type_of_content = $this->att( 'content' );
205 | $thumb_size = $this->att( 'thumbnail_size' );
206 |
207 | while ( $all_sermons->have_posts() ) {
208 | $all_sermons->the_post();
209 |
210 | $obj = $all_sermons->post;
211 |
212 | $sermon = array();
213 | $sermon['url'] = $obj->permalink();
214 | $sermon['name'] = $obj->title();
215 | $sermon['image'] = $do_thumb ? $obj->featured_image( $thumb_size ) : '';
216 | $sermon['do_image'] = (bool) $sermon['image'];
217 | $sermon['description'] = '';
218 | $sermon['do_description'] = $do_content;
219 | if ( $do_content ) {
220 | $sermon['description'] = 'excerpt' === $type_of_content
221 | ? $obj->loop_excerpt()
222 | : apply_filters( 'the_content', $obj->post_content );
223 | }
224 |
225 | $sermons[] = $sermon;
226 | }
227 |
228 | wp_reset_postdata();
229 |
230 | if ( $do_content ) {
231 | /*
232 | * Reset shortcode_object as well, as calling the content/excerpt
233 | * could trigger inception and change the object under us.
234 | */
235 | $this->shortcode_object = WDS_Shortcode_Instances::get( $this->shortcode, $my_level );
236 | }
237 |
238 | return $sermons;
239 | }
240 |
241 | }
242 |
--------------------------------------------------------------------------------
/includes/class-template-loader.php:
--------------------------------------------------------------------------------
1 | template = "{$template}{$this->extension}";
65 |
66 | if ( is_array( $name ) ) {
67 | $this->args = $name;
68 | } else {
69 | $this->args = $args;
70 |
71 | $name = (string) $name;
72 | if ( '' !== $name ) {
73 | $this->templates[] = $this->template = "{$template}-{$name}{$this->extension}";
74 | }
75 | }
76 |
77 | $this->templates[] = $file;
78 | }
79 |
80 | /**
81 | * Loads the view and outputs it
82 | *
83 | * @since 0.1.3
84 | *
85 | * @param boolean $echo Whether to output or return the template
86 | *
87 | * @return string Rendered template
88 | */
89 | public function load( $echo = false ) {
90 | $template = $this->locate_template();
91 |
92 | // No template found.
93 | if ( ! $template ) {
94 | return;
95 | }
96 |
97 | // Filter args before outputting template.
98 | $this->args = apply_filters( "template_args_for_{$this->template}", $this->args, $this );
99 |
100 | try {
101 | ob_start();
102 | // Do html
103 | include $template;
104 | // grab the data from the output buffer and add it to our $content variable
105 | $content = ob_get_clean();
106 | } catch ( Exception $e ) {
107 | wpdie( $e->getMessage() );
108 | }
109 |
110 | $content = apply_filters( "template_output_for_{$this->template}", $content, $this );
111 |
112 | if ( ! $echo ) {
113 | return $content;
114 | }
115 |
116 | echo $content;
117 | }
118 |
119 | /**
120 | * Retrieve the name of the highest priority template file that exists.
121 | *
122 | * Searches in the STYLESHEETPATH before TEMPLATEPATH and then this plugin's /templates
123 | * so that themes which inherit from a parent theme can just overload one file.
124 | *
125 | * @since 0.1.3
126 | *
127 | * @return string The located template filename.
128 | */
129 | protected function locate_template() {
130 | $located = '';
131 |
132 | foreach ( $this->templates as $template ) {
133 | if ( $located = $this->_locate( $template ) ) {
134 | return $located;
135 | }
136 | }
137 |
138 | return $located;
139 | }
140 |
141 | /**
142 | * Searches for template in 1) child theme, 2) parent theme, 3) this plugin.
143 | *
144 | * @since 0.1.3
145 | *
146 | * @param string $template Template file to search for.
147 | *
148 | * @return void
149 | */
150 | protected function _locate( $template ) {
151 | $theme_file_path = '/gc-sermons/' . $template;
152 |
153 | $locations = apply_filters( "template_locations_for_{$this->template}", array(
154 | STYLESHEETPATH . '/gc-sermons/',
155 | TEMPLATEPATH . '/gc-sermons/',
156 | GC_Sermons_Plugin::$path . 'templates/',
157 | ), $this );
158 |
159 | $located = '';
160 | foreach ( $locations as $location ) {
161 | if ( file_exists( $location . $template ) ) {
162 | $located = $location . $template;
163 | break;
164 | }
165 | }
166 |
167 | return $located;
168 | }
169 |
170 | /**
171 | * Get one of the $args values.
172 | *
173 | * @since 0.1.3
174 | *
175 | * @param string $arg The $args key.
176 | * @param mixed $default Mixed value.
177 | *
178 | * @return mixed Value or default.
179 | */
180 | public function get( $arg, $default = null ) {
181 | if ( isset( $this->args[ $arg ] ) ) {
182 | return $this->args[ $arg ];
183 | }
184 |
185 | return $default;
186 | }
187 |
188 | /**
189 | * Output one of the $args values.
190 | *
191 | * @since 0.1.3
192 | *
193 | * @param string $arg The $args key.
194 | * @param mixed $esc_cb An escaping function callback.
195 | * @param mixed $default Mixed value.
196 | *
197 | * @return mixed Value or default.
198 | */
199 | public function output( $arg, $esc_cb = '', $default = null ) {
200 | $val = $this->get( $arg, $default );
201 |
202 | echo $esc_cb ? $esc_cb( $val ) : $val;
203 | }
204 |
205 | /**
206 | * Conditionally output one of the $args values,
207 | * if the value (or another one specified) exists.
208 | *
209 | * @since 0.1.3
210 | *
211 | * @param string $arg The $args key.
212 | * @param mixed $esc_cb An escaping function callback.
213 | * @param mixed $arg_to_check Alternate arg to check instead of $arg.
214 | *
215 | * @return mixed Value if condition is met.
216 | */
217 | public function maybe_output( $arg, $esc_cb = '', $arg_to_check = null ) {
218 | $arg_to_check = null === $arg_to_check ? $arg : $arg_to_check;
219 |
220 | if ( $this->get( $arg_to_check ) ) {
221 | $this->output( $arg, $esc_cb );
222 | }
223 | }
224 |
225 | /**
226 | * Magic method to fetch the rendered view when calling the call as a string.
227 | *
228 | * @since 0.1.3
229 | *
230 | * @return string Rendered template's HTML output.
231 | */
232 | public function __toString() {
233 | return $this->load();
234 | }
235 |
236 | /**
237 | * Get a rendered HTML view with the given arguments and return the view's contents.
238 | *
239 | * @since 0.1.3
240 | *
241 | * @param string $template The template file name, relative to the includes/templates/ folder
242 | * - without .php extension
243 | * @param string $name The name of the specialised template. If array, will take the place of the $args.
244 | * @param array $args An array of arguments to extract as variables into the template
245 | *
246 | * @return string Rendered template output
247 | */
248 | public static function get_template( $template, $name = null, array $args = array() ) {
249 | $view = new self( $template, $name, $args );
250 | return $view->load();
251 | }
252 |
253 | /**
254 | * Render an HTML view with the given arguments and output the view's contents.
255 | *
256 | * @since 0.1.3
257 | *
258 | * @param string $template The template file name, relative to the includes/templates/ folder
259 | * - without .php extension
260 | * @param string $name The name of the specialised template. If array, will take the place of the $args.
261 | * @param array $args An array of arguments to extract as variables into the template
262 | *
263 | * @return void
264 | */
265 | public static function output_template( $template, $name = null, array $args = array() ) {
266 | $view = new self( $template, $name, $args );
267 | $view->load( 1 );
268 | }
269 |
270 | }
271 |
--------------------------------------------------------------------------------
/includes/taxonomies/class-speaker.php:
--------------------------------------------------------------------------------
1 | array( __( 'Speaker', 'gc-sermons' ), __( 'Speakers', 'gc-sermons' ), 'gcs-speaker' ),
36 | 'args' => array(
37 | 'hierarchical' => false,
38 | 'rewrite' => array( 'slug' => 'speaker' ),
39 | ),
40 | ) );
41 | }
42 |
43 | /**
44 | * Initiate our hooks
45 | *
46 | * @since 0.1.0
47 | * @return void
48 | */
49 | public function hooks() {
50 | add_action( 'cmb2_admin_init', array( $this, 'fields' ) );
51 | }
52 |
53 | /**
54 | * Add custom fields to the CPT
55 | *
56 | * @since 0.1.0
57 | * @return void
58 | */
59 | public function fields() {
60 | $fields = array(
61 | 'gc_sermon_speaker_connected_user' => array(
62 | 'name' => __( 'Connected User', 'gc-sermons' ),
63 | 'id' => 'gc_sermon_speaker_connected_user',
64 | 'desc' => __( 'Type the name of the WordPress user and select from the suggested options. By associating a speaker with a WordPress user, that WordPress user account details (first/last name, avatar, bio, etc) will be used as a fallback to the information here.', 'gc-sermons' ),
65 | 'type' => 'user_select_text',
66 | 'options' => array(
67 | 'minimum_user_level' => 0,
68 | ),
69 | ),
70 | $this->image_meta_key => array(
71 | 'name' => __( 'Speaker Avatar', 'gc-sermons' ),
72 | 'desc' => __( 'Select the speaker\'s avatar. Will only show if "Connected User" is not chosen, or if the "Connected User" does not have an avatar.', 'gc-sermons' ),
73 | 'id' => $this->image_meta_key,
74 | 'type' => 'file'
75 | ),
76 | );
77 |
78 | $this->add_image_column( __( 'Speaker Avatar', 'gc-sermons' ) );
79 |
80 | if ( function_exists( 'gc_staff' ) ) {
81 | unset( $fields['gc_sermon_speaker_connected_user'] );
82 |
83 | $staff = gc_staff()->staff;
84 | $name = $staff->post_type( 'singular' );
85 |
86 | $fields['gc_sermon_speaker_connected_staff'] = array(
87 | 'name' => sprintf( __( 'Connected %s', 'gc-sermons' ), $name ),
88 | 'id' => 'gc_sermon_speaker_connected_staff',
89 | 'desc' => sprintf( __( 'Type the name of the %1$s and select from the suggested options. By associating a speaker with a %1$s, that %1$s account details (first/last name, image, description, etc) will be used as a fallback to the information here.', 'gc-sermons' ), $name ),
90 | 'type' => 'post_search_text',
91 | 'post_type' => $staff->post_type(),
92 | 'select_type' => 'radio',
93 | 'select_behavior' => 'replace',
94 | );
95 |
96 | }
97 | $cmb = $this->new_cmb2( array(
98 | 'id' => 'gc_sermon_speaker_metabox',
99 | 'taxonomies' => array( $this->taxonomy() ), // Tells CMB2 which taxonomies should
100 | 'object_types' => array( 'term' ), // Tells CMB2 to use term_meta vs post_meta
101 | 'fields' => $fields,
102 | ) );
103 | }
104 |
105 | /**
106 | * Sets extra term data on the the term object, including the image and connected user object.
107 | *
108 | * @since 0.1.1
109 | *
110 | * @param WP_Term $term Term object
111 | * @param array $args Array of arguments.
112 | *
113 | * @return WP_Term|false
114 | */
115 | protected function extra_term_data( $term, $args ) {
116 | $term->connected_user = $term->connected_staff = null;
117 | $term->nickname = '';
118 |
119 | if ( function_exists( 'gc_staff' ) ) {
120 | if ( $connected_staff_id = get_term_meta( $term->term_id, 'gc_sermon_speaker_connected_staff', 1 ) ) {
121 | $term = $this->add_image( $term, $args['image_size'] );
122 | $term = $this->augment_speaker_info_with_staff_info( $term, $connected_staff_id, $args );
123 | }
124 | } else {
125 | if (
126 | ( $connected_user = get_term_meta( $term->term_id, 'gc_sermon_speaker_connected_user', 1 ) )
127 | && isset( $connected_user['id'] )
128 | ) {
129 | $term = $this->augment_speaker_info( $term, $connected_user['id'], $args );
130 | $term = $this->maybe_use_avatar( $term, $args );
131 | }
132 | }
133 |
134 | // If not connected user, do the default setting
135 | if ( ! $term->connected_user || ! $term->connected_staff || ! isset( $term->image_url ) ) {
136 | $term = parent::extra_term_data( $term, $args );
137 | }
138 |
139 | return $term;
140 | }
141 |
142 | /**
143 | * Takes a user ID and augments a speaker term object with user data.
144 | *
145 | * @since 0.1.1
146 | *
147 | * @param WP_Term $speaker Speaker term object.
148 | * @param int $user_id Connected user ID.
149 | * @param array $args Array of arguments.
150 | *
151 | * @return WP_Term Augmented term object.
152 | */
153 | protected function augment_speaker_info( $speaker, $user_id, $args ) {
154 | if ( ! $user_id ) {
155 | return $speaker;
156 | }
157 |
158 | $user = get_userdata( $user_id );
159 |
160 | if ( ! $user ) {
161 | return $speaker;
162 | }
163 |
164 | $speaker->connected_user = $user->data;
165 | $speaker->user_link = get_author_posts_url( $user->ID );
166 |
167 | // Fallback to user description
168 | if ( ! $speaker->description && ( $user_desc = $user->get( 'description' ) ) ) {
169 | $speaker->description = $user_desc;
170 | }
171 |
172 | // Override speaker name with user name
173 | if ( $first = $user->get( 'first_name' ) ) {
174 | $speaker->name = $first;
175 | if ( $last = $user->get( 'last_name' ) ) {
176 | $speaker->name .= ' ' . $last;
177 | }
178 | }
179 |
180 | // Add speaker nickname
181 | $speaker->nickname = $user->get( 'nickname' );
182 |
183 | return $speaker;
184 | }
185 |
186 | public function maybe_use_avatar( $speaker, $args = array() ) {
187 | $speaker = $this->add_image( $speaker, $args['image_size'] );
188 |
189 | if ( isset( $speaker->connected_user ) ) {
190 | if ( ! $speaker->image ) {
191 | // Add avatar
192 | $speaker->image = get_avatar( $speaker->connected_user->ID, $args['image_size'], '', $speaker->name );
193 | }
194 |
195 | if ( ! $speaker->image_url ) {
196 | $speaker->image_url = get_avatar_url( $speaker->connected_user->ID, array(
197 | 'size' => $args['image_size'],
198 | ) );
199 | }
200 | }
201 |
202 | return $speaker;
203 | }
204 |
205 | /**
206 | * Takes a staff member post ID and augments a speaker term object with staff data.
207 | *
208 | * @since 0.1.1
209 | *
210 | * @param WP_Term $speaker Speaker term object.
211 | * @param int $connected_staff_id Connected staff member post ID.
212 | * @param array $args Array of arguments.
213 | *
214 | * @return WP_Term Augmented term object.
215 | */
216 | protected function augment_speaker_info_with_staff_info( $speaker, $connected_staff_id, $args ) {
217 | if ( ! $connected_staff_id ) {
218 | return $speaker;
219 | }
220 |
221 | $staff = get_post( $connected_staff_id );
222 |
223 | if ( ! $staff || ! isset( $staff->ID ) ) {
224 | return $speaker;
225 | }
226 |
227 | $speaker->connected_staff = $staff = new GCST_Staff_Member( $staff );
228 |
229 | if (
230 | ( $connected_user = $staff->get_meta( 'gc_staff_connected_user' ) )
231 | && isset( $connected_user['id'] )
232 | ) {
233 | $speaker = $this->augment_speaker_info( $speaker, $connected_user['id'], $args );
234 | }
235 |
236 | $speaker->user_link = $staff->permalink();
237 |
238 | // Fallback to staff description
239 | if ( ! $speaker->description && $staff->post_content ) {
240 | $speaker->description = $staff->post_content;
241 | }
242 |
243 | // Override speaker name with user name
244 | if ( $first = $staff->get_meta( 'gc_staff_first' ) ) {
245 | $speaker->name = $first;
246 | if ( $last = $staff->get_meta( 'gc_staff_last' ) ) {
247 | $speaker->name .= ' ' . $last;
248 | }
249 | }
250 |
251 | if ( ! $speaker->image ) {
252 | $speaker->image = $staff->featured_image( $args['image_size'] );
253 | }
254 |
255 | if ( ! $speaker->image_url ) {
256 | $src = wp_get_attachment_image_src( $staff->image_id(), $args['image_size'] );
257 | $speaker->image_url = isset( $src[0] ) ? $src[0] : '';
258 | }
259 |
260 | return $speaker;
261 | }
262 |
263 | }
264 |
--------------------------------------------------------------------------------
/gc-sermons.php:
--------------------------------------------------------------------------------
1 | sermons = new GCS_Sermons( $this );
174 | $this->taxonomies = new GCS_Taxonomies( $this->sermons );
175 | $this->async = new GCS_Async( $this );
176 | $this->shortcodes = new GCS_Shortcodes( $this );
177 | } // END OF PLUGIN CLASSES FUNCTION
178 |
179 | /**
180 | * Add hooks and filters
181 | *
182 | * @since 0.1.0
183 | * @return void
184 | */
185 | public function hooks() {
186 | if ( ! defined( 'CMB2_LOADED' ) || ! defined( 'WDS_SHORTCODES_LOADED' ) ) {
187 | add_action( 'tgmpa_register', array( $this, 'register_required_plugin' ) );
188 | } else {
189 | add_action( 'init', array( $this, 'init' ) );
190 | $this->plugin_classes();
191 | }
192 | }
193 |
194 | /**
195 | * Requires CMB2 to be installed
196 | */
197 | public function register_required_plugin() {
198 |
199 | $plugins = array(
200 | array(
201 | 'name' => 'CMB2',
202 | 'slug' => 'cmb2',
203 | 'required' => true,
204 | 'version' => '2.2.1',
205 | ),
206 | );
207 |
208 | $config = array(
209 | 'domain' => 'gc-sermons',
210 | 'parent_slug' => 'plugins.php',
211 | 'capability' => 'install_plugins',
212 | 'menu' => 'install-required-plugins',
213 | 'has_notices' => true,
214 | 'is_automatic' => true,
215 | 'message' => '',
216 | 'strings' => array(
217 | 'page_title' => __( 'Install Required Plugins', 'cool-shortcode' ),
218 | 'menu_title' => __( 'Install Plugins', 'cool-shortcode' ),
219 | 'installing' => __( 'Installing Plugin: %s', 'cool-shortcode' ),
220 | // %1$s = plugin name
221 | 'oops' => __( 'Something went wrong with the plugin API.', 'cool-shortcode' ),
222 | 'notice_can_install_required' => _n_noop( 'The "WDS Shortcodes" plugin requires the following plugin: %1$s.', 'This plugin requires the following plugins: %1$s.' ),
223 | // %1$s = plugin name(s)
224 | 'notice_can_install_recommended' => _n_noop( 'This plugin recommends the following plugin: %1$s.', 'This plugin recommends the following plugins: %1$s.' ),
225 | // %1$s = plugin name(s)
226 | 'notice_cannot_install' => _n_noop( 'Sorry, but you do not have the correct permissions to install the %s plugin. Contact the administrator of this site for help on getting the plugin installed.', 'Sorry, but you do not have the correct permissions to install the %s plugins. Contact the administrator of this site for help on getting the plugins installed.' ),
227 | // %1$s = plugin name(s)
228 | 'notice_can_activate_required' => _n_noop( 'The following required plugin is currently inactive: %1$s.', 'The following required plugins are currently inactive: %1$s.' ),
229 | // %1$s = plugin name(s)
230 | 'notice_can_activate_recommended' => _n_noop( 'The following recommended plugin is currently inactive: %1$s.', 'The following recommended plugins are currently inactive: %1$s.' ),
231 | // %1$s = plugin name(s)
232 | 'notice_cannot_activate' => _n_noop( 'Sorry, but you do not have the correct permissions to activate the %s plugin. Contact the administrator of this site for help on getting the plugin activated.', 'Sorry, but you do not have the correct permissions to activate the %s plugins. Contact the administrator of this site for help on getting the plugins activated.' ),
233 | // %1$s = plugin name(s)
234 | 'notice_ask_to_update' => _n_noop( 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this plugin: %1$s.', 'The following plugins need to be updated to their latest version to ensure maximum compatibility with this plugin: %1$s.' ),
235 | // %1$s = plugin name(s)
236 | 'notice_cannot_update' => _n_noop( 'Sorry, but you do not have the correct permissions to update the %s plugin. Contact the administrator of this site for help on getting the plugin updated.', 'Sorry, but you do not have the correct permissions to update the %s plugins. Contact the administrator of this site for help on getting the plugins updated.' ),
237 | // %1$s = plugin name(s)
238 | 'install_link' => _n_noop( 'Begin installing plugin', 'Begin installing plugins' ),
239 | 'activate_link' => _n_noop( 'Activate installed plugin', 'Activate installed plugins' ),
240 | 'return' => __( 'Return to Required Plugins Installer', 'cool-shortcode' ),
241 | 'plugin_activated' => __( 'Plugin activated successfully.', 'cool-shortcode' ),
242 | 'complete' => __( 'All plugins installed and activated successfully. %s', 'cool-shortcode' ),
243 | // %1$s = dashboard link
244 | ),
245 | );
246 |
247 | tgmpa( $plugins, $config );
248 | }
249 |
250 | /**
251 | * Activate the plugin
252 | *
253 | * @since 0.1.0
254 | * @return void
255 | */
256 | public static function activate() {
257 | self::get_instance();
258 | flush_rewrite_rules();
259 | }
260 |
261 | /**
262 | * Deactivate the plugin
263 | * Uninstall routines should be in uninstall.php
264 | *
265 | * @since 0.1.0
266 | * @return void
267 | */
268 | public static function deactivate() {
269 | flush_rewrite_rules();
270 | }
271 |
272 | /**
273 | * Init hooks
274 | *
275 | * @since 0.1.0
276 | * @return void
277 | */
278 | public function init() {
279 | load_plugin_textdomain( 'gc-sermons', false, dirname( self::$basename ) . '/languages/' );
280 | }
281 |
282 | /**
283 | * Magic getter for our object.
284 | *
285 | * @since 0.1.0
286 | * @param string $field Field to get.
287 | * @throws Exception Throws an exception if the field is invalid.
288 | * @return mixed
289 | */
290 | public function __get( $field ) {
291 | switch ( $field ) {
292 | case 'version':
293 | return self::VERSION;
294 | case 'sermons':
295 | case 'taxonomies':
296 | case 'shortcodes':
297 | return $this->{$field};
298 | case 'series':
299 | case 'speaker':
300 | case 'topic':
301 | case 'tag':
302 | case 'scripture':
303 | return $this->taxonomies->{$field};
304 | default:
305 | throw new Exception( 'Invalid '. __CLASS__ .' property: ' . $field );
306 | }
307 | }
308 | }
309 |
310 | /**
311 | * Grab the GC_Sermons_Plugin object and return it.
312 | * Wrapper for GC_Sermons_Plugin::get_instance()
313 | *
314 | * @since 0.1.0
315 | * @return GC_Sermons_Plugin Singleton instance of plugin class.
316 | */
317 | function gc_sermons() {
318 | return GC_Sermons_Plugin::get_instance();
319 | }
320 |
321 | // Kick it off.
322 | add_action( 'plugins_loaded', array( gc_sermons(), 'hooks' ) );
323 | register_activation_hook( __FILE__, array( 'GC_Sermons_Plugin', 'activate' ) );
324 | register_deactivation_hook( __FILE__, array( 'GC_Sermons_Plugin', 'deactivate' ) );
325 |
326 |
--------------------------------------------------------------------------------
/functions.php:
--------------------------------------------------------------------------------
1 | taxonomies->series->taxonomy() ) ? get_queried_object() : 0;
48 | }
49 |
50 | if ( $term ) {
51 | return gc_sermons()->taxonomies->series->get( $term, $args );
52 | }
53 |
54 | return false;
55 | }
56 |
57 | /**
58 | * Gets a GCS_Speaker augmented term object from a term object or ID.
59 | *
60 | * @since 0.2.0
61 | *
62 | * @param mixed $term Term object or ID.
63 | * @param array $args Array of arguments.
64 | *
65 | * @return GCS_Speaker|false GCS_Speaker object if successful.
66 | */
67 | function gc_get_speaker_object( $term = 0, $args = array() ) {
68 | if ( ! $term ) {
69 | $term = is_tax( gc_sermons()->taxonomies->speaker->taxonomy() ) ? get_queried_object() : 0;
70 | }
71 |
72 | if ( $term ) {
73 | return gc_sermons()->taxonomies->speaker->get( $term, $args );
74 | }
75 |
76 | return false;
77 | }
78 |
79 | /**
80 | * Gets a GCS_Topic augmented term object from a term object or ID.
81 | *
82 | * @since 0.2.0
83 | *
84 | * @param mixed $term Term object or ID.
85 | * @param array $args Array of arguments.
86 | *
87 | * @return GCS_Topic|false GCS_Topic object if successful.
88 | */
89 | function gc_get_topic_object( $term = 0, $args = array() ) {
90 | if ( ! $term ) {
91 | $term = is_tax( gc_sermons()->taxonomies->topic->taxonomy() ) ? get_queried_object() : 0;
92 | }
93 |
94 | if ( $term ) {
95 | return gc_sermons()->taxonomies->topic->get( $term, $args );
96 | }
97 |
98 | return false;
99 | }
100 |
101 | /**
102 | * Gets a GCS_Tag augmented term object from a term object or ID.
103 | *
104 | * @since 0.2.0
105 | *
106 | * @param mixed $term Term object or ID.
107 | * @param array $args Array of arguments.
108 | *
109 | * @return GCS_Tag|false GCS_Tag object if successful.
110 | */
111 | function gc_get_tag_object( $term = 0, $args = array() ) {
112 | if ( ! $term ) {
113 | $term = is_tax( gc_sermons()->taxonomies->tag->taxonomy() ) ? get_queried_object() : 0;
114 | }
115 |
116 | if ( $term ) {
117 | return gc_sermons()->taxonomies->tag->get( $term, $args );
118 | }
119 |
120 | return false;
121 | }
122 |
123 | /**
124 | * Gets a GCS_Scripture augmented term object from a term object or ID.
125 | *
126 | * @since 0.2.0
127 | *
128 | * @param mixed $term Term object or ID.
129 | * @param array $args Array of arguments.
130 | *
131 | * @return GCS_Scripture|false GCS_Scripture object if successful.
132 | */
133 | function gc_get_scripture_object( $term = 0, $args = array() ) {
134 | if ( ! $term ) {
135 | $term = is_tax( gc_sermons()->taxonomies->scripture->taxonomy() ) ? get_queried_object() : 0;
136 | }
137 |
138 | if ( $term ) {
139 | return gc_sermons()->taxonomies->scripture->get( $term, $args );
140 | }
141 |
142 | return false;
143 | }
144 |
145 | /**
146 | * Get's info for a series attached to the sermon.
147 | *
148 | * @since 0.1.3
149 | *
150 | * @param mixed $sermon Post object or ID or (GCS_Sermon_Post object).
151 | * @param boolean $args Args array
152 | * @param array $get_series_args Args for GCS_Sermon_Post::get_series()
153 | *
154 | * @return string Sermon series info output.
155 | */
156 | function gc_get_sermon_series_info( $sermon = 0, $args = array(), $get_series_args = array() ) {
157 | if ( ! ( $sermon = gc_get_sermon_post( $sermon ) ) ) {
158 | // If no sermon, bail.
159 | return '';
160 | }
161 |
162 | $args = wp_parse_args( $args, array(
163 | 'remove_thumbnail' => false,
164 | 'remove_description' => true,
165 | 'thumbnail_size' => 'medium',
166 | 'wrap_classes' => '',
167 | ) );
168 |
169 | $get_series_args['image_size'] = isset( $get_series_args['image_size'] )
170 | ? $get_series_args['image_size']
171 | : $args['thumbnail_size'];
172 |
173 | if ( ! ( $series = $sermon->get_series( $get_series_args ) ) ) {
174 | // If no series, bail.
175 | return '';
176 | }
177 |
178 | $series->classes = $args['wrap_classes'];
179 | $series->do_image = ! $args['remove_thumbnail'] && $series->image;
180 | $series->do_description = ! $args['remove_description'] && $series->description;
181 | $series->url = $series->term_link;
182 |
183 | $content = '';
184 | $content .= GCS_Style_Loader::get_template( 'list-item-style' );
185 | $content .= GCS_Template_Loader::get_template( 'list-item', (array) $series );
186 |
187 | // Not a list item.
188 | $content = str_replace( array( ' false,
212 | 'thumbnail_size' => 'medium',
213 | 'wrap_classes' => '',
214 | ) );
215 |
216 | $get_speaker_args['image_size'] = isset( $get_speaker_args['image_size'] )
217 | ? $get_speaker_args['image_size']
218 | : $args['thumbnail_size'];
219 |
220 | if ( ! ( $speaker = $sermon->get_speaker( $get_speaker_args ) ) ) {
221 | // If no speaker, bail.
222 | return '';
223 | }
224 |
225 | // If no sermon or no sermon speaker, bail.
226 | if ( ! $sermon || ! ( $speaker = $sermon->get_speaker( $get_speaker_args ) ) ) {
227 | return '';
228 | }
229 |
230 | $speaker->image = ! $args['remove_thumbnail'] ? $speaker->image : '';
231 | $speaker->classes = $args['wrap_classes'];
232 |
233 | $content = GCS_Template_Loader::get_template( 'sermon-speaker-info', (array) $speaker );
234 |
235 | return $content;
236 | }
237 |
238 | /**
239 | * Get's related links output for the sermon.
240 | *
241 | * @since 0.1.3
242 | *
243 | * @param mixed $sermon Post object or ID or (GCS_Sermon_Post object).
244 | *
245 | * @return string Sermon related links output.
246 | */
247 | function gc_get_sermon_related_links( $sermon = 0 ) {
248 | $sermon = gc_get_sermon_post( $sermon );
249 |
250 | // If no sermon or no related links, bail.
251 | if ( ! $sermon || ! ( $links = $sermon->get_meta( 'gc_related_links' ) ) || ! is_array( $links ) ) {
252 | return '';
253 | }
254 |
255 | $content = GCS_Template_Loader::get_template( 'related-links', array(
256 | 'title' => __( 'Related Links', 'gc-sermons' ),
257 | 'links' => $links,
258 | ) );
259 |
260 | return $content;
261 | }
262 |
263 | /**
264 | * Get's video player for the sermon.
265 | *
266 | * @since 0.1.3
267 | *
268 | * @param mixed $sermon Post object or ID or (GCS_Sermon_Post object).
269 | * @param mixed $args Arguments passed to GCS_Sermon_Post::get_video_player().
270 | *
271 | * @return string Sermon video player output.
272 | */
273 | function gc_get_sermon_video_player( $sermon = 0, $args = array() ) {
274 | $sermon = gc_get_sermon_post( $sermon );
275 |
276 | // If no sermon or no related links, bail.
277 | if ( ! $sermon || ! ( $video_player = $sermon->get_video_player( $args ) ) ) {
278 | return '';
279 | }
280 |
281 | return $video_player;
282 | }
283 |
284 | /**
285 | * Get's audio player for the sermon.
286 | *
287 | * @since 0.1.3
288 | *
289 | * @param mixed $sermon Post object or ID or (GCS_Sermon_Post object).
290 | * @param mixed $args Arguments passed to GCS_Sermon_Post::get_audio_player().
291 | *
292 | * @return string Sermon audio player output.
293 | */
294 | function gc_get_sermon_audio_player( $sermon = 0, $args = array() ) {
295 | $sermon = gc_get_sermon_post( $sermon );
296 |
297 | // If no sermon or no related links, bail.
298 | if ( ! $sermon || ! ( $audio_player = $sermon->get_audio_player( $args ) ) ) {
299 | return '';
300 | }
301 |
302 | return $audio_player;
303 | }
304 |
305 | /**
306 | * Gets the next search results page link when using the search widget.
307 | *
308 | * @since 0.1.5
309 | *
310 | * @param int $total_pages Total number of pages.
311 | *
312 | * @return string Next results page link, if there is a next page.
313 | */
314 | function gc_search_get_next_results_link( $total_pages ) {
315 | $page = absint( gc__get_arg( 'results-page', 1 ) );
316 | $link = '';
317 |
318 | if ( ++$page <= $total_pages ) {
319 | $link = sprintf(
320 | '%s',
321 | esc_url( add_query_arg( 'results-page', $page ) ),
322 | apply_filters( 'gc_next_results_page_link_attributes', '' ),
323 | __( 'Older →', 'gc-sermons' )
324 | );
325 | }
326 |
327 | return $link;
328 | }
329 |
330 | /**
331 | * Gets the previous search results page link when using the search widget.
332 | *
333 | * @since 0.1.5
334 | *
335 | * @return string Next results page link, if there is a previous page.
336 | */
337 | function gc_search_get_previous_results_link() {
338 | $page = absint( gc__get_arg( 'results-page', 1 ) );
339 | $link = '';
340 |
341 | if ( $page-- > 1 ) {
342 | $url = $page > 1 ? add_query_arg( 'results-page', $page ) : remove_query_arg( 'results-page' );
343 | $link = sprintf(
344 | '%s',
345 | esc_url( $url ),
346 | apply_filters( 'gc_previous_results_page_link_attributes', '' ),
347 | __( '← Newer', 'gc-sermons' )
348 | );
349 | }
350 |
351 | return $link;
352 | }
353 |
354 | /**
355 | * Helper function for getting $_GET values with optional default value.
356 | *
357 | * @since 0.1.5
358 | *
359 | * @param string $arg Query arg to check
360 | * @param mixed $default Optional default value. Defaults to null.
361 | *
362 | * @return mixed Result of query var or default.
363 | */
364 | function gc__get_arg( $arg, $default = null ) {
365 | return isset( $_GET[ $arg ] ) ? $_GET[ $arg ] : $default;
366 | }
367 |
--------------------------------------------------------------------------------
/includes/taxonomies/class-taxonomies-base.php:
--------------------------------------------------------------------------------
1 | 512,
41 | );
42 |
43 | /**
44 | * The default args array for self::get_many()
45 | *
46 | * @var array
47 | * @since 0.1.1
48 | */
49 | protected $term_get_many_args_defaults = array(
50 | 'orderby' => 'name',
51 | 'augment_terms' => true,
52 | );
53 |
54 | /**
55 | * The image column title (if applicable).
56 | *
57 | * @var string
58 | * @since 0.1.3
59 | */
60 | protected $img_col_title = '';
61 |
62 | /**
63 | * Constructor
64 | * Register Taxonomy. See documentation in Taxonomy_Core, and in wp-includes/taxonomy.php
65 | *
66 | * @since 0.1.0
67 | * @param object $sermons GCS_Sermons object.
68 | * @return void
69 | */
70 | public function __construct( $sermons, $args ) {
71 | $this->sermons = $sermons;
72 | $this->hooks();
73 |
74 | $this->flush_cache = isset( $_GET['flush_cache'] ) && date( 'Y-m-d' ) === $_GET['flush_cache'];
75 |
76 | /*
77 | * Register this taxonomy
78 | * First parameter should be an array with Singular, Plural, and Registered name
79 | * Second parameter is the register taxonomy arguments
80 | * Third parameter is post types to attach to.
81 | */
82 | parent::__construct(
83 | $args['labels'],
84 | $args['args'],
85 | array( $this->sermons->post_type() )
86 | );
87 |
88 | add_action( 'plugins_loaded', array( $this, 'filter_values' ), 'plugins_loaded' === current_filter() ? 12 : 4 );
89 | add_action( 'wp_async_set_sermon_terms', array( $this, 'trigger_cache_flush' ), 10, 2 );
90 | }
91 |
92 | /**
93 | * Filter values before taxonomy is officially registered.
94 | *
95 | * @since 0.1.0
96 | *
97 | * @return void
98 | */
99 | public function filter_values() {
100 | $args = array(
101 | 'singular' => $this->singular,
102 | 'plural' => $this->plural,
103 | 'taxonomy' => $this->taxonomy,
104 | 'arg_overrides' => $this->arg_overrides,
105 | 'object_types' => $this->object_types,
106 | );
107 |
108 | $filtered_args = apply_filters( 'gcs_taxonomies_'. $this->id, $args, $this );
109 | if ( $filtered_args !== $args ) {
110 | foreach ( $args as $arg => $val ) {
111 | if ( isset( $filtered_args[ $arg ] ) ) {
112 | $this->{$arg} = $filtered_args[ $arg ];
113 | }
114 | }
115 | }
116 | }
117 |
118 | /** Columns ***************************************************************/
119 |
120 | /**
121 | * Register image columns for $this->taxonomy().
122 | *
123 | * @todo Need to disable JJJ's term image stuff for this taxonomy.
124 | * https://twitter.com/Jtsternberg/status/735542428522971136
125 | *
126 | * @since 0.1.3
127 | *
128 | * @param string $img_col_title The title for the Image column.
129 | */
130 | protected function add_image_column( $img_col_title ) {
131 | $this->img_col_title = $img_col_title ? $img_col_title : __( 'Image', 'gc-sermons' );
132 |
133 | $tax = $this->taxonomy();
134 |
135 | add_filter( "manage_edit-{$tax}_columns", array( $this, 'add_column_header' ) );
136 | add_filter( "manage_{$tax}_custom_column", array( $this, 'add_column_value' ), 10, 3 );
137 | }
138 |
139 | /**
140 | * Add the "tax-image" column to taxonomy terms list-tables.
141 | *
142 | * @since 0.1.3
143 | *
144 | * @param array $columns
145 | *
146 | * @return array
147 | */
148 | public function add_column_header( $columns = array() ) {
149 | $columns['tax-image'] = $this->img_col_title;
150 |
151 | return $columns;
152 | }
153 |
154 | /**
155 | * Output the value for the custom column.
156 | *
157 | * @since 0.1.3
158 | *
159 | * @param string $empty
160 | * @param string $custom_column
161 | * @param int $term_id
162 | *
163 | * @return mixed
164 | */
165 | public function add_column_value( $empty = '', $custom_column = '', $term_id = 0 ) {
166 |
167 | // Bail if no taxonomy passed or not on the `tax-image` column
168 | if ( empty( $_REQUEST['taxonomy'] ) || ( 'tax-image' !== $custom_column ) || ! empty( $empty ) ) {
169 | return;
170 | }
171 |
172 | $retval = '—';
173 |
174 | // Get the term data.
175 | $term = $this->get( $term_id, array( 'image_size' => 'thumb' ) );
176 |
177 | // Output image if not empty.
178 | if ( isset( $term->image_id ) && $term->image_id ) {
179 | $retval = wp_get_attachment_image( $term->image_id, 'thumb', false, array(
180 | 'style' => 'max-width:100%;height: auto;',
181 | ) );
182 |
183 | $link = get_edit_term_link( $term->term_id, $this->taxonomy(), $this->sermons->post_type() );
184 |
185 | if ( $link ) {
186 | $retval = ''. $retval .'';
187 | }
188 | }
189 |
190 | echo $retval;
191 | }
192 |
193 | /** Required by Extended Classes *****************************************/
194 |
195 | /**
196 | * Initiate our hooks
197 | *
198 | * @since 0.1.0
199 | * @return void
200 | */
201 | abstract function hooks();
202 |
203 | /** Helper Methods *******************************************************/
204 |
205 | public function new_cmb2( $args ) {
206 | $cmb_id = $args['id'];
207 | return new_cmb2_box( apply_filters( "gcs_cmb2_box_args_{$this->id}_{$cmb_id}", $args ) );
208 | }
209 |
210 | /**
211 | * Retrieve the terms for the most recent post which has this taxonomy set.
212 | *
213 | * @since 0.1.0
214 | *
215 | * @param boolean $get_single_term Whether to get the first term or all of them.
216 | *
217 | * @return GCS_Sermon_Post|false GC Sermon post object if successful.
218 | */
219 | public function most_recent( $get_single_term = false ) {
220 | static $terms = null;
221 |
222 | if ( null === $terms ) {
223 | $sermon = $this->most_recent_sermon();
224 |
225 | if ( ! $sermon ) {
226 | $terms = false;
227 | return $terms;
228 | }
229 |
230 | $terms = $sermon->{$this->id};
231 | $terms = $terms && $get_single_term && is_array( $terms ) ? array_shift( $terms ) : $terms;
232 | }
233 |
234 | return $terms;
235 | }
236 |
237 | /**
238 | * Retrieve the most recent sermon which has terms in this taxonomy.
239 | *
240 | * @since 0.2.0
241 | *
242 | * @return GCS_Sermon_Post|false GC Sermon post object if successful.
243 | */
244 | public function most_recent_sermon() {
245 | return $this->sermons->most_recent_with_taxonomy( $this->id );
246 | }
247 |
248 | /**
249 | * Wrapper for get_terms
250 | *
251 | * @since 0.1.1
252 | *
253 | * @param array $args Array of arguments (passed to get_terms).
254 | * @param array $single_term_args Array of arguments for GCS_Taxonomies_Base::get().
255 | *
256 | * @return array|false Array of term objects or false
257 | */
258 | public function get_many( $args = array(), $single_term_args = array() ) {
259 | $args = wp_parse_args( $args, $this->term_get_many_args_defaults );
260 | $args = apply_filters( "gcs_get_{$this->id}_args", $args );
261 |
262 | if ( isset( $args['orderby'] ) && 'sermon_date' === $args['orderby'] ) {
263 | $terms = $this->get_terms_in_sermon_date_order();
264 | } else {
265 | $terms = self::get_terms( $this->taxonomy(), $args );
266 | }
267 |
268 | if ( ! $terms || is_wp_error( $terms ) ) {
269 | return false;
270 | }
271 |
272 | if (
273 | isset( $args['augment_terms'] )
274 | && $args['augment_terms']
275 | && ! empty( $terms )
276 | // Don't augment for queries w/ greater than 100 terms, for perf. reasons.
277 | && 100 < count( $terms )
278 | ) {
279 | foreach ( $terms as $key => $term ) {
280 | $terms[ $key ] = $this->get( $term, $single_term_args );
281 | }
282 | }
283 |
284 | return $terms;
285 | }
286 |
287 | /**
288 | * Wrapper for get_terms that allows searching using a wildcard name.
289 | *
290 | * @since 0.1.5
291 | *
292 | * @param array $search_term The search term.
293 | * @param array $args Array of arguments for GCS_Taxonomies_Base::get_many().
294 | * @param array $single_term_args Array of arguments for GCS_Taxonomies_Base::get().
295 | *
296 | * @return array|false Array of term objects or false
297 | */
298 | public function search( $search_term, $args = array(), $single_term_args = array() ) {
299 | $args = wp_parse_args( $args, array(
300 | 'name__like' => sanitize_text_field( $search_term ),
301 | 'hide_empty' => false,
302 | 'orderby' => 'term_id',
303 | 'order' => 'DESC',
304 | 'cache_domain' => 'gc_sermons_search_' . $this->id,
305 | ) );
306 |
307 | return $this->get_many( $args, $single_term_args );
308 | }
309 |
310 | /**
311 | * Get a single term object
312 | *
313 | * @since 0.1.1
314 | *
315 | * @param object|int $term Term id or object
316 | * @param array $args Array of arguments.
317 | *
318 | * @return WP_Term|false Term object or false
319 | */
320 | public function get( $term, $args = array() ) {
321 | $term = isset( $term->term_id ) ? $term : get_term_by( 'id', $term, $this->taxonomy() );
322 | if ( ! isset( $term->term_id ) ) {
323 | return false;
324 | }
325 |
326 | $args = wp_parse_args( $args, $this->term_get_args_defaults );
327 | $args = apply_filters( "gcs_get_{$this->id}_single_args", $args, $term, $this );
328 |
329 | $term->term_link = get_term_link( $term );
330 | $term = $this->extra_term_data( $term, $args );
331 |
332 | return $term;
333 | }
334 |
335 | /**
336 | * Sets extra term data on the the term object, including the image, if applicable
337 | *
338 | * @since 0.1.1
339 | *
340 | * @param WP_Term $term Term object
341 | * @param array $args Array of arguments.
342 | *
343 | * @return WP_Term|false
344 | */
345 | protected function extra_term_data( $term, $args ) {
346 | if ( $this->image_meta_key ) {
347 | $term = $this->add_image( $term, $args['image_size'] );
348 | }
349 |
350 | return $term;
351 | }
352 |
353 | /**
354 | * Add term's image
355 | *
356 | * @since 0.1.1
357 | *
358 | * @param WP_Term $term Term object
359 | * @param string $size Size of the image to retrieve
360 | *
361 | * @return mixed URL if successful or set
362 | */
363 | protected function add_image( $term, $size = '' ) {
364 | if ( ! $this->image_meta_key ) {
365 | return $term;
366 | }
367 |
368 | $term->image_id = get_term_meta( $term->term_id, $this->image_meta_key . '_id', 1 );
369 | if ( ! $term->image_id ) {
370 |
371 | $term->image_url = get_term_meta( $term->term_id, $this->image_meta_key, 1 );
372 |
373 | $term->image = $term->image_url ? '
' : '';
374 |
375 | return $term;
376 | }
377 |
378 | if ( $size ) {
379 | $size = is_numeric( $size ) ? array( $size, $size ) : $size;
380 | }
381 |
382 | $term->image = wp_get_attachment_image( $term->image_id, $size ? $size : 'thumbnail' );
383 |
384 | $src = wp_get_attachment_image_src( $term->image_id, $size ? $size : 'thumbnail' );
385 | $term->image_url = isset( $src[0] ) ? $src[0] : '';
386 |
387 | return $term;
388 | }
389 |
390 | /**
391 | * Gets terms in the sermon date order. Result is cached for a max. of a day.
392 | *
393 | * @since 0.1.1
394 | *
395 | * @param bool $flush_cache Whether to get fresh results (flush cache)
396 | *
397 | * @return mixed Array of terms on success
398 | */
399 | protected function get_terms_in_sermon_date_order( $flush_cache = false ) {
400 | $this->flush_cache = $this->flush_cache || $flush_cache;
401 |
402 | $terms = get_transient( $this->id . '_in_sermon_date_order' );
403 |
404 | if ( ! $terms || $this->flush_cache ) {
405 | $sermons = $this->sermons->get_many( array(
406 | 'posts_per_page' => 1000,
407 | 'cache_results' => false,
408 | ) );
409 |
410 | $taxonomy = $this->taxonomy();
411 | $terms = array();
412 | if ( $sermons->have_posts() ) {
413 | foreach ( $sermons->posts as $post ) {
414 | $year = get_the_date( 'Y', $post );
415 | if ( $post_terms = get_the_terms( $post, $taxonomy ) ) {
416 | foreach ( $post_terms as $term ) {
417 | if ( ! isset( $terms[ $term->term_id ] ) ) {
418 | $term->year = $year;
419 | $terms[ $term->term_id ] = $term;
420 | }
421 | }
422 | }
423 | }
424 | }
425 |
426 | set_transient( $this->id . '_in_sermon_date_order', $terms, DAY_IN_SECONDS );
427 | }
428 |
429 | return $terms;
430 | }
431 |
432 | /**
433 | * Hooks into the wp_async_set_sermon_terms action, which is triggered when a post is saved.
434 | *
435 | * @since 0.1.1
436 | *
437 | * @param int $post_id Post ID
438 | * @param string $taxonomy Taxonomy
439 | */
440 | public function trigger_cache_flush( $post_id, $taxonomy ) {
441 | if (
442 | $this->taxonomy() !== $taxonomy
443 | || $this->sermons->post_type() !== get_post_type( $post_id )
444 | ) {
445 | return;
446 | }
447 |
448 | $this->get_terms_in_sermon_date_order( 1 );
449 | }
450 |
451 | /**
452 | * Wrapper for `get_terms` to account for changes in WP 4.5 where taxonomy
453 | * is expected as part of the arguments.
454 | *
455 | * @since 0.1.5
456 | *
457 | * @return mixed Array of terms on success
458 | */
459 | protected static function get_terms( $taxonomy, $args = array() ) {
460 | unset( $args['augment_terms'] );
461 | if ( version_compare( $GLOBALS['wp_version'], '4.5.0', '>=' ) ) {
462 | $args['taxonomy'] = $taxonomy;
463 | $terms = get_terms( $args );
464 | } else {
465 | $terms = get_terms( $taxonomy, $args );
466 | }
467 |
468 | return $terms;
469 | }
470 |
471 | /**
472 | * Magic getter for our object. Allows getting but not setting.
473 | *
474 | * @param string $field
475 | * @throws Exception Throws an exception if the field is invalid.
476 | * @return mixed
477 | */
478 | public function __get( $field ) {
479 | switch ( $field ) {
480 | case 'id':
481 | return $this->id;
482 | default:
483 | throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field );
484 | }
485 | }
486 | }
487 |
--------------------------------------------------------------------------------
/includes/class-sermon-post.php:
--------------------------------------------------------------------------------
1 | sermons->post_type();
94 |
95 | if ( $post->post_type !== $post_type ) {
96 | throw new Exception( 'Sorry, '. __CLASS__ .' expects a '. $post_type .' object.' );
97 | }
98 |
99 | $this->post = $post;
100 | }
101 |
102 | /**
103 | * Initate the video/audio media object
104 | *
105 | * @since 0.1.0
106 | *
107 | * @return array Array of video/audio media info.
108 | */
109 | protected function init_media() {
110 | $this->media = array(
111 | 'video' => array(),
112 | 'audio' => array(),
113 | );
114 | $this->add_media_type( 'video' );
115 | $this->add_media_type( 'audio' );
116 | return $this->media;
117 | }
118 |
119 | /**
120 | * Add media info to the media array for $type
121 | *
122 | * @since 0.1.0
123 | *
124 | * @param string $type type of media
125 | */
126 | protected function add_media_type( $type = 'video' ) {
127 | // Only audio/video allowed.
128 | $type = 'video' === $type ? $type : 'audio';
129 | $media = false;
130 |
131 | if ( $media_url = get_post_meta( $this->ID, "gc_sermon_{$type}_url", 1 ) ) {
132 | $media = array(
133 | 'type' => 'url',
134 | 'value' => $media_url
135 | );
136 | } elseif ( $media_src = get_post_meta( $this->ID, "gc_sermon_{$type}_src_id", 1 ) ) {
137 | $media = array(
138 | 'type' => 'attachment_id',
139 | 'value' => $media_src,
140 | 'attachment_url' => get_post_meta( $this->ID, "gc_sermon_{$type}_src", 1 )
141 | );
142 | } elseif ( $media_url = get_post_meta( $this->ID, "gc_sermon_{$type}_src", 1 ) ) {
143 | $media = array(
144 | 'type' => 'url',
145 | 'value' => $media_url,
146 | );
147 | }
148 |
149 | if ( $media ) {
150 | $this->media[ $type ] = $media;
151 | }
152 |
153 | return $this;
154 | }
155 |
156 | /**
157 | * Wrapper for wp_oembed_get/wp_video_shortcode
158 | *
159 | * @since 0.1.1
160 | *
161 | * @param array $args Optional. Args are passed to either WP_Embed::shortcode,
162 | * or wp_video_shortcode.
163 | * @return mixed The video player if successful.
164 | */
165 | public function get_video_player( $args = array() ) {
166 | global $wp_embed;
167 |
168 | $media = empty( $this->media ) ? $this->init_media() : $this->media;
169 | $video = isset( $media['video'] ) ? $media['video'] : array();
170 | if ( ! isset( $video['type'] ) ) {
171 | return '';
172 | }
173 |
174 | $video_url = '';
175 | if ( 'url' === $video['type'] ) {
176 | $wp_embed->post_ID = $this->ID;
177 | $video_player = $wp_embed->shortcode( $args, $video['value'] );
178 | } elseif ( 'attachment_id' === $video['type'] ) {
179 |
180 | $args['src'] = $video['attachment_url'];
181 | if ( $video_player = wp_video_shortcode( $args ) ) {
182 | $video_player = '' . $video_player . '
';
183 | }
184 | }
185 |
186 | return $video_player;
187 | }
188 |
189 | /**
190 | * Wrapper for wp_audio_shortcode
191 | *
192 | * @since 0.1.1
193 | *
194 | * @return mixed The audio player if successful.
195 | */
196 | public function get_audio_player() {
197 | // Lazy-load the media-getting
198 | if ( empty( $this->media ) ) {
199 | $this->init_media();
200 | }
201 |
202 | $audio = $this->media['audio'];
203 | if ( ! isset( $audio['type'] ) ) {
204 | return '';
205 | }
206 |
207 | $audio_url = '';
208 | if ( 'url' === $audio['type'] ) {
209 | $audio_url = $audio['value'];
210 | } elseif ( 'attachment_id' === $audio['type'] ) {
211 | $audio_url = $audio['attachment_url'];
212 | }
213 |
214 | if ( $audio_player = wp_audio_shortcode( array( 'src' => $audio_url ) ) ) {
215 | $audio_player = '' . $audio_player . '
';
216 | }
217 |
218 | return $audio_player;
219 | }
220 |
221 | /**
222 | * Wrapper for get_permalink.
223 | *
224 | * @since 0.1.1
225 | *
226 | * @return string Sermon post permalink.
227 | */
228 | public function permalink() {
229 | return get_permalink( $this->ID );
230 | }
231 |
232 | /**
233 | * Wrapper for get_the_title.
234 | *
235 | * @since 0.1.1
236 | *
237 | * @return string Sermon post title.
238 | */
239 | public function title() {
240 | return get_the_title( $this->ID );
241 | }
242 |
243 | /**
244 | * Wrapper for the_excerpt. Returns value. Must be used in loop.
245 | *
246 | * @since 0.1.3
247 | *
248 | * @return string Sermon post excerpt.
249 | */
250 | public function loop_excerpt() {
251 | ob_start();
252 | the_excerpt();
253 | // grab the data from the output buffer and add it to our $content variable
254 | $excerpt = ob_get_clean();
255 |
256 | return $excerpt;
257 | }
258 |
259 | /**
260 | * Wrapper for get_the_post_thumbnail which stores the results to the object
261 | *
262 | * @since 0.1.0
263 | *
264 | * @param string|array $size Optional. Image size to use. Accepts any valid image size, or
265 | * an array of width and height values in pixels (in that order).
266 | * Default 'full'.
267 | * @param string|array $attr Optional. Query string or array of attributes. Default empty.
268 | * @return string The post thumbnail image tag.
269 | */
270 | public function featured_image( $size = 'full', $attr = '' ) {
271 | // Unique id for the passed-in attributes.
272 | $id = md5( $attr );
273 |
274 | if ( ! isset( $attr['series_image_fallback'] ) || false !== $attr['series_image_fallback'] ) {
275 | $series_image_fallback = true;
276 | if ( isset( $attr['series_image_fallback'] ) ) {
277 | unset( $attr['series_image_fallback'] );
278 | }
279 | }
280 |
281 | if ( isset( $this->images[ $size ] ) ) {
282 | // If we got it already, then send it back
283 | if ( isset( $this->images[ $size ][ $id ] ) ) {
284 | return $this->images[ $size ][ $id ];
285 | } else {
286 | $this->images[ $size ][ $id ] = array();
287 | }
288 | } else {
289 | $this->images[ $size ][ $id ] = array();
290 | }
291 |
292 | $img = get_the_post_thumbnail( $this->ID, $size, $attr );
293 | $this->images[ $size ][ $id ] = $img ? $img : $this->series_image( $size, $attr );
294 |
295 | return $this->images[ $size ][ $id ];
296 | }
297 |
298 | /**
299 | * Wrapper for get_post_thumbnail_id
300 | *
301 | * @since 0.1.0
302 | *
303 | * @return string|int Post thumbnail ID or empty string.
304 | */
305 | public function featured_image_id() {
306 | return get_post_thumbnail_id( $this->ID );
307 | }
308 |
309 | /**
310 | * Get the series image.
311 | *
312 | * @since 0.1.0
313 | *
314 | * @param string|array $size Optional. Image size to use. Accepts any valid image size, or
315 | * an array of width and height values in pixels (in that order).
316 | * Default 'full'.
317 | * @param string|array $attr Optional. Query string or array of attributes. Default empty.
318 | * @return string The series image tag.
319 | */
320 | public function series_image( $size = 'full', $attr = '' ) {
321 | $args = array( 'image_size' => $size );
322 | $series = $this->get_series( $args );
323 |
324 | return $series->image;
325 | }
326 |
327 | /**
328 | * Get single speaker for this sermon
329 | *
330 | * @since 0.1.1
331 | *
332 | * @param array Args to pass to GCS_Taxonomies_Base::get()
333 | *
334 | * @return WP_Term|false Speaker term object.
335 | */
336 | public function get_speaker( $args = array() ) {
337 | $speakers = $this->speakers();
338 | if ( empty( $speakers ) ) {
339 | return false;
340 | }
341 |
342 | if ( null === $this->speaker ) {
343 | $this->speaker = gc_get_speaker_object( $speakers[0], $args );
344 | }
345 |
346 | return $this->speaker;
347 | }
348 |
349 | /**
350 | * Get single series for this sermon
351 | *
352 | * @since 0.1.1
353 | *
354 | * @param array Args to pass to GCS_Taxonomies_Base::get()
355 | *
356 | * @return WP_Term|false Series term object.
357 | */
358 | public function get_series( $args = array() ) {
359 | $series = $this->series();
360 | if ( empty( $series ) ) {
361 | return false;
362 | }
363 |
364 | if ( null === $this->single_series ) {
365 | $this->single_series = gc_get_series_object( $series[0], $args );
366 | }
367 |
368 | return $this->single_series;
369 | }
370 |
371 | /**
372 | * Get other sermons in the same series.
373 | *
374 | * @since 0.1.1
375 | *
376 | * @param array $args Array of WP_Query arguments.
377 | *
378 | * @return mixed WP_Query instance if successful.
379 | */
380 | public function get_others_in_series( $args = array() ) {
381 | $series = $this->get_series();
382 | if ( ! $series ) {
383 | return new WP_Error( 'no_series_for_sermon', __( 'There is no series associated with this sermon.', 'gc-sermons' ), $this->ID );
384 | }
385 |
386 | $args = wp_parse_args( $args, array(
387 | 'post__not_in' => array( $this->ID ),
388 | 'posts_per_page' => 10,
389 | 'no_found_rows' => true,
390 | ) );
391 |
392 | $args['tax_query'] = array(
393 | array(
394 | 'taxonomy' => $series->taxonomy,
395 | 'field' => 'slug',
396 | 'terms' => $series->slug,
397 | ),
398 | );
399 |
400 | return gc_sermons()->sermons->get_many( $args );
401 | }
402 |
403 | /**
404 | * Get other sermons by the same speaker.
405 | *
406 | * @since 0.1.1
407 | *
408 | * @param array $args Array of WP_Query arguments.
409 | *
410 | * @return mixed WP_Query instance if successful.
411 | */
412 | public function get_others_by_speaker( $args = array() ) {
413 | $speaker = $this->get_speaker();
414 | if ( ! $speaker ) {
415 | return new WP_Error( 'no_speaker_for_sermon', __( 'There is no speaker associated with this sermon.', 'gc-sermons' ), $this->ID );
416 | }
417 |
418 | $args = wp_parse_args( $args, array(
419 | 'post__not_in' => array( $this->ID ),
420 | 'posts_per_page' => 10,
421 | 'no_found_rows' => true,
422 | ) );
423 |
424 | $args['tax_query'] = array(
425 | array(
426 | 'taxonomy' => $speaker->taxonomy,
427 | 'field' => 'slug',
428 | 'terms' => $speaker->slug,
429 | ),
430 | );
431 |
432 | return gc_sermons()->sermons->get_many( $args );
433 | }
434 |
435 | /**
436 | * Wrapper for get_the_terms for the series taxonomy
437 | *
438 | * @since 0.1.0
439 | *
440 | * @return array Array of series terms
441 | */
442 | public function series() {
443 | if ( empty( $this->series ) ) {
444 | $this->series = $this->init_taxonomy( 'series' );
445 | }
446 |
447 | return $this->series;
448 | }
449 |
450 | /**
451 | * Wrapper for get_the_terms for the speaker taxonomy
452 | *
453 | * @since 0.1.0
454 | *
455 | * @return array Array of speaker terms
456 | */
457 | public function speakers() {
458 | if ( empty( $this->speakers ) ) {
459 | $this->speakers = $this->init_taxonomy( 'speaker' );
460 | }
461 |
462 | return $this->speakers;
463 | }
464 |
465 | /**
466 | * Wrapper for get_the_terms for the topic taxonomy
467 | *
468 | * @since 0.1.0
469 | *
470 | * @return array Array of topic terms
471 | */
472 | public function topics() {
473 | if ( empty( $this->topics ) ) {
474 | $this->topics = $this->init_taxonomy( 'topic' );
475 | }
476 |
477 | return $this->topics;
478 | }
479 |
480 | /**
481 | * Wrapper for get_the_terms for the tag taxonomy
482 | *
483 | * @since 0.1.0
484 | *
485 | * @return array Array of tag terms
486 | */
487 | public function tags() {
488 | if ( empty( $this->tags ) ) {
489 | $this->tags = $this->init_taxonomy( 'tag' );
490 | }
491 |
492 | return $this->tags;
493 | }
494 |
495 | /**
496 | * Wrapper for get_the_terms for the scripture taxonomy
497 | *
498 | * @since 0.1.0
499 | *
500 | * @return array Array of scripture terms
501 | */
502 | public function scriptures() {
503 | if ( empty( $this->scriptures ) ) {
504 | $this->scriptures = $this->init_taxonomy( 'scripture' );
505 | }
506 |
507 | return $this->scriptures;
508 | }
509 |
510 | /**
511 | * Initate the taxonomy.
512 | *
513 | * @since 0.1.0
514 | *
515 | * @param string $taxonomy Taxonomy to initiate
516 | *
517 | * @return array Array of terms for this taxonomy.
518 | */
519 | protected function init_taxonomy( $taxonomy ) {
520 | $tax_slug = gc_sermons()->taxonomies->{$taxonomy}->taxonomy();
521 | return get_the_terms( $this->ID, $tax_slug );
522 | }
523 |
524 | /**
525 | * Wrapper for get_post_meta
526 | *
527 | * @since 0.1.1
528 | *
529 | * @param string $key Meta key
530 | *
531 | * @return mixed Value of post meta
532 | */
533 | public function get_meta( $key ) {
534 | return get_post_meta( $this->ID, $key, 1 );
535 | }
536 |
537 | /**
538 | * Magic getter for our object.
539 | *
540 | * @param string $property
541 | * @throws Exception Throws an exception if the field is invalid.
542 | * @return mixed
543 | */
544 | public function __get( $property ) {
545 | $property = $this->translate_property( $property );
546 |
547 | // Automate
548 | switch ( $property ) {
549 | case 'series':
550 | case 'speakers':
551 | case 'topics':
552 | case 'tags':
553 | case 'scriptures':
554 | return $this->{$property}();
555 | case 'post':
556 | return $this->{$property};
557 | case 'media':
558 | // Lazy-load the media-getting
559 | if ( empty( $this->media ) ) {
560 | return $this->init_media();
561 | }
562 | return $this->media;
563 | default:
564 | // Check post object for property
565 | // In general, we'll avoid using same-named properties,
566 | // so the post object properties are always available.
567 | if ( isset( $this->post->{$property} ) ) {
568 | return $this->post->{$property};
569 | }
570 | throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $property );
571 | }
572 | }
573 |
574 | /**
575 | * Magic isset checker for our object.
576 | *
577 | * @param string $property
578 | * @throws Exception Throws an exception if the field is invalid.
579 | * @return mixed
580 | */
581 | public function __isset( $property ) {
582 | $property = $this->translate_property( $property );
583 |
584 | // Automate
585 | switch ( $property ) {
586 | case 'series':
587 | case 'speakers':
588 | case 'topics':
589 | case 'tags':
590 | case 'scriptures':
591 | $terms = $this->{$property}();
592 | return ! empty( $terms );
593 | default:
594 | // Check post object for property
595 | // In general, we'll avoid using same-named properties,
596 | // so the post object properties are always available.
597 | return isset( $this->post->{$property} );
598 | }
599 | }
600 |
601 | /**
602 | * Allow some variations on the object __getter
603 | *
604 | * @since NEXXT
605 | *
606 | * @param string $property Object property to fetch
607 | *
608 | * @return string Maybe-modified property name
609 | */
610 | protected function translate_property( $property ) {
611 | // Translate
612 | switch ( $property ) {
613 | case 'speaker':
614 | $property = 'speakers';
615 | break;
616 | case 'topic':
617 | $property = 'topics';
618 | break;
619 | case 'tag':
620 | $property = 'tags';
621 | break;
622 | case 'scripture':
623 | $property = 'scriptures';
624 | break;
625 | }
626 |
627 | return $property;
628 | }
629 |
630 | }
631 |
--------------------------------------------------------------------------------