HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/zelfverkopen.komma.pro/app/KommaApp/Properties/PropertyService.php
<?php


namespace App\KommaApp\Properties;

use App\KommaApp\Realworks\Models\RealworkObject;
use App\KommaApp\Realworks\Models\ObjectDetailsTranslation;
use GuzzleHttp\Client;
use Illuminate\Database\Eloquent\Collection;

class PropertyService
{

    const STATUS_AVAILABLE_SOLD = 'Verkocht';
    const STATUS_SOLD_UNDER_CONDITIONS = 'Verkocht onder voorbehoud';

    public function getPropertyPriceFilters()
    {

        $price = 0;
        $priceSteps = 100000;
        $maxPrice = 1000000;
        $priceOptions = [];

        do {
            $price += $priceSteps;
            $priceOptions[] = (object)[
                'value' => $price,
                'html'  => '€ ' . number_format($price, 0, ',', '.')
            ];
        } while ($price < $maxPrice);

        return $priceOptions;
    }

    /**
     * Generate the base property query
     *
     * @return mixed
     */
    private function getBasePropertyQueryBuilder(){
        return ObjectDetailsTranslation::join('object_details', 'object_details_translations.object_details_id', '=', 'object_details.id')
            ->join('objects', 'object_details.object_id', '=', 'objects.id')
            ->join('koop', 'object_details.id', '=', 'koop.object_details_id' )
            ->join('koop_translations', 'koop.id', '=', 'koop_translations.koop_id' )
            ->select('object_details_translations.*', 'objects.system_id', 'objects.id as object_id', 'object_details.long','object_details.lat', 'koop_translations.koop_prijs')
            ->orderBy('datum_invoer', 'desc');
    }


    /**
     * Get the array of relations
     */
    private function getPropertyRelationsArray(){
         return [
            'translatable',
            'translatable.object',
            'translatable.koop',
            'translatable.koop.translation',
        ];
    }

    public function getProperties($pagination = true, $itemsPerPage = 12, $withFilters = []){

        $properties = $this->getBasePropertyQueryBuilder();

        // Use with Relations, because load can't be used in combination with pagination
        $properties = $properties->with($this->getPropertyRelationsArray());

        if(sizeof($withFilters) !== 0) $properties = $this->addFilterRules($properties, $withFilters);

        // Get by pagination or all
        if($pagination) $properties = $properties->paginate($itemsPerPage);
        else $properties = $properties->get();

        // Decode the raw json because we need those data
        foreach ($properties as $property) {
            $this->convertPropertyForViewData($property);
            $this->bindMediaToProperty($property);
        }

        return $properties;
    }

    // Create shorter function for filters function
    public function getPropertiesWithFilters($filters, $pagination = true, $itemsPerPage = 12){
        return $this->getProperties($pagination, $itemsPerPage, $filters);
    }


    /*
     * Append addition filter rules
     */
    private function addFilterRules($queryBuilder, $withFilters){

        foreach($withFilters as $filter => $value){
            debug($filter. ' : '. $value);

            switch ($filter){
                case ('minimumPrice'):
                    $queryBuilder = $queryBuilder->where('koop_translations.koop_prijs', '>=', $value);
                    break;

                case ('maximumPrice'):
                    $queryBuilder = $queryBuilder->where('koop_translations.koop_prijs', '<=', $value);
                    break;
                case ('location'):
                    $queryBuilder = $queryBuilder->where('object_details_translations.woonplaats', 'LIKE', '%'.$value.'%');
                    break;

            }

        }

        return $queryBuilder;

    }

    public function getProperty($objectId)
    {

        if(!$property = $this->getBasePropertyQueryBuilder()
            ->where('objects.id', '=', $objectId)
            ->first()) throw abort(404);

        if(!isset($property->long) || !isset($property->lat) ) {
            $this->getLongAndLatOfProperty($property);
        }

        $this->convertPropertyForViewData($property);
        $this->bindMediaToProperty($property);

        return $property;

    }

    /**
     * Get the properties for the propertiesRow
     * In general this means 2 not sold and 1 sold property
     * And if there is no sold property available then we use 3 not sold
     *
     * @return mixed
     */
    public function getPropertiesForRow()
    {
        // Get the latest sold property
        $soldObject = $this->getBasePropertyQueryBuilder()
            ->whereIn('status_beschikbaarheid', [$this::STATUS_AVAILABLE_SOLD, $this::STATUS_SOLD_UNDER_CONDITIONS])
            ->first();

        // Determine the amount of not sold properties must get
        if ( ! $soldObject) $amountForSaleProperties = 3;
        else $amountForSaleProperties = 2;

        // Get latest properties which aren't sold
        $properties = $this->getBasePropertyQueryBuilder()
            ->where('status_beschikbaarheid', '!=', $this::STATUS_AVAILABLE_SOLD)
            ->take($amountForSaleProperties)
            ->get();

        // Push sold object to the end if found
        if ($soldObject) $properties->push($soldObject);

        //Load Relations
        // We do this here to reduce the amount of queries that needs to be executed
        $properties = $properties->load($this->getPropertyRelationsArray());

        // Decode the raw json because we need those data
        foreach ($properties as $property) {
            $this->convertPropertyForViewData($property);
            $this->bindMediaToProperty($property);
        }

        return $properties;
    }

