/** * Get the specified attribute of the object * * This is one of the many ways how to access an object's attribute. * <h2>Example:</h2> * <code> * use ADX\Core\Object; // Import the class into the current namespace * // $link is a fully configured and bound {@link Link} object * * // Retrieve or create an object * $object = Object::read( 'OU=admins,DC=corp,DC=company,DC=com', ['mail', 'givenname'], $link ); * * // Access the object's attribute * print_r( $object->get( 'mail' )->value() ); * </code> * * @param string The name of the attribute, as defined on the ldap server * * @return Attribute An instance of Attribute class, holding the attribute's value(s) */ public function get($attribute) { $attribute = strtolower($attribute); if (isset($this->data[$attribute])) { return $this->data[$attribute]; } elseif ($attribute == 'dn') { return $this->dn; } else { // If someone does something like $adxObject->samaccountname->set('val') but samaccountname is not // set in the object this will ensure that the script will not fail // and data modification can continue as necessary. // However, if we have the directory schema cached and user tries to retrieve an attribute // that does not exist in the schema, we want to throw an exception instead of creating // a new Attribute ( an exception would have been thrown during update process - AD would // complain about non-existent attribute ). if (Schema::isCached() && Schema::get($attribute) === null) { throw new IncorrectParameterException("Attribute {$attribute} does not exist in the Directory schema"); } // Either Schema is not cached or the attribute exists in the schema - let's continue $attribute = Attribute::make($attribute); $attribute->belongs_to($this); $this->data["{$attribute}"] = $attribute; return $attribute; } }
protected static function _convert($direction, $attribute, $values) { // Load the schema information for the current attribute $schema = Schema::get("{$attribute}"); $ats = $schema['attributesyntax'][0]; $oms = $schema['omsyntax'][0]; $values = (array) $values; $converted = array(); $method = null; $class = get_called_class(); // Based on syntax, choose the corresponding syntax conversion method switch ($ats) { case Syntax::Binary: case Syntax::NtSecDesc: $method = 'binary'; break; case Syntax::Boolean: $method = 'bool'; break; case Syntax::DnString: $method = 'object'; break; case Syntax::Integer: case Syntax::LargeInt: // Conversion not needed break; case Syntax::UnicodeString: case Syntax::TeletexString: case Syntax::PrintableString: case Syntax::NumericString: // Conversion not needed break; case Syntax::Time: switch ($oms) { case '23': // UTC Time format $method = 'utctime'; break; case '24': // Generalised Time format $method = 'generalisedtime'; break; } break; } // Define some syntax overrides based on attribute names ( a hit here will replace // the result from the previous switch ) switch ("{$attribute}") { case 'currenttime': // Not in schema, present on rootDSE $method = 'generalisedtime'; break; case 'issynchronized': // Not in schema, present on rootDSE // Not in schema, present on rootDSE case 'isglobalcatalogready': // Not in schema, present on rootDSE $method = 'bool'; break; case 'unicodepwd': // A password always needs special treatment $method = $attribute; break; case 'objectguid': // I want objectguid and msExchMailboxGuid shown // I want objectguid and msExchMailboxGuid shown case 'msexchmailboxguid': // as AD tools show it ( like Powershell ) $method = 'guid'; break; // These attributes have LargeInt as syntax, but their meaning is different ( they represent a time ) // These attributes have LargeInt as syntax, but their meaning is different ( they represent a time ) case 'pwdlastset': case 'accountexpires': case 'lastlogon': case 'lockouttime': $method = 'timestamp'; break; } // If a conversion method has been found, call it for all values in $value $method = '_' . $direction . '_' . $method; if (is_callable([$class, $method])) { foreach ($values as $value) { $converted[] = call_user_func([$class, $method], $value); } } else { $converted = $values; } // No conversion has been found - use the raw data // Aaand we are done! return $converted; }
/** * Create a new instance of an attribute * * You should explicitly create new objects of this class only rarely - usually * all you need to do is to set the property on the object, a new instance of the * Attribute class will be created for you automatically. * * @param string The ldap display name of the attribute to be created * @param mixed|array The initial value(s) this attribute should have * @param Object An instance of {@link Object} this attribute belongs to */ public function __construct($attribute, $values = array(), Object $object = null) { $args = func_get_args(); $shouldConvert = isset($args[3]) ? $args[3] : false; // This parameter is hidden $this->attribute = strtolower($attribute); // Check for presence of the schema definition for the current attribute $schema = Schema::get($attribute); if ($schema) { $this->attributeSyntax = $schema['attributesyntax'][0]; $this->omSyntax = $schema['omsyntax'][0]; $this->isSingleValued = isset($schema['issinglevalued']) ? $schema['issinglevalued'][0] == 'TRUE' : false; // I have to do manual conversion here $this->isConstructed = isset($schema['systemflags']) ? (bool) ($schema['systemflags'][0] & Enums\SystemFlags::AttrIsConstructed) : false; $this->isResolvable = $this->attributeSyntax === Enums\Syntax::DnString; } // Ensure we have the values in an array $values = (array) $values; // Convert the value to a valid php value ( bool, timestamp conversions etc. ) if ($shouldConvert) { $values = Converter::from_ldap($this, $values); } // Add new value or values to the attribute foreach ($values as $value) { $this->_set_value($value, null, true); } // Set the attribute's owner if ($object) { $this->belongs_to($object); } }