uc_nodetype: module to purchase right to publish node

Posts: 37
Joined: 11/28/2007

This is a follow-up to the post Purchase Right to Publish a Node.

GileS was nice enough to send me his module uc_nodetype, which allows users to create nodes at checkout and then stores each node as a serialized array. When an order is completed, the node is created. This functionality is similar to e-commerce's pay-per-node.

I'd like to work on finding and fixing some of the module's bugs and then get it posted in the contrib section of the site.

One bug that I'm having some trouble solving is getting the node body field to save. I'm finding that when I complete an order, the title and any CCK info saves from the array in the database to the new node. However, the body field does not transfer even though it is being saved in the database array. This issue can be easily overcome by not using the body field and instead using a cck field. But, it seems like something that should be fixed before posting the module in contrib.

I will post additional bugs as I find them. The uc_nodetype module is attached below.

AttachmentSize
uc_nodetype.zip13.41 KB
Posts: 12
Joined: 11/30/2007
Bug Finder

I am not sure I ever updated the .install file after making changes. It may be the same but here is the table structure.

AttachmentSize
nodetype.sql1.58 KB
Posts: 37
Joined: 11/28/2007

Just found an additional bug. CCK checkbox values saved during checkout don't seem to save to the new node. I'll investigate possible solutions and report back.

Posts: 37
Joined: 11/28/2007

I updated the code to fix bugs with the body field, cck multi-select fields, and a conflict with the path module. The body field and cck checkboxes should now save correctly.

I implemented a hack to prevent the path from saving to the url_alias table incorrectly. The $node->path is now set to NULL during the node-saving process. I found that if I didn't do this, the module would try to save the path as an array.

AttachmentSize
uc_nodetype_alt.zip29.32 KB
Posts: 37
Joined: 11/28/2007

I've got everything working except for cck file upload.

When you hit "Upload" to attach a cck imagefield image, the form refreshes but the image does not seem to attach. I think that this problem might be related to some sort of incompatibility between Upload.js and the Checkout page.

Please let me know if you have any idea what might be causing the problem. I am going crazy over here.

Posts: 1013
Joined: 08/14/2007
Bug FinderEarly adopter... addicted to alphas.Getting busy with the Ubercode.

Reporting another bug. When I attempted to purchase a new Product node, everything worked fine until I went to Submit the order. Attempting to post the form did 2 things:

- Sent me to /cart/checkout/review with a blank page.
- Logged me out.
- Demoted me. I was the administrator, and somehow purchasing the node (and trying to re-submit the form) cost me admin privileges. I also got an email saying "Sorry! You have left a role.".

So, yeah. Not sure where to start with these bugs.. also to allow someone to create a new File Download product might be problematic, unless they can edit their own node. Is that possible? The main issue is that the Features are where such options are kept, which is in a tab not seen during the checkout process. I haven't tried the "non-checkout" process yet so my questions might become moot.

--

"Pain don't hurt." - Dalton

Mike Nelson's RiffTrax! www.rifftrax.com

Posts: 37
Joined: 11/28/2007

I am trying to reproduce your series of errors and am having problems. Are you using uc_roles?

Posts: 1013
Joined: 08/14/2007
Bug FinderEarly adopter... addicted to alphas.Getting busy with the Ubercode.

Yeah I am. I also installed Expiry from the Contribs, although I'm not sure that's even necessary.

--

"Pain don't hurt." - Dalton

Mike Nelson's RiffTrax! www.rifftrax.com

Posts: 37
Joined: 11/28/2007

Hi Torgos,

I installed fresh versions of Ubercart and uc_nodetype on a test site and was able to get it working before installing expiry with one exception. I keep getting a white screen at cart/checkout/complete. I have increased my php memory limit to 900 MB, but it doesn't seem to be helping. I am using Ubercart 5.x-1.0-alpha8, the same version that I am using on my working site. Although I am getting a white screen, my orders do appear to be processing. I wrote out the steps I took when testing below.

To start out, here's what I did before setting up uc_roles:
1. Created a test product that is not shippable.
2. Created a new content type called "Purchased Node"
- I unchecked all of the options under Default options.
3. Activated uc_nodetype
4. Set types of nodes that can be created at "admin/store/settings/products/edit/features". The only type I selected was "Purchased Node." I set the change to occur when the order status is completed. I believe that this is the only option that works anyway. I also set 1 as the default quantity. I didn't select anything in Node stats display. I'm not quite sure what that is supposed to do.
4. Added the feature 'Node Creation' to my test product. I set the Model/SKU to my product and the Node Type to Purchased Node. I also set 1 as the quantity that the user can create and checked the box "Allow creating nodes in checkout."
5. Enabled COD and Check for testing under payment settings.

