Drupal-6: Why won't this node save? - php

I have constructed a set of nodes. After running them through node_save(), I get back an nid, and I can navigate to the page for that node, but they are empty. (No data is shown for any of the fields.)
When I go to the edit url for that node, I get this error message:
warning: call_user_func_array()
[function.call-user-func-array]: First
argument is expected to be a valid
callback, 'Bout_node_form' was given
in
/home/odp/public_html/includes/form.inc
on line 367.
Here is the print_r() of one node I am trying to save:
stdClass Object
(
[type] => Bout
[name] => Gary Oak
[title] => Bout - 0
[promote] => 1
[comment] => 2
[revision] =>
[format] => 0
[status] => 0
[field_weapon] => Array
(
[0] => Array
(
[value] => foil
)
)
[field_fencer] => Array
(
[0] => Array
(
[uid] => 3
)
)
[field_touches_scored] => Array
(
[0] => Array
(
[value] => 4
)
)
[field_meet] => Array
(
[0] => Array
(
[nid] => Drew
)
)
[field_round] => Array
(
[0] => Array
(
[value] => 1
)
)
[field_legacy_bout] => Array
(
[0] => Array
(
[value] => no
)
)
[teaser] =>
[uid] => 1
[created] => 1262732370
[validated] => 1
)
These nodes have all been run though node_validate(), and presumably that would have caught some errors. Also, this node is missing required taxonomy, but that isn't causing any error messages, either.
This is how node_validate() was called:
function preview_validate($form, &$form_state) {
$nodes_to_save = construct_nodes();
foreach ($nodes_to_save as $node) {
node_validate($node, $form);
if ($errors = form_get_errors()) {
form_set_error('', t('Validation error. No nodes saved.'));
}
}
$_SESSION[CONSTRUCTED_KEY] = $nodes_to_save;
}
This is where the error is coming from, in the core file includes/form.inc:
// If $callback was returned by a hook_forms() implementation, call it.
// Otherwise, call the function named after the form id.
$form = call_user_func_array(isset($callback) ? $callback : $form_id, $args);
The node shows up in the node table, but not the content_type_bout table.
This is the construct_nodes() function:
function construct_nodes() {
global $user;
$file = unserialize($_SESSION[FILE_KEY]);
$count = 0; // how many nodes have been created?
$success = TRUE; // have all the nodes thus far validated?
foreach ($file->parsed as $node) {
$odp = new StdClass();
$odp->type = $_SESSION[NODE_TYPE_KEY];
if (! in_array('name', $file->matched_keys)) {
$odp->name = $user->name;
}
if (! in_array('title', $file->matched_keys)) {
$odp->title = sprintf("%s - %s", $_SESSION[NODE_TYPE_KEY], $count);
}
$node_type_default = variable_get('node_options_'. $_SESSION[NODE_TYPE_KEY], array('status', 'promote')); //copied from blogapi module
$odp->promote = in_array('promote', $node_type_default);
$odp->comment = variable_get('comment_'. $_SESSION[NODE_TYPE_KEY], 2);
$odp->revision = in_array('revision', $node_type_default);
$odp->format = FILTER_FORMAT_DEFAULT;
$odp->status = CTN_DEFAULT_PUBLISHED;
// this makes the assumption that the field arrays will always have only one item
// doesn't handle taxonomy
foreach ($node as $field => $value) { // $field => value: [Touches scored] => 5
$node_key = $file->matched_keys[$field]; // $node_key will be something like: "field_meet" or "vid:4"
$vid = vidOfTaxKey($node_key);
if ($vid == NULL) {
$valTypes = $_SESSION[SAMPLE_NODE_KEY]->$node_key; // like: [0] => Array ( [uid] => 3 )
$valType = array_keys($valTypes[0]);
$odp->$node_key = array(array($valType[0] => $value));
}
}
$to_save[] = $odp;
$count++;
unset($submitted_odp);
}
return $to_save;
}
bout is a CCK-defined content type. Using the human name "Bout" for the type instead of the internal code name bout was, I believe, a source of error.

where is this custom content type defined? in a custom module, or via Administer > Content > Content types > Add content type? is it defined at all? if not, then no wonder you get this error: how is Drupal supposed to know what this content type is composed of and how to render its view and edit forms? try defining it, either way.
custom content (node) type names ([type] => Bout) must contain only lowercase letters, numbers, and underscores. try changing Bout to bout.
see also How do I create a node from a cron job in drupal? and http://drupal.org/node/178506#comment-895418 (the whole thread).

try this
<?php
$new_blognode = new stdClass();
$new_blognode->type = 'blog';
module_load_include('inc', 'node', 'node.pages');
$output .= drupal_get_form('blog_node_form', $new_blognode);
?>
note that you should change this to your needs

