Site Controller Support #116

Closed
opened 2017-08-30 23:17:14 +00:00 by mwweb · 3 comments
mwweb commented 2017-08-30 23:17:14 +00:00 (Migrated from github.com)

This is just a thought that I had for JCB.

I know that site controllers can currently be added using Component->component name ->settings tab->Files.

While this works, I think it would be good to have optional site controllers available within JCB. That way, the headers and copyright info remains updates and current, and keeps all files in the same area for maintenance.

My thoughts on how to add this, since controllers are more or less specialized, it could almost be like custom codes, where you have System Name, then instead of function name it would be controller name. Lastly, there would be the text area, but rather than custom code, it would be controller code.

Lastly, in Component->Settings, add another repeatable field below Site Views called Site Controllers.

When compiled, using Sermon Distributor as an example, if system name for a controller was Preacher, and the controller name was preacher, JCB would "copy" that code into a preacher.php file in the site/controllers folder with the header, copyright, and version info.

This is just a thought on extending JCB another step forward. This came about from my BIG component project, finally getting released this weekend, that has 10 site controller, and it would be nice having them all in a centralized location for maintaining.

Eventually this might be able to be built out more, but just integrating something basic for starters would be a good step.

This is just a thought that I had for JCB. I know that site controllers can currently be added using Component->component name ->settings tab->Files. While this works, I think it would be good to have optional site controllers available within JCB. That way, the headers and copyright info remains updates and current, and keeps all files in the same area for maintenance. My thoughts on how to add this, since controllers are more or less specialized, it could almost be like custom codes, where you have System Name, then instead of function name it would be controller name. Lastly, there would be the text area, but rather than custom code, it would be controller code. Lastly, in Component->Settings, add another repeatable field below Site Views called Site Controllers. When compiled, using Sermon Distributor as an example, if system name for a controller was Preacher, and the controller name was preacher, JCB would "copy" that code into a preacher.php file in the site/controllers folder with the header, copyright, and version info. This is just a thought on extending JCB another step forward. This came about from my BIG component project, finally getting released this weekend, that has 10 site controller, and it would be nice having them all in a centralized location for maintaining. Eventually this might be able to be built out more, but just integrating something basic for starters would be a good step.

Okay so controllers are usually there for forms, and buttons. So we did add ways to add controllers to site-views and to custom-admin-views, and even to extend admin-views. Via the Custom-Buttons tab, when you create a custom button, it opens place to add controller methods, and model methods. This way the controllers used in that view is edited in that view.

That way of adding controller custom script and so adding controllers is actually extremely powerful.

Remember the moment you have any custom script in JCB that you are using over and over, use custom coding area, and then just place the placeholder in the actual view or component's custom script area. This way you do not need to repeat yourself, and yet start forming a consistent improvement to all use cases if improving the custom code in the main custom code area.

This is what I have done, I have basic controller methods for various kind of controller tasks, and just pass the dynamic names to the custom code, and so I can place the code in all views were I need, event if I need a call to a method with this or that kind of value, and so safe my self so much time in typing it, or even coping it if I improve it in one place. I then in turn also have methods that are basically doing the same thing over and over in the models... and so I use the same approach.

Custom Coding is one of the hidden features of JCB that can make your life so much easier if you can start thinking of it as a way to do polymorphism inside JCB.

Okay I am getting a little of point here. But I hope you see that we already have a very dynamic, building centralized (in views) controller building concept. That you may over look, if you have not played with the custom buttons area.

You don't need to actually add a button to use the custom scripting areas. But the site and custom admin view actually allows you to add the buttons to your "Default View" area via a place holder called [[[SITE_TOOLBAR]]]

But if you write the buttons yourself, that target the controller... you can still add the custom controller methods in those PHP areas under the buttons modal.

Okay so controllers are usually there for forms, and buttons. So we did add ways to add controllers to site-views and to custom-admin-views, and even to extend admin-views. Via the Custom-Buttons tab, when you create a custom button, it opens place to add controller methods, and model methods. This way the controllers used in that view is edited in that view. That way of adding controller custom script and so adding controllers is actually extremely powerful. Remember the moment you have any custom script in JCB that you are using over and over, use custom coding area, and then just place the placeholder in the actual view or component's custom script area. This way you do not need to repeat yourself, and yet start forming a consistent improvement to all use cases if improving the custom code in the main custom code area. This is what I have done, I have basic controller methods for various kind of controller tasks, and just pass the dynamic names to the custom code, and so I can place the code in all views were I need, event if I need a call to a method with this or that kind of value, and so safe my self so much time in typing it, or even coping it if I improve it in one place. I then in turn also have methods that are basically doing the same thing over and over in the models... and so I use the same approach. Custom Coding is one of the hidden features of JCB that can make your life so much easier if you can start thinking of it as a way to do polymorphism inside JCB. Okay I am getting a little of point here. But I hope you see that we already have a very dynamic, building centralized (in views) controller building concept. That you may over look, if you have not played with the custom buttons area. You don't need to actually add a button to use the custom scripting areas. But the site and custom admin view actually allows you to add the buttons to your "Default View" area via a place holder called `[[[SITE_TOOLBAR]]]` But if you write the buttons yourself, that target the controller... you can still add the custom controller methods in those PHP areas under the buttons modal.

