/** * Send an email * * Usage example: * * $result = mail::send([ * 'to' => 'test@localhost', * 'cc' => 'cc@localhost', * 'bcc' => 'bcc@localhost', * 'subject' => 'test subject', * 'message' => 'test message', * 'attachments' => [ * ['path' => 'path to file', 'name' => 'test.txt'], * ['data' => '!!!data!!!', 'name' => 'test.txt', 'type' => 'plain/text'] * ] * ]); * * @param array $options */ public static function send($options) { $result = ['success' => false, 'error' => []]; // mail delivery first $mail_delivery_class = application::get('flag.global.mail.delivery.submodule', ['class' => 1]); if (empty($mail_delivery_class)) { throw new Exception('You need to specify mail delivery submodule'); } $mail_delivery_object = new $mail_delivery_class(); $temp = $mail_delivery_object->send($options); if (!$temp['success']) { array_merge3($result['error'], $temp['error']); } else { $result['success'] = true; } return $result; }
public static function import($file_name, $model_class, $options = array()) { $result = array('success' => false, 'error' => array()); do { // model $model = new $model_class(); // format $format = strtolower(pathinfo($file_name, PATHINFO_EXTENSION)); if (empty(self::$formats[$format]) || !(self::$formats[$format]['type'] == 1 || self::$formats[$format]['type'] == 3)) { $result['error'][] = 'Not supported upload format!'; @unlink($file_name); break; } $file_format = self::$formats[$format]; // reading file switch ($format) { case 'xlsx': $file_data = self::xlsx_to_array($file_name, $file_format['excel_code']); break; default: $file_data = self::csv_to_array($file_name, $file_format['delimiter'], $file_format['enclosure']); } // cleaning up unlink($file_name); // checking if ($file_data === false || empty($file_data)) { $result['error'][] = 'Error reading or empty file!'; break; } // transforming data $objects = array(); $temp = array_shift($file_data); $keys = $temp[0]; unset($temp[0]); foreach ($temp as $k => $v) { // fix array fields foreach ($v as $k2 => $v2) { $v2 = $v2 . ''; if (@$v2[0] == '{' && $v2[strlen($v2) - 1] == '}') { $v[$k2] = db::pg_parse_array($v2); } } $objects[] = array_combine($keys, $v); } // processing details if (!empty($objects) && !empty($file_data)) { foreach ($model->details as $k => $v) { $model2 = new $k(); if (isset($file_data[$model2->table])) { // if we have details of details $details_of_details = array(); $keys_of_details = array(); $options_of_details = array(); if (isset($model2->details)) { foreach ($model2->details as $k10 => $v10) { $model3 = new $k10(); if (isset($file_data[$model3->table])) { $options_of_details[$model3->table] = $v10['key']; $details_of_details[$model3->table] = $file_data[$model3->table]; $keys_of_details[$model3->table] = $details_of_details[$model3->table][0]; unset($file_data[$model3->table], $details_of_details[$model3->table][0]); } } // setting keys properly foreach ($details_of_details as $k10 => $v10) { foreach ($v10 as $k11 => $v11) { $details_of_details[$k10][$k11] = array_combine($keys_of_details[$k10], $v11); } } } // details itself $details = array(); $temp = $file_data[$model2->table]; $keys = $temp[0]; unset($file_data[$model2->table], $temp[0]); foreach ($temp as $k2 => $v2) { // fix array fields foreach ($v2 as $k9 => $v9) { $v9 = $v9 . ''; if (@$v9[0] == '{' && $v9[strlen($v9) - 1] == '}') { $v2[$k9] = db::pg_parse_array($v9); } } // combining keys and values to make an assocoative array $value = array_combine($keys, $v2); // if we have details of details if (!empty($details_of_details)) { foreach ($details_of_details as $k10 => $v10) { // main keys $keys10 = array(); foreach ($options_of_details[$k10] as $k12 => $v12) { $keys10[] = $value[$k12]; } $keys10 = implode('-', $keys10); // lopping though all items foreach ($v10 as $k11 => $v11) { $keys11 = array(); foreach ($options_of_details[$k10] as $k12 => $v12) { $keys11[] = $v11[$v12]; } $keys11 = implode('-', $keys11); if ($keys10 == $keys11) { $value[$k10][] = $v11; } } } } // putting back into loop $details[] = $value; } // if we have rows if (!empty($details)) { foreach ($objects as $k2 => $v2) { // keys $keys = array(); foreach ($v['key'] as $k3 => $v3) { $keys[] = $v2[$k3]; } $keys = implode('-', $keys); foreach ($details as $k3 => $v3) { $keys2 = array(); foreach ($v['key'] as $k4 => $v4) { $keys2[] = $v3[$v4]; } $keys2 = implode('-', $keys2); if ($keys2 == $keys) { $objects[$k2][$model2->table][] = $v3; } } } } } } } // saving if (!empty($objects)) { if (empty($options['all_objects_as_array'])) { foreach ($objects as $k => $v) { // replacing values in some cases if (!empty($options['replace_values'])) { foreach ($options['replace_values'] as $k2 => $v2) { $v[$k2] = $v2; } } $save_result = $model->save($v); if (!$save_result['success']) { array_merge3($result['error'], $save_result['error']); } } } else { foreach ($objects as $k => $v) { // replacing values in some cases if (!empty($options['replace_values'])) { foreach ($options['replace_values'] as $k2 => $v2) { $objects[$k2] = $v2; } } } $save_result = $model->save($objects); if (!$save_result['success']) { array_merge3($result['error'], $save_result['error']); } } } if (empty($result['error'])) { $result['success'] = true; } } while (0); return $result; }
/** * Process models * * @param array $options * @return array */ public static function process_models($options = []) { $result = ['success' => false, 'error' => [], 'hint' => [], 'data' => []]; do { // we need to process all dependencies first $dep = self::process_deps_all($options); if (!$dep['success']) { $result = $dep; $result['error'][] = 'You must fix all dependency related errors first before processing models.'; break; } // proccesing models if (empty($dep['data']['model_processed'])) { $result['error'][] = 'You do not have models to process!'; break; } $object_attributes = []; $object_relations = []; $object_forms = []; $flag_relation = application::get('dep.submodule.numbers.data.relations') ? true : false; $object_documentation = []; $object_import = []; $ddl = new numbers_backend_db_class_ddl(); // run 1 to deterine virtual tables $first = true; $virtual_models = $dep['data']['model_processed']; run_again: foreach ($virtual_models as $k => $v) { $k2 = str_replace('.', '_', $k); if ($v == 'object_table') { $model = factory::model($k2, true); foreach (['attributes', 'audit', 'addresses'] as $v0) { if ($model->{$v0}) { $v01 = $v0 . '_model'; $virtual_models[str_replace('_', '.', $model->{$v01})] = 'object_table'; } } } } if ($first) { $first = false; goto run_again; // some widgets have attributes } $dep['data']['model_processed'] = array_merge_hard($dep['data']['model_processed'], $virtual_models); $domains = object_data_domains::get_static(); // run 2 foreach ($dep['data']['model_processed'] as $k => $v) { $k2 = str_replace('.', '_', $k); if ($v == 'object_table') { $model = factory::model($k2, true); $temp_result = $ddl->process_table_model($model); if (!$temp_result['success']) { array_merge3($result['error'], $temp_result['error']); } $object_documentation[$v][$k2] = $k2; // relation if ($flag_relation) { if (!empty($model->relation)) { $domain = $model->columns[$model->relation['field']]['domain'] ?? null; if (!empty($domain)) { $domain = str_replace('_sequence', '', $domain); $type = $domains[$domain]['type']; } else { $type = $model->columns[$model->relation['field']]['type']; } $object_relations[$k2] = ['rn_relattr_code' => $model->relation['field'], 'rn_relattr_name' => $model->title, 'rn_relattr_model' => $k2, 'rn_relattr_domain' => $domain, 'rn_relattr_type' => $type, 'rn_relattr_inactive' => !empty($model->relation['inactive']) ? 1 : 0]; } if (!empty($model->attributes)) { $object_attributes[$k2] = ['rn_attrmdl_code' => $k2, 'rn_attrmdl_name' => $model->title, 'rn_attrmdl_inactive' => 0]; } } } else { if ($v == 'object_sequence') { $temp_result = $ddl->process_sequence_model($k2); if (!$temp_result['success']) { array_merge3($result['error'], $temp_result['error']); } $object_documentation[$v][$k2] = $k2; } else { if ($v == 'object_function') { $temp_result = $ddl->process_function_model($k2); if (!$temp_result['success']) { array_merge3($result['error'], $temp_result['error']); } $object_documentation[$v][$k2] = $k2; } else { if ($v == 'object_extension') { $temp_result = $ddl->process_function_extension($k2); if (!$temp_result['success']) { array_merge3($result['error'], $temp_result['error']); } $object_documentation[$v][$k2] = $k2; } else { if ($v == 'object_import') { $object_import[$k2] = ['model' => $k2]; } } } } } } // if we have erros if (!empty($result['error'])) { break; } // db factory $db_factory = factory::get('db'); // we load objects from database $loaded_objects = []; foreach ($ddl->db_links as $k => $v) { $ddl_object = $db_factory[$k]['ddl_object']; $temp_result = $ddl_object->load_schema($k); if (!$temp_result['success']) { array_merge3($result['error'], $temp_result['error']); } else { $loaded_objects[$k] = $temp_result['data']; } } // if we have erros if (!empty($result['error'])) { break; } // get a list of all db links $db_link_list = array_unique(array_merge(array_keys($ddl->objects), array_keys($loaded_objects))); // if we are dropping schema if ($options['mode'] == 'drop') { $ddl->objects = []; } // compare schemas per db link $schema_diff = []; $total_per_db_link = []; $total = 0; foreach ($db_link_list as $k) { // we need to have a back end for comparison $compare_options['backend'] = $db_factory[$k]['backend']; // comparing $temp_result = $ddl->compare_schemas(isset($ddl->objects[$k]) ? $ddl->objects[$k] : [], isset($loaded_objects[$k]) ? $loaded_objects[$k] : [], $compare_options); if (!$temp_result['success']) { array_merge3($result['hint'], $temp_result['error']); } else { $schema_diff[$k] = $temp_result['data']; if (!isset($total_per_db_link[$k])) { $total_per_db_link[$k] = 0; } $total_per_db_link[$k] += $temp_result['count']; $total += $temp_result['count']; } } // if there's no schema changes if ($total == 0) { if ($options['mode'] == 'commit') { goto import_data; } else { $result['success'] = true; } break; } // we need to provide a list of changes foreach ($total_per_db_link as $k => $v) { $result['hint'][] = ''; $result['hint'][] = "Db link {$k} requires {$v} changes!"; // printing summary $result['hint'][] = ' * Link ' . $k . ': '; foreach ($schema_diff[$k] as $k2 => $v2) { $result['hint'][] = ' * ' . $k2 . ': '; foreach ($v2 as $k3 => $v3) { $result['hint'][] = ' * ' . $k3 . ' - ' . $v3['type']; } } } // if we are in no commit mode we exit if (!in_array($options['mode'], ['commit', 'drop'])) { break; } // generating sql foreach ($total_per_db_link as $k => $v) { if ($v == 0) { continue; } $ddl_object = $db_factory[$k]['ddl_object']; foreach ($schema_diff[$k] as $k2 => $v2) { foreach ($v2 as $k3 => $v3) { // we need to make fk constraints last to sort MySQL issues if ($k2 == 'new_constraints' && $v3['type'] == 'constraint_new' && $v3['data']['type'] == 'fk') { $schema_diff[$k][$k2 . '_fks'][$k3]['sql'] = $ddl_object->render_sql($v3['type'], $v3); } else { $schema_diff[$k][$k2][$k3]['sql'] = $ddl_object->render_sql($v3['type'], $v3, ['mode' => $options['mode']]); } } } } // print_r($schema_diff); // exit; // executing sql foreach ($total_per_db_link as $k => $v) { if ($v == 0) { continue; } $db_object = new db($k); // if we are dropping we need to disable foregn key checks if ($options['mode'] == 'drop') { if ($db_object->backend == 'mysqli') { $db_object->query('SET foreign_key_checks = 0;'); // we also need to unset sequences unset($schema_diff[$k]['delete_sequences']); } } foreach ($schema_diff[$k] as $k2 => $v2) { foreach ($v2 as $k3 => $v3) { if (empty($v3['sql'])) { continue; } if (is_array($v3['sql'])) { $temp = $v3['sql']; } else { $temp = [$v3['sql']]; } foreach ($temp as $v4) { $temp_result = $db_object->query($v4); if (!$temp_result['success']) { array_merge3($result['error'], $temp_result['error']); goto error; } } } } } // if we got here - we are ok $result['success'] = true; } while (0); import_data: // we need to import data if (!empty($object_import) && $options['mode'] == 'commit') { $result['hint'][] = ''; foreach ($object_import as $k => $v) { $data_object = new $k(); $data_result = $data_object->process(); if (!$data_result['success']) { throw new Exception(implode("\n", $data_result['error'])); } $result['hint'] = array_merge($result['hint'], $data_result['hint']); } } // relation if ($flag_relation && $options['mode'] == 'commit') { $result['hint'][] = ''; $model2 = factory::model('numbers_data_relations_model_relation_attributes'); // insert new models if (!empty($object_relations)) { foreach ($object_relations as $k => $v) { $result_insert = $model2->save($v, ['pk' => ['rn_relattr_code'], 'ignore_not_set_fields' => true]); } $result['hint'][] = ' * Imported relation models!'; } // we need to process forms foreach ($dep['data']['submodule_dirs'] as $v) { $dir = $v . 'model/form/'; if (!file_exists($dir)) { continue; } $files = helper_file::iterate($dir, ['only_extensions' => ['php']]); foreach ($files as $v2) { $model_name = str_replace(['../libraries/vendor/', '.php'], '', $v2); $model_name = str_replace('/', '_', $model_name); $model = new $model_name(['skip_processing' => true]); if (empty($model->form_object->misc_settings['option_models'])) { continue; } // loop though fields foreach ($model->form_object->misc_settings['option_models'] as $k3 => $v3) { $object_forms[$model_name . '::' . $k3] = ['rn_relfrmfld_form_code' => $model_name, 'rn_relfrmfld_form_name' => $model->title, 'rn_relfrmfld_field_code' => $k3, 'rn_relfrmfld_field_name' => $v3['field_name'], 'rn_relfrmfld_relattr_id' => $v3['model'], 'rn_relfrmfld_inactive' => 0]; } } } if (!empty($object_forms)) { // load all relation models $data = $model2->get(['pk' => ['rn_relattr_model']]); $model = factory::model('numbers_data_relations_model_relation_formfields'); foreach ($object_forms as $k => $v) { if (empty($data[$v['rn_relfrmfld_relattr_id']])) { continue; } $v['rn_relfrmfld_relattr_id'] = $data[$v['rn_relfrmfld_relattr_id']]['rn_relattr_id']; $result_insert = $model->save($v, ['pk' => ['rn_relfrmfld_form_code', 'rn_relfrmfld_field_code'], 'ignore_not_set_fields' => true]); } $result['hint'][] = ' * Imported relation form fields!'; } // todo: import models //print_r2($object_attributes); if (!empty($object_attributes)) { $model = factory::model('numbers_data_relations_model_attribute_models'); foreach ($object_attributes as $k => $v) { $result_insert = $model->save($v, ['pk' => ['rn_attrmdl_code'], 'ignore_not_set_fields' => true]); } $result['hint'][] = ' * Imported attribute models!'; } } // we need to generate documentation $system_documentation = application::get('system_documentation'); if (!empty($system_documentation) && $options['mode'] == 'commit') { $model = factory::model($system_documentation['model']); /* print_r2($object_documentation); $documentation_result = $model->update($object_documentation, $system_documentation); if (!$documentation_result['success']) { $result['error'] = array_merge($result['error'], $documentation_result['error']); } */ } error: return $result; }
/** * Validate * * @param array $options * @return array */ public function validate($options) { $result = ['success' => false, 'error' => [], 'data' => ['from' => '', 'subject' => '', 'to' => [], 'message' => [], 'attachments' => [], 'requires_fetching' => false]]; do { // processing from if (isset($options['from'])) { $from = $options['from']; } else { $from = application::get('flag.global.mail.from'); } if (empty($from['email'])) { $result['error'][] = 'You need to specify from email address!'; } else { $result['data']['from'] = $from; } // processing subject if (isset($options['subject'])) { $result['data']['subject'] = $options['subject']; } // processing message if (is_string($options['message'])) { $result['data']['message'][] = ['data' => $options['message']]; } else { if (isset($options['message']['data'])) { $result['data']['message'][] = $options['message']; } else { $result['data']['message'] = $options['message']; } } // detecting type for each message part $flags = []; foreach ($result['data']['message'] as $k => $v) { // we need to determine mesage type if (!isset($v['type'])) { if ($v['data'] == html_entity_decode(strip_tags($v['data']))) { $result['data']['message'][$k]['type'] = 'text/plain'; $flags['text'] = 1; } else { $result['data']['message'][$k]['type'] = 'text/html'; $flags['html'] = $k; } } else { if (!in_array($v['type'], object_type_mail_messages::$data)) { $result['error'][] = 'Unknown type: ' . $v['type']; } } // charset if (!isset($v['charset'])) { $result['data']['message'][$k]['charset'] = 'utf-8'; } // encoding if (!isset($v['encoding'])) { $result['data']['message'][$k]['encoding'] = '7bit'; } } // if we have html version but does not that text version we autogenerate if (isset($flags['html']) && empty($flags['text'])) { $temp = str_replace(['<br/>', '<br />', '<br>', '<hr/>', '<hr />', '<hr>'], "\n", $result['data']['message'][$flags['html']]['data']); array_unshift($result['data']['message'], ['type' => 'text/plain', 'data' => html_entity_decode(strip_tags($temp)), 'charset' => 'utf-8', 'encoding' => '7bit']); } // validating receipients foreach (['to', 'cc', 'bcc'] as $r) { $result['data'][$r] = []; if (!isset($options[$r])) { continue; } // validating $temp = $this->validate_recepient($options[$r]); if (!$temp['success']) { array_merge3($result['error'], $temp['error']); } else { $result['data'][$r] = $temp['data']; if (!empty($temp['requires_fetching'])) { $result['data']['requires_fetching'] = true; } } } // processing attachments if (!empty($options['attachments'])) { // if we have one attachment if (isset($options['attachments']['path']) || isset($options['attachments']['data'])) { $temp = [$options['attachments']]; } else { $temp = $options['attachments']; } $finfo = finfo_open(FILEINFO_MIME_TYPE); foreach ($temp as $v) { if (isset($v['path'])) { $type = finfo_file($finfo, $v['path']); if ($type === false) { $result['error'][] = 'Unknown attachment type!'; } else { $result['data']['attachments'][] = ['type' => $type, 'data' => file_get_contents($v['path']), 'name' => basename($v['path'])]; } } else { if (isset($v['data'])) { if (empty($v['type'])) { $result['error'][] = 'Unknown attachment type!'; } else { $result['data']['attachments'][] = ['type' => $v['type'], 'data' => $v['data'], 'name' => isset($v['name']) ? $v['name'] : '']; } } } } finfo_close($finfo); } // if we have errors we break if ($result['error']) { break; } // if we got here, means we are ok $result['success'] = 1; } while (0); // we need to unset data key if we have an error if (!$result['success']) { unset($result['data']); } return $result; }