To test:
1. Purchased product and filled out node-specific information.
2. After pressing "complete" on checkout screen, the checkout seemed to go through. When I went to the orders screen, my order was there. I changed its status to "Completed".
3. When I checked the content page, the new content was there.

Next, I activated uc_roles for the product, and tried to go through the same process.

To start out:
1. I added the role "tester."
2. I made "tester" a role at admin/store/settings/products/edit/features. I made the order status change when an order is completed and left the expiration stuff blank.
3. I added Role assignment as a feature to the previously created product and left all the expiration stuff blank. I also made the item non-shippable.

To test:
1. Purchased the product and filled out the node-specific information.
2. When I completed the transaction, the screen went white. I think that this might be a memory issue.
3. I made the order complete. After doing this, the new node was created and the role 'tester' was assigned.

I also tried purchasing the product as an anonymous user and the order did go through.

Finally, I tried to get it to work with expiry. I think that I am doing something wrong because although I am setting the expiry time, I am not getting email notifications.

Also, just wanted to mention that I am trying to attach a file download within a node. Its for a job board and I want someone to be able to upload their organization's logo. In addition, I am using Node Expire to expire the job listings. I am not sure if that is important but I thought you might be interested.

I've attached the latest version of my code, although I doubt that its going to solve your problem.

AttachmentSize
uc_nodetype_v3.zip29.82 KB
Posts: 37
Joined: 11/28/2007

I think I've identified the problem with uploads. On the cart/checkout page the javascript needed to create an iFrame preview of an uploaded image is not being called.

Do you have any idea why this is happening?

I have also noticed that the node fieldsets are not uncollapsing on the checkout page. Is there some sort of Ubercart javascript fix that I need to implement? Should I start a new thread or is this just specific to this module?

Posts: 1013
Joined: 08/14/2007
Bug FinderEarly adopter... addicted to alphas.Getting busy with the Ubercode.

Sorry for not following up, I'm writing a custom module to do what we need (since it is pretty specialized, and is going to use a Perl script to handle the large file uploads).

Anyways to troubleshoot your white screen problem, put this into the top of your index.php:

error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

That'll show you any fatal errors (which Drupal chokes on). It's helped me tons.

--

"Pain don't hurt." - Dalton

Mike Nelson's RiffTrax! www.rifftrax.com

Posts: 37
Joined: 11/28/2007

Thanks for the tip! I'll add it and report back.

Posts: 37
Joined: 11/28/2007

Thanks for the great tip!

After adding your code, I found a problem with the uc_expiry module.

Fatal error: Call to undefined function uc_get_order_status_id() in /Users/juliakm/workspace/drupal_ubercart_test/sites/all/modules/ubercart/contrib/uc_expiry/uc_expiry.module on line 352

I wonder if your permissions problem is due to expiry and uc_nodetype not working well together.

Posts: 48
Joined: 01/31/2008

Wondering if you ever got everything to work the way you wanted. Also, is this a similar module?

http://www.ubercart.org/contrib/2470

Posts: 37
Joined: 11/28/2007

I got close. Unfortunately, I couldn't ever figure out how to make file uploads attach. I know that it's some sort of javascript problem, but I can't figure it out. I've run out of time to work on this and I had to go with e-commerce's paypernode. Sad I'm looking forward to using Ubercart in the future.

Posts: 48
Joined: 01/31/2008

Does pay-per-node pretty much do everything you need? I glanced at ecommerce but was drawn by the look of Ubercart and how easy it was to setup.

Posts: 37
Joined: 11/28/2007

Yes. Paypernode, combined with skipcart and a little custom code worked out well. The custom code redirects the user to the appropriate add node page after payment.

Posts: 37
Joined: 11/28/2007

Just wanted to note that I'm back to using Ubercart. While pay-per-node and e-commerce worked, the client hated the interface. I've got uc_nodetype working to meet my own needs and will try to build a more general version by the end of the month. My biggest problem has been coming up with a standard way to get cck fields to save.

Posts: 48
Joined: 01/31/2008

Have you tried using PayPal Node?

