/**
     * @param string $sql
     * @return bool
     */
    public static function query($sql)
    {
        if (!is_null(self::$db))
        {
            XMLImportMonitor::log($sql, 'sql');

            self::$db->query($sql);
            return true;
        }
        return false;
    }
    /**
     * @return void
     */
    public function buildFields()
    {
        $fieldList = $this->rootNode->childNodes;

        foreach ($fieldList as $fieldNode)
        {
            if ($fieldNode instanceof DOMElement)
            {
                if (!$fieldNode->hasAttribute('name'))
                {
                    XMLImportMonitor::log('Not a valid field : A field has no name attribute', 'error');
                    continue;
                }
                $fieldName = strtolower(trim($fieldNode->getAttribute('name')));

                $this->fieldArray[$fieldName][] = new XMLField($fieldNode, $fieldName);
            }
        }
    }
    /**
     * @param XMLField[]|XMLField $xmlField
     * @return mixed
     */
    public function getFieldContent($xmlField)
    {
        $rootImport = $this->importINI->variable( 'XMLImportSettings', 'RootImport' );

        if (is_array($xmlField))
        {
            /* @type $xmlField XMLField[] */
            $mapping = XMLImportMapping::getByFieldName($xmlField[0]->getParentType(), $xmlField[0]->internalFieldName);
        }
        elseif (is_null($xmlField->fieldNode))
            return false;
        else
            $mapping = XMLImportMapping::getByFieldName($xmlField->getParentType(), $xmlField->internalFieldName);

        /* @type $xmlField XMLField */
        switch ($mapping['type'])
        {
            case 'text':
            {
                /* @type $xmlField XMLField */
                $fieldContent = strip_tags(trim($xmlField->fieldNode->nodeValue));
                $returnContent = $fieldContent;
            }
            break;
            case 'image':
            case 'video':
            case 'pdf':
            case 'audio':
            case 'contact':
            case 'file':
            case 'media_content':
            case 'html_media':
            {
                if (!is_array($xmlField))
                {
                    try
                    {
                        $xmlFieldBuilder    = new XMLFieldBuilder($this->xmlParser, $this->importINI, $xmlField->fieldNode);
                        $xmlFieldMixer      = new self($xmlFieldBuilder, $this->xmlParser, $this->importINI, $this->publisherInfos, $this->rootImportFolder);
                        $fieldContent       = $xmlFieldMixer->process($mapping['type']);

                        if ( !isset($fieldContent['language']) )
                        {
                            $emulatedXMLField                       = new stdClass();
                            $emulatedXMLField->calculatedValue      = $this->publisherInfos['default_language'];
                            $emulatedXMLField->internalFieldName    = 'language';
                            $fieldContent['language']               = $emulatedXMLField;
                            $illustrativeMediaFields                = XMLImportMapping::getByFieldName('illustrative_media', $xmlField->internalFieldName);

                            if ( $illustrativeMediaFields === false && $this->publisherInfos['default_language_medias'] == 0 )
                                XMLImportMonitor::log($xmlField->internalFieldName . ' : The Field\'s language has been defaulted to ' . $this->publisherInfos['default_language'] . ', publisher settings says it shouldn\'t have.', 'warning');
                        }

                        $returnContent = $fieldContent;
                    }
                    catch (MandatoryException $e)
                    {
                        XMLImportMonitor::log($xmlField->internalFieldName . ' : ' . $e->getMessage(), 'warning');
                    }
                }
                else
                {
                    $returnContent = false;

                    /* @type $xmlField XMLField[] */
                    foreach ($xmlField as $index => $field)
                    {
                        if (is_null($field->fieldNode))
                            continue;

                        try
                        {
                            $xmlFieldBuilder    = new XMLFieldBuilder($this->xmlParser, $this->importINI, $field->fieldNode);
                            $xmlFieldMixer      = new self($xmlFieldBuilder, $this->xmlParser, $this->importINI, $this->publisherInfos, $this->rootImportFolder);
                            $fieldContent       = $xmlFieldMixer->process($mapping['type']);

                            if (is_array($fieldContent) && count($fieldContent) > 0)
                            {
                                if ( !isset($fieldContent['language']) )
                                {
                                    $emulatedXMLField                       = new stdClass();
                                    $emulatedXMLField->calculatedValue      = $this->publisherInfos['default_language'];
                                    $emulatedXMLField->internalFieldName    = 'language';
                                    $fieldContent['language']               = $emulatedXMLField;
                                    $illustrativeMediaFields                = XMLImportMapping::getByFieldName('illustrative_media', $field->internalFieldName);

                                    if ( $illustrativeMediaFields === false && $this->publisherInfos['default_language_medias'] == 0 )
                                        XMLImportMonitor::log($field->internalFieldName . ' : The Field\'s language has been defaulted to ' . $this->publisherInfos['default_language'] . ', publisher settings says it shouldn\'t have.', 'warning');
                                }

                                $field->calculatedValue = $fieldContent;
                                $returnContent          = true;
                            }
                            else
                                unset($xmlField[$index]);

                            $this->blobedFiles = array_merge($this->blobedFiles, $xmlFieldMixer->blobedFiles);
                        }
                        catch (MandatoryException $e)
                        {
                            XMLImportMonitor::log($field->internalFieldName . ':' . $e->getMessage(), 'warning');

                            unset($xmlField[$index]);
                        }
                    }
                }
            }
            break;
            case 'richtext':
            {

                $fieldContent = str_replace(array(
                        "\n\r",
                        "\n",
                        "\r"
                    ), array(
                        ' ',
                        ' ',
                        ' '
                    ), trim($xmlField->fieldNode->nodeValue)
                );

                $returnContent = $fieldContent;
            }
            break;
            case 'taxonomy':
            {
                $fieldContent = str_replace( ' ', '', trim($xmlField->fieldNode->nodeValue) );
                $contentArray = explode('|', $fieldContent);

                if ($contentArray !== false && $contentArray != "")
                {
                    $mmDB = MMDB::instance();

                    foreach ($contentArray as $key => $value)
                    {
                        $value = trim($value);
                        if ($value != "")
                        {
                            //Check if key exists in table 'taxonomy'
                            $result = $mmDB->arrayQuery('SELECT 1 FROM mm_taxonomy WHERE code = "' . $contentArray[$key] . '"');

                            if (empty($result))
                            {
                                XMLImportMonitor::log('The taxonomy {' . $contentArray[$key] . '} in field {' . $xmlField->fieldName . '} doesn\'t exists', 'notice');

                                unset($contentArray[$key]);
                            }
                            else
                                $contentArray[$key] = $value;
                        }
                        else
                            unset($contentArray[$key]);
                    }
                    if (count($contentArray))
                    {
                        $returnContent = array_unique($contentArray);
                    }
                }
            }
            break;
            case 'integer':
            {
                $fieldContent = filter_var(trim($xmlField->fieldNode->nodeValue), FILTER_VALIDATE_INT);

                if ($fieldContent !== false)
                    $returnContent = $fieldContent;
            }
            break;
            case 'date':
            {
                $fieldContent = trim($xmlField->fieldNode->nodeValue);
                $datePattern  = "/(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}) (?P<hour>\d{2}):(?P<minute>\d{2})/";

                if (preg_match($datePattern, $fieldContent, $m))
                    $returnContent = "{$m['year']}-{$m['month']}-{$m['day']} {$m['hour']}:{$m['minute']}:00";
            }
            break;
            case 'filename':
            {
                $folderMap = array(
                    'image' => 'images',
                    'html' => 'html',
                    'pdf' => 'pdf',
                    'audio' => 'audio',
                    'video' => 'videos',
                    'link' => 'link',
                    'file' => 'file',
                    'html_media' => 'html'
                );

                if ( trim($xmlField->fieldNode->nodeValue) != "" )
                {
                    $fieldContent = trim($xmlField->fieldNode->nodeValue);

                    if (isset($folderMap[$xmlField->getParentType()]))
                        $folder = $folderMap[$xmlField->getParentType()];
                    else
                        break;
                    
                    $filepathFromRootImport = "{$this->rootImportFolder}/{$this->publisherInfos['path']}/$folder/$fieldContent";

                    if ( file_exists( "$rootImport/$filepathFromRootImport" )
                        || file_exists ( "$rootImport/{$this->rootImportFolder}/{$this->publisherInfos['path']}/archived/$folder/$fieldContent" ) )
                    {
                        if ($mapping['specialProcess'] == 'storeBlob')
                            $returnContent = "$rootImport/$filepathFromRootImport";
                        else
                            $returnContent  = $filepathFromRootImport;
                    }
                    else
                        $fieldContent = "{$this->rootImportFolder}/{$this->publisherInfos['path']}/$folder/$fieldContent";
                }
            }
            break;
            case 'wxh':
            {
                $fieldContent = trim($xmlField->fieldNode->nodeValue);

                if (preg_match("/(\d+)\s*[xX\s]\s*(\d+)/", $fieldContent, $match))
                    $returnContent = "{$match[1]}x{$match[2]}";
            }
            break;
            case 'email':
            {
                $fieldContent = filter_var(trim($xmlField->fieldNode->nodeValue), FILTER_VALIDATE_EMAIL);

                if ($fieldContent !== false)
                    $returnContent = $fieldContent;
            }
            break;
            case 'media_type':
            {
                /* @type $availableRelatedContent array */
                $fieldContent            = strtolower(trim($xmlField->fieldNode->nodeValue));
                $availableRelatedContent = $this->importINI->variable('XMLImportSettings', 'AvailableRelatedContent');

                if (in_array($fieldContent, $availableRelatedContent))
                    $returnContent = $fieldContent;
            }
            break;
            case 'enum':
            {
                $fieldContent = strtolower(trim($xmlField->fieldNode->nodeValue));
                $enumMapping  = XMLImportMapping::getByFieldName('enum_values', $xmlField->internalFieldName);

                if ( $enumMapping !== false && in_array($fieldContent, $enumMapping) )
                    $returnContent = $fieldContent;
            }
            break;
            case 'boolean':
            {
                $fieldContent = filter_var(trim($xmlField->fieldNode->nodeValue), FILTER_VALIDATE_BOOLEAN);
                $returnContent = ($fieldContent === false) ? 0 : 1;
            }
            break;
            case 'reference_article_id':
            {
                $fieldContent  = trim($xmlField->fieldNode->nodeValue);
                $returnContent = $fieldContent;
            }
            break;
            default:
            {
                XMLImportMonitor::log('The field {' . $xmlField->fieldName . '} has an unknown type : {' . $mapping['type'] . '}', 'error');
                return false;
            }
        }

        if (!isset($returnContent))
        {
            if (!empty($fieldContent) && (is_string($fieldContent) || is_numeric($fieldContent)))
            {
                $reportValue = $fieldContent;

                XMLImportMonitor::log('The field {' . $xmlField->fieldName . '} of type {' . $mapping['type'] . '} has an incorrect value : {' . $reportValue . '}', 'warning');
            }

            return false;
        }

        if (!is_array($xmlField))
            $xmlField->calculatedValue = $returnContent;

        return $returnContent;
    }
    /**
     * Appends a file to quarentaine list
     * @param string $publisher
     * @param string $file
     * @param string $message
     */
    public function appendAlert($publisher, $file, $message)
    {
        $this->quarantaineFiles[] = array(
            'publisher' => $publisher,
            'file'      => $file,
            'message'   => $message,
        );

        XMLImportMonitor::log( "File $publisher/$file putted in quarantaine", "error" );
    }
    public static function commitFile()
    {
        self::writeDatas();

        self::$file      = '';
        self::$publisher = '';
        self::$datas     = array();
    }
    /**
     * @param string $type
     * @param array $fieldArray
     * @param array $conditions
     * @throws XMLImportDBException
     * @return bool
     */
    private static function updateDB( $type, $fieldArray, $conditions )
    {
        $type = self::getAdjustedType( $fieldArray, $type );

        if ( empty( $type ) || empty( $fieldArray ) )
            return false;

        $table                    = 'content';
        $sqlFields                = self::buildSQLFields( $type, $table, $fieldArray );
        $sqlFields['must_update'] = array( 'key' => 'must_update', 'value' => 1 );
        $sqlFields                = array_merge(self::getAllFieldsFromTable($table), $sqlFields);
        if( empty($sqlFields['parent_id']['value']) )
            $sqlFields['parent_id']['value'] = null;
        $sql                      = sprintf( "UPDATE $table SET %s WHERE id=%s", self::implodeWithKeys( ", ", " = ", $sqlFields ), $conditions['content_id'] ); 
        $result                   = XMLImportDB::query(  $sql  );

        if ( !$result )
            throw new XMLImportDBException( 'The content has not been successfuly updated' );

        XMLImportMonitor::log( 'The content has been successfuly updated', 'info' );

        $table     = $type;
        $sqlFields = self::buildSQLFields( $type, $table, $fieldArray );

        if ( !isset( $conditions['id'] ) )
        {
            $sqlFields['content_id'] = array('key' => 'content_id','value' => $conditions['content_id']);
            $sql                     = "INSERT INTO %s SET %s";
            $result                  = XMLImportDB::query( sprintf($sql, $table, self::implodeWithKeys( ", ", " = ", $sqlFields )) );

            if ( $result )
            {
                XMLImportMonitor::log( ucfirst( $type ) . " {$conditions['id']} successfuly created", 'info' );
                $conditions['id']       = XMLImportDB::lastSerialID( $table, 'id' );
                $conditions['language'] = $sqlFields['language']['value'];
            }
        }
        else
        {
            // merge $sqlFields with empty values for clear values which not present in xml
            $sqlFields = array_merge(self::getAllFieldsFromTable($table), $sqlFields);
            $sql       = "UPDATE %s SET %s WHERE id=%s";
            $result    = XMLImportDB::query( sprintf($sql, $table, self::implodeWithKeys( ", ", " = ", $sqlFields ), $conditions['id']) );

            if ( $result )
            {
                XMLImportMonitor::log( ucfirst( $type ) . " {$conditions['id']} successfuly updated", 'info' );
                $conditions['language'] = $sqlFields['language']['value'];
            }
        }

        if ( !$result )
            throw new XMLImportDBException( ucfirst( $type ) . ' not successfuly updated' );

        if ( $type != 'article' )
        {
            $conditions['table_name']    = $table;
            $conditions['content_order'] = isset( $fieldArray['comp_art_order'] ) ? $fieldArray['comp_art_order']->calculatedValue : 0;
        }

        return $conditions;
    }
    /**
     * @param string $publisher
     * @param string $xmlFile
     * @param array $blobedFiles
     */
    public function archiveFiles( $publisher, $xmlFile, $blobedFiles )
    {
        $this->buildArchiveFolder( $publisher );

        $rootImport             = $this->importINI->variable( 'XMLImportSettings', 'RootImport' );
        $publisherFolder        = "$rootImport/{$this->rootImportFolder}/$publisher";
        $publisherArchiveFolder = "$publisherFolder/archived";

        self::handleModeUATFile( "$publisherFolder/$xmlFile", "$publisherArchiveFolder/$xmlFile" );

        XMLImportMonitor::log( "Archive xml file : $publisherFolder/$xmlFile => $publisherArchiveFolder/$xmlFile", 'info' );
        XMLImportMonitor::setMonitorData('nb_of_retry', 0);

        foreach ( $blobedFiles as $blobedFile )
        {
            $tmpFile = str_replace( "$publisherFolder/", '', $blobedFile );

            if ( $tmpFile == $blobedFile )
            {
                XMLImportMonitor::log( "Unarchivable blobed file : $blobedFile", 'warning' );
            }
            else
            {
                self::handleModeUATFile( "$publisherFolder/$tmpFile", "$publisherArchiveFolder/$tmpFile" );
                XMLImportMonitor::log( "Archive blobed file : $publisherFolder/$tmpFile => $publisherArchiveFolder/$tmpFile", 'info' );
            }
        }
    }