0

I have very little experience working with Drupal and it may be possible that I'm missing something very basic here.

I have created a module to add/update nodes pro-grammatically from an XML file, this nodes have a file for images. For every node there's a French version and an English version, this means that they share the same images. When I import these nodes I would like to avoid refetching the images (since those are already into the public:// folder) and populate only the image field.

The first run goes smoothly, the images are fetched and saved from URL for all the English nodes using this code:

if(!file_exists("public://" . $name)) {
    $file_temp = file_get_contents($URL);
    $file_temp = file_save_data($file_temp, "public://" . $name, FILE_EXISTS_REPLACE);
}

$node->field_image[LANGUAGE_NONE][$k]['fid'] = $file_temp->fid;
$node->field_image[LANGUAGE_NONE][$k]['title'] = $name;

The second round, for the french nodes, what I've done is:

else {
    $file_temp = new stdClass();
    // Get the image id corresponding to the $name parameter, returns string.
    $file_temp->fid = _xml_importer_get_image_id($name, $table, $fid, $title);
}

$node->field_image[LANGUAGE_NONE][$k]['fid'] = $file_temp->fid;
$node->field_image[LANGUAGE_NONE][$k]['title'] = $name;

This works, in a sense, meaning that the fields are populated correctly and the image are shared between the nodes, the problem is that I get warning and notices for this part.

This is the full dump:

Warning: array_flip() [function.array-flip]: Can only flip STRING and INTEGER values! in DrupalDefaultEntityController->load() (line 178 of /drupal/includes/entity.inc). Notice: Trying to get property of non-object in file_field_presave() (line 220 of drupal/modules/file/file.field.inc). Strict warning: Creating default object from empty value in file_field_presave() (line 221 of drupal/modules/file/file.field.inc). Notice: Undefined property: stdClass::$uri in file_save() (line 566 of drupal/includes/file.inc). Warning: array_flip() [function.array-flip]: Can only flip STRING and INTEGER values! in DrupalDefaultEntityController->load() (line 178 of drupal/includes/entity.inc). Notice: Trying to get property of non-object in file_field_presave() (line 220 of drupal/modules/file/file.field.inc). Strict warning: Creating default object from empty value in file_field_presave() (line 221 of drupal/modules/file/file.field.inc). Notice: Undefined property: stdClass::$uri in file_save() (line 566 of drupal/includes/file.inc). SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'uri' Warning: array_flip() [function.array-flip]: Can only flip STRING and INTEGER values! in DrupalDefaultEntityController->load() (line 178 of drupal/includes/entity.inc). Notice: Trying to get property of non-object in file_field_presave() (line 220 of drupal/modules/file/file.field.inc). Strict warning: Creating default object from empty value in file_field_presave() (line 221 of drupal/modules/file/file.field.inc). Notice: Undefined property: stdClass::$uri in file_save() (line 566 of drupal/includes/file.inc). Warning: array_flip() [function.array-flip]: Can only flip STRING and INTEGER values! in DrupalDefaultEntityController->load() (line 178 of drupal/includes/entity.inc). Notice: Trying to get property of non-object in file_field_presave() (line 220 of drupal/modules/file/file.field.inc). Strict warning: Creating default object from empty value in file_field_presave() (line 221 of drupal/modules/file/file.field.inc). Notice: Undefined property: stdClass::$uri in file_save() (line 566 of drupal/includes/file.inc).

I looked for this kind of warnings/notices and I found out that somewhere I'm passing some parameters not in a correct way (e.g. arrays instead of strings) and for me doesn't make sense. My guess is that not invoking file_save_data has some effect on the file_managed table and gives missing or malformed parameter, anyway with my poor experience I may be very well mistaking.

This is the full code snippet I'm using:

for($k=0; $k<sizeof($file_list); $k++) {
    if(!file_exists("public://" . $file_list[$k]->name)) {
        $file_temp = file_get_contents($URL);
        $file_temp = file_save_data($file_temp, "public://" . $file_list[$k]->name, FILE_EXISTS_REPLACE);
    }
    else {
        $file_temp = new stdClass();
        // Get the image id corresponding to the $name parameter, returns string.
        $file_temp->fid = _xml_importer_get_image_id($file_list[$k]->name, $table, $fid, $title);
    }
    $node->field_image[LANGUAGE_NONE][$k]['fid'] = $file_temp->fid;
    $node->field_image[LANGUAGE_NONE][$k]['title'] = $file_list[$k]->name;
}

And this is the function _xml_importer_get_image_id:

_xml_importer_get_image_id($image_name, $table, $field, $title_field) {

    $query = db_select($table, 'ill')
        ->condition('ill.' . $title_field, $image_name, '=')
        ->fields('ill', array($field))
        ->execute()
        ->fetchCol();

    if(empty($query)) {
            return false;
    }
    else{
        return (string)$query[0];
    }
}
4
  • I'd guess the problem is in the _xml_importer_get_image_id() function. BTW if that really is your full code snippet then $k isn't defined which won't help
    – Clive
    Jul 16, 2013 at 15:44
  • @Clive I added the _xml_importer_get_image_id() function and the for cycle for the $k variable, I left it out at the beginning because i thought it was not important, I forgot to say that every node can have more than 1 image.
    – Ende Neu
    Jul 16, 2013 at 15:52
  • Cool that makes more sense...where is $file_list coming from?
    – Clive
    Jul 16, 2013 at 15:55
  • It comes from $file_list = $xml->xpath($xpath_query), I dsm'd the hell out of this xpath parsing and I know I get all the names correctly (otherwise it wouldn't work at all, meaning it wouldn't fetch the images).
    – Ende Neu
    Jul 16, 2013 at 15:59

1 Answer 1

0

I found that with my snippet I was totally bypassing the Drupal file management system, I corrected the issue in this way:

else {
    $file_temp = file_load(_xml_importer_get_image_id($image_xpath[$k]->value, $table, $field, $title));
}
$node->field_image[LANGUAGE_NONE][$k]['fid'] = $file_temp->fid;
$node->field_image[LANGUAGE_NONE][$k]['title'] = $file_list[$k]->name;

Another problem was that there was the same image name twice inside the XML file, had to check for duplicate to avoid breaking some unicity constraint from the database.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.