Posts: 37
Joined: 11/28/2007

PayPal node is a great module. I ended up needing to use Authorize.net for authentication.

Posts: 12
Joined: 02/22/2008

Hi Julia,

I am looking for the same functionality in your original "Purchase Right to Publish a Node" post. And am wondering how you are going with your solution, and if possible point me in the right direction or what version of the mentioned solutions you used/started with.

Best Regards,

Nathan

EDIT:

I have documented a separate approach to this module here:

Pay to Publish using workflow_ng

Posts: 14
Joined: 04/06/2008

Couldnt this be accomplished using Role assignment? Make a role that allows the user to post a content type. Then after they post '1*quantity' demote their role?

Just thought?

Zach

Posts: 23
Joined: 04/04/2008

I've been following the threads here on this subject as well as reading dozens of posts on drupal.org and other articles about this. I think I've found a solution that will work for me without having to create a new module!

What I need to do is give a user (must be logged in) the ability to create and pay for a node strictly for a site moderator(without administrator access) to view. The node includes CCK imagefield where they can upload multiple images. So the node needs to be created as unpublished but a person who does not have administrator access needs to be able to see it.

I haven't worked out all the kinks yet but to accomplish this I am using the following modules...

Ubercart (of course)
uc_node_atc contrib module (to link a node to a product)
CCK (including imagefield and computedfield)
Workflow_ng (Not the same as Workflow! That was the source of alot of confusion for me)
Workflow (including workflow_access)
Actions
Inline Registration (this adds the registration/login form to the node creation form)

The Workflow and Actions modules must be the latest versions which include the new Drupal 6 actions.

Here are the steps I've taken to accomplish this:

  • Create a content type for the node to be submitted ("submission type" for example). This type includes two computed fields, price and quantity.
  • Create a product class ("submission product"). This is because I will eventually have multiple products of this kind.
  • Create a "submission product" node that the "submission type" node(s) will be mapped to.
  • Map the fields in the Node to Product settings
  • Create a Workflow (NOT Workflow_ng) with two states, "created" and "paid for". Then click Actions to assign access levels based on states and state transitions. For instance while in "created" state the author can edit the node but not in "paid for" state. Only moderators can view the node in "paid for" state.
  • Now go to Workflow_ng and create a rule with "Content created" event, with condition "Content has type" of "submission type(s)", and actions "Add node to cart" and "Page Redirect". This actually maps the submission node to the product node and adds the product node to the cart thanks to uc_node_atc. Then redirects to the cart.
  • Create another rule with the event "A payment gets entered for an order". The conditions are "Check the order balance" which should be 0 or less and "Order has a product of a particular class" which should be the product class created in step two. Add the Action "Execute custom PHP code". My custom php code gets the submitted node from the order and runs the action 'workflow_select_next_state_action' on it. This is one of the default actions included with the Workflow module. You can see this action in the Actions section under Site configuration where there should be an action called "Change workflow state of post to next state".

This worked perfectly! I created a "submission node" which put the node in the "created state" and redirected me to the cart. Once I went through the checkout process and paid, the submission node was changed to the "paid for" state.

Now i need to be able to list all nodes in the "paid for" state for the moderator. This screams Views so I'll be working on that next.

One of the kinks I need to work out is cleaning up submission nodes that were never paid for. I'll probably use Workflow itself to delete nodes that are in the "created" state for more than a specified amount of time.

Hope this helps someone or gives them some ideas. Let me know what you think. I'll be back to post more after I'm done cheering if this works as planned or crying if it doesn't. Smiling

--

Chisholm Technologies, Inc.
Custom software development since 1999!
www.chisholmtech.com

Posts: 3959
Joined: 08/07/2007
AdministratorHead Code Monkey - I eat bugs.

That's quite a piece of work. Cool I'm glad you were able to figure this out, and I hope the Views don't give you much headache. They should be at least as simple as anything you posted above, likely easier.

If you don't mind, would you be able to add the contents of your above post along w/ how the Views turn out as a tutorial in our User's Guide? You just have to go here and click on Add child page. That would rock.

Posts: 23
Joined: 04/04/2008

Thanks! You're right about the Views. Actually, the most difficult part of this whole thing was not the process above, but getting the imagefield module to do what I wanted. I needed to add fields to each image uploaded. I wound up having to patch the imagefield module for my purposes. So I think the worst is behind me.

