File: /var/www/limestate-api/Models/Sync.php
<?php
class Sync extends Db_Model {
static $strict = false;
public static function numLine( $i, $string ) {
Output::rewrite( ' - ' . ( $i + 1 ) . '. ' . $string );
}
public static function complexes() {
Complex::update( [
'published' => 0,
], null );
$updated = $created = 0;
$complexes = BitrixApi::getComplexes();
Output::title( 'Синхронизируем данные по комплексам' );
Output::write( 'Найдено: ' . $complexes->totalCount );
Output::write( '' );
foreach ( $complexes->objects as $i => $complex ) {
self::numLine($i, 'ищем запись');
$complexRecord = Complex::getByOldId($complex->ID);
$name = strip_tags($complex->name);
Output::write($name);
Output::write('');
self::numLine($i, 'получаем имя');
$beautification = unserialize($complex->beautification);
if (is_array($beautification)) {
$beautification = strip_tags($beautification['TEXT']);
$beautification = empty($beautification) ? '' : Typograf::clear($beautification);
} else {
$beautification = '';
}
self::numLine( $i, 'получаем благоустройство' );
$infrastructure = unserialize( $complex->infrastructure );
if (is_array($infrastructure)) {
$infrastructure = strip_tags($infrastructure['TEXT']);
$infrastructure = empty($infrastructure) ? '' : Typograf::clear($infrastructure);
} else {
$infrastructure = '';
}
self::numLine( $i, 'получаем инфраструктуру' );
$metroId = self::getMetroId($complex->station);
$cityDistrictId = self::getCityDistrictId($complex->city_district);
$developerId = self::getDeveloperId($complex->developer);
$isCompleted = 0;
if ( $complex->deadline == 'сдан' ) {
$isCompleted = 1;
} else {
if ( is_numeric( $complex->deadline ) && is_numeric( $complex->quarter ) ) {
$currentQuarter = ceil( date( 'n' ) / 3 );
if ( date( 'Y' ) > $complex->deadline ||
( $currentQuarter > $complex->quarter && date( 'Y' ) == $complex->deadline ) ) {
$isCompleted = 1;
}
}
}
$complexData = [
'old_ID' => $complex->ID,
'name' => $name,
'alias' => $complex->code,
'description' => Typograf::clear( $complex->description ),
'beautification' => $beautification,
'infrastructure' => $infrastructure,
'city_district_id' => $cityDistrictId,
'metro_id' => $metroId,
'developer_id' => $developerId,
'completed_year' => is_numeric( $complex->deadline ) ? $complex->deadline : null,
'completed_quarter' => is_numeric( $complex->quarter ) ? $complex->quarter : null,
'is_completed' => $isCompleted,
'latlng' => $complex->coord,
'published' => 1,
'category_id' => 1, // Элитная недвижимость
'city_id' => 1,
'region_id' => 1
];
if ( $complexRecord ) {
self::numLine( $i, 'обновляем запись' );
$complexId = $complexRecord->id;
Complex::update($complexData , [
'id' => $complexId
] );
$updated ++;
} else {
self::numLine( $i, 'создаём запись' );
$complexId = Complex::create($complexData);
$created ++;
}
// StreetName
ComplexStreets::rewrite($complex->address, $complexId);
// Gallery
$bitrixData = BitrixApi::getComplex( $complex->ID );
self::numLine( $i, 'обновляем галерею' );
//Attachment::clear('Complex', $complexId, 'photo');
$ids = [];
if ( ! empty( $bitrixData ) ) {
$gallery = self::fixUrl($bitrixData->gallery_huge);
} else {
$gallery = [];
}
foreach ( $gallery as $url ) {
$attachmentId = Attachment::getId( $url, 'Complex', $complexId );
$pathInfo = pathinfo( $url );
if ( empty( $attachmentId ) ) {
$attachmentId = Attachment::createWithThumbnail([
'file' => $url,
'file_type' => 'photo',
'attachable_id' => $complexId,
'attachable_type' => 'Complex',
'original_filename' => $pathInfo['basename'],
'created_at' => date( 'Y-m-d H:i:s' ),
'is_external' => 1
] );
}
$ids[] = $attachmentId;
}
Attachment::clearWithout('Complex', $complexId, 'photo', $ids);
}
Output::rewrite( '' );
Output::write( 'обновлены: ' . $updated );
Output::write( 'созданы: ' . $created );
Output::success( 'данные успешно синхронизированы' );
}
public static function fixUrl($url) {
$url = str_replace('https://limestate.ru', 'https://bitrix.limestate.ru', $url);
$url = str_replace('http://limestate.ru', 'https://bitrix.limestate.ru', $url);
return $url;
}
public static function buildings($complexId = null) {
$toFlush = [
'category_id' => 1,
'published' => 1,
];
if (!empty($complexId)) {
$toFlush['complex_id'] = $complexId;
}
Building::update( [
'published' => 0
], $toFlush );
Output::title( 'Синхронизируем данные по домам' );
$complexes = Complex::$db->select('id', 'name', 'old_ID')->from(Complex::$table_name . ' c')
->where('published = ?', 1);
if (!empty($complexId)) {
$complexes->where('c.id = ?', $complexId);
}
$complexes = $complexes->fetchAll();
Output::write( 'Комплексов: ' . count($complexes));
Output::write( '' );
$updated = $created = 0;
foreach($complexes as $complex) {
Output::log($complex->name . '(' . $complex->old_ID . ')');
$buildings = BitrixApi::getBuildings($complex->old_ID);
Output::write( 'Найдено: ' . count($buildings));
Output::write( '' );
$i = 1;
$buildingsList = [];
foreach ( $buildings as $building ) {
self::numLine( $i, 'ищем запись' );
$buildingRecord = Building::getByOldId( $building->id );
$metroId = self::getMetroId($building->metro);
$cityDistrictId = self::getCityDistrictId($building->city_district);
$developerId = self::getDeveloperId($building->developer);
$streetTypeId = self::getStreetTypeId($building->street_type);
$finishingTypeId = self::getFinishingTypeId($building->finishing_type);
$houseTypeId = self::getHouseTypeId($building->house_type);
$isCompleted = 0;
if ( mb_strtolower(trim($building->completed_year)) == 'сдан' || $building->completed_year == 'cдан') {
$isCompleted = 1;
$building->completed_year = null;
$building->completed_quarter = null;
} else {
if ( is_numeric( $building->completed_year ) && is_numeric( $building->completed_quarter ) ) {
$currentQuarter = ceil( date( 'n' ) / 3 );
if ( date( 'Y' ) > $building->completed_year ||
( $currentQuarter > $building->completed_quarter && date( 'Y' ) == $building->completed_year ) ) {
$isCompleted = 1;
}
}
}
$floors = array_map(function($item) {
return (int)$item;
}, explode('-', $building->floors));
$maxFloor = count($floors) > 1 ? max($floors) : $floors[0];
$buildingData = [
'name' => $building->name,
'alias' => Helper::puntoSwitcher( $building->name, 'T->eng' ),
'old_ID' => $building->id,
'street_name' => $building->street_name,
'floors' => $maxFloor,
'floors_info' => $building->floors ?? '',
'region_id' => 1,
'metro_id' => $metroId,
'city_id' => 1,
'city_district_id' => $cityDistrictId,
'started_year' => (int)$building->started_year,
'started_quarter' => (int)$building->started_quarter,
'is_completed' => (int)$isCompleted,
'completed_year' => (int)$building->completed_year,
'completed_quarter' => (int)$building->completed_quarter,
'developer_id' => (int)$developerId,
'complex_id' => (int)$complex->id,
'latlng' => $building->latlng,
'housing_number' => $building->housing_number,
'category_id' => 1, // Элитная недвижимость
'street_type_id' => $streetTypeId,
'flats_count' => $building->flats_count,
'rooms_count' => $building->rooms_count,
'finishing_type_id' => $finishingTypeId,
'house_type_id' => $houseTypeId,
'published' => (int)($building->active == 'Y'),
'block_number' => $building->block_number ? $building->block_number : 1,
];
if ( $buildingRecord ) {
self::numLine( $i, 'обновляем запись' );
$buildingData['updated_at'] = date('Y-m-d H:i:s');
$buildingId = $buildingRecord->id;
Building::update($buildingData , [
'id' => $buildingId
] );
$updated++;
} else {
self::numLine( $i, 'создаём запись' );
$buildingData['updated_at'] = date('Y-m-d H:i:s');
$buildingData['created_at'] = date('Y-m-d H:i:s');
$buildingId = Building::create($buildingData);
$created++;
}
$buildingsList[] = $buildingId;
$buildingRawData = BitrixApi::getBuilding($buildingData['old_ID']);
// Floors plans
//Attachment::clear('Building', $buildingId, 'floor-plan');
$ids = [];
if (!empty($buildingRawData[0]->floors_plans)) {
foreach($buildingRawData[0]->floors_plans as $floorNumber => $url) {
$attachmentId = Attachment::getId( $url, 'Building', $buildingId );
if ( empty( $attachmentId ) ) {
$attachmentId = Attachment::create( [
'file' => $url,
'file_type' => 'floor-plan',
'attachable_id' => $buildingId,
'attachable_type' => 'Building',
'original_filename' => $floorNumber,
'created_at' => date( 'Y-m-d H:i:s' ),
'is_external' => 1
] );
}
$ids[] = $attachmentId;
}
}
Attachment::clearWithout('Building', $buildingId, 'floor-plan', $ids);
//Attachment::clear('Building', $buildingId, 'photo');
$ids = [];
if (!empty($buildingRawData[0]->gallery_huge)) {
foreach($buildingRawData[0]->gallery_huge as $url) {
$attachmentId = Attachment::getId( $url, 'Building', $buildingId );
$pathInfo = pathinfo( $url );
if ( empty( $attachmentId ) ) {
$attachmentId = Attachment::createWithThumbnail([
'file' => $url,
'file_type' => 'photo',
'attachable_id' => $buildingId,
'attachable_type' => 'Building',
'original_filename' => $pathInfo['basename'],
'created_at' => date( 'Y-m-d H:i:s' ),
'is_external' => 1
] );
}
$ids[] = $attachmentId;
}
}
Attachment::clearWithout('Building', $buildingId, 'photo', $ids);
$i++;
}
if (!empty($buildingsList)) {
Building::$db->query( 'DELETE FROM ' . Building::$table_name
. ' WHERE complex_id = ' . $complex->id
. ' AND id NOT IN (' . implode(',', $buildingsList) . ')');
} else {
Building::$db->delete(Building::$table_name, [
'complex_id' => $complex->id
]);
}
}
Output::rewrite( '' );
Output::write( 'обновлены: ' . $updated );
Output::write( 'созданы: ' . $created );
Output::success( 'данные успешно синхронизированы' );
}
public static function usedBuildings() {
$toFlush = [
'published' => 1,
'category_id' => 2,
'complex_id' => 0
];
Building::update( [
'published' => 0
], $toFlush );
Output::title( 'Синхронизируем данные по домам вторички' );
$buildings = BitrixApi::getUsedBuildings();
Output::write( 'Найдено: ' . count($buildings));
$updated = $created = 0;
Output::write( '' );
$i = 1;
foreach ( $buildings as $building ) {
self::numLine( $i, 'ищем запись' );
$buildingRecord = Building::getByOldId( $building->id );
$metroId = self::getMetroId($building->metro);
$cityDistrictId = self::getCityDistrictId($building->city_district);
$developerId = self::getDeveloperId($building->developer);
$streetTypeId = self::getStreetTypeId($building->street_type);
$finishingTypeId = self::getFinishingTypeId($building->finishing_type);
$houseTypeId = self::getHouseTypeId($building->house_type);
$isCompleted = 0;
if ( trim($building->completed_year) == 'сдан' || $building->completed_year == 'cдан') {
$isCompleted = 1;
$building->completed_year = null;
$building->completed_quarter = null;
} else {
if ( is_numeric( $building->completed_year ) && is_numeric( $building->completed_quarter ) ) {
$currentQuarter = ceil( date( 'n' ) / 3 );
if ( date( 'Y' ) > $building->completed_year ||
( $currentQuarter > $building->completed_quarter && date( 'Y' ) == $building->completed_year ) ) {
$isCompleted = 1;
}
}
}
$floors = array_map(function($item) {
return (int)$item;
}, explode('-', $building->floors));
$maxFloor = count($floors) > 1 ? max($floors) : $floors[0];
$buildingData = [
'name' => $building->name,
'alias' => Helper::puntoSwitcher( $building->name, 'T->eng' ),
'old_ID' => $building->id,
'street_name' => $building->street_name,
'floors' => $maxFloor,
'floors_info' => $building->floors ?? '',
'region_id' => 1,
'metro_id' => $metroId,
'city_id' => 1,
'city_district_id' => $cityDistrictId,
'started_year' => $building->started_year,
'started_quarter' => $building->started_quarter,
'is_completed' => $isCompleted,
'completed_year' => (int)$building->completed_year,
'completed_quarter' => (int)$building->completed_quarter,
'developer_id' => $developerId,
'complex_id' => 0,
'latlng' => $building->latlng,
'housing_number' => $building->housing_number,
'category_id' => 2, // Вторичная недвижимость
'street_type_id' => $streetTypeId,
'flats_count' => $building->flats_count,
'rooms_count' => $building->rooms_count,
'finishing_type_id' => $finishingTypeId,
'house_type_id' => $houseTypeId,
'published' => 1,
'block_number' => 1
];
if ( $buildingRecord ) {
self::numLine( $i, 'обновляем запись' );
$buildingData['updated_at'] = date('Y-m-d H:i:s');
$buildingId = $buildingRecord->id;
Building::update($buildingData , [
'id' => $buildingId
] );
$updated++;
} else {
self::numLine( $i, 'создаём запись' );
$buildingData['updated_at'] = date('Y-m-d H:i:s');
$buildingData['created_at'] = date('Y-m-d H:i:s');
$buildingId = Building::create($buildingData);
$created++;
}
$i++;
}
Output::rewrite( '' );
Output::write( 'обновлены: ' . $updated );
Output::write( 'созданы: ' . $created );
Output::success( 'данные успешно синхронизированы' );
}
public static function flats($buildingId = null) {
$toFlush = [
'published' => 1,
];
if (!empty($buildingId)) {
$toFlush['building_id'] = $buildingId;
}
Flat::update( [
'published' => 0,
], $toFlush );
Output::title( 'Синхронизируем данные по квартирам' );
$buildingsSql = Building::$db->select('id', 'name', 'old_ID')->from(Building::$table_name . ' c')
->where('published = ?', 1);
if (!empty($buildingId)) {
$buildingsSql->where('id = ?', $buildingId);
}
$buildings = $buildingsSql->fetchAll();
$updated = $created = 0;
foreach($buildings as $building) {
Output::log($building->name . '(' . $building->old_ID . ')');
$flats = BitrixApi::getFlats($building->old_ID);
Output::write( 'Найдено: ' . count($flats));
Output::write( '' );
$i = 1;
foreach ( $flats as $flat ) {
self::numLine( $i, 'ищем запись' );
$flatRecord = Flat::getByOldId( $flat->ID );
$rooms = (int)$flat->rooms;
$floor = (int)$flat->floor;
$flatData = [
'alias' => 0,
'old_ID' => $flat->ID,
'alias' => $floor . '-' . $rooms . '-' . $flat->number,
'floor' => $floor,
'rooms' => $rooms,
'total_area' => $flat->total_area,
'living_area' => $flat->living_area,
'rooms_area' => self::sumString($flat->rooms_area),
'kitchen_area' => $flat->kitchen_area,
'number' => $flat->number,
'price' => $flat->price,
'base_price' => $flat->base_price,
'building_id' => $building->id,
'balcony_type_id' => BalconyType::getId($flat->balcony),
'bathroom_type_id' => BathroomType::getId($flat->bathroom),
'view_type_id' => ViewType::getId($flat->view),
'assignment' => (int)$flat->assignments,
'contractor' => (int)$flat->contractor,
'old_ID' => $flat->ID,
'published' => 1,
'description' => $flat->description ?: $flat->text,
];
if ( $flatRecord ) {
self::numLine( $i, 'обновляем запись' );
$flatData['updated_at'] = date('Y-m-d H:i:s');
$flatId = $flatRecord->id;
Flat::update($flatData , [
'id' => $flatId
] );
$updated++;
} else {
self::numLine( $i, 'создаём запись' );
$flatData['updated_at'] = date('Y-m-d H:i:s');
$flatData['created_at'] = date('Y-m-d H:i:s');
$flatId = Flat::create($flatData);
$created++;
}
//Options
$options = !empty($flat->options) ? explode(',', $flat->options) : [];
FlatOptionRelation::clear($flatId);
foreach($options as $option) {
$optionId = FlatOption::getId($option);
if (!empty($optionId)) {
FlatOptionRelation::create( [
'flat_id' => $flatId,
'option_id' => $optionId
] );
}
}
// Gallery
$bitrixData = BitrixApi::getFlat( $flat->ID );
self::numLine( $i, 'обновляем галерею' );
if ( !empty($bitrixData) && !empty($bitrixData->flat_gallery_huge)) {
$gallery = $bitrixData->flat_gallery_huge;
} else {
$gallery = [];
}
$ids = [];
foreach ( $gallery as $url ) {
$attachmentId = Attachment::getId( $url, 'Flat', $flatId );
$pathInfo = pathinfo( $url );
if ( empty( $attachmentId ) ) {
$attachmentId = Attachment::createWithThumbnail([
'file' => $url,
'file_type' => 'photo',
'attachable_id' => $flatId,
'attachable_type' => 'Flat',
'original_filename' => $pathInfo['basename'],
'created_at' => date( 'Y-m-d H:i:s' ),
'is_external' => 1
]);
}
$ids[] = $attachmentId;
}
Attachment::clearWithout('Flat', $flatId, 'photo', $ids);
// Floor plan
//Attachment::clear('Flat', $flatId, 'floor-plan');
$ids = [];
if (!empty($flat->floor_plan)) {
$url = 'http://bitrix.limestate.ru/upload/' . $flat->floor_plan;
$attachmentId = Attachment::getId( $url, 'Flat', $flatId );
$pathInfo = pathinfo( $url );
if ( empty( $attachmentId ) ) {
$attachmentId = Attachment::createWithThumbnail([
'file' => $url,
'file_type' => 'floor-plan',
'attachable_id' => $flatId,
'attachable_type' => 'Flat',
'original_filename' => $pathInfo['basename'],
'created_at' => date( 'Y-m-d H:i:s' ),
'is_external' => 1
] );
}
}
Attachment::clearWithout('Flat', $flatId, 'floor-plan', $ids);
// Plan
//Attachment::clear('Flat', $flatId, 'plan');
$ids = [];
if (!empty( $flat->plan)) {
$url = 'http://bitrix.limestate.ru/upload/' . $flat->plan;
$attachmentId = Attachment::getId( $url, 'Flat', $flatId );
$pathInfo = pathinfo( $url );
if ( empty( $attachmentId ) ) {
$attachmentId = Attachment::createWithThumbnail([
'file' => $url,
'file_type' => 'plan',
'attachable_id' => $flatId,
'attachable_type' => 'Flat',
'original_filename' => $pathInfo['basename'],
'created_at' => date( 'Y-m-d H:i:s' ),
'is_external' => 1
] );
}
$ids[] = $attachmentId;
}
Attachment::clearWithout('Flat', $flatId, 'plan', $ids);
$i++;
}
}
Output::rewrite( '' );
Output::write( 'обновлены: ' . $updated );
Output::write( 'созданы: ' . $created );
Output::success( 'данные успешно синхронизированы' );
}
public static function getMetroId($stationName){
$metroId = Metro::getId( trim($stationName) );
if ( empty( $metroId ) && !empty( $stationName ) ) {
if ( self::$strict ) {
Output::log( $stationName . ' – неизвесная станция метро' );
die( '!' );
} else {
$metroId = 0;
}
}
return $metroId;
}
public static function getCityDistrictId($cityDistrict){
$cityDistrictId = CityDistricts::getId($cityDistrict);
if ( empty( $cityDistrictId ) ) {
if ( self::$strict && ! empty( $cityDistrict ) ) {
Output::error( $cityDistrict . ' – неизвесный район' );
die( '!' );
} else {
$cityDistrictId = 0;
}
}
return $cityDistrictId;
}
public static function getDeveloperId($developer) {
$developerId = Developer::getId( $developer );
if ( empty($developerId)) {
if (!empty($developer)) {
$developerId = Developer::create([
'name' => $developer,
'created_at' => date('Y-m-d H:i:s')
]);
} else {
$developerId = 0;
}
}
return $developerId;
}
public static function getStreetTypeId($streetType) {
$streetTypeId = StreetType::getId( $streetType );
return $streetTypeId;
}
public static function getFinishingTypeId($finishingType) {
$finishingTypeId = FinishingType::getId( $finishingType );
return $finishingTypeId;
}
public static function getHouseTypeId($houseType) {
$houseTypeId = HouseType::getId( $houseType );
return $houseTypeId;
}
public static function sumString($string) {
$arr = explode('+', $string);
return array_sum($arr);
}
public static function prepareSync() {
global $CFG;
Output::log('Preparing migration ');
$cmd = 'mysqldump -u ' . $CFG->db['write']['username'] . ' -p' . $CFG->db['write']['password']
. (!empty($CFG->db['write']['port']) ? (' -P ' . $CFG->db['write']['port']) : '')
. (!empty($CFG->db['write']['host']) ? (' -h ' . $CFG->db['write']['host']) : '')
. ' --add-drop-table ' . $CFG->db['write']['database'] . ' | gzip > sync_dump.sql.gz';
Output::write($cmd);
exec($cmd);
$cmd2 = 'gunzip < sync_dump.sql.gz | mysql -u ' . $CFG->temp_db['write']['username'] . ' -p' . $CFG->temp_db['write']['password']
. (!empty($CFG->temp_db['write']['port']) ? ' -P ' . $CFG->temp_db['write']['port'] : '')
. (!empty($CFG->temp_db['write']['host']) ? ' -h ' . $CFG->temp_db['write']['host'] : '')
. ' ' . $CFG->temp_db['write']['database'];
Output::write($cmd2);
exec($cmd2);
Db_Model::$db->init($CFG->temp_db);
Output::success('Preparing migration: complete');
}
public static function completeSync() {
global $CFG;
Output::log('Completing migration ');
Db_Model::$db->init($CFG->db);
$cmd = 'mysqldump -u ' . $CFG->temp_db['write']['username'] . ' -p' . $CFG->temp_db['write']['password']
. (!empty($CFG->temp_db['write']['port']) ? (' -P ' . $CFG->temp_db['write']['port']) : '')
. (!empty($CFG->temp_db['write']['host']) ? (' -h ' . $CFG->temp_db['write']['host']) : '')
. ' --add-drop-table ' . $CFG->temp_db['write']['database'] . ' | gzip > complete_dump.sql.gz';
Output::write($cmd);
exec($cmd);
$cmd2 = 'gunzip < complete_dump.sql.gz | mysql -u ' . $CFG->db['write']['username'] . ' -p' . $CFG->db['write']['password']
. (!empty($CFG->db['write']['port']) ? ' -P ' . $CFG->db['write']['port'] : '')
. (!empty($CFG->db['write']['host']) ? ' -h ' . $CFG->db['write']['host'] : '')
. ' ' . $CFG->db['write']['database'];
Output::write($cmd2);
exec($cmd2);
Output::success('Completing migration: complete');
}
public static function failNotify($e) {
Output::error($e->getMessage());
exit;
}
}