You do realize that you can call any controller from any other view... so you could use just one view to handle all your controller calls... instead of 10 controllers you can have one. Call the site view API, and then name the methods what you would like to do with your API, and if cross site posting should be checked, if must be a registered use of the site. so lets say I have a method in your controller.

public function backup()
{
	// get params
	if (!isset($this->params) || ![[[Component]]]Helper::checkObject($this->params))
	{
		$this->params = JComponentHelper::getParams('com_[[[component]]]');
	}
	// get all component IDs to backup
	$pks = [[[component]]]Helper::getComponentIDs();
	// Get the model
	$model = [[[component]]]Helper::getModel('joomla_components', JPATH_ADMINISTRATOR . '/components/com_[[[component]]]');
	// set user
	$model->user = $this->getApiUser();
	// make sure to set active type to backup
	$model->activeType = '[[[arg0]]]';
	// set auto loader
	[[[Component]]]Helper::autoLoader('smart');
	// manual backup message
	$backupNotice = array();
	// get the data to export
	if ([[[Component]]]Helper::checkArray($pks) && $model->getSmartExport($pks))
	{
		$backupNotice[] = JText::_('Backup was done successfully');
		$backupNoticeStatus = 'Success';
		// set the key string
		if ([[[component]]]Helper::checkString($model->key) && strlen($model->key) == 32)
		{
			$textNotice = array();
			$keyNotice = '<h1>' . JText::sprintf('The package key is: <code>%s</code>', $model->key) . '</h1>';
			$textNotice[] = JText::sprintf('The package key is: %s', $model->key);
			$keyNotice .= JText::_('Your data is encrypted with a AES 128 bit encryption using the above 32 character key. Without this key it will take the current technology with a brute force attack method more then <a href="http://random-ize.com/how-long-to-hack-pass/" target="_blank" title="How long to hack pass">700 000 000 000 000 000 000 000 000 000 000</a> years to crack theoretically. Unless they have this key above, so do keep it safe.') . '<br />';
			// set the package owner info
			if ((isset($model->info['getKeyFrom']['company']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['company'])) || (isset($model->info['getKeyFrom']['owner']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['owner'])))
			{
				$ownerDetails = '<h2>' . JText::_('Package Owner Details') . '</h2>';
				$textNotice[] = '# ' . JText::_('Package Owner Details');
				$ownerDetails .= '<ul>';
				if (isset($model->info['getKeyFrom']['company']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['company']))
				{
					$ownerDetails .= '<li>' . JText::sprintf('<em>Company:</em> <b>%s</b>', $model->info['getKeyFrom']['company']) . '</li>';
					$textNotice[] = '- ' . JText::sprintf('Company: %s', $model->info['getKeyFrom']['company']);
				}
				// add value only if set
				if (isset($model->info['getKeyFrom']['owner']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['owner']))
				{
					$ownerDetails .= '<li>' . JText::sprintf('<em>Owner:</em> <b>%s</b>', $model->info['getKeyFrom']['owner']) . '</li>';
					$textNotice[] = '- ' . JText::sprintf('Owner: %s', $model->info['getKeyFrom']['owner']);
				}
				// add value only if set
				if (isset($model->info['getKeyFrom']['website']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['website']))
				{
					$ownerDetails .= '<li>' . JText::sprintf('<em>Website:</em> <b>%s</b>', $model->info['getKeyFrom']['website']) . '</li>';
					$textNotice[] = '- ' . JText::sprintf('Website: %s', $model->info['getKeyFrom']['website']);
				}
				// add value only if set
				if (isset($model->info['getKeyFrom']['email']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['email']))
				{
					$ownerDetails .= '<li>' . JText::sprintf('<em>Email:</em> <b>%s</b>', $model->info['getKeyFrom']['email']) . '</li>';
					$textNotice[] = '- ' . JText::sprintf('Email: %s', $model->info['getKeyFrom']['email']);
				}
				// add value only if set
				if (isset($model->info['getKeyFrom']['license']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['license']))
				{
					$ownerDetails .= '<li>' . JText::sprintf('<em>License:</em> <b>%s</b>', $model->info['getKeyFrom']['license']) . '</li>';
					$textNotice[] = '- ' . JText::sprintf('License: %s', $model->info['getKeyFrom']['license']);
				}
				// add value only if set
				if (isset($model->info['getKeyFrom']['copyright']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['copyright']))
				{
					$ownerDetails .= '<li>' . JText::sprintf('<em>Copyright:</em> <b>%s</b>', $model->info['getKeyFrom']['copyright']) . '</li>';
					$textNotice[] = '- ' . JText::sprintf('Copyright: %s', $model->info['getKeyFrom']['copyright']);
				}							
				$ownerDetails .= '</ul>';
				$backupNotice[] = JText::_('Owner details was set');
			}
			else
			{
				$ownerDetails = '<h2>' . JText::_('Package Owner Not Set') . '</h2>';
				$textNotice[] = '# ' . JText::_('Package Owner Details');
				$ownerDetails .= JText::_('To change the package owner defaults. Open the <b>JCB Global Options</b>, go to the <b>Company</b> tab and add the correct company details there.') . '<br />';
				$textNotice[] = JText::_('To change the package owner defaults. Open the JCB Global Options, go to the Company tab and add the correct company details there.');
				$ownerDetails .= '<h3>' . JText::_('You should add the correct owner details.') . '</h3>';
				$textNotice[] = '## ' .  JText::_('You should add the correct owner details.');
				$ownerDetails .= JText::_('Since the owner details are displayed during <b>import process</b> before adding the key, this way if the user/dev <b>does not</b> have the key they can see <b>where to get it</b>.') . '<br />';
				$textNotice[] = JText::_('Since the owner details are displayed during import process before adding the key, this way if the user/dev does not have the key they can see where to get it.');
				$backupNotice[] = JText::_('Check your owner details, it has not been set. Open the JCB Global Options, go to the Company tab and add the correct company details there.');
			}
		}
		else
		{
			$keyNotice = '<h1>' . JText::_('This package has no key.') . '</h1>';
			$textNotice[] = '# ' . JText::_('This package has no key.');
			$ownerDetails = JText::_('That means anyone who has this package can install it into JCB. To add an export key simply open the component, go to the tab called <b>settings</b>, bottom right there is a field called <b>Export Key</b>.') . '<br />';
			$textNotice[] = JText::_('That means anyone who has this package can install it into JCB. To add an export key simply open the component, go to the tab called settings, bottom right there is a field called Export Key.');
			$backupNotice[] = JText::_('No keys were found. To add an export key simply open the component, go to the tab called settings, bottom right there is a field called Export Key.');
		}
		// get email
		if ($email = $this->params->get('backup_email', null))
		{
			// plain text
			$plainText = implode("\n", $textNotice);
			// set hash to track changes
			$hashTracker = md5($plainText);
			if ([[[Component]]]Helper::newHash($hashTracker))
			{
				// Build final massage.
				$message = $keyNotice . $ownerDetails . '<br /><small>HASH: ' . $hashTracker . '</small>';
				// set the subject
				$subject = JText::_('Joomla Component Builder - Backup Key');
				// email the message
				[[[component]]]Email::send($email, $subject, [[[component]]]Email::setTableBody($message, $subject), $plainText, 1);
				$backupNotice[] = JText::_('Email with the new key was send');
			}
			else
			{
				$backupNotice[] = JText::_('Key has not changed');
			}
		}
	}
	else
	{
		$backupNotice[] = JText::_('Backup failed, please try again. If the error continue, please contact your system administrator.');
		$backupNoticeStatus = 'Error';
		if ([[[component]]]Helper::checkString($model->packagePath))
		{
			// clear all if not successful
			[[[Component]]]Helper::removeFolder($model->packagePath);
		}
		if ([[[component]]]Helper::checkString($model->zipPath))
		{
			// clear all if not successful
			JFile::delete($model->zipPath);
		}				
	}
	// quite only if auto backup (adding this script from custom code :)
	if ('backup' === '[[[arg0]]]')
	{
		echo "# " . $backupNoticeStatus . "\n" .implode("\n", $backupNotice);
		jexit();
	}
	$this->setRedirect(JRoute::_('index.php?option=com_[[[component]]]&view=joomla_components', false), implode("<br />", $backupNotice), $backupNoticeStatus);
	return;
}

