Has anyone use this User Defined Form module from Silverstripe? - php

It's a long short question since Silverstripe is still pretty new in the CMS market as compared to others...
As the subject heading states, has anyone played with silverstripe and use one of these User defined form module as part of its core API?
I'm wonder has anyone attempted to make successful modifications module to suit their own custom requirements?
What I find it challenging about this is there's lack of code samples or documentation that would allow to appreciate how User Defined form works and how I can modify and manipulate its configuration settings to what I want to achieve?
Is there anybody out there who can lend a helping hand on this?

I have used the module. What modifications are you hoping to make exactly? You can easily decorate or subclass parts of a module to add custom functionality without modifying the core code.
Here's some documentation that could give you some insight into the Decorator option.
http://doc.silverstripe.org/sapphire/en/reference/dataobjectdecorator
But yeah, let us know what you are trying to do and I should be able to give you more detailed suggestions :)
Given your additional info below -
It might not be worth using UDF for this, the work required would not be much more or less than the more straight forward option to create a frontend form from scratch. http://doc.silverstripe.org/sapphire/en/topics/forms
But if you wanted to go ahead with UDF you would need to do something like -
1) extend UserDefinedForm eg. CustomUserDefinedForm extends UserDefinedForm to have an extra field/dbfield where you could select the name of the DataObject to map to.
2) Decorate EditableFormField to have an extra field that maps it to the appropriate field of the DataObject.
3) extend UserDefinedForm_Controller eg. CustomUserDefinedForm_Controller extends UserDefinedForm_Controller and override the 'process' method. This is where the form is saved and the email is sent. You would need to add code to loop over the fields and save them to the dataobject specified on the form.

Related

Symfony2 bundle as a plugin

Consider situation where I have some default bundle that hypothetically create some empty page with menu on left and some content (if there is any). Then I create a new bundle and I normally turn it on in AppKernel. Now should magic start: bundle by his own (no need to add any options in default bundle etc.) hooks up and creates his menu entry (and if chosen, renders his content). How should I do this, is there any proper way to do this? What if I want to have multiple "hooks", for example, adding also new form in user profile edit, or adding new tab on some other place?
I'm thinking about looking for some "initialize bundle event" that I could listen to and pass data thru it. But maybe there is better solution. I would love to see your ideas :)
Looking at the initializeBundles method of the Kernel, it doesn't look easy or intended to dynamically add bundles during the bootup process.
However, the AppKernel.php file is on the forefront, it is an override of Kernel and can be customized to supply a dynamic set of bundles to the implemented registerBundles method.
You will need to make sure the imported content is properly added to the autoloader, but avoid modifying the distribution source at runtime, try to make it as imported as possible.
I don't want to go into great detail on the technicalities as I have not done this myself and it will require a lot of experimentation. I do know that Drupal 8 uses Symfony2 and has its own plugin system, but I don't think it takes bundles as plugins.
If you manage to pull this off I suspect it will allow 100% integration between the application and the plugins, but just be aware that it also allows 100% overriding access to said plugins.

Where is the best place to put application-wide logic (notifications) in CakePHP?

I've had a quick search on Stackoverflow but not really found an answer to a question that I have. Sorry if it's already been answered and I've missed it!
I'm working on an application, and similarly to Facebook, there will be 'notifications' but in my case it'll be items that require actions from the user. It would just be a 'count' of the actions that are required and nothing else.
I've followed a fat model, skinny controller approach through my application and so far so good. I have a good idea of what goes where, and when to use a plugin, app model, app controller, etc.
However, I'm a little confused about where to put this notification/action 'count'. I'm guessing either afterFilter() in the app_controller.php file, but that's just a guess. I'm just looking for the most efficient place to put it.
So, where's the best/fastest/most efficient place to put this count call?
Thanks!
Kingsley
EDIT: I just realised it's worth pointing out that this particular call is on a model. So, at the moment I have to load that model, and then call it.
The ideal place is in an Element. You can then use requestAction() to tell it where to retrieve it's data from.
The Element is placed into a view (or used to display a Flash message). Within it, it pulls it's data (requestAction) from a Controller's Action. That action get's it's data from the Model of your choice just like you would in any other action. This allows complete separation of concerns (ie MVC).

