//  [java]
	public function fetch_optionals($rowid = null, $optionsArray = null)
	{
		// phpcs:enable
		global $conf, $extrafields;

		if (empty($rowid)) {
			$rowid = $this->id;
		}
		if (empty($rowid) && isset($this->rowid)) {
			$rowid = $this->rowid; // deprecated
		}

		// To avoid SQL errors. Probably not the better solution though
		if (!$this->table_element) {
			return 0;
		}

		$this->array_options = array();

		if (!is_array($optionsArray)) {
			// If $extrafields is not a known object, we initialize it. Best practice is to have $extrafields defined into card.php or list.php page.
			if (!isset($extrafields) || !is_object($extrafields)) {
				require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
				$extrafields = new ExtraFields($this->db);
			}

			// Load array of extrafields for elementype = $this->table_element
			if (empty($extrafields->attributes[$this->table_element]['loaded'])) {
				$extrafields->fetch_name_optionals_label($this->table_element);
			}
			$optionsArray = (!empty($extrafields->attributes[$this->table_element]['label']) ? $extrafields->attributes[$this->table_element]['label'] : null);
		} else {
			global $extrafields;
			dol_syslog("Warning: fetch_optionals was called with param optionsArray defined when you should pass null now", LOG_WARNING);
		}

		$table_element = $this->table_element;
		if ($table_element == 'categorie') {
			$table_element = 'categories'; // For compatibility
		}

		// Request to get complementary values
		if (is_array($optionsArray) && count($optionsArray) > 0) {
			$sql = "SELECT rowid";
			foreach ($optionsArray as $name => $label) {
				if (empty($extrafields->attributes[$this->table_element]['type'][$name]) || $extrafields->attributes[$this->table_element]['type'][$name] != 'separate') {
					$sql .= ", ".$name;
				}
			}
			$sql .= " FROM ".MAIN_DB_PREFIX.$table_element."_extrafields";
			$sql .= " WHERE fk_object = ".((int) $rowid);

			//dol_syslog(get_class($this)."::fetch_optionals get extrafields data for ".$this->table_element, LOG_DEBUG);		// Too verbose
			$resql = $this->db->query($sql);
			if ($resql) {
				$numrows = $this->db->num_rows($resql);
				if ($numrows) {
					$tab = $this->db->fetch_array($resql);

					foreach ($tab as $key => $value) {
						// Test fetch_array ! is_int($key) because fetch_array result is a mix table with Key as alpha and Key as int (depend db engine)
						if ($key != 'rowid' && $key != 'tms' && $key != 'fk_member' && !is_int($key)) {
							// we can add this attribute to object
							if (!empty($extrafields) && in_array($extrafields->attributes[$this->table_element]['type'][$key], array('date', 'datetime'))) {
								//var_dump($extrafields->attributes[$this->table_element]['type'][$key]);
								$this->array_options["options_".$key] = $this->db->jdate($value);
							} else {
								$this->array_options["options_".$key] = $value;
							}

							//var_dump('key '.$key.' '.$value.' type='.$extrafields->attributes[$this->table_element]['type'][$key].' '.$this->array_options["options_".$key]);
						}
					}

					// If field is a computed field, value must become result of compute
					foreach ($tab as $key => $value) {
						if (!empty($extrafields) && !empty($extrafields->attributes[$this->table_element]['computed'][$key])) {
							//var_dump($conf->disable_compute);
							if (empty($conf->disable_compute)) {
								$this->array_options["options_".$key] = dol_eval($extrafields->attributes[$this->table_element]['computed'][$key], 1, 0, '');
							}
						}
					}
				}

				$this->db->free($resql);

				if ($numrows) {
					return $numrows;
				} else {
					return 0;
				}
			} else {
				$this->errors[]=$this->db->lasterror;
				return -1;
			}
		}