@@ -796,26 +796,7 @@ public function closest($selector): Query
796796 */
797797 public function parent ($ selector = null ): Query
798798 {
799- $ found = new SplObjectStorage ();
800- foreach ($ this ->matches as $ m ) {
801- while ($ m ->parentNode ->nodeType !== XML_DOCUMENT_NODE ) {
802- $ m = $ m ->parentNode ;
803- // Is there any case where parent node is not an element?
804- if ($ m ->nodeType === XML_ELEMENT_NODE ) {
805- if (! empty ($ selector )) {
806- if (QueryPath::with ($ m , null , $ this ->options )->is ($ selector ) > 0 ) {
807- $ found ->attach ($ m );
808- break ;
809- }
810- } else {
811- $ found ->attach ($ m );
812- break ;
813- }
814- }
815- }
816- }
817-
818- return $ this ->inst ($ found , null );
799+ return $ this ->getParentElements ($ selector , true );
819800 }
820801
821802 /**
@@ -835,19 +816,45 @@ public function parent($selector = null): Query
835816 * @see siblings()
836817 */
837818 public function parents ($ selector = null ): Query
819+ {
820+ return $ this ->getParentElements ($ selector , false );
821+ }
822+
823+ /**
824+ * Get ancestor(s) of each element in the DOMQuery.
825+ *
826+ * If a selector is present, only matching ancestors will be retrieved.
827+ *
828+ * @param string|null $selector
829+ * A valid CSS 3 Selector.
830+ * @param bool $immediate
831+ * If function should return only the immediate parent
832+ *
833+ * @return DOMQuery
834+ * A DOMNode object containing the matching ancestors.
835+ * @throws ParseException
836+ * @throws Exception
837+ */
838+ private function getParentElements (?string $ selector , bool $ immediate ): Query
838839 {
839840 $ found = new SplObjectStorage ();
840841 foreach ($ this ->matches as $ m ) {
841- while ($ m ->parentNode ->nodeType !== XML_DOCUMENT_NODE ) {
842+ while ($ m ->parentNode && $ m -> parentNode ->nodeType !== XML_DOCUMENT_NODE ) {
842843 $ m = $ m ->parentNode ;
843844 // Is there any case where parent node is not an element?
844845 if ($ m ->nodeType === XML_ELEMENT_NODE ) {
845846 if (! empty ($ selector )) {
846847 if (QueryPath::with ($ m , null , $ this ->options )->is ($ selector ) > 0 ) {
847848 $ found ->attach ($ m );
849+ if ($ immediate ) {
850+ break ;
851+ }
848852 }
849853 } else {
850854 $ found ->attach ($ m );
855+ if ($ immediate ) {
856+ break ;
857+ }
851858 }
852859 }
853860 }
0 commit comments