1<?php 2/** 3 * This file is part of the FreeDSx LDAP package. 4 * 5 * (c) Chad Sikorra <Chad.Sikorra@gmail.com> 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11namespace FreeDSx\Ldap\Operation\Response; 12 13use FreeDSx\Asn1\Asn1; 14use FreeDSx\Asn1\Type\AbstractType; 15use FreeDSx\Asn1\Type\OctetStringType; 16use FreeDSx\Asn1\Type\SequenceType; 17use FreeDSx\Ldap\Entry\Attribute; 18use FreeDSx\Ldap\Entry\Dn; 19use FreeDSx\Ldap\Entry\Entry; 20use FreeDSx\Ldap\Exception\ProtocolException; 21 22/** 23 * A search result entry. RFC 4511, 4.5.2. 24 * 25 * SearchResultEntry ::= [APPLICATION 4] SEQUENCE { 26 * objectName LDAPDN, 27 * attributes PartialAttributeList } 28 * 29 * PartialAttributeList ::= SEQUENCE OF 30 * partialAttribute PartialAttribute 31 * 32 * @author Chad Sikorra <Chad.Sikorra@gmail.com> 33 */ 34class SearchResultEntry implements ResponseInterface 35{ 36 protected const TAG_NUMBER = 4; 37 38 /** 39 * @var Entry 40 */ 41 protected $entry; 42 43 /** 44 * @param Entry $entry 45 */ 46 public function __construct(Entry $entry) 47 { 48 $this->entry = $entry; 49 } 50 51 /** 52 * @return Entry 53 */ 54 public function getEntry(): Entry 55 { 56 return $this->entry; 57 } 58 59 /** 60 * {@inheritdoc} 61 */ 62 public static function fromAsn1(AbstractType $type) 63 { 64 $attributes = []; 65 $dn = $type->getChild(0); 66 if ($dn === null) { 67 throw new ProtocolException('The search result entry is malformed.'); 68 } 69 70 $partialAttributes = $type->getChild(1); 71 if ($partialAttributes !== null) { 72 foreach ($partialAttributes as $partialAttribute) { 73 $values = []; 74 $attrValues = $partialAttribute->getChild(1); 75 if ($attrValues !== null) { 76 /** @var SequenceType $attrValues */ 77 foreach ($attrValues->getChildren() as $attrValue) { 78 /** @var OctetStringType $attrValue */ 79 $values[] = $attrValue->getValue(); 80 } 81 } 82 83 $attributes[] = new Attribute($partialAttribute->getChild(0)->getValue(), ...$values); 84 } 85 } 86 87 return new self(new Entry( 88 new Dn($dn->getValue()), 89 ...$attributes 90 )); 91 } 92 93 /** 94 * {@inheritdoc} 95 */ 96 public function toAsn1(): AbstractType 97 { 98 /** @var SequenceType $asn1 */ 99 $asn1 = Asn1::application(self::TAG_NUMBER, Asn1::sequence()); 100 101 $partialAttributes = Asn1::sequenceOf(); 102 foreach ($this->entry->getAttributes() as $attribute) { 103 $partialAttributes->addChild(Asn1::sequence( 104 Asn1::octetString($attribute->getDescription()), 105 Asn1::setOf(...array_map(function ($v) { 106 return Asn1::octetString($v); 107 }, $attribute->getValues())) 108 )); 109 } 110 $asn1->addChild(Asn1::octetString($this->entry->getDn()->toString())); 111 $asn1->addChild($partialAttributes); 112 113 return $asn1; 114 } 115} 116