Yes, I'd be happy to add it to the tutorial.

--

Chisholm Technologies, Inc.
Custom software development since 1999!
www.chisholmtech.com

Posts: 3959
Joined: 08/07/2007
AdministratorHead Code Monkey - I eat bugs.

Awesome. Glad to hear you were able to put it all together. Smiling

That's what I love about Drupal... with all these modules laying around like little Lego pieces, you can put them together in ways the developers never would've expected. Viva la Drupal.

Posts: 6
Joined: 03/11/2008

amaria, this is a great recipe, I'm using a modified version of it after giving up on uc_nodetype.

But what I can't figure out is, where you say "My custom php code gets the submitted node from the order and runs the action" - how does it get the node exactly? It seems to me that once the order is placed it is no longer linked in any obvious way to the node. Would you mind posting your php code for the final rule?

Posts: 23
Joined: 04/04/2008

dafeder, the submission product in the order has a parent_node in its data array. Here's the code...

<?php
$prods
= $order->products;
foreach (
$prods as $prod) {
  if (
$prod->type=='submission_product')  && array_key_exists('parent_node', $prod->data) && !empty($prod->data['parent_node']) ) {
   
$submitted_node = node_load($prod->data['parent_node']);
   
actions_do('workflow_select_next_state_action', $submitted_node);
  }
}
?>

That gets each product in the order that is a submission product and gets the parent_node from its data array. Then loads the node and performs the workflow action.

If you know you're only going to have one product of this type in the cart, then you can break the foreach loop after finding that product. There may also be a way to run the action on multiple node id's in one call so as not to load the entire node object just to change it's state. But I haven't had time to play around with that yet.

--

Chisholm Technologies, Inc.
Custom software development since 1999!
www.chisholmtech.com

Posts: 6
Joined: 03/11/2008

Thanks amaria - after a bit of experimenting to get this to work with my setup it is working very well.

I skipped the workflow aspect of this and am just having the workflow-ng rule set the node status to published. So in place of

<?php
    actions_do
('workflow_select_next_state_action', $submitted_node);
?>

I have

<?php
    $node
->status = 1;
   
node_save($node);
?>

This makes do essentially what uc_nodetype was doing. So far, very happy with the results.

Posts: 23
Joined: 04/04/2008

Glad it worked out for you. I'm only using the Workflow module because it's so very easy to setup access based on states and state transitions. Barring that, yes everything can be done with workflow-ng.

One question though, did you set the "Order has a product of a particular class" condition? That doesn't work for me. I eventually had to create custom PHP code to find out if the cart has items of a class.

Also, another thing I have to work out is when that item is removed from the cart it doesn't remove the parent node. I'm debating on whether or not it should.

--

Chisholm Technologies, Inc.
Custom software development since 1999!
www.chisholmtech.com

Posts: 6
Joined: 03/11/2008

No, actually I didn't, but I didn't try. I'm not really using classes - I based the action on the nodetype of the parent node - I'm using this both as part of an event registration system and as a pay-to-publish system for two different nodetypes. Here is the full action:

<?php
foreach ($order->products as $prod) {
    if (
array_key_exists('parent_node', $prod->data) && !empty($prod->data['parent_node']) ) {
       
$node = node_load($prod->data['parent_node']);
        switch (
$node->type) {
            case
'eventreg_data':
               
$node->field_paid[0]['value'] = 1;
                break;
            case
'freelance_listing':
            case
'job_listing':
               
$node->status = 1;
            default:
            break;
        }
       
node_save($node);
    }
}
?>

Posts: 14
Joined: 04/06/2008

I have got this working somewhat, but it seems that when a user makes a purchase the node gets posted with only the title and the body field. It doesn't carry over any of the CCK fields at all.

This is really strange because on one install it is working fine, but on another install it isnt carrying over the cck fields. I'm guessing that this is conflicting with another module somehow or maybe it doesn't like one of the field types?

Attached are the working CCK and nonworking CCK types. Let me know if anyone has any ideas.

Thanks in advance,
Zach

*****UPDATED
The problem lies with CCK Groups. I removed the groups and it seems to work now. Unofficially reporting this bug. Can we turn this into a Contrib?

Posts: 37
Joined: 11/28/2007

Sorry for disappearing. I switched jobs in April and stopped receiving notifications for this thread. I'm really excited to see that you got this working!

To delete the nodes that have not been approved, have you thought about adding a cron job?