Now the link to this Controller will all around the site will look like this:
<a href="/index.php?option=com_[[[component]]]&task=api.backup">Backup</a>
I am sure you know this, but just for any other that my stumble upon this post.

You do realize that you can call any controller from any other view... so you could use just one view to handle all your controller calls... instead of 10 controllers you can have one. Call the site view API, and then name the methods what you would like to do with your API, and if cross site posting should be checked, if must be a registered use of the site. so lets say I have a method in your controller. ``` public function backup() { // get params if (!isset($this->params) || ![[[Component]]]Helper::checkObject($this->params)) { $this->params = JComponentHelper::getParams('com_[[[component]]]'); } // get all component IDs to backup $pks = [[[component]]]Helper::getComponentIDs(); // Get the model $model = [[[component]]]Helper::getModel('joomla_components', JPATH_ADMINISTRATOR . '/components/com_[[[component]]]'); // set user $model->user = $this->getApiUser(); // make sure to set active type to backup $model->activeType = '[[[arg0]]]'; // set auto loader [[[Component]]]Helper::autoLoader('smart'); // manual backup message $backupNotice = array(); // get the data to export if ([[[Component]]]Helper::checkArray($pks) && $model->getSmartExport($pks)) { $backupNotice[] = JText::_('Backup was done successfully'); $backupNoticeStatus = 'Success'; // set the key string if ([[[component]]]Helper::checkString($model->key) && strlen($model->key) == 32) { $textNotice = array(); $keyNotice = '<h1>' . JText::sprintf('The package key is: <code>%s</code>', $model->key) . '</h1>'; $textNotice[] = JText::sprintf('The package key is: %s', $model->key); $keyNotice .= JText::_('Your data is encrypted with a AES 128 bit encryption using the above 32 character key. Without this key it will take the current technology with a brute force attack method more then <a href="http://random-ize.com/how-long-to-hack-pass/" target="_blank" title="How long to hack pass">700 000 000 000 000 000 000 000 000 000 000</a> years to crack theoretically. Unless they have this key above, so do keep it safe.') . '<br />'; // set the package owner info if ((isset($model->info['getKeyFrom']['company']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['company'])) || (isset($model->info['getKeyFrom']['owner']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['owner']))) { $ownerDetails = '<h2>' . JText::_('Package Owner Details') . '</h2>'; $textNotice[] = '# ' . JText::_('Package Owner Details'); $ownerDetails .= '<ul>'; if (isset($model->info['getKeyFrom']['company']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['company'])) { $ownerDetails .= '<li>' . JText::sprintf('<em>Company:</em> <b>%s</b>', $model->info['getKeyFrom']['company']) . '</li>'; $textNotice[] = '- ' . JText::sprintf('Company: %s', $model->info['getKeyFrom']['company']); } // add value only if set if (isset($model->info['getKeyFrom']['owner']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['owner'])) { $ownerDetails .= '<li>' . JText::sprintf('<em>Owner:</em> <b>%s</b>', $model->info['getKeyFrom']['owner']) . '</li>'; $textNotice[] = '- ' . JText::sprintf('Owner: %s', $model->info['getKeyFrom']['owner']); } // add value only if set if (isset($model->info['getKeyFrom']['website']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['website'])) { $ownerDetails .= '<li>' . JText::sprintf('<em>Website:</em> <b>%s</b>', $model->info['getKeyFrom']['website']) . '</li>'; $textNotice[] = '- ' . JText::sprintf('Website: %s', $model->info['getKeyFrom']['website']); } // add value only if set if (isset($model->info['getKeyFrom']['email']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['email'])) { $ownerDetails .= '<li>' . JText::sprintf('<em>Email:</em> <b>%s</b>', $model->info['getKeyFrom']['email']) . '</li>'; $textNotice[] = '- ' . JText::sprintf('Email: %s', $model->info['getKeyFrom']['email']); } // add value only if set if (isset($model->info['getKeyFrom']['license']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['license'])) { $ownerDetails .= '<li>' . JText::sprintf('<em>License:</em> <b>%s</b>', $model->info['getKeyFrom']['license']) . '</li>'; $textNotice[] = '- ' . JText::sprintf('License: %s', $model->info['getKeyFrom']['license']); } // add value only if set if (isset($model->info['getKeyFrom']['copyright']) && [[[component]]]Helper::checkString($model->info['getKeyFrom']['copyright'])) { $ownerDetails .= '<li>' . JText::sprintf('<em>Copyright:</em> <b>%s</b>', $model->info['getKeyFrom']['copyright']) . '</li>'; $textNotice[] = '- ' . JText::sprintf('Copyright: %s', $model->info['getKeyFrom']['copyright']); } $ownerDetails .= '</ul>'; $backupNotice[] = JText::_('Owner details was set'); } else { $ownerDetails = '<h2>' . JText::_('Package Owner Not Set') . '</h2>'; $textNotice[] = '# ' . JText::_('Package Owner Details'); $ownerDetails .= JText::_('To change the package owner defaults. Open the <b>JCB Global Options</b>, go to the <b>Company</b> tab and add the correct company details there.') . '<br />'; $textNotice[] = JText::_('To change the package owner defaults. Open the JCB Global Options, go to the Company tab and add the correct company details there.'); $ownerDetails .= '<h3>' . JText::_('You should add the correct owner details.') . '</h3>'; $textNotice[] = '## ' . JText::_('You should add the correct owner details.'); $ownerDetails .= JText::_('Since the owner details are displayed during <b>import process</b> before adding the key, this way if the user/dev <b>does not</b> have the key they can see <b>where to get it</b>.') . '<br />'; $textNotice[] = JText::_('Since the owner details are displayed during import process before adding the key, this way if the user/dev does not have the key they can see where to get it.'); $backupNotice[] = JText::_('Check your owner details, it has not been set. Open the JCB Global Options, go to the Company tab and add the correct company details there.'); } } else { $keyNotice = '<h1>' . JText::_('This package has no key.') . '</h1>'; $textNotice[] = '# ' . JText::_('This package has no key.'); $ownerDetails = JText::_('That means anyone who has this package can install it into JCB. To add an export key simply open the component, go to the tab called <b>settings</b>, bottom right there is a field called <b>Export Key</b>.') . '<br />'; $textNotice[] = JText::_('That means anyone who has this package can install it into JCB. To add an export key simply open the component, go to the tab called settings, bottom right there is a field called Export Key.'); $backupNotice[] = JText::_('No keys were found. To add an export key simply open the component, go to the tab called settings, bottom right there is a field called Export Key.'); } // get email if ($email = $this->params->get('backup_email', null)) { // plain text $plainText = implode("\n", $textNotice); // set hash to track changes $hashTracker = md5($plainText); if ([[[Component]]]Helper::newHash($hashTracker)) { // Build final massage. $message = $keyNotice . $ownerDetails . '<br /><small>HASH: ' . $hashTracker . '</small>'; // set the subject $subject = JText::_('Joomla Component Builder - Backup Key'); // email the message [[[component]]]Email::send($email, $subject, [[[component]]]Email::setTableBody($message, $subject), $plainText, 1); $backupNotice[] = JText::_('Email with the new key was send'); } else { $backupNotice[] = JText::_('Key has not changed'); } } } else { $backupNotice[] = JText::_('Backup failed, please try again. If the error continue, please contact your system administrator.'); $backupNoticeStatus = 'Error'; if ([[[component]]]Helper::checkString($model->packagePath)) { // clear all if not successful [[[Component]]]Helper::removeFolder($model->packagePath); } if ([[[component]]]Helper::checkString($model->zipPath)) { // clear all if not successful JFile::delete($model->zipPath); } } // quite only if auto backup (adding this script from custom code :) if ('backup' === '[[[arg0]]]') { echo "# " . $backupNoticeStatus . "\n" .implode("\n", $backupNotice); jexit(); } $this->setRedirect(JRoute::_('index.php?option=com_[[[component]]]&view=joomla_components', false), implode("<br />", $backupNotice), $backupNoticeStatus); return; } ``` Now the link to this Controller will all around the site will look like this: ` <a href="/index.php?option=com_[[[component]]]&task=api.backup">Backup</a>` I am sure you know this, but just for any other that my stumble upon this post.
mwweb commented 2017-09-08 08:29:55 +00:00 (Migrated from github.com)

I saw the custom buttons options, but hadn't really dug into it. Since I'm FINALLY 99% complete on the component (and companion modules), I think I will start experimenting and "playing" with the custom buttons after I have released this. Who knows, once I start digging through my controllers, I might find some code that can be condensed. This main component is HUGE, and even another guy I brought in to write some javascript, said it's a monster of a component, at currently just over 120,000 lines of code, but he did say that it's some of the cleanest code that he's had the pleasure to work with (although he just created some js files for me).

I saw the custom buttons options, but hadn't really dug into it. Since I'm FINALLY 99% complete on the component (and companion modules), I think I will start experimenting and "playing" with the custom buttons after I have released this. Who knows, once I start digging through my controllers, I might find some code that can be condensed. This main component is HUGE, and even another guy I brought in to write some javascript, said it's a monster of a component, at currently just over 120,000 lines of code, but he did say that it's some of the cleanest code that he's had the pleasure to work with (although he just created some js files for me).
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: joomla/Component-Builder#116
No description provided.