I am using the H5P content type with the 'course' module. I am also writing a custom function that automatically creates all the course titles and pages from a CSV input file. Thus one can handily create your entire outline in a spread sheet and then import it into Drupal.

All is going well except the H5P content type requires the H5P type field to be populated. I would like the create an H5P content page with the H5P type empty and to be completed later. How can I do that in the best way?

I could programmatically assign the H5P type to an existing type and then the course designer could update it later. However, the problem with that method is that the H5P type version seems to be part of the assignment as well. So if I later update the H5P modules would that be a problem?

Ideally I would like the H5P content type field to be empty when programmatically creating the page. Any ideas?

Comments

webservant316 created an issue. See original summary.

webservant316’s picture

Title: Create H5P page with empty H5P content type? » Create H5P page programmatically with empty H5P content type?
falcon’s picture

For others reading this this issue is relevant:
https://www.drupal.org/node/2426511

If possible I think it would be better to wait with creating the H5P content node until you have valid data for it. Could you store the temp data using a different data structure? If not I don't see any clean solutions. Perhaps create some kind of dummy H5P content type for the purpose that is replaced with real data. The H5P dummy content type wouldn't have any update issues since it never would be updated.

webservant316’s picture

Then can you offer guidance or an example of how to programmatically create an H5P node, assigning the H5P field to a valid placeholder? What fields must be populated before calling node_save($node);

falcon’s picture

To save time I normally don't provide detailed coding help unless the problem is relevant for many in the H5P community. Are you planning on sharing some results of this job?

If you look at h5p_validate I think it will give a picture of what fields are required.

webservant316’s picture

okay I figured it out... since we cannot create an H5P node without populating the H5P content type field I then picked the most generic h5p content type so that I can at least create the node and then later the node author can edit the node h5P content to be whatever they want. Here is something that worked for me...

/* node base */
$node				= new stdClass();
$node->is_new		= TRUE;
$node->type			= 'h5p_content';
$node->language		= LANGUAGE_NONE;
node_object_prepare($node);
$node = node_submit($node);
$node->uid			= $user->uid;
$node->title		= 'test';
$node->body[$node->language][0]['value']	= 'test';
$node->body[$node->language][0]['summary']	= '';
$node->body[$node->language][0]['format']	= 'filtered_html';

/* minimum assignments below for h5p content */
$node->h5p_type = "create";
$node->disable = 0;
$node->embed_type = 'div';
$node->main_library_id = 16;
$node->h5p_library = 'H5P.DocumentationTool 1.2';
$node->json_content['taskDescription'] = 'Documentation tool';
$node->json_content['pagesList'] = array(0=>array('params'=>array()));
$json = array(	'taskDescription' => 'Documentation tool',
				'pagesList' => array(
					0 => array(
						'params' => array()
						)
					)
				);
$node->json_content = json_encode($json);
$node->add_directly = array('new'=>NULL);

/* save */
node_save($node);

I don't like the hard coding of $node->main_library_id = 16, so any ideas about how to make that general would help. Perhaps I can read the h5p_libraries table to grab the ID I want. Will this ID always remain the same if I reload or update the libraries? What remains constant, the numerical ID or the machine_name?

Actually this solution works quite nicely and it might the solution to including h5p content directly in a course outline. I propose that you create a new H5P content type that is even more general and perhaps not even listed for front end users that is just a placeholder content type for developers. That way h5p content can be created programmatically very easily without having to change your code to try to handle an h5p node with no h5p content assigned because we can just assign the placehold content type, or like I did it above.

falcon’s picture

Great, thank you for sharing! The machine_name remains the same.

webservant316’s picture

Does $node->main_library_id = 16; remain the same also?

Also any thoughts about this idea?

I propose that you create a new H5P content type that is even more general and perhaps not even listed for front end users that is just a placeholder content type for developers. That way h5p content can be created programmatically very easily without having to change your code to try to handle an h5p node with no h5p content assigned because we can just assign the placehold content type, or like I did it above

falcon’s picture

I think main_library_id changes when you get a new minor or major version of the library.

Adding an official "dummy library" doesn't feel like a good idea. I don't think that we want to facilitate the creation of invalid/dummy H5P nodes at all. Smells like trouble to me, but we might consider removing some requirements that we're currently enforcing.

webservant316’s picture

Not an invalid type, but a simpler H5P type.

For example how about a simple HTML body type? That way you don't have to change your code to prepare for an empty H5P field. The course module could then create H5P nodes automatically initially assigned to this new simple H5P type.

webservant316’s picture

I am still interested in this feature request.

Again the idea is to be able to create an H5P node programmatically. In my use case I am uploading a new course outline and have written a module that automatically creates all the nodes needed for the course. Check it out at https://www.drupal.org/sandbox/webservant316/2808195. This is a huge time saver for the course designer. Currently for H5P nodes in the outline I know that I want H5P nodes at different places in the course and so want to create the node with the title and any basic H5P type. I don't even care what type it is because once the H5P node is created I can then change the H5P type later.