    private function convertPropertyForViewData(&$property)
    {

        // Create slug for this property
        $property->slug = 'woning-' . \Str::slug($property->system_id) . '-' . \Str::slug($property->woonplaats) . '-' . \Str::slug($property->straatnaam) . '-' . \Str::slug($property->huisnummer);
        if (isset($property->huisnummer_toevoeging) && $property->huisnummer_toevoeging != '') {
            $property->slug .= '-' . \Str::slug($property->huisnummer_toevoeging);
        }

        // Convert location to lowercase and capitalize by word
        $property->location = ucwords(strtolower($property->woonplaats));

        // Get the price of the property
        if (isset($property->translatable->koop)) {
            $property->price = $property->translatable->koop->translation->koop_prijs;
        }elseif (isset($property->translatable->huur)) {
            $property->price = $property->translatable->huur->translation->huur_prijs;
        }else {
            $this->sendPropertyDataErrorMail($property->translatable->object->id, '', 4);
        }

        // Convert the price to right format
        if (isset($property->price)) {
            $property->price_formated = number_format($property->price, 0, ',', '.');
        }else {
            $property->price_formated = '';
        }

        // Convert status
        switch ($property->status_beschikbaarheid) {
            case ('Beschikbaar'):
                $property->status = 1;
                break;

            case ('Verkocht'):
                $property->status = 2;
                break;

            case ('Verkocht onder voorbehoud'):
                $property->status = 3;
                break;

            case ('Onder bod'):
                $property->status = 4;
                break;

            case ('Ingetrokken'):
                $property->status = 5;
                break;

            default:
                $this->sendPropertyDataErrorMail($property->translatable->object->id, 'status_beschikbaarheid', 2,
                    $property->status_beschikbaarheid);
                $property->status = 0;
                break;
        }

        // Detect if the raw json data is found
        if (isset($property->translatable->object->raw_json)) {

            // Decode and append the needed variables to the property
            $propertyJson = json_decode($property->translatable->object->raw_json);

            // Get show price variable
            if (isset($propertyJson->Web) && isset($propertyJson->Web->PrijsTonen)) {

                if ($propertyJson->Web->PrijsTonen == 'ja') {
                    $property->showPrice = true;
                }elseif ($propertyJson->Web->PrijsTonen == 'nee') {
                    $property->showPrice = false;
                }// Unexpected variable
                else {
                    $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Web->PrijsTonen', 2,
                        $propertyJson->Web->PrijsTonen);
                }
            }else {
                $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Web(->PrijsTonen)');
            }

            // Get Values of Property
            if (isset($propertyJson->Wonen)) {

                // Load global information of object

                // Get Floors information
                if (isset($propertyJson->Wonen->Verdiepingen)) {

                    // Amount of floors
                    if (isset($propertyJson->Wonen->Verdiepingen->Aantal)) {
                        $property->amountOfFloors = $propertyJson->Wonen->Verdiepingen->Aantal;
                    }else {
                        $this->sendPropertyDataErrorMail($property->translatable->object->id,
                            'Wonen->Verdiepingen->Aantal');
                    }

                    // Amount of rooms
                    if (isset($propertyJson->Wonen->Verdiepingen->AantalKamers)) {
                        $property->amountOfRooms = $propertyJson->Wonen->Verdiepingen->AantalKamers;
                    }else {
                        $this->sendPropertyDataErrorMail($property->translatable->object->id,
                            'Wonen->Verdiepingen->AantalKamers');
                    }

                    // Amount of bedrooms
                    if (isset($propertyJson->Wonen->Verdiepingen->AantalSlaapKamers)) {
                        $property->amountOfBedrooms = $propertyJson->Wonen->Verdiepingen->AantalSlaapKamers;
                    }else {
                        $this->sendPropertyDataErrorMail($property->translatable->object->id,
                            'Wonen->Verdiepingen->AantalSlaapKamers');
                    }

                }else {
                    $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Wonen->Verdiepingen');
                }

                // Get Other Property information
                // Through these we will just loop in the blade
                if (isset($propertyJson->Wonen->WonenDetails)) {
                    $property->details = $propertyJson->Wonen->WonenDetails;
                }else {
                    $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Wonen->WonenDetails');
                }

                if (isset($propertyJson->Wonen->Woonlagen)) {
                    $property->propertyFloors = $propertyJson->Wonen->Woonlagen;
                }
                else {
                    $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Wonen->Woonlagen');
                }

                // Get Subtype specific data
                if (isset($propertyJson->Wonen->Woonhuis)) {
                    $property->typeId = 1;

                    // Get Type Name
                    if (isset($propertyJson->Wonen->Woonhuis->TypeWoning)) {
                        $property->typeName = ucfirst($propertyJson->Wonen->Woonhuis->TypeWoning);
                    }else {
                        $this->sendPropertyDataErrorMail($property->translatable->object->id,
                            'Wonen->Woonhuis->TypeWoning');
                    }

                    // Get Sort Name
                    if (isset($propertyJson->Wonen->Woonhuis->SoortWoning)) {
                        $property->sortName = ucfirst($propertyJson->Wonen->Woonhuis->SoortWoning);
                    }else {
                        $this->sendPropertyDataErrorMail($property->translatable->object->id,
                            'Wonen->Woonhuis->SoortWoning');
                    }

                }
                elseif (isset($propertyJson->Wonen->Appartement)) {
                    $property->typeId = 2;

                    // Get Type Name
                    if (isset($propertyJson->Wonen->Appartement->KenmerkAppartement)) {
                        $property->typeName = ucfirst($propertyJson->Wonen->Appartement->KenmerkAppartement);
                    }
//                    else { // Don't log this because it can be empty
//                        $this->sendPropertyDataErrorMail($property->translatable->object->id,
//                            'Wonen->Appartement->KenmerkAppartement');
//                    }

                    // Get Sort Name
                    if (isset($propertyJson->Wonen->Appartement->SoortAppartement)) {
                        $property->sortName = ucfirst($propertyJson->Wonen->Appartement->SoortAppartement);
                    }else {
                        $this->sendPropertyDataErrorMail($property->translatable->object->id,
                            'Wonen->Appartement->SoortAppartement');
                    }

                    // Get Apartment Floor
                    if (isset($propertyJson->Wonen->Appartement->Woonlaag)) {
                        $property->apartmentFloor = $propertyJson->Wonen->Appartement->Woonlaag;
                    }
//                    else { // Don't log this because it can be empty
//                        $this->sendPropertyDataErrorMail($property->translatable->object->id,
//                            'Wonen->Appartement->Woonlaag');
//                    }
                }// When Subtype is used that isn't defined send message
                else {
                    $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Wonen->{Type}', 3);
                }
            }

            // Property also can be a lot
            elseif (isset($propertyJson->Bouwgrond)) {

                // Get Property information
                if (isset($propertyJson->Bouwgrond->HuidigeBestemming)) {
                    $property->destination = $propertyJson->Bouwgrond->HuidigeBestemming;
                }else {
                    $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Bouwgrond->HuidigeBestemming');
                }

                if (isset($propertyJson->Bouwgrond->HuidigGebruik)) {
                    $property->currentUse = $propertyJson->Bouwgrond->HuidigGebruik;
                }else {
                    $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Bouwgrond->HuidigGebruik');
                }

                if (isset($propertyJson->Bouwgrond->Bouwrijp)) {
                    $property->constructReady = $propertyJson->Bouwgrond->Bouwrijp;
                }else {
                    $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Bouwgrond->Bouwrijp');
                }

                if (isset($propertyJson->Bouwgrond->Liggingen) && isset($propertyJson->Bouwgrond->Liggingen->Ligging)) {

                    $positionString = [];
                    if(count($propertyJson->Bouwgrond->Liggingen) > 1) {
                        foreach ($propertyJson->Bouwgrond->Liggingen->Ligging as $key => $positionString) {
                        if($key !== 0) $positionString .= ', ';
                            $positionString .= $positionString;
                        }
                    } else {
                        $positionString = $propertyJson->Bouwgrond->Liggingen->Ligging;
                    }

                    $property->position = $positionString;
                }else {
                    $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Bouwgrond->Liggingen{->Ligging}');
                }
            }
            else {
                $this->sendPropertyDataErrorMail($property->translatable->object->id, 'Wonen|Bouwgrond');
            }
        }

    }

    private function bindMediaToProperty(&$property)
    {

        // Define the public path of the property
        $publicPath = $property->translatable->object->public_path;

        // Check if realworks folder for property exists
        if (file_exists(public_path($publicPath))) {

            $folders = scandir(public_path($publicPath)); // Get files in folder in ascending order
            $folders = array_diff($folders, ['..', '.']); // Remove Up or Down directors of Linux
            $folders = array_values($folders); // Reset array to only values


            $media = [];

            // Loop through the folders
            foreach ($folders as $folder) {

                if (file_exists(public_path($publicPath . $folder))) {

                    // Change naming to English if needed
                    switch ($folder) {
                        case ('HoofdFoto'):
                            $folderName = 'headerImage';
                            break;

                        case ('Foto'):
                            $folderName = 'images';
                            break;

                        case ('Plattegrond'):
                            $folderName = 'map';
                            break;

                        default:
                            $folderName = strtolower($folder);
                            break;
                    }

                    $media[$folderName] = [];

                    // Find files inside folder
                    $files = scandir(public_path($publicPath . $folder)); // Get files in folder in ascending order
                    $files = array_diff($files, ['..', '.']); // Remove Up or Down directors of Linux
                    $files = array_values($files); // Reset array to only values

                    foreach ($files as $file) {

                        // For the file location we don't need the public path because they should be based upon the root of the site instead of server
                        $src = $publicPath . $folder . '/' . $file;

                        // For images we grab the width, height
                        if (in_array($folderName, ['images', 'headerImage'])) {

                            /*
                             * Try to get the image size an images
                             * On error skip this file
                             */
                            try
                            {
                                /*
                                 * 0 = width
                                 * 1 = height
                                 */
                                $imageSize = getimagesize(public_path($src));

                                $media[$folderName][] = (object)[
                                    'src'    => $src,
                                    'width'  => $imageSize[0],
                                    'height' => $imageSize[1],
                                ];
                            }
                            catch(\Exception $e)
                            {
                                \Log::warning('Error getimagesize on path: '.$src);
                            }


                        }else {
                            $media[$folderName][] = $src;
                        }
                    }
                }
            }

            $property->media = (object)$media;

        } // Send error mail for not finding realworks folder
        else {
            $this->sendPropertyDataErrorMail($property->translatable->object->id, $publicPath);
        }
    }

    private function getLongAndLatOfProperty(&$property){

        // Generate geocoding string
        $geocodingUrlString = config('services.googleMaps.geocodingUrl');

        $location = $property->straatnaam. ' '.$property->huisnummer.$property->huisnummer_toevoeging.', '.$property->postcode;

        if($property->land == 'NL') $location .= ' Netherlands';

        $geocodingUrlString .= '?address='.$location;
        $geocodingUrlString .= '&key='.config('services.googleMaps.apiKeyServer');

        try {

            // Make geocoding request
            $client = new Client();
            $response = $client->get($geocodingUrlString);
//            debug($geocodingUrlString);

            $locationString = $response->getBody()->getContents();

            // Decode json string
            $locationJson = json_decode($locationString);
            $results = $locationJson->results;

            // Check that there are results and make the first the main
            if(sizeof($results) == 0 ) return false;
            $mainResult = $results[0];

            // Add the received response to the model
            $property->translatable->location_json = $locationString;

            // Check that de data we want isset
            if(isset($mainResult->geometry) && isset($mainResult->geometry->location)){

                // Add the desired variables
                $property->translatable->long = $mainResult->geometry->location->lng;
                $property->translatable->lat = $mainResult->geometry->location->lat;

                // Also bind them to the loaded property
                $property->long = $mainResult->geometry->location->lng;
                $property->lat = $mainResult->geometry->location->lat;
            }

            // Save the model
            $property->translatable->save();

        }
        catch (\Exception $e){
            debug($e->getRequest());
            debug($e->getResponse());
            return false;
        }
    }

    private function sendPropertyDataErrorMail($propertyId, $dataTail, $errorType = 1, $variable = '')
    {
        // Don't send the mails on production
//        if (\App::environment('production')) return false;

        switch ($errorType) {
            case (1):
                $errorString = 'Not found Property Tail';
                break;

            case (2):
                $errorString = 'Unexpected Property Variable';
                break;

            case (3):
                $errorString = 'Not defined Property Type';
                break;

            case (4):
                $errorString = 'No Submodel Property';
                break;

            default:
                $errorString = 'Unknown Property Error';
                break;
        }

//        \Mail::send('site.emails.propertyDataError', [
//            'propertyId'  => $propertyId,
//            'dataTail'    => $dataTail,
//            'errorType'   => $errorType,
//            'errorString' => $errorString,
//            'variable'    => $variable
//        ], function ($message) use ($propertyId, $errorString) {
//
//            $message->from(\Config::get('mail.from.address'), \Config::get('mail.from.name'));
//            $message->to(\Config::get('mail.admin.address'));
//
//            // Set subject
//            $message->subject($errorString . ': Object id ' . $propertyId);
//
//        });

    }


}