This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/**
* Abtract class to be used as a theme template.
* Must be implemented before using this class.
* There are some special functions that can declared (as protected) in implementations to perform main actions:
* - install: (Protected) Additional actions to run when activating the theme (Settings are already created).
* - update: (Protected) Actions to update the theme to a new version. (Updating version on DB is done after this).
* Takes old theme version as a parameter. Settings are already updated from defaults.
* - defaults: (Protected) Returns the default module settings. Used to install, update and fill.
* - registerSidebars: The place where to register all theme sidebars by using register_sidebar() function.
* - init: (Protected) Actions to run when plugins initialization is performed (on init hook).
* - widgetsInit: (Protected) Actions to init theme widgets (In widgets_init).
* - startUp: (Protected) Actions to run at system startup (before plugins are loaded).
* - _adminMenus: (Hook, must be public) Set the menus in WordPress Dashboard.
*
* @author Jordi Canals
* @package Alkivia
* @subpackage Framework
* @link http://alkivia.org
* @uses akSettings
*/
abstract class akTheme
{
/**
* Theme ID. Is the theme internal short name.
* Filled in constructor (as a constructor param). Used for translations textdomain.
* @var string
*/
protected $ID;
/**
* Theme style.css main file.
* Cointains the full path to the theme style's file considering if it is a child theme.
* @var string
*/
protected $style_file;
/**
* Theme data. Readed from the main plugin file header and the readme file.
* Filled in loadThemeData(). Called in constructor.
* From the filename:
* - 'ID' - Plugin internal short name. Taken from main plugin's file name.
* Fom the file header:
* - 'Name' - Name of the theme.
* - 'Title' - Long title for the theme. As WP 2.8 is the same as 'Name'.
* - 'URI' - Theme's page URI.
* - 'Description' - Description of theme's features.
* - 'Author' - Author name and link (to author home).
* - 'Version' - Theme Version number.
* - 'Template' - The parent theme (If this is a child theme).
* - 'Tags' - An array of theme tags features.
* @var array
*/
protected $theme_data;
/**
* Same as $theme_data but for child themes.
*
* @see akTheme::theme_data
* @var array
*/
protected $child_data = array();
/**
* Theme saved data.
* - 'post' - Saves the current post.
* - 'more' - Saves the read more status.
* @var array
*/
protected $saved;
/**
* Holds the global 'settings' object.
* This object has been created on the framework loader.
* @var akSettings
*/
protected $cfg;
/**
* Flag to see if we are installing (activating for first time) or reactivating the theme.
* @var boolean
*/
protected $installing = false;
/**
* Flag to see if theme needs to be updated.
* @var boolean
*/
protected $needs_update = false;
/**
* Class constructor.
* Calls the implementated method 'startUp' if it exists. This is done at theme's loading time.
* Prepares admin menus by setting an action for the implemented method '_adminMenus' if it exists.
*
* @uses do_action() Calls the 'ak_theme_loaded' action hook.
* @param string $ID Theme internal short name (known as theme ID).
* @return akTheme
*/
public function __construct ( $ID = '' ) {
$this->style_file = STYLESHEETPATH . '/style.css';
$this->ID = ( empty($ID) ) ? strtolower(basename(TEMPLATEPATH)) : trim($ID) ;
$this->loadThemeData();
$this->loadTranslations();
// We are installing the theme for the first time.
if ( $this->installing ) {
$this->installTheme();
}
// Set the theme sidebars
if ( function_exists('register_sidebars') && method_exists($this, 'registerSidebars') ) {
$this->registerSidebars();
}
// Configure some global theme options.
$this->configureTheme();
// Load admin styles
if ( is_admin() ) {
add_action('admin_print_styles', array($this, '_adminStyles'));
}
// Init modules and widgets (Here we update the theme).
add_action('init', array($this, '_themeInit'));
add_action('widgets_init', array($this, '_widgetsInit'));
// Add theme administration menus.
if ( method_exists($this, '_adminMenus') ) {
add_action('admin_menu', array($this, '_adminMenus')); // Add Panel menus.
}
// Startup the plugin.
if ( method_exists($this, 'startUp') ) {
$this->startUp();
}
do_action('ak_theme_loaded');
}
/**
* Load theme translations.
* Load the translation for main template and child theme (if exists).
*
* @return void
*/
final private function loadTranslations() {
load_theme_textdomain('aktheme', TEMPLATEPATH . '/lang');
if ( TEMPLATEPATH !== STYLESHEETPATH && is_dir(STYLESHEETPATH . '/lang') ) {
load_theme_textdomain('akchild', STYLESHEETPATH . '/lang');
}
}
/**
* Configure the theme based on theme settings.
*
* @uses do_action() Calls the 'ak_theme_options_set' action hook.
* @return void
*/
final private function configureTheme() {
// Set metatags
add_action('wp_head', array($this, '_metaTags') );
// Set the theme favicon
if ( ! $this->getOption('disable-favicon') ) {
add_action('wp_head', array($this, '_favicon'));
add_action('admin_head', array($this, '_favicon'));
}
// Enable self ping.
if ( ! $this->getOption('enable-selfping') ) {
add_action('pre_ping', array($this, '_disableSelfPing'));
}
do_action('ak_theme_options_set');
}
/**
* Installs the theme.
* Saves the theme version in DB, and calls the 'install' method.
*
* @uses do_action() Calls the 'ak_theme_installed' action hook.
* @return void
*/
final private function installTheme () {
// If there is an additional function to perform on installation.
if ( method_exists($this, 'install') ) {
$this->install();
}
// Save options and version
$this->cfg->saveOptions($this->ID);
add_option($this->ID . '_version', $this->theme_data['Version']);
do_action('ak_theme_installed');
}
/**
* Init the theme (In action 'plugins_loaded')
* Here whe call the 'update' and 'init' functions. This is done after the plugins are loaded.
* Also the theme version and settings are updated here.
*
* @uses do_action() Calls the 'ak_theme_updated' action hook.
* @hook action 'init'
* @access private
* @return void
*/
final function _themeInit () {
// Check if the module needs to be updated.
if ( $this->needs_update ) {
if ( method_exists($this, 'update') ) {
$version = get_option($this->ID . '_version');
$this->update($version);
}
$this->cfg->saveOptions($this->ID);
update_option($this->ID . '_version', $this->theme_data['Version']);
do_action('ak_theme_updated');
}
// Call the custom init for the theme when plugins are loaded.
if ( method_exists($this, 'init') ) {
$this->init();
}
}
/**
* Inits the widgets (In action 'widgets_init')
* In own themes standard sidebar always will be present (No check needed).
*
* @hook action 'widgets_init'
* @access private
* @return void
*/
final function _widgetsInit () {
if ( method_exists($this, 'widgetsInit') ) {
$this->widgetsInit();
}
do_action('ak_theme_widgets_init');
}
/**
* Disables self pings.
* This will disable sending pings to our own blog.
*
* @author Michael D. Adams
* @link http://blogwaffe.com/2006/10/04/421/
* @version 0.2
* @hook action 'pre_ping'
* @param array $links Link list of URLs to ping.
*/
final function _disableSelfPing( &$links ) {
$home = get_option( 'home' );
foreach ( $links as $l => $link ) {
if ( 0 === strpos( $link, $home ) ) {
unset($links[$l]);
}
}
}
/**
* Prepares and enqueues admin styles.
* Uses the filter 'ak_theme_style_admin' for the admin style URL.
*
* @uses apply_filters() Calls the 'ak_theme_style_admin' on the style file URL.
* @hook action 'admin_print_styles'
* @access private
* @return void
*/
final function _adminStyles () {
$url = '';
if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists(STYLESHEETPATH . '/admin.css') ) {
$url = get_stylesheet_directory_uri() . '/admin.css';
} elseif ( file_exists(TEMPLATEPATH . '/admin.css') ) {
$url = get_template_directory_uri() . '/admin.css';
}
$url = apply_filters('ak_theme_style_admin', $url);
if ( ! empty($url) ) {
wp_register_style($this->ID, $url, false, $this->theme_data['Version']);
wp_enqueue_style($this->ID);
}
}
/**
* Returns a theme option.
* If no specific option is requested, returns all options.
* If requested a non existent settings, returns $default.
*
* @param $name Name for the option to return.
* @param $default Default value to use if the option does not exists.
* @return mixed The option's value or an array with all options.
*/
public function getOption ( $name = '', $default = false ) {
return $this->cfg->getSetting($this->ID, $name, $default);
}
/**
* Updates a theme option.
*
* @param string $name Option Name
* @param mixed $value Option value
* @return void
*/
public function updateOption ( $name, $value ) {
$this->cfg->updateOption($this->ID, $name, $value );
}
/**
* Replaces ALL theme options by new ones.
*
* @param array $options Array with all options pairs (name=>value)
* @return void
*/
public function setNewOptions ( $options ) {
$this->cfg->replaceOptions($this->ID, $options);
}
/**
* Returns theme data.
* This data is loaded from the template style.css file.
*
* @see akTheme::$theme_data
* @return mixed The parameter requested or an array wil all data.
*/
public function getThemeData ( $name = '' ) {
if ( empty($name) ) {
return $this->theme_data;
} elseif ( isset( $this->theme_data[$name]) ) {
return $this->theme_data[$name];
} else {
return false;
}
}
/**
* Returns child theme data.
* This data is loaded from the child style.css file.
*
* @see akTheme::$child_data
* @return mixed The parameter requested or an array wil all data.
*/
public function getChildData ( $name = '' ) {
if ( empty($name) ) {
return $this->child_data;
} elseif ( isset( $this->child_data[$name]) ) {
return $this->child_data[$name];
} else {
return false;
}
}
/**
* Checks if an option can be maneged on settings page.
* Looks at the alkivia.ini file and if set there, the option will be disabled.
*
* @param string $option Option name.
* @param boolean $show_notice Show a notice if disabled.
* @return boolean If administration is allowed or not.
*/
public function allowAdmin( $option, $show_notice = true ) {
if ( $this->cfg->isForced($this->ID, $option) ) {
if ( $show_notice ) {
echo '' . __('Option blocked by administrator.', 'aktheme') . '';
}
return false;
} else {
return true;
}
}
/**
* Loads theme data and settings.
* Data is loaded from style.css file headers. Settings from Database.
*
* @return void
*/
private function loadThemeData () {
if ( empty($this->theme_data) ) {
$this->theme_data = get_theme_data(TEMPLATEPATH . '/style.css');
}
if ( TEMPLATEPATH !== STYLESHEETPATH && empty($this->child_data) ) {
$this->child_data = get_theme_data($this->style_file);
}
$this->cfg = ak_settings_object();
if ( method_exists($this, 'defaults') ) {
$this->cfg->setDefaults($this->ID, $this->defaults());
}
$ver = get_option($this->ID . '_version');
if ( false === $ver ) {
$this->installing = true;
} elseif ( version_compare($ver, $this->theme_data['Version'], 'ne') ) {
$this->needs_update = true;
}
}
/**
* Saves the current post state.
* Used if we are looping a new query to reset previous state.
*
* @return void
*/
final protected function savePost() {
global $post, $more;
$this->saved['post'] = $post;
$this->saved['more'] = $more;
}
/**
* Restores the current post state.
* Saved in savePost()
*
* @return void
*/
final protected function restorePost() {
global $post, $more;
$more = $this->saved['more'];
$post = $this->saved['post'];
if ( $post ) {
setup_postdata($post);
}
}
/**
* Sets the favicon for the theme.
*
* @uses apply_filters() Calls apply_filters with the 'ak_theme_favicon' hook and the favicon url as content.
* @hook actions 'wp_head' and 'admin_head'
* @access private
* @return void
*/
final function _favicon () {
$file = '/images/favicon.ico';
$favicon = $this->getOption('favicon-url');
if ( false === $favicon ) {
if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists(STYLESHEETPATH . $file) ) {
$favicon = get_stylesheet_directory_uri() . $file;
} elseif ( file_exists(TEMPLATEPATH . $file) ) {
$favicon = get_template_directory_uri() . $file;
} else {
$favicon = '';
}
}
$favicon = apply_filters('ak_theme_favicon', $favicon);
if ( ! empty($favicon) ) {
echo '' . PHP_EOL;
}
}
/**
* Adds meta names for parent and child themes to head.
*
* @hook action 'wp_head'
* @access private
* @return void
*/
function _metaTags() {
echo '' . PHP_EOL;
if ( false !== $this->getChildData('Name') ) {
echo '' . PHP_EOL;
}
}
}