/*!
Returns the objects which have at least one keyword in common

\return an array of eZContentObjectTreeNode instances, or null if the attribute is not stored yet
64
function relatedObjects()
    {
        $return = false;
        if ( $this->ObjectAttributeID )
        {
            $return = array();

            // Fetch words
            $db = eZDB::instance();

            $wordArray = $db->arrayQuery( "SELECT * FROM ezkeyword_attribute_link
                                           WHERE objectattribute_id='" . $this->ObjectAttributeID ."' " );

            $keywordIDArray = array();
            // Fetch the objects which have one of these words
            foreach ( $wordArray as $word )
            {
                $keywordIDArray[] = $word['keyword_id'];
            }

            $keywordCondition = $db->generateSQLINStatement( $keywordIDArray, 'keyword_id' );

            if ( count( $keywordIDArray ) > 0 )
            {
                $objectArray = $db->arrayQuery( "SELECT DISTINCT ezcontentobject_attribute.contentobject_id FROM ezkeyword_attribute_link, ezcontentobject_attribute
                                                  WHERE $keywordCondition AND
                                                        ezcontentobject_attribute.id = ezkeyword_attribute_link.objectattribute_id
                                                        AND  objectattribute_id <> '" . $this->ObjectAttributeID ."' " );

                $objectIDArray = array();
                foreach ( $objectArray as $object )
                {
                    $objectIDArray[] = $object['contentobject_id'];
                }

                if ( count( $objectIDArray ) > 0 )
                {
                    $aNodes = eZContentObjectTreeNode::findMainNodeArray( $objectIDArray );

                    foreach ( $aNodes as $key => $node )
                    {
                        $theObject = $node->object();
                        if ( $theObject->canRead() )
                        {
                            $return[] = $node;
                        }
                    }
                }
            }
        }
        return $return;
    }
1274280
static function makeObjectsArray( $array , $with_contentobject = true )
    {
        $retNodes = array();
        if ( !is_array( $array ) )
            return $retNodes;

        foreach ( $array as $node )
        {
            unset( $object );

            if( $node['node_id'] == 1 )
            {
                if( !isset( $node['name'] ) || !$node['name'] )
                    $node['name'] = ezpI18n::tr( 'kernel/content', 'Top Level Nodes' );
            }

            $object = new self( $node );
            // If the name is not set it will be fetched later on when
            // getName()/attribute( 'name' ) is accessed.
            if ( isset( $node['name'] ) )
            {
                $object->setName( $node['name'] );
            }

            if ( isset( $node['class_serialized_name_list'] ) )
            {
                $node['class_name'] = eZContentClass::nameFromSerializedString( $node['class_serialized_name_list'] );
                $object->ClassName = $node['class_name'];
            }
            if ( isset( $node['class_identifier'] ) )
                $object->ClassIdentifier = $node['class_identifier'];

            if ( isset( $node['is_container'] ) )
                $object->ClassIsContainer = $node['is_container'];

            if ( $with_contentobject )
            {
                if ( isset( $node['class_name'] ) )
                {
                    unset( $node['remote_id'] );
                    $contentObject = new eZContentObject( $node );

                    $permissions = array();
                    $contentObject->setPermissions( $permissions );
                    $contentObject->setClassName( $node['class_name'] );
                    if ( isset( $node['class_identifier'] ) )
                        $contentObject->ClassIdentifier = $node['class_identifier'];

                }
                else
                {
                    $contentObject = new eZContentObject( array());
                    if ( isset( $node['name'] ) )
                         $contentObject->setCachedName( $node['name'] );
                }
                if ( isset( $node['real_translation'] ) && $node['real_translation'] != '' )
                {
                    $object->CurrentLanguage = $node['real_translation'];
                    $contentObject->CurrentLanguage = $node['real_translation'];
                }
                if ( $node['node_id'] == 1 )
                {
                    $contentObject->ClassName = 'Folder';
                    $contentObject->ClassIdentifier = 'folder';
                    $contentObject->ClassID = 1;
                    $contentObject->SectionID = 1;
                }

                $object->setContentObject( $contentObject );
            }
            $retNodes[] = $object;
        }
        return $retNodes;
    }
565810
public static function getList($data)
    {
        // Return Null if Null
        if ($data === null) {
            return null;
        }

        if (is_a($data, get_class(new \stdClass()))) {
            //This means, root element is object

            $accessibleProperties = get_object_vars($data);

            if (count($accessibleProperties) == 1
                && (isset($accessibleProperties['error']) || isset($accessibleProperties['errors']))
            ) {
                // Object is only an error {"error":"message"} or {"errors":["error1":"message1"]}
                return new Error(JsonConverter::encode($data));
            } else {
                return new static(JsonConverter::encode($data));
            }
        }

        $list = array();

        if (is_array($data)) {
            $data = JsonConverter::encode($data);
        }

        if (JsonValidator::validate($data)) {
            // It is valid JSON
            $decoded = JsonConverter::decode($data);
            if ($decoded === null) {
                return $list;
            }
            if (is_array($decoded)) {
                foreach ($decoded as $k => $v) {
                    $list[] = self::getList($v);
                }
            }
            if (is_a($decoded, get_class(new \stdClass()))) {
                //This means, root element is object
                $list[] = new static(JsonConverter::encode($decoded));
            }
        }

        return $list;
    }
13269
static function metaDataArray( &$attributes, $skipRelationAttributes = false )
    {
        $metaDataArray = array();
        if ( !is_array( $attributes ) )
            return false;
        foreach( $attributes as $attribute )
        {
            $classAttribute = $attribute->contentClassAttribute();
            if ( !$classAttribute->attribute( 'is_searchable' ) )
            {
                continue;
            }

            $datatype = $attribute->dataType();
            if ( $skipRelationAttributes && $datatype->isRelationType() )
            {
                continue;
            }

            $attributeMetaData = $datatype->metaData($attribute);
            if ( $attributeMetaData !== false )
            {
                if ( !is_array( $attributeMetaData ) )
                {
                    $attributeMetaData = array( array( 'id' => '',
                                                       'text' => $attributeMetaData ) );
                }
                $metaDataArray = array_merge( $metaDataArray, $attributeMetaData );
            }
        }
        return $metaDataArray;
    }
978066
function objectAttributeContent( $contentObjectAttribute )
    {
        $value = $contentObjectAttribute->attribute( 'data_text' );

        $countryList = explode( ',', $value );
        $resultList = array();
        foreach ( $countryList as $alpha2 )
        {
            $eZCountry = eZCountryType::fetchCountry( $alpha2, 'Alpha2' );
            $resultList[$alpha2] = $eZCountry ? $eZCountry : '';
        }
        // Supporting of previous version format.
        // For backwards compatibility.
        if ( count( $resultList ) == 1 and $resultList[$value] == '' )
            $resultList = $value;

        $content = array( 'value' => $resultList );
        return $content;
    }
168372
public function contentObject()
    {
        $contentID = $this->attribute( 'content_id' );
        //TODO:try to get the language id
        $languageID = $this->attribute( 'language_id' );
        return eZContentObject::fetch( $contentID );
    }
1107036
static function findMainNode( $objectID, $asObject = false )
    {
        $objectID = (int)$objectID;
        $query = "SELECT node_id
                  FROM ezcontentobject_tree
                  WHERE contentobject_id=$objectID AND
                  main_node_id = node_id";
        $db = eZDB::instance();
        $nodeListArray = $db->arrayQuery( $query );
        if ( count( $nodeListArray ) == 1 )
        {
            if ( $asObject )
            {
                 return eZContentObjectTreeNode::fetch( $nodeListArray[0]['node_id'] );
            }
            else
            {
                return $nodeListArray[0]['node_id'];
            }

        }
        else if ( count( $nodeListArray ) > 1 )
        {
            eZDebug::writeError( $nodeListArray , "There are more then one main_node for objectID: $objectID" );
        }

        return null;
    }
1263456
function metaData( $contentObjectAttribute )
    {
        $object = $this->objectAttributeContent( $contentObjectAttribute );
        if ( $object )
        {
            // Does the related object exist in the same language as the current content attribute ?
            if ( in_array( $contentObjectAttribute->attribute( 'language_code' ), $object->attribute( 'current' )->translationList( false, false ) ) )
            {
                $attributes = $object->attribute( 'current' )->contentObjectAttributes( $contentObjectAttribute->attribute( 'language_code' ) );
            }
            else
            {
                $attributes = $object->contentObjectAttributes();
            }

            return eZContentObjectAttribute::metaDataArray( $attributes, true );
        }
        return false;
    }
138204
protected function nullObjectAttributes() : array
    {
        $attributesMap = $this->getAttributesDictionnary();

        $normalizedAttributes = [];

        foreach ($attributesMap as $embedKey => $parentKey) {
            $normalizedAttributes[$parentKey] = null;
        }

        return $normalizedAttributes;
    }
1042093
function deleteStoredObjectAttribute( $contentObjectAttribute, $version = null )
    {
        if ( $version != null ) // Do not delete if discarding draft
        {
            return;
        }

        $contentObjectAttributeID = $contentObjectAttribute->attribute( "id" );

        $db = eZDB::instance();

        /* First we retrieve all the keyword ID related to this object attribute */
        $res = $db->arrayQuery( "SELECT keyword_id
                                 FROM ezkeyword_attribute_link
                                 WHERE objectattribute_id='$contentObjectAttributeID'" );
        if ( !count ( $res ) )
        {
            /* If there are no keywords at all, we abort the function as there
             * is nothing more to do */
            return;
        }
        $keywordIDs = array();
        foreach ( $res as $record )
            $keywordIDs[] = $record['keyword_id'];
        $keywordIDString = implode( ', ', $keywordIDs );

        /* Then we see which ones only have a count of 1 */
        $res = $db->arrayQuery( "SELECT keyword_id
                                 FROM ezkeyword, ezkeyword_attribute_link
                                 WHERE ezkeyword.id = ezkeyword_attribute_link.keyword_id
                                     AND ezkeyword.id IN ($keywordIDString)
                                 GROUP BY keyword_id
                                 HAVING COUNT(*) = 1" );
        $unusedKeywordIDs = array();
        foreach ( $res as $record )
            $unusedKeywordIDs[] = $record['keyword_id'];
        $unusedKeywordIDString = implode( ', ', $unusedKeywordIDs );

        /* Then we delete those unused keywords */
        if ( $unusedKeywordIDString )
            $db->query( "DELETE FROM ezkeyword WHERE id IN ($unusedKeywordIDString)" );

        /* And as last we remove the link between the keyword and the object
         * attribute to be removed */
        $db->query( "DELETE FROM ezkeyword_attribute_link
                     WHERE objectattribute_id='$contentObjectAttributeID'" );
    }
487802
public static function subTree( $args )
    {
        $parentNodeID = isset( $args[0] ) ? $args[0] : null;
        $limit = isset( $args[1] ) ? $args[1] : 25;
        $offset = isset( $args[2] ) ? $args[2] : 0;
        $sort = isset( $args[3] ) ? self::sortMap( $args[3] ) : 'published';
        $order = isset( $args[4] ) ? $args[4] : false;
        $objectNameFilter = isset( $args[5] ) ? $args[5] : '';

        if ( !$parentNodeID )
        {
            throw new ezcBaseFunctionalityNotSupportedException( 'Fetch node list', 'Parent node id is not valid' );
        }

        $node = eZContentObjectTreeNode::fetch( $parentNodeID );
        if ( !$node instanceOf eZContentObjectTreeNode )
        {
            throw new ezcBaseFunctionalityNotSupportedException( 'Fetch node list', "Parent node '$parentNodeID' is not valid" );
        }

        $ezjscoreIni = eZINI::instance( 'ezjscore.ini' );
        $hardLimit = (int)$ezjscoreIni->variable( 'ezjscServer_ezjscnode', 'HardLimit' );

        if ( $hardLimit > 0 && $limit > $hardLimit )
        {
            $limit = $hardLimit;
        }

        $params = array( 'Depth' => 1,
                         'Limit' => $limit,
                         'Offset' => $offset,
                         'SortBy' => array( array( $sort, $order ) ),
                         'DepthOperator' => 'eq',
                         'ObjectNameFilter' => $objectNameFilter,
                         'AsObject' => true );

       // fetch nodes and total node count
        $count = $node->subTreeCount( $params );
        if ( $count )
        {
            $nodeArray = $node->subTree( $params );
        }
        else
        {
            $nodeArray = array();
        }
        unset( $node );// We have on purpose not checked permission on $node itself, so it should not be used

        // generate json response from node list
        if ( $nodeArray )
        {
            $list = ezjscAjaxContent::nodeEncode( $nodeArray, array( 'formatDate' => 'shortdatetime',
                                                                     'fetchThumbPreview' => true,
                                                                     'fetchSection' => true,
                                                                     'fetchCreator' => true,
                                                                     'fetchClassIcon' => true ), 'raw' );
        }
        else
        {
            $list = array();
        }

        return array( 'parent_node_id' => $parentNodeID,
                      'count' => count( $nodeArray ),
                      'total_count' => (int)$count,
                      'list' => $list,
                      'limit' => $limit,
                      'offset' => $offset,
                      'sort' => $sort,
                      'order' => $order );
    }
1232698
function objectAttributeContent( $contentObjectAttribute )
    {
        if ( $contentObjectAttribute->attribute( 'data_int' ) != 0 )
        {
           $gmapObject = eZGmapLocation::fetch( $contentObjectAttribute->attribute( 'id' ), $contentObjectAttribute->attribute( 'version' ) );
           if ( !$gmapObject instanceof eZGmapLocation )
           {
               $gmapObject = eZGmapLocation::create( $contentObjectAttribute->attribute( 'id' ), $contentObjectAttribute->attribute( 'version' ), '', '' );
               // This happens when attribute is cloned, since sync() is called before init() on attribute.
               //eZDebug::writeWarning( 'eZGmapLocation::fetch returned empty, even though data_int says there is content. Might be data corruption! ' . var_export(debug_backtrace( false ), true), __METHOD__ );
           }
        }
        else
        {
    	   $gmapObject = eZGmapLocation::create( $contentObjectAttribute->attribute( 'id' ), $contentObjectAttribute->attribute( 'version' ), '', '' );
        }

        return $gmapObject;
    }
130259
static public function makeObjectsArray( $array , $with_contentobject = true, array $propertiesOverride = null, $lang = null )
    {
        $retNodes = array();
        if ( !is_array( $array ) )
            return $retNodes;

        foreach ( $array as $node )
        {
            if ( $propertiesOverride !== null )
            {
                $node = $propertiesOverride + $node;
            }

            if ( $node['node_id'] == 1 && (!array_key_exists( 'name', $node ) || !$node['name'] ) )
            {
                $node['name'] = ezpI18n::tr( 'kernel/content', 'Top Level Nodes' );
            }

            $object = new eZContentObjectTreeNode(
                array(
                    "node_id" => $node["node_id"],
                    "parent_node_id" => $node["parent_node_id"],
                    "main_node_id" => $node["main_node_id"],
                    "contentobject_id" => isset( $node["id"] ) ? $node["id"] : $node["contentobject_id"],
                    "contentobject_version" => $node["contentobject_version"],
                    "contentobject_is_published" => $node["contentobject_is_published"],
                    "depth" => $node["depth"],
                    "sort_field" => $node["sort_field"],
                    "sort_order" => $node["sort_order"],
                    "priority" => $node["priority"],
                    "modified_subnode" => $node["modified_subnode"],
                    "path_string" => $node["path_string"],
                    "path_identification_string" => $node["path_identification_string"],
                    "remote_id" => $node["remote_id"],
                    "is_hidden" => $node["is_hidden"],
                    "is_invisible" => $node["is_invisible"],
                )
            );
            // If the name is not set it will be fetched later on when
            // getName()/attribute( 'name' ) is accessed.
            if ( isset( $node['name'] ) )
            {
                $object->setName( $node['name'] );
            }

            if ( isset( $node['class_serialized_name_list'] ) )
            {
                $node['class_name'] = eZContentClass::nameFromSerializedString( $node['class_serialized_name_list'] );
                $object->ClassName = $node['class_name'];
            }
            if ( isset( $node['class_identifier'] ) )
                $object->ClassIdentifier = $node['class_identifier'];

            if ( isset( $node['is_container'] ) )
                $object->ClassIsContainer = $node['is_container'];

            if ( $with_contentobject )
            {
                if ( isset( $node['class_name'] ) )
                {
                    $row = array(
                        "id" => $node["id"],
                        "section_id" => $node["section_id"],
                        "owner_id" => $node["owner_id"],
                        "contentclass_id" => $node["contentclass_id"],
                        "name" => $node["name"],
                        "published" => $node["published"],
                        "modified" => $node["modified"],
                        "current_version" => $node["current_version"],
                        "status" => $node["status"],
                        "remote_id" => $node["object_remote_id"],
                        "language_mask" => $node["language_mask"],
                        "initial_language_id" => $node["initial_language_id"],
                        "class_name" => $node["class_name"],
                    );

                    if ( isset( $node['class_identifier'] ) )
                        $row['class_identifier'] = $node['class_identifier'];

                    $contentObject = new eZContentObject( $row );
                }
                else
                {
                    $contentObject = new eZContentObject( array() );
                    if ( isset( $node['name'] ) )
                         $contentObject->setCachedName( $node['name'] );
                }
                if ( isset( $node['real_translation'] ) && $node['real_translation'] != '' )
                {
                    if ( $node['real_translation'] == $lang )
                    {
                        $object->CurrentLanguage = $node['real_translation'];
                    }

                    $contentObject->CurrentLanguage = $node['real_translation'];
                }
                if ( $node['node_id'] == 1 )
                {
                    $contentObject->ClassName = 'Folder';
                    $contentObject->ClassIdentifier = 'folder';
                    $contentObject->ClassID = 1;
                    $contentObject->SectionID = 1;
                }

                $object->setContentObject( $contentObject );
            }
            $retNodes[] = $object;
        }
        return $retNodes;
    }
1272192
function hasObjectAttributeContent( $contentObjectAttribute )
    {
        $page = $contentObjectAttribute->content();
        $zones = $page->attribute( 'zones' );
        if ( !is_array( $zones ) )
            return false;

        foreach ( $zones as $zone )
        {
            if ( $zone->getBlockCount() > 0 )
                return true;
        }

        return false;
    }
881650
static function fetchAll( $asObject = true )
    {
        return eZPersistentObject::fetchObjectList( eZUserSetting::definition(),
                                                    null,
                                                    null,
                                                    null,
                                                    null,
                                                    $asObject );
    }
1246345
static function fetchByContentObjectID( $contentObjectID, $languageCode = null, $asObject = true )
    {
        $condition = array();
        $condition['contentobject_id'] = $contentObjectID;
        $condition['data_type_string'] = 'ezmedia';
        if ( $languageCode != null )
        {
            $condition['language_code'] = $languageCode;
        }
        $custom = array( array( 'operation' => 'DISTINCT id',
                             'name' => 'id' ) );
        $ids = eZPersistentObject::fetchObjectList( eZContentObjectAttribute::definition(),
                                             array(),
                                             $condition,
                                             null,
                                             null,
                                             false,
                                             false,
                                             $custom );
        $mediaFiles = array();
        foreach ( $ids as $id )
        {
            $mediaFileObjectAttribute = eZMedia::fetch( $id['id'], null, $asObject );
            $mediaFiles = array_merge( $mediaFiles, $mediaFileObjectAttribute );
        }
        return $mediaFiles;
    }
1355688
function objectAttributeContent( $contentObjectAttribute )
    {
        $userID = $contentObjectAttribute->attribute( "contentobject_id" );
        if ( empty( $GLOBALS['eZUserObject_' . $userID] ) )
        {
            $GLOBALS['eZUserObject_' . $userID] = eZUser::fetch( $userID );
        }

        $user = eZUser::fetch( $userID );
        eZDebugSetting::writeDebug( 'kernel-user', $user, 'user' );

        //Looking for a "draft" and loading its content
        $serializedDraft = $contentObjectAttribute->attribute( 'data_text' );

        if ( !empty( $serializedDraft ) )
        {
            $user = $this->updateUserDraft( $user, $serializedDraft );
        }

        return $user;
    }