Joomla com_user extending similar to com_categories and com_content

Ok this is just something I feel I should ask as I could not find any reference to this in any kind of documentation, and reading through the actual code to figure out the best way to accomplish this would take far longer then hope to spend.
When you enter the Article manager you have a navigation link to the Category manager and vice versa. I would like to do something similar with my component and the default User manager.
I already have a profile plugin to extend the users to suit my needs, but I would like the configuration of it seamless so adjusting the com_user component to integrate better with my component is what I am looking for.
So my question is with the com_content and com_categories they use the "extension" parameter. Is it possible to add similar functionality without a full core override of the com_users? If I do a full override there is a chance of some extensions not working due to reliance on the users.
I am willing to clarify if anything does not make sense, this question is more to see the extent you can "extend" Joomla without overrides.
UPDATE:
I have found a cool technique, not quite an answer though.
You can override just the list controller/model/view in your component, and if you based it off of the current com_users component you can make it look like a direct integration.
The only edits you need to do is making sure any routes to the users view instead pass to your component.
There is one issue with this however, when you add a new user or edit one, once you finish it will direct you to the main user manager. A system plugin may help with this but only if there is a reliable way to detect when the user was edited through your component, rather then the users manager.
Note: The problem with adding an override to the user view is that it has 5-6 other MVC components it relies on, so in the interest of making it easy to update with core com_users updates it is best to avoid that if at all possible.
Another thing needed is to make sure to find the language file for com_users and add all entries to your component.
I feel there may still be a better answer out there, but doing it this way does not impact the core much, and would be easy to update with updates to com_users.
I am opening a bounty on this, I feel of every question I ever asked this is one that will have the most benefit to the community. So here is a condensed version of the question.
What would be an easy way to integrate a core component into a custom component and have it route through that component seamlessly with the least edits to the core component.
I'm not exactly clear on what you want but if you're talking about the toolbar submenu's like this in com_content:
The example you give of Categories (i.e. com_categories) is specific support added where you can pass in a link to com_catgories with your extension identifier (the extension=com_mycomponent) and it will load the sidebar menu for your extension. This is so core categories can be shared amongst various components [see Add Categories].
You may already be aware of the following, but, if you want to know how to add a sidebar menu to your components manager view you can call JHtmlSidebar::addEntry($title, $link, $active);
Typically this is put in your extensions primary helper file in a function called addSubmenu($vName) (which is what & where com_categories will look for to display your toolbar sub-menu). Its called addSubmenu() because the sidebar morphed from being the toolbar submenu in previous versions of Joomla.
e.g. this is the addSubmenu() method in the ContentHelper class defined in administrator/com_content/helpers/content.php
/**
* Configure the Linkbar.
*
* #param string $vName The name of the active view.
*
* #return void
* #since 1.6
*/
public static function addSubmenu($vName)
{
JHtmlSidebar::addEntry(
JText::_('JGLOBAL_ARTICLES'),
'index.php?option=com_content&view=articles',
$vName == 'articles'
);
JHtmlSidebar::addEntry(
JText::_('COM_CONTENT_SUBMENU_CATEGORIES'),
'index.php?option=com_categories&extension=com_content',
$vName == 'categories');
JHtmlSidebar::addEntry(
JText::_('COM_CONTENT_SUBMENU_FEATURED'),
'index.php?option=com_content&view=featured',
$vName == 'featured'
);
}
By comparison the com_categories helper class CategoriesHelper has a very different addSubmenu() method which looks for the calling extensions core helper class (if one isn't found it defaults to com_content).
There isn't any support like that in com_users so you will probably have to create a system plugin that fires onAfterRoute and adds your submenu item based whether or not your component has provided a suitable parameter, like the extension=com_myextension. It would be a bit of a swizzle but it should work — the only thing is as you would be adding a submenu item before the component is dispatched your new submenu item would like always be the first item in the com_users submenu. It wouldn't be a complete replacement like com_categories supports.
Unfortunately there aren't any triggers in com_users that I can find that would be of any help in swizzling the entire sidebar menu.
The next option is to use something like Donald Gilbert's gist to create a system plugin that allows you to override any core class by creating a substitute version of your own — obviously this will have issues with any significant updates but if you're careful you could limit the override to your specific situation.
If thats not enough/overkill you may want to try a system plugin that responds to onAfterDispatch at which point you would have the page before its returned to browser and you could hack the HTML, but thats very ugly and be prone to breaking if users change their admin template.
Of course, I could be completely wrong and theres a better way to do it in 3.x. Maybe someone else will chime in.

A php plugin architecture

I'm trying to think of a way to create a plugin architecture for my own framework. I've read numerous topics and post here and on other sites. And basically i've came to the following solution which seems to be the only good option in PHP (currently).
The idea is that every class extends a sort of observer like class. So a Template class, BaseController etc. always extend a Plugin class.
class BaseController extends Plugin
{
public function __construct()
{
// Plugin check, notify all loaded plugins
$this->checkForEarlyHooks();
// Init some standard stuff
$this->view = new Template();
$this->baseLayout = 'layout.html';
$this->something = new Something();
// Plugin check, notify all loaded plugins
$this->checkForLateHooks();
}
}
So what basically happends here is that when an indexController extends a baseController a plugin check is done. In this case for the constructor. This can be convenient when you want to do a some sort of login check with a plugin, before an Action method is actually invoked.
The Plugin class can resolve from what class is got called from and knows for what functions to look for in the loaded plugins.
Also note that it checks the loaded plugin list 2 times. One before anything is loaded (early) in the constructor, and one when all vars are loaded (late).
I can also add variables to the "checkForLateHooks()" function. So the hook functions can manipulate those too, like the 'baseLayout' variable.
A hook function would look like this:
public function hookConstruct ( &$baseLayout )
{
$baseLayout = 'login.html';
}
Now basically my question is, is this approach any good? I know there are probably alot of other ways to do it too. But i mainly don't want to run into design problems later on. It seems like a good idea now, but you never know how things work out later on...
If i remember it right (from all the posts the i've read), this is kinda like WordPress does it (and some other frameworks).
UPDATE: answer now reflects the up-to-date links and better description.
There are certainly many different ways to design a plugin system and perhaps asking on https://softwareengineering.stackexchange.com/ would give you more ideas, but I'll try to help by sharing my ideas and experience.
I'll share some of my own experiences which I've learned through a series of my own frameworks. Currently Agile UI and Agile Data both support many wasy to be extended, but I'll focus on the "Components"
HOOKS
When you look to inject code into the existing object, a hook is a standard way to go. It's the best option for extending the application or flow with an established structure.
While refactoring my frameworks, I've separated hook implementation into a separate trait and documented it here: http://agile-core.readthedocs.io/en/develop/hook.html
Host application:
... some code here ..
$this->hook('beforeInit');
$this->init();
$this->hook('afterInit');
... code goes on ..
Plugin:
$host_app->addHook('beforeInit', function($object) {
echo "About to execute init of $object";
});
UI COMPONENTS
Components present a different design pattern, which is suitable for the User Interfaces. You start with the page/app layout which is then broken down into Menu, Header, Footer, Content.
A component is an object which can be associated with Layout or the other component. Each component is capable of rendering and passing extra HTML/JS to its parent. Most of components would also be an interractive objects.
This approach is called "Render Tree" and application execution goes through 2 stages - "initialization of a render tree" and then "rendering".
Host Application:
$layout->menu = new \atk4\ui\Menu();
$layout->add($layout->menu, 'TopMenu');
The above code show how a new Component (Menu) can be initialized and inserted into the $layou. Furthermore the HTML output of $menu is directed into {$TopMenu} tag, which is defined in the HTML template of Layout.
Plug-in can interact with the render tree by:
adding more components anywhere in the tree
affecting existing components (e.g. add new menu item)
destroying any of the existing components
When those approaches are combined, you can use something like this:
$app->addHook('afterInitLayout', function($app) {
$app->layout->menu->destroy(); // remove default menu
$app->layout->menu = new \plugin\SuperMenu();
$app->layout->add($app->layout->menu);
});
This can be used to replace standard menu with a more powerful implementation from your add-on.
My implementation of components is documented here:
http://agile-ui.readthedocs.io/en/latest/view.html#initializing-render-tree
UI / DATA SEPARATION
Although perhaps not so much answer for a question, but another powerful way to extending is a separation of concerns. All of the UI components in Agile UI do not know how to do anything with data.
While many UI generators require developer to manually build them up and link up with data, I am injecting "Model" object like this:
$form->setModel(new User($db)); // populates name, surname and gender fields
Demo: http://ui.agiletoolkit.org/demos/form2.php (2nd form)
In this approach object User contains enough meta-data for the Form to populate it's fields, captions perform validation and also save/load data.
Since "User" class can also be declared in an add-on it makes a pretty powerful way to extend existing functionality by adding support for new data entities.
OTHER APPROACHES
Some other approaches to extend with add-ons include:
Factory:
The ability to resolve class specified as a string into namespace / file:
$api->add('MyClass');
Gives ability for add-on to re-route standard classes but is not very friendly with type-hinting in IDEs.
New types / Traits:
Add-on can provide new classes adding Persistences, Table Columns, Form Fields, Actions etc.
CONCLUSION
I think add-on deign boils down to:
simplicity of installation and use
does add-on need to operate out-of-the-box?
avoiding conflicts between add-ons
defining different add-on types - authentication, UI, behaviour
can add-on extend another add-on
will add-on fit application design, data and architecture?
give a lot of power to add-ons without sacrificing performance
Have a look at PHPPlugin on https://github.com/gheevel/PHPPlugin. A simple PHP plugin framework inspired by eclipse and jira plugin architectures. Basically, your application can define extension points and plugin instances can register on those extension points for providing extra functionality. Works well in combination with composer and/or symfony.

Creating a simple custom view in SugarCRM

I am trying to use the MVC architecture of sugarcrm to add a new action and with that a new view.
I have managed to create a controller with the action and also a class view, the only thing I can't figure out is how to create a simple html page.
Do I really have to use the metada way of sugarcrm?? I just want a simple form with two or three fields.
Are there alternatives to the metadata or do I really have to use it to create my simple page????
You will want to stay within the metadata framework to create your new page if possible. However, once you are in the view controllers, you can echo out anything you wish and still stay "upgrade safe" by overriding the display() function. But, the right way to do what you are wanting to accomplish above is to not only override the display() function but also create a new tpl file (custom/modules//tpls/view.tpl) and then perform whatever you need to perform PHP wise and then assign the variables via the smarty templating engine (I know this sounds complicated - but it's not. It's actually pretty straightforward once you understand Smarty).
One other thing - make sure you are doing all of this (including your controllers and view files) in the custom/modules directory. As this will also keep things upgrade safe. And keep you free from all kinds of headaches in the future. :)
Here is a link to the SugarCRM Developer's Guide online and also a link to their Developer's website. SugarCRM has a pretty good community of developers on the forums so feel free to ask questions there as well.
Developer's Guide:
http://developers.sugarcrm.com/docs/OS/5.2/-docs-Developer_Guides-Developer_Guide_5.2-toc.html
Developer's Site:
http://developers.sugarcrm.com/
Hope this all helps!
Try to do following:
create a new module
put your page into custom/modules/
using URL index.php?module=&action= (without php extension, of course) you can access to your page.
If you'd like to have different action name and page name then you should add the file action_file_map.php
into your module directory and specify inside the mapping:
$action_file_map['action_name'] = 'path_to_your_page';
Note that action_name must be all lowercase - the SugarController won't be able to to match mixed-case actions (true as of SugarCRM 6.1.2).

Categories