$node['type']='bout'; NOT $node['type']='Bout';
Confirm that you are not struck with simple caps problem.

Related

set class html attribute to a specific variable within a multidimensional array

I have a question that is probably extremely simple, but I just can't get my head around it. And if I'm using the wrong lingo, please let me know....
I'm using a list_helper class to help display a list of records, 1 set per row.
Here is the code I'm working with:
foreach ($records as $record) {
$record_array = get_object_vars($record);
$row = array();
foreach ($fields as $i => $field) {
$value = NULL;
if (isset($field['getter']) && is_callable($field['getter'])) {
$value = call_user_func($field['getter'], $record);
} else if (isset($field['key']) && isset($record_array[($key = $field['key'])])) {
$value = $record_array[$key];
}
if(isset($field['class_attr'])) {
echo $value;
$value->attributes['class'] = 'test';
}
}
}
What I'm trying to achieve (in the last 4 lines of code) is set an HTML class attribute to a specific record. One of the fields (completion_date) has been tagged as having a 'class_attr' value assigned to it in another php page. Something like:
'label' => 'compl_date',
'class_attr' => 'test'
When I echo $value it returns the correct field, but when I want to assign a HTML class attribute to that date field (i.e. completion_date), it returns an
error: Warning: Attempt to modify property of non-object.
This is not code I have written myself, so I'm sure I'm missing something here.
When looking at the $field object, it returns the following details:
Array
(
[0] => Array
(
[label] => Completion date
[class_attr] => testcase
[getter] => Closure Object
(
[this] =>
local_courses_all_current_courses_list Object
(
[model:local_courses_all_current_courses_list:private] =>
local_courses_current_courses_model Object
(
)
[params:local_base_list_helper:private] => Array
(
[action] => 0
[action_arg] =>
[action_confirm] =>
[page] => 0
[per_page] => 30
)
[prefix:local_base_list_helper:private] =>
[display] => local_base_display_helper Object
(
)
)
[parameter] => Array
(
[$record] =>
)
)
)
)
Can anyone point me in the right direction? I have been wrestling with this little thing for over 2 days now and I'm out of options....
Thanks

Regex to Extract Report ID Out of a multi-dimensional array with PHP

Here's my problem. We got some sample PHP that didn't work so I've been trying to write this more or less "by the seat of my pants". My regex is rusty and I've not dealt with multidimensional arrays, so this is outside my realm of experience.
I'm getting an array like this one but I only want the report ID's where [1] contains the word "Export" and then I need to pass those to another script where I have to do more or less the same thing to get a result set ID that I can pass to another script that I can actually export.
[0] => Array
(
[0] => REPORTIDXXXXXXXXXXXXXXXXXXXXXXXXXXX
[1] => REPORT EXPORT NAME#1
[2] => REPORT DESCRIPTION #1
[3] => 2012-10-02T17:31:30
)
[1] => Array
(
[0] => REPORTIDYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
[1] => REPORTOTHERNAME#2
[2] => REPORTDESCRIPTION #2
[3] => 2012-09-28T15:15:17
)
[2] => Array
(
[0] => REPORTIDZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
[1] => REPORT EXPORT NAME#3
[2] => REPORT DESCRIPTION #3
[3] => 2012-09-28T14:59:17
)
Something like this should work:
function get_report_ids(array $rs) {
$results = array();
// loop over your data structure
foreach($rs as $key => $data) {
// If element 1 contains EXPORT (case insensitive)
if(stripos($data[1], 'EXPORT') !== false) {
// regex to capture the ID from element 0
if(preg_match('/^EXPORTID(.*)$/i', $data[0], $matches)) {
// add the ID to the results array
$results[] = $matches[1];
}
}
}
// if we had results then return the array, otherwise return null
return !empty($results) ? $results : null;
}
Example return value:
array(
0 => 'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
1 => 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ'
)

CakePHP Model Query Return Data Formating

