I'm working on a webiste that has one store already live and I'm trying to make the second store/website working.
The new website has a template that includes some observers that even if I disable the modules through System -> Configuration -> Advanced as this this only Disable Modules Output not the actual module, therefore if there are any Observers they will still be loaded and will run.
Searched online and didn't found a complete solution for this. On this other post the user Eric Hainer proposed a solution to that allows to load modules depending checking the $_SERVER['MAGE_RUN_CODE'] variable but this does not work if you have cache active as when you load the store that has the modules in it will put them in the cache.
So my solution was to modify the file
app/code/core/Mage/Core/Model/Config/Options.php to save the cache on different folders depending on the store
First I copied the file to app/code/local/Mage/Core/Model/Config/Options.php to avoid changing a core file
and on the constructor added this lines
//custom code to save cache on different folders per website
$runCode = (isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default');
$this->_data['cache_dir'] = $this->_data['var_dir'].DS.'cache'.$runCode;
Here is how the constructor looks like
protected function _construct()
{
$appRoot= Mage::getRoot();
$root = dirname($appRoot);
$this->_data['app_dir'] = $appRoot;
$this->_data['base_dir'] = $root;
$this->_data['code_dir'] = $appRoot.DS.'code';
$this->_data['design_dir'] = $appRoot.DS.'design';
$this->_data['etc_dir'] = $appRoot.DS.'etc';
$this->_data['lib_dir'] = $root.DS.'lib';
$this->_data['locale_dir'] = $appRoot.DS.'locale';
$this->_data['media_dir'] = $root.DS.'media';
$this->_data['skin_dir'] = $root.DS.'skin';
$this->_data['var_dir'] = $this->getVarDir();
$this->_data['tmp_dir'] = $this->_data['var_dir'].DS.'tmp';
//custom code to save cache on different folders per website
$runCode = (isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default');
$this->_data['cache_dir'] = $this->_data['var_dir'].DS.'cache'.$runCode;
$this->_data['log_dir'] = $this->_data['var_dir'].DS.'log';
$this->_data['session_dir'] = $this->_data['var_dir'].DS.'session';
$this->_data['upload_dir'] = $this->_data['media_dir'].DS.'upload';
$this->_data['export_dir'] = $this->_data['var_dir'].DS.'export';
}
This will do the job but there are some issues:
Clear cache will probably not work
Updates will not be applied automatically as we copied this files from core
Is there any other way to do this?
This post continues here
Disable the module output per store in the backend under advanced. Then edit your module observer functions and check for that configuration to disable the complete module functionality:
if(Mage::getStoreConfigFlag('advanced/modules_disable_output/YOUR_MODULE'))
return false;
Most community modules already have it's own configuration to enable/disable functionality per store.
Related
I'm new to moodle plugin development and am trying to create a plugin that displays a page to the admin where I can add my on php code.
In brief, what I want the plugin to do I have already achieved in a standard php file that I upload to the moodle root. From here you can call the file e.g. yourdomain.co.uk/moodlelocation/myfile.php and it will run as expected.
The problem with this is it isn't secure since anyone can load the myfile.php and in turn run the scripts on the page. It also means any one else using this script (it will be given away for free when complete) would need to FTP into their hosting and upload two php files to their moodle install.
Due to this, I thought a plugin (a very very basic plugin) may be the best solution. They could then load the page in the admin via the "site administration". e.g. site administration > Development > MyPlugin. I am assuming I could then also restrict the plugin's main page to admins only (??).
So to recap, I can create a php page that has my script all rocking and rolling BUT I need to make this into a plugin.
I did some reading and I think a "local" plugin was the easiest way to go (??).
I have managed to get the local plugin up and running using the below in local/webguides/inex.php :
<?php
// Standard config file and local library.
require_once(__DIR__ . '/../../config.php');
// Setting up the page.
$PAGE->set_context(context_system::instance());
$PAGE->set_pagelayout('standard');
$PAGE->set_title("webguides");
$PAGE->set_heading("webguides");
$PAGE->set_url(new moodle_url('/local/webguides/index.php'));
// Ouput the page header.
echo $OUTPUT->header();
echo 'MY php CODE here etc';
?>
This works fine but with two problems:
Anyone can access it via http://domain/local/webguides/index.php
There is no link to it in the site administration (so the user would need to type the URL in).
Can anyone shed any light how I would achieve the two steps above?
Thanks in advance
p.s. ideally I'd like to keep the plugin to as few files as possible so if the required code could be added to the local/webguides/index.php file it would be preferred.
You need to create a capability, then require that capability before displaying the page.
First, have a look at local/readme.txt - this gives an overview of the files needed for a local plugin.
Or read the documentation at https://docs.moodle.org/dev/Local_plugins
Also have a look at existing local plugins so you can see how they are created - https://moodle.org/plugins/?q=type:local
At a bare minimum, you need
local/webguides/db/access.php - this will have the capability
local/webguides/lang/en/local_webguides.php
local/webguides/version.php
Plus your index file
local/webguides/index.php
In the db/access.php file have something like
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
'local/webguides:view' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => array(
),
),
);
You might also need 'riskbitmask' => RISK_XXX depending on if there are any risks in you code. Such as RISK_CONFIG, RISK_PERSONAL, etc.
In lang/en/local_webguides.php have something like
defined('MOODLE_INTERNAL') || die();
$string['pluginname'] = 'Webguides';
$string['webguides:view'] = 'Able to view webguids';
In version.php have something like
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2020051901; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2015051109; // Requires this Moodle version.
$plugin->component = 'local_webguides'; // Full name of the plugin (used for diagnostics).
Replace 2015051109 with the version of Moodle you are using - this will be in version.php in the root folder.
Then in your index.php file use this near the top.
require_capability('local/webguides:view', context_system::instance());
So only users with that capability will have access to the page.
EDIT:
You can add a link via settings.php using something like
defined('MOODLE_INTERNAL') || die;
if ($hassiteconfig) {
$page = new admin_externalpage(
'local_webguides',
get_string('pluginname', 'local_webguides'),
new moodle_url('/local/webguides/index.php'),
'local/webguides:view'
);
$ADMIN->add('localplugins', $page);
}
Then in your index page ad this
require_once($CFG->libdir.'/adminlib.php');
and remove require_login() and require_capability() and replace with
admin_externalpage_setup('local_webguides');
I'm using the drupal FAQ module which sends an email to the admin including the authors username as hyperlink, defined via:
'creator' => theme('username', array('account' => user_load($node->uid), 'plain' => TRUE)),
http://cgit.drupalcode.org/faq_ask/tree/faq_ask.module?id=9f4fbb7859c8fc24977f5d67cd589685236e442d#n480
unfortunately it only links to /users/joeblock and thus missing the site url https://example.com which means it won't work in emails.
Joe Block
I already tried the module pathologic hoping it adds the site url but didn't help (perhaps because the rendered ahref includes a / infront of it).
Is it possible to modify the hyperlink just for this instance to insert the siteurl?
Update:
adding $variables['link_options']['absolute'] = true;into includes/theme.inc worked.
function theme_username($variables) {
if (isset($variables['link_path'])) {
// We have a link path, so we should generate a link using l().
// Additional classes may be added as array elements like
// $variables['link_options']['attributes']['class'][] = 'myclass';
$variables['link_options']['absolute'] = true;
$output = l($variables['name'] . $variables['extra'], $variables['link_path'], $variables['link_options']);
}
Yes, it's possible! the faq module uses the theme username. This theme is defined in includes/theme.inc function theme_username
In your custom theme you can implement the template_process_username hook and alter the $variables array.
The theme username uses the url function to create the url. This function accepts the absolute attribute to build an absolute url.
to create this function you can create a custom theme https://www.drupal.org/docs/7/theming/howto/create-a-new-custom-theme-with-css-alone and put the yourthemename_process_username function inside the template.php file of your custom theme.
Otherwise you can add the function in a custom module.
Let's do an example with a custom module (with the markus name) because is much more common to create a custom module than a custom theme.
Create the site/all/modules/custom/markus directory.
Inside this directory create the markus.module file with this content:
<?php
function markus_node_presave($node){
if( $node->type == 'faq' ){
drupal_static('markus_faq_node_save', true);
}
}
function markus_process_username( &$variables ){
if( drupal_static('markus_faq_node_save', false) ){
// alter the link_options only when you came from the ask module otherwise, without
// this if, all the username links in drupal will be absolute url.
// Actually this is not a problem but it may be overkilling
$variables['link_options']['absolute'] = true;
}
}
create the markus.info file inside the markus directory with this content:
name = markus
description = "my custom module"
core = 7.x
package = "markus"
Now from the admin menu enable your theme.
It's better to implement the markus_process_username function in a custom module and not to edit the includes/theme.inc file because in this way you can update drupal much more easly. The drupal core should never be edited :)
In Prestashop 1.6, from a FrontController, I have to send a mail to the administrator of the Shop.
This part works well but I got problems to include a link to the administration page of a specific customer.
The only thing I miss is the name of the administration directory. I would be able to parse and concatenate the PS_ADMIN_DIR constant but it is not available from the FrontController.
I'm kinda stuck here.
Here is the code :
$admin_customer_link =
_PS_BASE_URL_
.__PS_BASE_URI__
/* Missing the Administration directory name here */
.$this->context->link->getAdminLink('AdminCustomers', false)
."&id_customer=".(int)$customer->id."&viewcustomer";
The output I got :
http://127.0.0.1:8080/prestashop/index.php?controller=AdminCustomers&id_customer=2&viewcustomer
The output I need :
http://127.0.0.1:8080/prestashop/administration/index.php?controller=AdminCustomers&id_customer=2&viewcustomer
Any help will be appreciated.
There is no (standard) way to know the administration folder from a front controller, otherwise all the security will flushed down the toilet :).
What you can do is to retrieve the administration folder from the module 'configuration' or when you install it, and save it somewhere, at the moment I suggest into the database but maybe there is a more safely mode.
Something like:
public function install()
{
// your stuff
$current_dir = $_SERVER['PHP_SELF']; // this give you the current dir (administration folder included)
$administration_folder = /* Clean your string with a string replace or preg */
Configuration::updateValue('PS_MYMOD_ADMIN_DIR', $administration_folder);
return true;
}
Then in your front controller retrieve it by:
$adminfolder = Configuration::get('PS_MYMOD_ADMIN_DIR');
However I hope you know that you're creating a security breach through e-mail...
Hope it helps
Since the use of the administration directory name from the Front End and sending a link to the administration in e-mail is not a good idea for security purpose, I choose to implement this another way.
Instead of send the administration customer's page link to the webmaster by e-mail, I create a new customer Thread and message. After that, I send an e-mail to the customer service. So, when they log in the Back Office, they see a new notification who leads them to the specific user.
Here is the code :
ModuleFrontController
// Create a new Customer Thread
$ct = new CustomerThread();
if (isset($customer->id)) {
$ct->id_customer = (int)$customer->id;
}
$ct->id_shop = (int)$this->context->shop->id;
$ct->id_contact = $contact->id;
$ct->id_lang = (int)$this->context->language->id;
$ct->email = $customer->email;
$ct->status = 'open';
$ct->token = Tools::passwdGen(12);
$ct->add();
// Add a new message to the Customer Thread
if ($ct->id) {
$cm = new CustomerMessage();
$cm->id_customer_thread = $ct->id;
$cm->message = $message;
$cm->ip_address = (int)ip2long(Tools::getRemoteAddr());
$cm->user_agent = $_SERVER['HTTP_USER_AGENT'];
$cm->add();
}
Hope it helps someone in the same situation.
I stored several values in new fields of my plugin in the settings.php
However now I'm trying to put those values that I made onscreen, and I couldn't find a way to do that in moodle. Is there a way to do this in Moodle?
Any help is greatly appreciated. Thanks!
If you named the setting in settings.php something like 'PLUGINNAME/SETTINGNAME' (e.g. in the enrol_manual core plugin has a setting called 'enrol_manual/expiredaction'), then you can retrieve a single setting via:
$value = get_config('PLUGINNAME', 'SETTINGNAME');
$value = get_config('enrol_maual', 'expiredaction'); // For example.
If you want all the settings for a given plugin, then you can call:
$values = get_config('PLUGINNAME');
$values = get_config('enrol_manual'); // For example.
If, however, you've followed the bad practice of several of the settings for older core plugins, and the setting is called something like 'MYPLUGIN_SETTINGNAME', then you can retrieve the setting by calling:
$value = get_config('core', 'PLUGINNAME_SETTINGNAME');
$value = get_config('core', 'forum_displaymode'); // For example.
OR
global $CFG;
$value = $CFG->PLUGINNAME_SETTINGNAME;
$value = $CFG->forum_displaymode; // For example.
Naming settings without the '/' is bad, as it means the settings are loaded into the main $CFG global, which is already pretty bloated. Organising them into plugins also means all the plugin settings can be loaded as a simple object.
hi i have a custom script that I call with ajax to retrieve some db info but for some reason it will not allow me to make the calls from this file. yet when i put the code in a page in the templates diretory lets say tpl_products_all_default.php they run fine. what do i need to do to be able to run queries from a custom script?
$sql = "select products_model from products where products_model = :productMdel:";
$sql = $db->bindVars($sql, ':productMdel:', 'C021', 'string');
$result = $db->Execute($sql);
if ($result->RecordCount() > 0) {
echo 'Model number = ' . $result->fields['products_model'];
} else {
echo 'Sorry, no record found for product number ' . $theProductId;
}
I may have an answer for you, though I'll admit it's not an optimal setup as it requires your custom file to be placed into the root directory.
If your custom file is being placed in the root (/your_custom_file.php) you can do the following to get access to the $db with the following require statement:
require('includes/application_top.php');
This will initialize all of the globals, and also call the includes/initsystem.php, which will spin through the values in the autoloader and include each script. The auto_loader can be viewed at includes/auto_loaders/config.core.php. In v1.5, you can see it finally includes the init_database.php script on lines 81-82. The init_database.php file finally initializes $db.
I initially ran into the same issue you had, and almost missed this setup because I had originally added my custom files to a custom directory like /my_module_extensions/my_file.php which failed. It seems the application_top.php loads everything with relative paths, so when executing under a directory other than the root, it would fail.
I hope this helps!
EDIT: Originally thought you were talking about an admin customization. I reworded this to relate to the public side. This also works from the admin side, if you need to extend the admin console.
Not true you can use an include from anywhere.
such as:
require_once('inc/php/application_top.php');
or
require_once('http://example.com/inc/php/application_top.php');