I figured out how to do this above at #6. However, since then there have been API breaking changes and so I had to update the code. I figured it out, BUT my whole solution is a hack because I have hard coded the library information.

So in summary, 1) please reconsider my feature request to add a simple HTML content type with simple instructions for programmatic creation, 2) if possible please explain how I can improve my own code without hard coding the library information, and 3) my revised example of programmatic H5P creation is below. Thanks.

$node = new stdClass();
$node->type = 'h5p_content';
$node->language = LANGUAGE_NONE;
node_object_prepare($node);
$node->uid = $user->uid;
$node->active = TRUE;
$node->title = $title;
$node->body[$node->language][0]['value'] = '';
$node->body[$node->language][0]['summary'] = '';
$node->body[$node->language][0]['format'] = 'filtered_html';
$node->path['pathauto'] = TRUE;
$node->h5p_type = "create";
$node->disable = 0;
$node->embed_type = 'div';
$node->main_library_id = 153;
$node->main_library['name'] = 'H5P.DocumentationTool';
$node->main_library['majorVersion'] = 1;
$node->main_library['minorVersion'] = 4;
$node->json_content['taskDescription'] = 'Documentation tool';
$node->json_content['pagesList'] = array(0 => array('params' => array()));
$json = array(
    'taskDescription' => 'Documentation tool',
    'pagesList' => array(0 => array('params' => array())),
);
$node->json_content = json_encode($json);
webservant316’s picture

Category: Support request » Feature request
webservant316’s picture

Title: Create H5P page programmatically with empty H5P content type? » Allow programmatic creation of a new simple H5P content type
Version: 7.x-1.15 » 7.x-1.x-dev
icc’s picture

I'm not entirely sure that I understand what it's you want to achieve, but it sounds like this should belong in a supplementary module.
What sort of code changes do you require from the H5P module?

webservant316’s picture

No I would think this should be in H5P core.

#1 create a new simple H5P content type that is simply any valid HTML content.

#2 clearly document programmatic creation of H5P content, especially the newly proposed HTML content type.

falcon’s picture

I don't think we want to pursue this quite specific feature for D7. In D8 which hopefully soon(I know there are still a few miles to go) is the most relevant version H5P is a field type and this solution would probably be less relevant?

webservant316’s picture

well perhaps I am the only with a use case, but I thought if the feature was there others might use it. In my use case the course_admin module allows for a course creator to externally create a course outline specify the entire course outline, books, and content node types in a simple spread sheet. The course_admin parser reads the spread sheet and automatically creates the course outline and all the nodes, including H5P nodes. Currently H5P nodes are created as an empty 'documentation' type. Then the course author visits each page to add the body content or in the case of H5P nodes sets the preferred type and uses the H5P editor to finish the node creation.

This tools saves a ton of time because course outlines may be more easily drafted in tools like excel. The challenge is the programmatic creation of H5P nodes is not pretty and was broken in the last version so I had to figure it all out again. So hoping for some improvement in support for programmatic creation of H5P nodes.

webservant316’s picture

I just had to tune up my course_admin module again to handle programmatic creation of a default H5P type. This is the code I use to programmatically create an H5P node...

$node = new stdClass();
$node->type = 'h5p_content';
$node->language = LANGUAGE_NONE;
node_object_prepare($node);
$node->uid = $user->uid;
$node->active = TRUE;
$node->title = $title;
$node->body[$node->language][0]['value'] = '';
$node->body[$node->language][0]['summary'] = '';
$node->body[$node->language][0]['format'] = 'filtered_html';
$node->path['pathauto'] = TRUE;  
$node->h5p_type = "create";
$node->disable = 0;
$node->embed_type = 'div';
$node->h5p_library = 'H5P.DocumentationTool 1.4';
$node->main_library_id = 153;
$node->main_library['name'] = 'H5P.DocumentationTool';
$node->main_library['majorVersion'] = 1;
$node->main_library['minorVersion'] = 4;
$node->json_content['taskDescription'] = 'Documentation tool';
$node->json_content['pagesList'] = array(0 => array('params' => array()));
$json = array(
        'taskDescription' => 'Documentation tool',
        'pagesList' => array(0 => array('params' => array())),
);
$node->json_content = json_encode($json);

Something changed so that $node->h5p_library needed to be set.

webservant316’s picture

Again I would love this feature and think it could be useful for others. Private message me and perhaps I could explain better over the phone or with a screen share.

falcon’s picture

I can see why it can be very useful, it is just that it isn't useful enough to justify the maintenance and complexity burden. If this were the only extra thing we added it wouldn't be a problem at all, but we get a lot of requests and we don't want to add much more to D7.