2017-07-01 20:29:49 +00:00
< ? php
namespace Pterodactyl\Repositories\Eloquent ;
2020-07-07 04:25:00 +00:00
use Illuminate\Http\Request ;
2017-08-12 20:29:01 +00:00
use Webmozart\Assert\Assert ;
2018-01-05 04:49:50 +00:00
use Illuminate\Support\Collection ;
2022-11-25 20:29:04 +00:00
use Illuminate\Support\Facades\DB ;
2022-10-14 16:59:20 +00:00
use Illuminate\Database\Eloquent\Model ;
2017-11-18 01:01:42 +00:00
use Pterodactyl\Repositories\Repository ;
2020-07-07 04:25:00 +00:00
use Illuminate\Database\Eloquent\Builder ;
2017-08-12 20:29:01 +00:00
use Illuminate\Database\Query\Expression ;
2018-01-05 04:49:50 +00:00
use Illuminate\Database\Eloquent\ModelNotFoundException ;
2018-01-11 05:19:03 +00:00
use Illuminate\Contracts\Pagination\LengthAwarePaginator ;
2017-07-01 20:29:49 +00:00
use Pterodactyl\Contracts\Repository\RepositoryInterface ;
2017-07-08 19:07:51 +00:00
use Pterodactyl\Exceptions\Model\DataValidationException ;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException ;
2017-07-01 20:29:49 +00:00
abstract class EloquentRepository extends Repository implements RepositoryInterface
{
2022-10-14 16:59:20 +00:00
protected bool $useRequestFilters = false ;
2020-07-07 04:25:00 +00:00
/**
* Determines if the repository function should use filters off the request object
* present when returning results . This allows repository methods to be called in API
* context ' s such that we can pass through ? filter [ name ] = Dane & sort = desc for example .
*/
2022-10-14 16:59:20 +00:00
public function usingRequestFilters ( bool $usingFilters = true ) : self
2020-07-07 04:25:00 +00:00
{
$this -> useRequestFilters = $usingFilters ;
return $this ;
}
/**
* Returns the request instance .
*/
2022-10-14 16:59:20 +00:00
protected function request () : Request
2020-07-07 04:25:00 +00:00
{
return $this -> app -> make ( Request :: class );
}
/**
* Paginate the response data based on the page para .
*/
2022-10-14 16:59:20 +00:00
protected function paginate ( Builder $instance , int $default = 50 ) : LengthAwarePaginator
2020-07-07 04:25:00 +00:00
{
2021-01-23 20:33:34 +00:00
if ( ! $this -> useRequestFilters ) {
2020-07-07 04:25:00 +00:00
return $instance -> paginate ( $default );
}
return $instance -> paginate ( $this -> request () -> query ( 'per_page' , $default ));
}
2017-07-01 20:29:49 +00:00
/**
2018-01-05 04:49:50 +00:00
* Return an instance of the eloquent model bound to this
* repository instance .
*/
2022-10-14 16:59:20 +00:00
public function getModel () : Model
2018-01-05 04:49:50 +00:00
{
return $this -> model ;
}
/**
* Return an instance of the builder to use for this repository .
2017-07-01 20:29:49 +00:00
*/
2022-10-14 16:59:20 +00:00
public function getBuilder () : Builder
2017-07-01 20:29:49 +00:00
{
return $this -> getModel () -> newQuery ();
}
/**
2018-01-05 04:49:50 +00:00
* Create a new record in the database and return the associated model .
*
* @ throws \Pterodactyl\Exceptions\Model\DataValidationException
2017-07-01 20:29:49 +00:00
*/
2022-10-14 16:59:20 +00:00
public function create ( array $fields , bool $validate = true , bool $force = false ) : Model | bool
2017-07-01 20:29:49 +00:00
{
2022-11-28 16:56:03 +00:00
/** @var \Pterodactyl\Models\Model $instance */
2017-07-01 20:29:49 +00:00
$instance = $this -> getBuilder () -> newModelInstance ();
2018-01-05 04:49:50 +00:00
( $force ) ? $instance -> forceFill ( $fields ) : $instance -> fill ( $fields );
2017-07-01 20:29:49 +00:00
2021-01-23 20:33:34 +00:00
if ( ! $validate ) {
2017-07-01 20:29:49 +00:00
$saved = $instance -> skipValidation () -> save ();
} else {
2021-01-23 20:33:34 +00:00
if ( ! $saved = $instance -> save ()) {
2022-06-26 20:31:48 +00:00
throw new DataValidationException ( $instance -> getValidator (), $instance );
2017-07-01 20:29:49 +00:00
}
}
return ( $this -> withFresh ) ? $instance -> fresh () : $saved ;
}
/**
2018-01-05 04:49:50 +00:00
* Find a model that has the specific ID passed .
*
* @ throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
2017-07-01 20:29:49 +00:00
*/
2022-10-14 16:59:20 +00:00
public function find ( int $id ) : Model
2017-07-01 20:29:49 +00:00
{
2018-01-05 04:49:50 +00:00
try {
return $this -> getBuilder () -> findOrFail ( $id , $this -> getColumns ());
2022-10-14 16:59:20 +00:00
} catch ( ModelNotFoundException ) {
2021-01-23 20:33:34 +00:00
throw new RecordNotFoundException ();
2017-07-01 20:29:49 +00:00
}
}
2017-07-08 19:07:51 +00:00
/**
2018-01-05 04:49:50 +00:00
* Find a model matching an array of where clauses .
2017-07-08 19:07:51 +00:00
*/
2018-01-05 04:49:50 +00:00
public function findWhere ( array $fields ) : Collection
2017-07-01 20:29:49 +00:00
{
2017-07-08 20:04:59 +00:00
return $this -> getBuilder () -> where ( $fields ) -> get ( $this -> getColumns ());
}
/**
2018-01-05 04:49:50 +00:00
* Find and return the first matching instance for the given fields .
*
* @ throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
2017-07-08 20:04:59 +00:00
*/
2022-10-14 16:59:20 +00:00
public function findFirstWhere ( array $fields ) : Model
2017-07-08 20:04:59 +00:00
{
2018-01-05 04:49:50 +00:00
try {
return $this -> getBuilder () -> where ( $fields ) -> firstOrFail ( $this -> getColumns ());
2022-10-14 16:59:20 +00:00
} catch ( ModelNotFoundException ) {
2021-01-23 20:33:34 +00:00
throw new RecordNotFoundException ();
2017-07-08 20:04:59 +00:00
}
2017-07-01 20:29:49 +00:00
}
2017-08-05 22:20:07 +00:00
/**
2018-01-05 04:49:50 +00:00
* Return a count of records matching the passed arguments .
2017-08-05 22:20:07 +00:00
*/
2018-01-05 04:49:50 +00:00
public function findCountWhere ( array $fields ) : int
2017-08-05 22:20:07 +00:00
{
return $this -> getBuilder () -> where ( $fields ) -> count ( $this -> getColumns ());
}
2017-07-01 20:29:49 +00:00
/**
2018-01-05 04:49:50 +00:00
* Delete a given record from the database .
2017-07-01 20:29:49 +00:00
*/
2018-01-05 04:49:50 +00:00
public function delete ( int $id , bool $destroy = false ) : int
2017-07-01 20:29:49 +00:00
{
2018-01-05 04:49:50 +00:00
return $this -> deleteWhere ([ 'id' => $id ], $destroy );
2017-08-09 02:21:10 +00:00
}
/**
2018-01-05 04:49:50 +00:00
* Delete records matching the given attributes .
2017-08-09 02:21:10 +00:00
*/
2018-01-05 04:49:50 +00:00
public function deleteWhere ( array $attributes , bool $force = false ) : int
2017-08-09 02:21:10 +00:00
{
$instance = $this -> getBuilder () -> where ( $attributes );
2017-07-01 20:29:49 +00:00
2017-08-09 02:21:10 +00:00
return ( $force ) ? $instance -> forceDelete () : $instance -> delete ();
2017-07-01 20:29:49 +00:00
}
/**
2018-01-05 04:49:50 +00:00
* Update a given ID with the passed array of fields .
*
* @ throws \Pterodactyl\Exceptions\Model\DataValidationException
* @ throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
2017-07-01 20:29:49 +00:00
*/
2022-10-14 16:59:20 +00:00
public function update ( int $id , array $fields , bool $validate = true , bool $force = false ) : Model | bool
2017-07-01 20:29:49 +00:00
{
2018-01-05 04:49:50 +00:00
try {
2022-11-28 16:56:03 +00:00
/** @var \Pterodactyl\Models\Model $instance */
2018-01-05 04:49:50 +00:00
$instance = $this -> getBuilder () -> where ( 'id' , $id ) -> firstOrFail ();
2022-10-14 16:59:20 +00:00
} catch ( ModelNotFoundException ) {
2021-01-23 20:33:34 +00:00
throw new RecordNotFoundException ();
2017-07-01 20:29:49 +00:00
}
2018-01-05 04:49:50 +00:00
( $force ) ? $instance -> forceFill ( $fields ) : $instance -> fill ( $fields );
2017-07-01 20:29:49 +00:00
2021-01-23 20:33:34 +00:00
if ( ! $validate ) {
2017-07-01 20:29:49 +00:00
$saved = $instance -> skipValidation () -> save ();
} else {
2021-01-23 20:33:34 +00:00
if ( ! $saved = $instance -> save ()) {
2022-06-26 20:31:48 +00:00
throw new DataValidationException ( $instance -> getValidator (), $instance );
2017-07-01 20:29:49 +00:00
}
}
2017-07-08 19:17:07 +00:00
return ( $this -> withFresh ) ? $instance -> fresh () : $saved ;
2017-07-01 20:29:49 +00:00
}
2020-04-04 23:07:09 +00:00
/**
* Update a model using the attributes passed .
*/
2022-10-14 16:59:20 +00:00
public function updateWhere ( array $attributes , array $values ) : int
2020-04-04 23:07:09 +00:00
{
return $this -> getBuilder () -> where ( $attributes ) -> update ( $values );
}
2017-07-24 00:57:43 +00:00
/**
2018-01-05 04:49:50 +00:00
* Perform a mass update where matching records are updated using whereIn .
* This does not perform any model data validation .
2017-07-24 00:57:43 +00:00
*/
2018-01-05 04:49:50 +00:00
public function updateWhereIn ( string $column , array $values , array $fields ) : int
2017-07-24 00:57:43 +00:00
{
2018-01-05 04:49:50 +00:00
Assert :: notEmpty ( $column , 'First argument passed to updateWhereIn must be a non-empty string.' );
2017-08-12 20:29:01 +00:00
2017-07-24 00:57:43 +00:00
return $this -> getBuilder () -> whereIn ( $column , $values ) -> update ( $fields );
}
2017-07-08 19:07:51 +00:00
/**
2018-01-05 04:49:50 +00:00
* Update a record if it exists in the database , otherwise create it .
*
* @ throws \Pterodactyl\Exceptions\Model\DataValidationException
* @ throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
2017-07-08 19:07:51 +00:00
*/
2022-10-14 16:59:20 +00:00
public function updateOrCreate ( array $where , array $fields , bool $validate = true , bool $force = false ) : Model | bool
2017-07-01 20:29:49 +00:00
{
2018-01-05 04:49:50 +00:00
foreach ( $where as $item ) {
Assert :: true ( is_scalar ( $item ) || is_null ( $item ), 'First argument passed to updateOrCreate should be an array of scalar or null values, received an array value of %s.' );
}
try {
$instance = $this -> setColumns ( 'id' ) -> findFirstWhere ( $where );
2022-10-14 16:59:20 +00:00
} catch ( RecordNotFoundException ) {
2018-01-05 04:49:50 +00:00
return $this -> create ( array_merge ( $where , $fields ), $validate , $force );
}
return $this -> update ( $instance -> id , $fields , $validate , $force );
2017-07-01 20:29:49 +00:00
}
2017-07-15 16:52:34 +00:00
/**
2018-01-05 04:49:50 +00:00
* Return all records associated with the given model .
*
2020-07-07 04:25:00 +00:00
* @ deprecated Just use the model
2017-07-15 16:52:34 +00:00
*/
2018-01-05 04:49:50 +00:00
public function all () : Collection
2017-07-15 16:52:34 +00:00
{
2020-09-13 18:29:47 +00:00
return $this -> getBuilder () -> get ( $this -> getColumns ());
2017-07-15 16:52:34 +00:00
}
2017-07-20 01:49:41 +00:00
2018-01-11 05:19:03 +00:00
/**
* Return a paginated result set using a search term if set on the repository .
*/
public function paginated ( int $perPage ) : LengthAwarePaginator
{
2020-09-13 18:29:47 +00:00
return $this -> getBuilder () -> paginate ( $perPage , $this -> getColumns ());
2018-01-11 05:19:03 +00:00
}
2017-07-20 01:49:41 +00:00
/**
2018-01-05 04:49:50 +00:00
* Insert a single or multiple records into the database at once skipping
* validation and mass assignment checking .
2017-07-20 01:49:41 +00:00
*/
2018-01-05 04:49:50 +00:00
public function insert ( array $data ) : bool
2017-07-20 01:49:41 +00:00
{
return $this -> getBuilder () -> insert ( $data );
}
2017-07-25 02:34:10 +00:00
2017-08-06 02:10:32 +00:00
/**
* Insert multiple records into the database and ignore duplicates .
*/
2018-01-05 04:49:50 +00:00
public function insertIgnore ( array $values ) : bool
2017-08-06 02:10:32 +00:00
{
if ( empty ( $values )) {
return true ;
}
2018-01-05 04:49:50 +00:00
foreach ( $values as $key => $value ) {
ksort ( $value );
$values [ $key ] = $value ;
2017-08-06 02:10:32 +00:00
}
$bindings = array_values ( array_filter ( array_flatten ( $values , 1 ), function ( $binding ) {
2021-01-23 20:33:34 +00:00
return ! $binding instanceof Expression ;
2017-08-06 02:10:32 +00:00
}));
$grammar = $this -> getBuilder () -> toBase () -> getGrammar ();
$table = $grammar -> wrapTable ( $this -> getModel () -> getTable ());
$columns = $grammar -> columnize ( array_keys ( reset ( $values )));
$parameters = collect ( $values ) -> map ( function ( $record ) use ( $grammar ) {
return sprintf ( '(%s)' , $grammar -> parameterize ( $record ));
}) -> implode ( ', ' );
2022-11-29 17:53:59 +00:00
$driver = DB :: getPdo () -> getAttribute ( \PDO :: ATTR_DRIVER_NAME );
2022-11-25 20:29:04 +00:00
switch ( $driver ) {
case 'mysql' :
$statement = " insert ignore into $table ( $columns ) values $parameters " ;
break ;
case 'pgsql' :
$statement = " insert into $table ( $columns ) values $parameters on conflict do nothing " ;
break ;
default :
2022-11-29 17:53:59 +00:00
throw new \RuntimeException ( " Unsupported database driver \" $driver\ " for insert ignore . " );
2022-11-25 20:29:04 +00:00
}
2017-08-06 02:10:32 +00:00
return $this -> getBuilder () -> getConnection () -> statement ( $statement , $bindings );
}
2018-05-26 18:58:49 +00:00
/**
2018-06-02 21:32:26 +00:00
* Get the amount of entries in the database .
2018-05-26 18:58:49 +00:00
*
2020-07-07 04:25:00 +00:00
* @ deprecated just use the count method off a model
2018-05-26 18:58:49 +00:00
*/
public function count () : int
{
return $this -> getBuilder () -> count ();
}
2017-07-01 20:29:49 +00:00
}