I am new to moodle. I have created a local plugin setmotd.
A new menu item is not getting added to Site Administration.
Using moodle 2.8.5
In lib.php i have placed function :
function local_setmotd_extends_settings_navigation($settingsnav, $context)
{
global $CFG, $PAGE;
/*
// Only let users with the appropriate capability see this settings item.
if( ! has_capability('local_plugin/setmotd:view', $context) )
{
return;
}
*/
if($settingnode = $settingsnav->find('root', navigation_node::TYPE_SETTING))
{
$setMotdMenuLbl = get_string('menutitle', 'local_setmotd');
$setMotdUrl = new moodle_url('/local/setmotd/set_motd.php');
$setMotdnode = navigation_node::create(
$setMotdMenuLbl,
$setMotdUrl,
navigation_node::NODETYPE_LEAF);
if ($PAGE->setMotdUrl->compare($setMotdUrl, URL_MATCH_BASE)) {
$setMotdnode->make_active();
}
$settingnode->add_node($setMotdnode);
}
}
Please help.
I am able to add menu item.I checked in moodle/lib/navigationlib.php , class settings_navigation in method load_administration_settings, the following line :
$referencebranch = $this->add(get_string('administrationsite'), null, self::TYPE_SITE_ADMIN, null, 'root');
So, with "root", the navigation_node type has to be TYPE_SITE_ADMIN, not
TYPE_SETTING.
In firefox firebug, I had earlier noticed in the ajax call for loading site administration menu, that the css class for "root" was named TYPE_SITE_ADMIN.
Note, that I am not yet able to make the new menu item active. So notice that, that part using $PAGE, is commented.
function local_setmotd_extends_settings_navigation(settings_navigation $settingsnav, context $context)
{
global $CFG, $PAGE;
/*
// Only let users with the appropriate capability see this settings item.
if( ! has_capability('local/setmotd:view', $context) )
{
return;
}
*/
$settingnode = $settingsnav->find('root', navigation_node::TYPE_SITE_ADMIN);
if( $settingnode )
{
$setMotdMenuLbl = get_string('menutitle', 'local_setmotd');
$setMotdUrl = new moodle_url('/local/setmotd/set_motd.php');
$setMotdnode = navigation_node::create(
$setMotdMenuLbl,
$setMotdUrl,
navigation_node::NODETYPE_LEAF);
/*
if ($PAGE->$setMotdUrl->compare($setMotdUrl, URL_MATCH_BASE)) {
$setMotdnode->make_active();
}
*/
$settingnode->add_node($setMotdnode);
}
}
Related
Is there a possibility in TYPO3 10 LTS to change the option fallbackType in the site configuration for a single page?
Background:
I use for the site the option fallbackType fallback. But for a few page I need fallbackType strict. Up to TYPO3 8 this could be achieved with a simple extension template and different config configurations. Is there a way in TYPO3 10?
As far as i know there is no possibility to configurate TYPO3 to behave in this way. The only way to override the language configuration for a single page is a custom middleware.
You can find a working example here: https://github.com/qbus-agentur/typo3-dynamic-language-mode.
I changed the main function:
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$lang = $this->getCurrentSiteLanguage($request);
$pageArguments = $this->getPageArguments($request);
if ($lang === null || $pageArguments === null) {
return $handler->handle($request);
}
// get current page ID
$currentRouting = $request->getAttribute('routing');
$currentPage = $currentRouting->getPageId();
$site = $request->getAttribute('site');
$default = $site->getLanguages()[0];
if ($lang->getLanguageId() !== $default->getLanguageId()) {
// Check if page is in $pagesWhereToChange and apply a dynamic language configuration in that case
if (in_array($currentPage, $this->pagesWhereToChange) > 0) {
\Closure::bind(function() use ($lang, $newId) {
$lang->fallbackType = 'free';
$lang->fallbackLanguageIds = [];
}, null, SiteLanguage::class)();
}
}
return $handler->handle($request);
}
Where $this->pagesWhereToChange is an array of pages:
/**
* pagesWhereToChange
*
* #var array
*/
protected $pagesWhereToChange = [30,41];
It's not possible to configure the array with typoscript because TSFE is not rendered yet.
I am using a custom plugin and I need to add the page title as one of the plugin's settings variables:
plugin.tx_fsearch {
settings {
resultsPath = search-results/brand/{field:title}/make/{field:title}
resultsPath.insertData = 1
}
}
However this is outputting the word 'Array' instead of the path I need.
Does anyone know how I might be able to make this work?
There is no stdWrap available for settings in extbase extensions, no matter if using TEXT cObj or insertData!
As a workaround, you can fix that yourself by doing something like EXT:news does here https://github.com/georgringer/news/blob/master/Classes/Controller/NewsController.php#L495
public function injectConfigurationManager(
\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
) {
$this->configurationManager = $configurationManager;
$typoScriptService = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Service\TypoScriptService::class);
$typoScriptArray = $typoScriptService->convertPlainArrayToTypoScriptArray($originalSettings);
$stdWrapProperties = GeneralUtility::trimExplode(',', $originalSettings['useStdWrap'], true);
foreach ($stdWrapProperties as $key) {
if (is_array($typoScriptArray[$key . '.'])) {
$originalSettings[$key] = $this->configurationManager->getContentObject()->stdWrap(
$originalSettings[$key],
$typoScriptArray[$key . '.']
);
}
}
}
$this->settings = $originalSettings;
}
Or you skip the TS part and call the stdWrap directly in your controller.
Try TEXT object
plugin.tx_fsearch {
settings {
resultsPath = TEXT
resultsPath.value = search-results/brand/{field.title}/make/{field.title}
}
}
I got a problem to save custom values for embededforms in root form.
I can actually edit a "manifestation" and i can add as much as i want "commande_wifi".
Everything is good saved.
I need to customize the process for every "commande_wifi" ( there is a 'puht' value depending on other values of the object() ). I have already lost a few hours only to do that.
save() is only called on the root form
That’s right! Only the root form has save() called. So if there’s other logic you want to run, you will want to override the saveEmbeddedForm method and call that code before. Oversimplification ahead: when you save a form with embedded forms, it calls $this->getObject()->save(), then it calls saveEmbeddedForms, which, for each embedded form, calls $form->saveEmbeddedForms() and then calls $form->getObject()->save(). This is critical to know, as it will save you a lot of headaches later on.
http://jmather.com/2011/01/29/6-things-to-know-about-embedded-forms-in-symfony/
I've tried to overwrite the saveembededForms() but fail at this point.
class manifestationForm extends BasemanifestationForm
{
public function configure()
{
$this->embedRelation('commande_wifi');
}
public function addNewFields($number){
$new_commandes = new BaseForm();
for($i=0; $i <= $number; $i+=1){
$commande = new Commande_wifi();
$commande->setManifestation($this->getObject());
$commande_form = new commande_wifiForm($commande);
$new_commandes->embedForm($i,$commande_form);
}
$this->embedForm('new', $new_commandes);
}
public function bind(array $taintedValues = null, array $taintedFiles = null){
$new_commandes = new BaseForm();
foreach($taintedValues['new'] as $key => $new_commande){
$commande = new Commande_wifi();
$commande->setManifestation($this->getObject());
$commande_form = new commande_wifiForm($commande);
$new_commandes->embedForm($key,$commande_form);
}
$this->embedForm('new',$new_commandes);
parent::bind($taintedValues, $taintedFiles);
}
public function saveEmbeddedForm($con = null, $forms = null)
{
if ($con === NULL)
{
$con = $this->getConnection();
}
if ($forms === NULL)
{
$forms = $this->getEmbeddedForms();
}
foreach ($forms as $form)
{
if ($form instanceof sfFormObject)
{
$form->saveEmbeddedForms($con);
$form->getObject()->setPuht(99);
$form->getObject()->save($con);
}
else
{
$this->saveEmbeddedForms($con, $form->getEmbeddedForms());
}
//$form->getObject()->setPuht(99)->save();
}
}
}
It's won ASAP i can access the embedForm Object().
Any suggestion?
I have a many to many relation between Product and Properties. I'm using embedRelation() in my Product form to edit a Product and it's Properties. Properties includes images which causes my issue. Every time I save the form the updated_at column is updated for file properties even when no file is uploaded.
Therefore, I want to exclude empty properties when saving my form.
I'm using Symfony 1.4 and Doctrine 1.2.
I'm thinking something like this in my ProductForm.class.php, but I need some input on how to make this work.
Thanks
class ProductForm extends BaseProductForm
{
public function configure()
{
unset($this['created_at'], $this['updated_at'], $this['id'], $this['slug']);
$this->embedRelation('ProductProperties');
}
public function saveEmbeddedForms($con = null, $forms = null)
{
if (null === $forms)
{
$properties = $this->getValue('ProductProperties');
$forms = $this->embeddedForms;
foreach($properties as $p)
{
// If property value is empty, unset from $forms['ProductProperties']
}
}
}
}
I ended up avoiding Symfony's forms and saving models instead of saving forms. It can be easier when playing with embedded forms. http://arialdomartini.wordpress.com/2011/04/01/how-to-kill-symfony%E2%80%99s-forms-and-live-well/
Solved it by checking if posted value is a file, and if both filename and value_delete is null I unset from the array. It might not be best practice, but it works for now.
Solution based on http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms
class ProductPropertyValidatorSchema extends sfValidatorSchema
{
protected function configure($options = array(), $messages = array())
{
// N0thing to configure
}
protected function doClean($values)
{
$errorSchema = new sfValidatorErrorSchema($this);
foreach($values as $key => $value)
{
$errorSchemaLocal = new sfValidatorErrorSchema($this);
if(array_key_exists('value_delete', $values))
{
if(!$value && !$values['value_delete'])
{
unset($values[$key]);
}
}
// Some error for this embedded-form
if (count($errorSchemaLocal))
{
$errorSchema->addError($errorSchemaLocal, (string) $key);
}
}
// Throws the error for the main form
if (count($errorSchema))
{
throw new sfValidatorErrorSchema($this, $errorSchema);
}
return $values;
}
}
Our Zend_Log is initialized by only adding the following lines to application.ini
resources.log.stream.writerName = "Stream"
resources.log.stream.writerParams.mode = "a"
So Zend_Application_Resource_Log will create the instance for us.
We are already able to access this instance in controllers via the following:
public function getLog()
{
$bootstrap = $this->getInvokeArg('bootstrap');
//if (is_null($bootstrap)) return false;
if (!$bootstrap->hasPluginResource('Log')) {
return false;
}
$log = $bootstrap->getResource('Log');
return $log;
}
So far, so good.
Now we want to use the same log instance in model classes, where we can not access the bootstrap.
Our first idea was to register the very same Log instance in Zend_Registry to be able to use Zend_Registry::get('Zend_Log') everywhere we want:
in our Bootstrap class:
protected function _initLog() {
if (!$this->hasPluginResource('Log')) {
throw new Zend_Exception('Log not enabled');
}
$log = $this->getResource('Log');
assert( $log != null);
Zend_Registry::set('Zend_Log', $log);
}
Unfortunately this assertion fails ==> $log IS NULL --- but why??
It is clear that we could just initialize the Zend_Log manually during bootstrapping without using the automatism of Zend_Application_Resource_Log, so this kind of answers will not be accepted.
This is the final solution. We basically shall not call the function _initLog()
Big thanks to ArneRie!
// Do not call this function _initLog() !
protected function _initRegisterLogger() {
$this->bootstrap('Log');
if (!$this->hasPluginResource('Log')) {
throw new Zend_Exception('Log not enabled in config.ini');
}
$logger = $this->getResource('Log');
assert($logger != null);
Zend_Registry::set('Zend_Log', $logger);
}
Possible it is not bootstraped at this time, try:
try {
$this->bootstrap('log'); // bootstrap log
$logger = $this->getResource('log');
} catch (Zend_Application_Bootstrap_Exception $e) {
$logger = new Zend_Log();
$writer = new Zend_Log_Writer_Null();
$logger->addWriter($writer);
}
$registry = Zend_Registry::set('logger', $logger);