scriptotek / php-marc

Simple interface for working with MARC records using the File_MARC package
MIT License
51 stars 11 forks source link

Marc\Record->getFields() fatal error on php 8.1 #27

Open hrvoj3e opened 6 months ago

hrvoj3e commented 6 months ago
$xml = $this->fetchXml($identifier);
$record = Marc\Record::fromString($xml);
$fields = $record->getFields();
Fatal error: Uncaught TypeError: array_map(): Argument #2 ($array) must be of type array, 
File_MARC_List given in /einwww/mycode/marc21import/vendor/scriptotek/marc/src/Record.php:115 
Stack trace: #0 /einwww/mycode/marc21import/vendor/scriptotek/marc/src/Record.php(115): 
array_map() #1 /einwww/mycode/marc21import/Marc21Import.php(125): 
Scriptotek\Marc\Record->getFields() #2
php8.1 /usr/local/bin/composer  require scriptotek/marc

{
    "require": {
        "scriptotek/marc": "^3.0"
    }
}

  - Installing ck/php-marcspec (2.0.3): Extracting archive
  - Installing pear/pear_exception (v1.0.2): Extracting archive
  - Installing pear/file_marc (1.4.1): Extracting archive
  - Installing ck/file_marc_reference (v1.2.0): Extracting archive
  - Installing scriptotek/marc (v3.0.0): Extracting archive

I tried manually using "pear/file_marc": "master@dev" but it has not helped

{
    "require": {
        "scriptotek/marc": "^3.0",
        "pear/file_marc": "master@dev"
    }
}

  - Installing ck/php-marcspec (2.0.3): Extracting archive
  - Installing pear/pear_exception (v1.0.2): Extracting archive
  - Installing pear/file_marc (dev-master 7085b9e): Extracting archive
  - Installing ck/file_marc_reference (v1.2.0): Extracting archive
  - Installing scriptotek/marc (v3.0.0): Extracting archive
hrvoj3e commented 4 months ago

There is a workaround if you force PCRE tag matching.

// fetch all fields works OK
$foundFields = $record->getFields('.*', pcre: true);

// same fix MUST be used when fetching all subfields
$fieldUsed->getSubfields('.*', pcre: true);

Scriptotek\Marc\Record::getFields() has a bug as it has in docs @return \Scriptotek\Marc\Fields\Field[] An array of wrapped fields. but that is not true and it throws fatal error.

This works because using PCRE it will return an array (it uses File_MARC_Record::getFields()) which Scriptotek\Marc\Record::getFields() expects

    function getFields($spec = null, $pcre = null)
    {
        if (!$spec) {
            return $this->fields;   // <-------- THIS IS PROBLEMATIC as it returns \File_MARC_List
        }

        // Okay, we're actually looking for something specific
        $matches = array();
        foreach ($this->fields as $field) {
            if (($pcre && preg_match("/$spec/", $field->getTag()))
                || (!$pcre && $spec == $field->getTag())
            ) {
                $matches[] = $field;
            }
        }
        return $matches;
    }