Link back query not working for ContentBlocksFieldPlugin - content-management-system

I am new to hippo cms so apologies if i am not using correct terminologies.
I have followed this link and got the first query working cms hippo docs
I have got 2 doctypes Master and Servant respectively.
Master doctype java and yaml file are as follows
#HippoEssentialsGenerated(internalName = "website:link")
public List<HippoBean> getLink() {
return getLinkedBeans("website:link", HippoBean.class);
}
yaml code
/link:
/cluster.options:
base.path: /content/documents
jcr:primaryType: frontend:pluginconfig
last.visited.enabled: true
nodetypes:
- website:servant
caption: Link
field: link
hint: ''
jcr:primaryType: frontend:plugin
plugin.class: org.hippoecm.frontend.editor.plugins.field.NodeFieldPlugin
wicket.id: ${cluster.id}.field
/link:
hipposysedit:mandatory: false
hipposysedit:multiple: true
hipposysedit:ordered: false
hipposysedit:path: website:link
hipposysedit:primary: false
hipposysedit:type: hippo:mirror
hipposysedit:validators:
- optional
jcr:primaryType: hipposysedit:field
Master has got linkedbean to link to servant doctype as shown above.
Now in the Servant doctype i would like to show the master details, so i added a query as shown below and it works as expected.
public Master getParentDetails() {
final HstRequestContext context = RequestContextProvider.get();
try {
HstQuery linkedBeanQuery = ContentBeanUtils.createIncomingBeansQuery(
this.getCanonicalBean(), context.getSiteContentBaseBean(),
"*/website:link/#hippo:docbase",
Master.class, false);
linkedBeanQuery.setLimit(1);
return (Master) linkedBeanQuery.execute().getHippoBeans().nextHippoBean();
} catch (QueryException queryException) {
log.warn("QueryException ", queryException);
}
return null;
}
The problem is when i change the plugin class in Master to plugin.class: org.onehippo.forge.contentblocks.ContentBlocksFieldPlugin and add compound list compoundList: website:junior things stop working and give error.
Note that now the getlink() method and the link yaml code shown above is moved into a new compound called junior.
Master is just for allowing multiple compounds of junior with appropriate code as shown below.
#HippoEssentialsGenerated(internalName = "website:servantlink");
public List<HippoBean> getServantlink() {
return getLinkedBeans("website:servantlink", HippoBean.class);
}
yaml code
/servantlink:
/cluster.options:
jcr:primaryType: frontend:pluginconfig
nodetypes:
- website:servant
caption: groups
compoundList: website:junior
contentPickerType: links
field: servantlink
hint: ''
jcr:primaryType: frontend:plugin
plugin.class: org.onehippo.forge.contentblocks.ContentBlocksFieldPlugin
wicket.id: ${cluster.id}.field
wicket.skin: skin/content-blocks.css
/servantlink:
hipposysedit:mandatory: false
hipposysedit:multiple: true
hipposysedit:ordered: false
hipposysedit:path: website:servantlink
hipposysedit:type: hippo:compound
hipposysedit:validators:
- contentblocks-validator
jcr:primaryType: hipposysedit:fiel
So my question is how the query should be now?
Any help would be highly appreciated. Thanks in advance

It looks like in the new situation, you're creating compounds of type website:junior that have the link. So in the incoming beans query, change "*/website:link/#hippo:docbase" accordingly.
Hope that helps,
Jeroen

So finally got it working
The master java class should be as follows. Please note use getChildBeansByName instead of getLinkedBeans here.
#HippoEssentialsGenerated(internalName = "website:servantlink");
public List<HippoBean> getServantlink() {
return getChildBeansByName("website:servantlink");
}
No changes in the master.yaml its all good.
Now the query part in Servant java class should be as follows.
final HstRequestContext context = RequestContextProvider.get();
try {
HstQuery linkedBeanQuery = ContentBeanUtils.createIncomingBeansQuery(
this.getCanonicalBean(), context.getSiteContentBaseBean(),
"website:servantlink/website:link/#hippo:docbase",
Master.class, false);
linkedBeanQuery.setLimit(1);
return (Master) linkedBeanQuery.execute().getHippoBeans().nextHippoBean();
} catch (QueryException queryException) {
log.warn("QueryException ", queryException);
}
return null;
}
The most important part is this website:servantlink/website:link/#hippo:docbase.

