2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								< ? php  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 09:26:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								declare ( strict_types  =  1 );  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// {{{ License
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This file is part of GNU social - https://www.gnu.org/software/social
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GNU social is free software: you can redistribute it and/or modify
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// it under the terms of the GNU Affero General Public License as published by
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the Free Software Foundation, either version 3 of the License, or
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// (at your option) any later version.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GNU social is distributed in the hope that it will be useful,
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// but WITHOUT ANY WARRANTY; without even the implied warranty of
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GNU Affero General Public License for more details.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// You should have received a copy of the GNU Affero General Public License
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// along with GNU social.  If not, see <http://www.gnu.org/licenses/>.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// }}}
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-08 15:10:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								namespace  Component\Collection\Util ;  
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								use  App\Core\Event ;  
						 
					
						
							
								
									
										
										
										
											2021-12-24 09:27:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								use  App\Entity\Actor ;  
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								use  App\Util\Exception\ServerException ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								use  Doctrine\Common\Collections\Criteria ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								abstract  class  Parser  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2021-10-10 09:23:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Merge  $parts  into  $criteria_arr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    private  static  function  connectParts ( array  & $parts ,  array  & $criteria_arr ,  string  $last_op ,  mixed  $eb ,  bool  $force  =  false ) :  void 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        foreach  ([ ' '  =>  'orX' ,  '|'  =>  'orX' ,  '&'  =>  'andX' ]  as  $op  =>  $func )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( $last_op  ===  $op  ||  $force )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                $criteria_arr []  =  $eb -> { $func }( ... $parts ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    /** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Parse  $input  string  into  a  Doctrine  query  Criteria 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Currently  doesn ' t  support  nesting  with  parenthesis  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  recognises  either  spaces  ( currently  `or` ,  should  be  fuzzy  match ),  `OR`  or  `|`  ( `or` )  and  `AND`  or  `&`  ( `and` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-23 13:27:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  TODO :  Better  fuzzy  match ,  implement  exact  match  with  quotes  and  nesting  with  parens 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-26 14:09:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  TODO :  Proper  parser ,  tokenize  better .  Mostly  a  rewrite 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 05:44:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-26 14:09:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ return  array { ? Criteria ,  ? Criteria }  [ ? $note_criteria ,  ? $actor_criteria ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								     */ 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 20:28:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    public  static  function  parse ( string  $input ,  ? string  $locale  =  null ,  ? Actor  $actor  =  null ,  int  $level  =  0 ) :  array 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( $level  ===  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $input  =  trim ( preg_replace ([ '/\s+/' ,  '/\s+AND\s+/' ,  '/\s+OR\s+/' ],  [ ' ' ,  '&' ,  '|' ],  $input ),  ' |&' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-23 13:27:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        $left                =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $right               =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 05:44:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        $lenght              =  mb_strlen ( $input ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $eb                  =  Criteria :: expr (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $note_criteria_arr   =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $actor_criteria_arr  =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $note_parts          =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $actor_parts         =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $last_op             =  null ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( $index  =  0 ;  $index  <  $lenght ;  ++ $index )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $end    =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $match  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            foreach  ([ '&' ,  '|' ,  ' ' ]  as  $delimiter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( $input [ $index ]  ===  $delimiter  ||  $end  =  ( $index  ===  $lenght  -  1 ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-23 13:27:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    $term       =  mb_substr ( $input ,  $left ,  $end  ?  null  :  $right  -  $left ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    $note_res   =  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    $actor_res  =  null ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-11 20:28:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    Event :: handle ( 'CollectionQueryCreateExpression' ,  [ $eb ,  $term ,  $locale ,  $actor ,  & $note_res ,  & $actor_res ]); 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-26 22:17:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  ( \is_null ( $note_res )  &&  \is_null ( $actor_res ))  {  // @phpstan-ignore-line
 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-21 04:48:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        //throw new ServerException("No one claimed responsibility for a match term: {$term}");
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        // It's okay if the term doesn't exist, just perform a regular search
 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-08 21:25:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    } 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-26 14:09:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  ( ! empty ( $note_res ))  {  // @phpstan-ignore-line currently an open bug. See https://web.archive.org/web/20220226131651/https://github.com/phpstan/phpstan/issues/6234
 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-11 19:33:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        if  ( \is_array ( $note_res ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            $note_res  =  $eb -> orX ( ... $note_res ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 09:26:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        $note_parts []  =  $note_res ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-08 21:25:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    } 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-26 14:09:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  ( ! empty ( $actor_res ))  {  // @phpstan-ignore-line currently an open bug. See https://web.archive.org/web/20220226131651/https://github.com/phpstan/phpstan/issues/6234
 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-11 19:33:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        if  ( \is_array ( $actor_res ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-23 13:27:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            $actor_res  =  $eb -> orX ( ... $actor_res ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-11 19:33:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 09:26:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        $actor_parts []  =  $actor_res ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    $right  =  $left  =  $index  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 09:23:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  ( ! \is_null ( $last_op )  &&  $last_op  !==  $delimiter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        self :: connectParts ( $note_parts ,  $note_criteria_arr ,  $last_op ,  $eb ,  force :  false ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        $last_op  =  $delimiter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    $match  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-26 22:17:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    break ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-26 22:17:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // TODO
 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-26 14:09:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( ! $match )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                ++ $right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-23 13:27:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        $note_criteria   =  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        $actor_criteria  =  null ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-26 14:09:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( ! empty ( $note_parts ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 09:23:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self :: connectParts ( $note_parts ,  $note_criteria_arr ,  $last_op ,  $eb ,  force :  true ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 05:44:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            $note_criteria  =  new  Criteria ( $eb -> orX ( ... $note_criteria_arr )); 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-08 21:25:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-26 14:09:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( ! empty ( $actor_parts ))  {  // @phpstan-ignore-line weird, but this whole thing needs a rewrite
 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 09:23:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self :: connectParts ( $actor_parts ,  $actor_criteria_arr ,  $last_op ,  $eb ,  force :  true ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            $actor_criteria  =  new  Criteria ( $eb -> orX ( ... $actor_criteria_arr )); 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-10 05:44:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  [ $note_criteria ,  $actor_criteria ]; 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-27 10:39:58 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}