Commit 0fad50eb authored by mattwire's avatar mattwire

Release 1.0 for CiviCRM 5.28

parent fe0ad57d
......@@ -15,15 +15,6 @@ class CRM_Haystack_Form_SettingsCustom extends CRM_Haystack_Form_Settings {
*/
public static function addSelectElement(&$form, $name, $setting) {
switch ($name) {
case 'theme':
$form->add(
'select',
$name,
$setting['description'],
['Haystack' => 'Haystack - based on CiviCRM Admin Utilities', 'Shelford' => 'Shelford - targetted to match Joomla admin theme']
);
break;
case 'theme_frontend':
$form->add(
'select',
......
<?php
/**
* Created by PhpStorm.
* User: matthew
* Date: 28-02-2019
* Time: 19:32
/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
use CRM_Haystack_ExtensionUtil as E;
class CRM_Haystack_Main {
public function isAdmin() {
return (!CRM_Core_Config::singleton()->userFrameworkFrontend || CRM_Core_Config::singleton()->userFramework == 'drupal');
public static function hookCivicrmCssUrl($themes, $themeKey, $cssExt, $cssFile) {
return \Civi\Core\Themes\Resolvers::simple($themes, $themeKey, $cssExt, $cssFile);
}
/**
* Disable CiviCRM resources from front-end.
*
* Are we in admin backend?
* @return bool
*/
public function resources_disable() {
// Clear any custom CSS URL that is configured.
Civi::settings()->set('customCSSURL', NULL);
// Maybe disable core stylesheet.
if ((boolean) CRM_Haystack_Settings::getValue('disable_civicrm_core_css')) {
Civi::settings()->set('disable_core_css', TRUE);
$this->resource_disable( 'civicrm', 'css/civicrm.css' );
}
public static function isAdmin() {
return (!CRM_Core_Config::singleton()->userFrameworkFrontend || CRM_Core_Config::singleton()->userFramework == 'drupal');
}
if (!$this->isAdmin()) {
/**
* Disable resources
*/
public static function resources_disable() {
if (!self::isAdmin()) {
// Maybe disable navigation stylesheet (there's no menu on the front-end).
$this->resource_disable('civicrm', 'css/civicrmNavigation.css');
// If Shoreditch present.
if ($this->shoreditch_is_active()) {
// Maybe disable Shoreditch stylesheet.
$this->resource_disable('org.civicrm.shoreditch', 'css/custom-civicrm.css');
// Maybe disable Shoreditch Bootstrap stylesheet.
$this->resource_disable('org.civicrm.shoreditch', 'css/bootstrap.css');
}
else {
// Maybe disable custom stylesheet (not provided by Shoreditch).
//if ( $this->setting_get( 'css_custom', '0' ) == '1' ) {
$this->custom_css_disable();
}
self::resource_disable('civicrm', 'css/civicrmNavigation.css');
}
}
/**
* Enable CiviCRM theme resources
*
......@@ -58,96 +43,94 @@ class CRM_Haystack_Main {
*
* @throws \CRM_Core_Exception
*/
public function resources_enable($region, $cmsOnly = FALSE) {
public static function resources_enable($cmsOnly = FALSE) {
$region = 'html-header';
// Load a cms specific css file
if ($region == 'html-header') {
switch (strtolower(CRM_Core_Config::singleton()->userFramework)) {
case 'joomla':
$css = 'joomla';
break;
case 'wordpress':
$css = 'wordpress';
break;
case 'drupal':
$css = 'drupal7';
break;
default:
$css = 'drupal7';
}
switch (strtolower(CRM_Core_Config::singleton()->userFramework)) {
case 'joomla':
$css = 'joomla';
break;
case 'wordpress':
$css = 'wordpress';
break;
case 'drupal':
$css = 'drupal7';
break;
default:
$css = 'drupal7';
}
$theme = CRM_Haystack_Settings::getValue('theme');
if (file_exists(E::path("theme/{$theme}/{$css}.css"))) {
CRM_Core_Resources::singleton()
->addStyleFile('haystack', "theme/{$theme}/{$css}.css", -50, $region);
}
if (file_exists(E::path("theme/Haystack/{$css}.css"))) {
CRM_Core_Resources::singleton()
->addStyleFile('haystack', "theme/Haystack/{$css}.css", -50, $region);
}
if (!$cmsOnly && self::isAdmin()) {
CRM_Core_Resources::singleton()
if (!$cmsOnly && self::isAdmin()) {
CRM_Core_Resources::singleton()
->addStyleUrl(\Civi::service('asset_builder')->getUrl('main.css'), -40, $region)
->addScriptFile('haystack', 'js/inputreadonly.js', -50, $region);
// Responsive datatables only makes sense for CiviCRM admin interfaces
if ((boolean) CRM_Haystack_Settings::getValue('responsive_datatables')) {
// If we want responsive datatables?
CRM_Core_Resources::singleton()
->addStyleFile('haystack', 'css/responsive.dataTables.min.css', -50, $region);
CRM_Core_Resources::singleton()
->addScriptFile('haystack', 'js/dataTables.responsive.min.js', -50, $region);
}
if ((boolean) CRM_Haystack_Settings::getValue('responsive_tables')) {
// If we want responsive tables?
CRM_Core_Resources::singleton()
->addStyleFile('haystack', 'css/responsivetables.css', -50, $region);
CRM_Core_Resources::singleton()
->addScriptFile('haystack', 'js/responsivetables.js', -50, $region);
}
// Responsive datatables only makes sense for CiviCRM admin interfaces
if ((boolean) CRM_Haystack_Settings::getValue('responsive_datatables')) {
// If we want responsive datatables?
CRM_Core_Resources::singleton()
->addStyleFile('haystack', 'css/responsive.dataTables.min.css', -50, $region);
CRM_Core_Resources::singleton()
->addScriptFile('haystack', 'js/dataTables.responsive.min.js', -50, $region);
}
if ((boolean) CRM_Haystack_Settings::getValue('responsive_tables')) {
// If we want responsive tables?
CRM_Core_Resources::singleton()
->addStyleFile('haystack', 'css/responsivetables.css', -50, $region);
CRM_Core_Resources::singleton()
->addScriptFile('haystack', 'js/responsivetables.js', -50, $region);
}
}
switch ((int)CRM_Haystack_Settings::getValue('theme_frontend')) {
case 0:
// Never
$loadFrontend = FALSE;
break;
case 1:
// Only frontend
if (!$this->isAdmin()) {
$loadFrontend = TRUE;
}
break;
case 2:
// Only Backend
if ($this->isAdmin()) {
$loadFrontend = TRUE;
}
break;
switch ((int)CRM_Haystack_Settings::getValue('theme_frontend')) {
case 0:
// Never
$loadFrontend = FALSE;
break;
case 3:
// Frontend and Backend
case 1:
// Only frontend
if (!self::isAdmin()) {
$loadFrontend = TRUE;
break;
}
break;
default:
case 2:
// Only Backend
if (self::isAdmin()) {
$loadFrontend = TRUE;
}
break;
}
case 3:
// Frontend and Backend
$loadFrontend = TRUE;
break;
if ($loadFrontend) {
if ($this->isAdmin()) {
if (file_exists(E::path("theme/{$theme}/frontend.css"))) {
CRM_Core_Resources::singleton()
->addStyleUrl(\Civi::service('asset_builder')->getUrl('frontend.css'), -50, $region);
}
}
else {
$this->addCssToFrontend('frontend.css', $region);
default:
$loadFrontend = TRUE;
}
if ($loadFrontend) {
if (self::isAdmin()) {
if (file_exists(E::path("theme/Haystack/frontend.css"))) {
CRM_Core_Resources::singleton()
->addStyleUrl(\Civi::service('asset_builder')->getUrl('frontend.css'), -50, $region);
}
}
else {
self::addCssToFrontend('frontend.css', $region);
}
}
}
public function addCssToFrontend($cssFile, $region) {
public static function addCssToFrontend($cssFile, $region) {
if (function_exists('wp_enqueue_style')) {
// Add frontend css for Wordpress
wp_enqueue_style(
......@@ -171,30 +154,29 @@ class CRM_Haystack_Main {
* Disable a resource enqueued by CiviCRM.
*
*
* @param str $extension The name of the extension e.g. 'org.civicrm.shoreditch'. Default is CiviCRM core.
* @param str $file The relative path to the resource. Default is CiviCRM core stylesheet.
* @param string $extension The name of the extension e.g. 'org.civicrm.shoreditch'. Default is CiviCRM core.
* @param string $file The relative path to the resource. Default is CiviCRM core stylesheet.
*/
public function resource_disable($extension = 'civicrm', $file = 'css/civicrm.css') {
public static function resource_disable($extension = 'civicrm', $file = 'css/civicrm.css') {
// Get the resource URL.
$url = $this->resource_get_url( $extension, $file );
$url = self::resource_get_url( $extension, $file );
// Kick out if not enqueued.
if ( $url === false ) return;
// Set to disabled.
CRM_Core_Region::instance('html-header')->update( $url, array( 'disabled' => FALSE ) );
CRM_Core_Region::instance('html-header')->update( $url, ['disabled' => FALSE]);
}
/**
* Get the URL of a resource if it is enqueued by CiviCRM.
*
* @param str $extension The name of the extension e.g. 'org.civicrm.shoreditch'. Default is CiviCRM core.
* @param str $file The relative path to the resource. Default is CiviCRM core stylesheet.
* @return bool|str $url The URL if the resource is enqueued, false otherwise.
* @param string $extension The name of the extension e.g. 'org.civicrm.shoreditch'. Default is CiviCRM core.
* @param string $file The relative path to the resource. Default is CiviCRM core stylesheet.
* @return bool|string $url The URL if the resource is enqueued, false otherwise.
*/
public function resource_get_url( $extension = 'civicrm', $file = 'css/civicrm.css' ) {
public static function resource_get_url( $extension = 'civicrm', $file = 'css/civicrm.css' ) {
// Get registered URL.
$url = CRM_Core_Resources::singleton()->getUrl( $extension, $file, TRUE );
......@@ -208,54 +190,4 @@ class CRM_Haystack_Main {
return $url;
}
/**
* Disable any custom CSS file enqueued by CiviCRM.
*
*/
public function custom_css_disable() {
// Get CiviCRM config.
$config = CRM_Core_Config::singleton();
// Bail if there's no custom CSS file.
if ( empty( $config->customCSSURL ) ) return;
// Get registered URL.
$url = CRM_Core_Resources::singleton()->addCacheCode( $config->customCSSURL );
// Get registration data from region.
$registration = CRM_Core_Region::instance('html-header')->get( $url );
// Bail if not registered.
if ( empty ( $registration ) ) return;
// Set to disabled.
CRM_Core_Region::instance('html-header')->update( $url, array( 'disabled' => TRUE ) );
}
/**
* Determine if the Shoreditch CSS file is being used.
*
* @return bool $shoreditch True if Shoreditch CSS file is used, false otherwise.
*/
public function shoreditch_is_active() {
// Assume not.
$shoreditch = false;
// Get the current Custom CSS URL.
$config = CRM_Core_Config::singleton();
// Has the Shoreditch CSS been activated?
if ( strstr( $config->customCSSURL, 'org.civicrm.shoreditch' ) !== false ) {
// Shoreditch CSS is active.
$shoreditch = true;
}
return $shoreditch;
}
}
......@@ -2,8 +2,8 @@
This provides a simple, modern theme for CiviCRM (based on the theme supplied in CiviCRM Admin Utilities for Wordpress).
![Screenshot](/images/contactsummary.png)
![Screenshot](/images/activitypopup.png)
![Screenshot](images/contactsummary.png)
![Screenshot](images/activitypopup.png)
## Sync with civicrm-admin-utilities wordpress extension
......@@ -17,8 +17,8 @@ Go to Administer->Customize Data and Screens->Haystack theme settings to configu
## Requirements
* PHP v7.1+
* CiviCRM 5.20+
* PHP v7.2+
* CiviCRM 5.28+
## Licensing
The extension is licensed under [AGPL-3.0](LICENSE.txt).
......
......@@ -3,11 +3,17 @@
Releases use the following numbering system:
**{major}.{minor}.{incremental}**
Where:
* major: Major refactoring or rewrite - make sure you read and test very carefully!
* minor: Breaking change in some circumstances, or a new feature. Read carefully and make sure you understand the impact of the change.
* incremental: A "safe" change / improvement. Should *always* be safe to upgrade.
* **[BC]**: Items marked with [BC] indicate a breaking change that will require updates to your code if you are using that code in your extension.
## Release 1.0
* Use standard theming system
* Drop support for Shelford theme (it's now available via https://github.com/vingle/st.visuali.finsburypark/)
## Release 0.16
* Add inputreadonly.js to set all input fields as disabled when they have the property readonly (this is required to disable radio elements) - see https://github.com/civicrm/civicrm-core/pull/16451
......
......@@ -24,9 +24,9 @@ class CRM_Haystack_ExtensionUtil {
* Translated text.
* @see ts
*/
public static function ts($text, $params = array()) {
public static function ts($text, $params = []) {
if (!array_key_exists('domain', $params)) {
$params['domain'] = array(self::LONG_NAME, NULL);
$params['domain'] = [self::LONG_NAME, NULL];
}
return ts($text, $params);
}
......@@ -82,7 +82,7 @@ use CRM_Haystack_ExtensionUtil as E;
/**
* (Delegated) Implements hook_civicrm_config().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_config
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config
*/
function _haystack_civix_civicrm_config(&$config = NULL) {
static $configured = FALSE;
......@@ -100,7 +100,7 @@ function _haystack_civix_civicrm_config(&$config = NULL) {
array_unshift($template->template_dir, $extDir);
}
else {
$template->template_dir = array($extDir, $template->template_dir);
$template->template_dir = [$extDir, $template->template_dir];
}
$include_path = $extRoot . PATH_SEPARATOR . get_include_path();
......@@ -112,7 +112,7 @@ function _haystack_civix_civicrm_config(&$config = NULL) {
*
* @param $files array(string)
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_xmlMenu
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_xmlMenu
*/
function _haystack_civix_civicrm_xmlMenu(&$files) {
foreach (_haystack_civix_glob(__DIR__ . '/xml/Menu/*.xml') as $file) {
......@@ -123,7 +123,7 @@ function _haystack_civix_civicrm_xmlMenu(&$files) {
/**
* Implements hook_civicrm_install().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_install
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install
*/
function _haystack_civix_civicrm_install() {
_haystack_civix_civicrm_config();
......@@ -135,12 +135,12 @@ function _haystack_civix_civicrm_install() {
/**
* Implements hook_civicrm_postInstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_postInstall
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_postInstall
*/
function _haystack_civix_civicrm_postInstall() {
_haystack_civix_civicrm_config();
if ($upgrader = _haystack_civix_upgrader()) {
if (is_callable(array($upgrader, 'onPostInstall'))) {
if (is_callable([$upgrader, 'onPostInstall'])) {
$upgrader->onPostInstall();
}
}
......@@ -149,7 +149,7 @@ function _haystack_civix_civicrm_postInstall() {
/**
* Implements hook_civicrm_uninstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_uninstall
*/
function _haystack_civix_civicrm_uninstall() {
_haystack_civix_civicrm_config();
......@@ -161,12 +161,12 @@ function _haystack_civix_civicrm_uninstall() {
/**
* (Delegated) Implements hook_civicrm_enable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_enable
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_enable
*/
function _haystack_civix_civicrm_enable() {
_haystack_civix_civicrm_config();
if ($upgrader = _haystack_civix_upgrader()) {
if (is_callable(array($upgrader, 'onEnable'))) {
if (is_callable([$upgrader, 'onEnable'])) {
$upgrader->onEnable();
}
}
......@@ -175,13 +175,13 @@ function _haystack_civix_civicrm_enable() {
/**
* (Delegated) Implements hook_civicrm_disable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_disable
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_disable
* @return mixed
*/
function _haystack_civix_civicrm_disable() {
_haystack_civix_civicrm_config();
if ($upgrader = _haystack_civix_upgrader()) {
if (is_callable(array($upgrader, 'onDisable'))) {
if (is_callable([$upgrader, 'onDisable'])) {
$upgrader->onDisable();
}
}
......@@ -193,10 +193,11 @@ function _haystack_civix_civicrm_disable() {
* @param $op string, the type of operation being performed; 'check' or 'enqueue'
* @param $queue CRM_Queue_Queue, (for 'enqueue') the modifiable list of pending up upgrade tasks
*
* @return mixed based on op. for 'check', returns array(boolean) (TRUE if upgrades are pending)
* for 'enqueue', returns void
* @return mixed
* based on op. for 'check', returns array(boolean) (TRUE if upgrades are pending)
* for 'enqueue', returns void
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_upgrade
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_upgrade
*/
function _haystack_civix_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
if ($upgrader = _haystack_civix_upgrader()) {
......@@ -217,22 +218,23 @@ function _haystack_civix_upgrader() {
}
/**
* Search directory tree for files which match a glob pattern
* Search directory tree for files which match a glob pattern.
*
* Note: Dot-directories (like "..", ".git", or ".svn") will be ignored.
* Note: In Civi 4.3+, delegate to CRM_Utils_File::findFiles()
*
* @param $dir string, base dir
* @param $pattern string, glob pattern, eg "*.txt"
* @return array(string)
* @param string $dir base dir
* @param string $pattern , glob pattern, eg "*.txt"
*
* @return array
*/
function _haystack_civix_find_files($dir, $pattern) {
if (is_callable(array('CRM_Utils_File', 'findFiles'))) {
if (is_callable(['CRM_Utils_File', 'findFiles'])) {
return CRM_Utils_File::findFiles($dir, $pattern);
}
$todos = array($dir);
$result = array();
$todos = [$dir];
$result = [];
while (!empty($todos)) {
$subdir = array_shift($todos);
foreach (_haystack_civix_glob("$subdir/$pattern") as $match) {
......@@ -243,7 +245,7 @@ function _haystack_civix_find_files($dir, $pattern) {
if ($dh = opendir($subdir)) {
while (FALSE !== ($entry = readdir($dh))) {
$path = $subdir . DIRECTORY_SEPARATOR . $entry;
if ($entry{0} == '.') {
if ($entry[0] == '.') {
}
elseif (is_dir($path)) {
$todos[] = $path;
......@@ -254,25 +256,27 @@ function _haystack_civix_find_files($dir, $pattern) {
}
return $result;
}
/**
* (Delegated) Implements hook_civicrm_managed().
*
* Find any *.mgd.php files, merge their content, and return.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_managed
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_managed
*/
function _haystack_civix_civicrm_managed(&$entities) {
$mgdFiles = _haystack_civix_find_files(__DIR__, '*.mgd.php');
sort($mgdFiles);
foreach ($mgdFiles as $file) {
$es = include $file;
foreach ($es as $e) {
if (empty($e['module'])) {
$e['module'] = E::LONG_NAME;
}
$entities[] = $e;
if (empty($e['params']['version'])) {
$e['params']['version'] = '3';
}
$entities[] = $e;
}
}
}
......@@ -284,7 +288,7 @@ function _haystack_civix_civicrm_managed(&$entities) {
*
* Note: This hook only runs in CiviCRM 4.4+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_caseTypes
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_caseTypes
*/
function _haystack_civix_civicrm_caseTypes(&$caseTypes) {
if (!is_dir(__DIR__ . '/xml/case')) {
......@@ -295,14 +299,13 @@ function _haystack_civix_civicrm_caseTypes(&$caseTypes) {
$name = preg_replace('/\.xml$/', '', basename($file));
if ($name != CRM_Case_XMLProcessor::mungeCaseType($name)) {
$errorMessage = sprintf("Case-type file name is malformed (%s vs %s)", $name, CRM_Case_XMLProcessor::mungeCaseType($name));
CRM_Core_Error::fatal($errorMessage);
// throw new CRM_Core_Exception($errorMessage);
throw new CRM_Core_Exception($errorMessage);
}
$caseTypes[$name] = array(
$caseTypes[$name] = [
'module' => E::LONG_NAME,
'name' => $name,
'file' => $file,
);
];
}
}
......@@ -313,7 +316,7 @@ function _haystack_civix_civicrm_caseTypes(&$caseTypes) {
*
* Note: This hook only runs in CiviCRM 4.5+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_angularModules
*/
function _haystack_civix_civicrm_angularModules(&$angularModules) {
if (!is_dir(__DIR__ . '/ang')) {
......@@ -331,6 +334,25 @@ function _haystack_civix_civicrm_angularModules(&$angularModules) {
}
}
/**
* (Delegated) Implements hook_civicrm_themes().
*
* Find any and return any files matching "*.theme.php"
*/
function _haystack_civix_civicrm_themes(&$themes) {
$files = _haystack_civix_glob(__DIR__ . '/*.theme.php');
foreach ($files as $file) {
$themeMeta = include $file;
if (empty($themeMeta['name'])) {
$themeMeta['name'] = preg_replace(':\.theme\.php$:', '', basename($file));
}
if (empty($themeMeta['ext'])) {
$themeMeta['ext'] = E::LONG_NAME;
}
$themes[$themeMeta['name']] = $themeMeta;
}
}
/**
* Glob wrapper which is guaranteed to return an array.
*
......@@ -341,11 +363,12 @@ function _haystack_civix_civicrm_angularModules(&$angularModules) {
*
* @link http://php.net/glob
* @param string $pattern
* @return array, possibly empty
*
* @return array
*/
function _haystack_civix_glob($pattern) {
$result = glob($pattern);
return is_array($result) ? $result : array();
return is_array($result) ? $result : [];
}
/**
......@@ -356,16 +379,18 @@ function _haystack_civix_glob($pattern) {
* 'Mailing', or 'Administer/System Settings'
* @param array $item - the item to insert (parent/child attributes will be