Related

Unable to add tasks from the provideTasks function

Following on from this question I have another question about how to implement the provideTasks method of the registerTaskProvider.
Using the npm extension as an example I have tried to implement a basic function, to simply return a single, hard-coded, task. This would then be extended to actually parse a file, ready to add dynamic tasks. However, I have been unable to get this to work.
The code that I am trying is:
vscode.workspace.findFiles('**/*.cake').then((files) => {
if (files.length === 0) {
return emptyTasks;
}
try {
const result: vscode.Task[] = [];
result.push(new vscode.Task({type: 'cake', script: 'NuGet-Restore'} as CakeTaskDefinition, 'Nuget-Restore', 'cake', new vscode.ShellExecution('npm install'), []));
console.log(result);
return Promise.resolve(result);
} catch (e) {
return Promise.resolve(emptyTasks);
}
});
Even though I can see that result contains a Task, I don't see it populated in the Task drop down list.
Can anyone offer any help in why this is not working?
A repository with the current code can be found here.
UPDATE
I have just edited the above code to be the following:
try {
const result: vscode.Task[] = [];
result.push(new vscode.Task({ type: 'cake', script: 'NuGet-Restore' } as CakeTaskDefinition, 'Nuget-Restore', 'cake', new vscode.ShellExecution('npm install'), []));
console.log(result);
return Promise.resolve(result);
} catch (e) {
return Promise.resolve(emptyTasks);
}
By not including the initial findFiles function, it correctly populates the Task Menu with the single hard-coded Task. Why is it that I can't do the return from within the findFiles method? I now suspect that this is a TypeScript/JavaScript problem, rather than one with the provideTasks function, but I am still looking for some help on this.
What is the recommended approach for what I am trying to do? Thanks in advance!
You need to return findFiles to ensure the tasks are actually returned from the task provider:
return vscode.workspace.findFiles('**/*.cake').then((files) => {
...
});
Using "noImplicitReturns": true in your tsconfig.json—or, even better, "strict": true—can help catch bugs like this

Double registration form in moodle

I'm editing a site based on moodle, and i need to create a double registration form. The first is already set (for schools), i need to create another one for private user. What would be the best way to do it?
Would be worth to copy the main signup files (signup.php and signup_form.php) and then make changes there?
Really thanks
I think the best solution would be to create a new authentication plugin.
https://docs.moodle.org/dev/Authentication_plugins
Maybe copy the code from here /auth/email into /auth/newname - replacing email with newname in the code.
Possibly extend the class? so something like this in /auth/newname/auth.php
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/auth/email/auth.php');
class auth_plugin_newname extends auth_plugin_email {
...
function can_signup() {
return true;
}
...
Then copy /login/signup_form.php into /auth/newname/signup_form.php
The next bit I'm not too sure about but you will probably need to modify /login/signup.php
Around the lines
if (empty($CFG->registerauth)) {
print_error('notlocalisederrormessage', 'error', '', 'Sorry, you may not use this page.');
}
$authplugin = get_auth_plugin($CFG->registerauth);
Change to
if (optional_param('newname', false, PARAM_BOOL)) {
$authplugin = get_auth_plugin('newname');
} else {
if (empty($CFG->registerauth)) {
print_error('notlocalisederrormessage', 'error', '', 'Sorry, you may not use this page.');
}
$authplugin = get_auth_plugin($CFG->registerauth);
}
Then for private registrations use
http://www.yoursite.com/login/signup.php?newname=1
Replace 'newname' with the name of your new authentication plugin.

codeigniter2, nusoap, soap server and examples

A morning of googling I've learnt a few things.
Many people would like to use their CI2 installs to make a soap server for other apps to talk to their app.
However, each forum post I find ends in 'This doesn't work in CI2' or similar.
I've found this article:
http://phpmaster.com/web-services-with-php-and-soap-1/
Which is GREAT... but I can't get it working in CI2.
I've put my library in place, renamed where needed and this code is bringing up many errors.
I've not started on the client side yet.
`class soap extends CI_Controller {
function __construct ()
{
parent:: __construct ();
$this->load->library('nusoap_base');
}
function index()
{
$this->nusoap = new soap_server();
$this->nusoap->register("getProd");
$this->nusoap->service($HTTP_RAW_POST_DATA);
}
function getProd($category) {
if ($category == "books") {
return join(",", array(
"The WordPress Anthology",
"PHP Master: Write Cutting Edge Code",
"Build Your Own Website the Right Way"));
}
else {
return "No products listed under that category";
}
}
}`
Got fed up, using CI REST library instead (cheers Phil!)
:)