I'm looking for a way to make it so cake returns all database data in the same format/structure... Currently it returns two different types of format depending on the relationship.
If a model 'B' is associated with the current model 'A' being queried it will then place model associations for 'B' underneath it as you can see in [User] below. I want it so that all queries use that structure.
example:
$this->find('all', ....
returns:
Array
(
[0] => Array
(
[UserGroup] => Array
(
[id] => 53
[user_id] => 100003332014851
[media_id] =>
[name] => john
[description] => qwasdfad
)
[User] => Array
(
[id] => 100003332014851
[session_id] => ssm2qbrotmm13ho1ipm8ii2492
[username] =>
[password] => -1
[Planner] => Array
(
)
[Purchase] => Array
(
)
[Listing] => Array
(
)
)
)
I want this to look like:
Array
(
[0] => Array
(
[UserGroup] => Array
(
[id] => 53
[user_id] => 100003332014851
[media_id] =>
[name] => john
[description] => qwasdfad
[User] => Array
(
[id] => 100003332014851
[session_id] => ssm2qbrotmm13ho1ipm8ii2492
[username] =>
[password] => -1
[Planner] => Array
(
)
[Purchase] => Array
(
)
[Listing] => Array
(
)
)
)
)
)
In CakePHP, the find() method return data like your first format. But If you want to format like second one then you have to process it by hand (try to avoid this if possible)
$data = $this->find('all');
$assocs = Set::extract('/User', $data); // extracting all `User` array
foreach($assocs as $key => $assoc) {
unset($data[$key]['User']); // removing the associate `User` from `$data`
$data[$key]['UserGroup']['User'] = $assoc['User']; // adding associate under `UserGroup`
}
ended up doing this... it changes the output to what we need. The top level item does not have a header which is fine I just adjusted our scripts for that... maybe this will help somebody else if they need a custom idea
also no guarantee this covers all possible results but so far it works with all the queries we have.
class AppModel extends Model {
function afterFind($results, $primary) {
//if this is a primary, structure like a secondary so entire site is same format
if ($primary) {
$class = get_class($this);
//simple fix for primary
foreach ($results as $key => $result) {
$result = $this->formatData($result, $class);
$results[$key] = $result;
}
}
return $results;
}
function formatData($result, $class) {
$array = array();
if (isset($result[$class])) {
$array = $result[$class];
unset($result[$class]);
}
$array += $result;
return $array;
}
You can also use contain in this case along with find as UserGroup.User for your desired result

PHP Accessing named array elements issue

I have an array which is generated from an XML file and it shows me like below when printed with print_r
Array
(
[cxname] => Global CX 87 123
[ipaddress] => 66.240.55.87
[slots] => Array
(
[slot] => Array
(
[0] => Array
(
[slotno] => 1
[cardtype] => 0x24
[modelno] => OP3524J
[label1] => OP
[label2] => Module
[severity] => Minor
)
[1] => Array
(
[slotno] => 2
[cardtype] => 0x25
[modelno] => OP3524K
[label1] => OP
[label2] => Module
[severity] => Major
)
)
)
)
When I print like this, it shows nothing
echo $dataArray->cxname;
But following code works and prints "Global CX 87 123 "
echo $dataArray["cxname"];
How can I make it work as above example.
Just do this:
$dataArray = (object)$dataArray;
It'll convert the array in an stdClass object and allow you to use it that way. Please note that this will only convert the first level for the array. You'll have to create a function to recurse through the array if you want to access all levels that way. For example:
<?php
function arrayToObject($array) {
if(!is_array($array)) {
return $array;
}
$object = new stdClass();
if (is_array($array) && count($array) > 0) {
foreach ($array as $name=>$value) {
$name = strtolower(trim($name));
if (!empty($name)) {
$object->$name = arrayToObject($value);
}
}
return $object;
}
else {
return FALSE;
}
}
For more information, have a look at http://www.richardcastera.com/blog/php-convert-array-to-object-with-stdclass. To find out about typecasting, you can also read http://www.php.net/manual/en/language.types.object.php#language.types.object.casting.
This:
echo $dataArray["cxname"];
is the way you access array elements. But this:
echo $dataArray->cxname;
is the way, you access class members.
If you want to access the data as class members, you have to use a xml parser which returns classes (or objects), not arrays.
If you have got the XML string, you can parse it into an object by using simplexml_load_string().

PHP function return value nested array removed

I have a function that builds a collection of user objects from the database:
public static function GetUsersByGroup($instanceID, $groupID)
{
$col = null;
if($groupID != null)
{
$col = UserGroup::GetCollection("User" ,_DB_GET_ALL_INSTANCE_USERGROUP_MEMBERS,array ($instanceID, $groupID));
}
else
{
$col = UserGroup::GetCollection("User" ,_DB_GET_ALL_INSTANCE_NOGROUP_MEMBERS,$instanceID);
}
echo "this is the collection I am going to return: <pre>";
print_r($col);
echo "</pre>";
return $col;
}
The method has some debug output at the bottom, but the point is if I call that method with a null groupid param i.e it runs the second condition, it prints out a nice indication of the collection that I expected to receive, which is great.
However ..
Here is my calling method:
echo "<br> Collection passed through is: </br>";
$collection = UserGroup::GetUsersByGroup($this->GetInstance()->id,$grouplist->GetCurrentCommandParam());
print_r($collection);
$userlist->UpdateCollection($collection);
$userlist->DeSelect();
The intresting thing is the output:
this is the collection I am going to return:
Collection Object
(
[_valueType:protected] => User
[_isBasicType:protected] =>
[_validateFunc:protected] =>
[_collection:protected] => Array
(
[0] => User Object
(
[valid] =>
[validationMessage] =>
[id] => 29
[table:private] => user
[fields:private] => Array
(
[title] => mrs
[fname] => Kirsty
[lname] => Howden
[email] => kirsty2#softyolk.com
[password] => xxxxxxxx
[lastlogin] => 2009-07-05 15:20:13
[instanceID] => 2
[deliveryAddress] =>
[invoiceAddress] =>
[tel] => 01752848484
[isAdmin] => 0
[disabled] => 0
[mustAuthorise] =>
[usergroupID] =>
)
[validationRules:private] => Array
(
)
[_profileStartTime:protected] =>
[_profileTag:protected] =>
)
[1] => User Object
(
[valid] =>
[validationMessage] =>
[id] => 31
[table:private] => user
[fields:private] => Array
(
[title] => master
[fname] => Seb
[lname] => Howden
[email] => seb#antithug.co.uk
[password] => xxxxxxxxx
[lastlogin] => 2009-07-09 02:02:24
[instanceID] => 2
[deliveryAddress] => saltash
[invoiceAddress] => saltash
[tel] => 8908908
[isAdmin] => 0
[disabled] => 0
[mustAuthorise] =>
[usergroupID] =>
)
[validationRules:private] => Array
(
)
[_profileStartTime:protected] =>
[_profileTag:protected] =>
)
)
)
Collection passed through is:
this is the collection I am going to return:
Collection Object
(
[_valueType:protected] => User
[_isBasicType:protected] =>
[_validateFunc:protected] =>
[_collection:protected] => Array
(
)
)
Collection Object ( [_valueType:protected] => User [_isBasicType:protected] => [_validateFunc:protected] => [_collection:protected] => Array ( ) )
The object returned has been modified??
If the GetUsersByGroup method is called with a userGroupID i.e the first case, then output is all as expected.
If i remove the conditional from the method and simply return $col = UserGroup::GetCollection("User" ,_DB_GET_ALL_INSTANCE_NOGROUP_MEMBERS,$instanceID); then all output is as expected.
It seems that the else condition executes correctly, and then is corrupted on return, but this only happens if the else condition is present, remove the else condition, and simply return the result of the method call in the else condition, and all is as expected.
Any idea please?
Thanks
ADDED THE UserGroup::GetCollection Method (this is a deep rabbit hole though, could go on)
protected static function GetCollection($class, $sqlID, $params = null)
{
$dal = DAL::GetInstance(); //not to be confused with the Instance object, this is an instance of DAL
$collection = new Collection($class);
$items = $dal->QueryForAssoc($sqlID,$params);
foreach($items as $item)
{
$itemObject = new $class();
$itemObject->LoadFromList($item);
$collection->add($itemObject);
}
return $collection;
}
To further clarify the follwing works fine ::
public static function GetUsersByGroup($instanceID, $groupID)
{
$col = null;
//if($groupID != null)
//{
//$col = UserGroup::GetCollection("User" ,_DB_GET_ALL_INSTANCE_USREGROUP_MEMBERS,array ($instanceID, $groupID));
//}
//else
//{
$col = UserGroup::GetCollection("User" ,_DB_GET_ALL_INSTANCE_NOGROUP_MEMBERS,$instanceID);
// }
return $col;
}
I only see the issue if the line is in the else block.
The likely problem here lies in your UserGroup::GetCollection function. PHP 5 passes all objects by reference, so if you are doing any sort of modification in this routine based on the way you are retrieving these objects, then this modification will persist after UserGroup::GetCollection has finished.
I would examine carefully the differences between these two function calls and make sure there are no object changes happening in UserGroup::GetCollection.
$col = UserGroup::GetCollection("User" ,_DB_GET_ALL_INSTANCE_USERGROUP_MEMBERS,array ($instanceID, $groupID));
vs.
$col = UserGroup::GetCollection("User" ,_DB_GET_ALL_INSTANCE_NOGROUP_MEMBERS,$instanceID);
Turns out the method is being called twice, the second call is using the other condition, and returning a blank collection (the problem result).
By setting an echo in each condition I could see as they are called, and first the null case is called and then the non null.
The actual error is that I had a stateful list calling the method twice in the same postback. Hard to catch.
Thanks for looking

Categories