Logic behind linkage of ExpandoObject() members and FB Graph API

Just started today some dev using Facebook SDK and i can't figure out the logic followed to link the members of the expando object to the fields in the Graph API objects in the example bellow that was taken from facebook C# SDK docs:
public ActionResult RestFacebookPage()
{
FacebookApp app = new FacebookApp();
dynamic parameters = new ExpandoObject();
parameters.page_ids = "85158793417";
parameters.method = "pages.getInfo";
parameters.fields = "name";
dynamic result = app.Api(parameters);
return View("FacebookPage", result);
}
I do understand the page_ids and fields, but not pages.getInfo. It would be great if someone could enlighten me here and tell me where in the documentation i can find a reference that leads me to this....
Thanks a lot!
Not sure I understand what you are asking but there is a pretty decent example about translating php to facebook-c#-sdk over on their project page. Then you can just look up the official facebook developer documentation directly.
If you were asking more off a "how is this implemented" type of question, the best way to do this in my opinion is to break at the line containing app.Api and from there just step through the code. In the Api method there is a check to see if the parameters dictionary contains a key "method". If there is, the sdk figures the call is bound for the old rest api, not the graph api. A few stack frames lower we find the code that makes the url:
protected virtual Uri GetUrl(string name, string path, IDictionary parameters)
{
Contract.Requires(!String.IsNullOrEmpty(name));
Contract.Ensures(Contract.Result() != default(Uri));
if (_domainMaps[name] == null)
{
throw new ArgumentException("Invalid url name.");
}
UriBuilder uri = new UriBuilder(_domainMaps[name]);
if (!String.IsNullOrEmpty(path))
{
if (path[0] == '/')
{
if (path.Length > 1)
{
path = path.Substring(1);
}
else
{
path = string.Empty;
}
}
if (!String.IsNullOrEmpty(path))
{
uri.Path = UriEncoder.EscapeDataString(path);
}
}
if (parameters != null)
{
uri.Query = parameters.ToJsonQueryString();
}
return uri.Uri;
}
You should probably step into this method yourself to see what the variables hold and it should make sense to you. The source is always the best documentation. Hope this helps.

How to get the complete request that calls my MVC2 controller?

Newbie question … sorry ;-)
I have to write and to integrate a new website in a complex web application.
My new (MVC2) website will be hosted on a separate server and only called when the user clicks on a link in the already existing, complex website.
Means I(!) define the URL which calls my(!) new website.
But “they” (the calling, already existing, complex web application/website) will add an attribute to the url. This attribute is the sessionID.
Ok, I think I understand already that this calls my (MVC2) controller.
But how can I get in my (MVC2) controller the “calling URL” (which include the added sessionID)?
Hopefully that someone understand what I ask ;-)
Thanks in advance!
I want just share my little parser - hopefully it helps someone. ;-)
Also requests like
(Request.Url.Query =) "?sessionID=12345678901234567890123456789012&argumentWithoutValue&x=1&y&z=3"
will be well parsed.
Here my code:
Hashtable attributes = new Hashtable();
string query = Request.Url.Query;
string[] arrPairs = query.Split('&'); // ...?x=1&y=2
if (arrPairs != null)
{
foreach(string s in arrPairs)
{
if (!String.IsNullOrEmpty(s))
{
string onePair = s.Replace("?", "").Replace("&", "");
if (onePair.Contains("="))
{
string[] arr = onePair.Split('=');
if (arr != null)
{
if (arr.Count() == 2)
{
attributes.Add(arr[0], arr[1]);
}
}
}
else
{
// onePair does not contain a pair!
attributes.Add(onePair, "");
}
}
}
You really should set your URL and Route to be more MVC-Like. The URL you are calling should be:
newapp/controller/action/sessionId
Then set your route up:
routes.MapRoute(
"sessionId",
"{controller}/{action}/{sessionId}",
new { controller = "controller", action = "action", sessionId = 0 });
Then in your controller:
public ActionResult Action(int sessionId)
{
}
In your controller you still have direct access to the Request object, so you can use Request.Url, etc.
Does that answer your question, or is it something else that you need?