Phalcon BeforeSave not receiving data before saving? - php

Before I save my model, I would like to check if $ CONT_CEDULA meets the requirements. If not, then don't save. But when saving, it is as if the variable $ CONT_CEDULA hasn't got any data. I want to know if I'm doing well or need some other event or function. Also, the echo outputs no data.
beforeSave method
public function beforeSave() {
echo $this->$CONT_CEDULA;
switch (strlen($this->$CONT_CEDULA)) {
case 10:
return validarCI($this->$CONT_CEDULA);
break;
case 13:
return validarRUC($this->$CONT_CEDULA);
break;
default:
echo "Numero de caracteres invalidos" ;
return FALSE;
}
SpmContacto model
<?php
class SpmContacto extends \Phalcon\Mvc\Model {
public $CONT_CODIGO;
public $CONT_CEDULA;
public $CONT_RUCIDE;
public $CONT_NOMBRE;
public $CON_ESTADO;
public $CONT_TELEFO;
public $CONT_DIRECC;
public $CONT_AREA;
public $CONT_CARGO;
public $CONT_TIPOXX;
public $CONT_EMAIL;
public $CONT_USUARIO;
public $CONT_CLAVE;
public $CONT_CLAVEE;
public $CONT_FECNACI;
public $CONT_FECINSC;
public $CONT_TIPOCODIGO;
/**
* Initialize method for model.
*/
public function initialize() {
$this->setSchema("SPOLS");
$this->hasMany('CONT_CODIGO', 'SPMREFERENCIA', 'CONT_CODIGO', array('alias' => 'SPMREFERENCIA'));
$this->hasMany('CONT_CODIGO', 'SPTDETALLE', 'CONT_CODIGO', array('alias' => 'SPTDETALLE'));
$this->hasMany('CONT_CODIGO', 'SPTENCABEZADO', 'CONT_CODIGO', array('alias' => 'SPTENCABEZADO'));
}
function validarCI($strCedula) {
$suma = 0;
$strOriginal = $strCedula;
$intProvincia = substr($strCedula, 0, 2);
$intTercero = $strCedula[2];
$intUltimo = $strCedula[9];
if (!settype($strCedula, "float"))
return FALSE;
if ((int) $intProvincia < 1 || (int) $intProvincia > 23)
return FALSE;
if ((int) $intTercero == 7 || (int) $intTercero == 8)
return FALSE;
for ($indice = 0; $indice < 9; $indice++) {
//echo $strOriginal[$indice],'</br>';
switch ($indice) {
case 0:
case 2:
case 4:
case 6:
case 8:
$arrProducto[$indice] = $strOriginal[$indice] * 2;
if ($arrProducto[$indice] >= 10)
$arrProducto[$indice] -= 9;
//echo $arrProducto[$indice],'</br>';
break;
case 1:
case 3:
case 5:
case 7:
$arrProducto[$indice] = $strOriginal[$indice] * 1;
if ($arrProducto[$indice] >= 10)
$arrProducto[$indice] -= 9;
//echo $arrProducto[$indice],'</br>';
break;
}
}
foreach ($arrProducto as $indice => $producto)
$suma += $producto;
$residuo = $suma % 10;
$intVerificador = $residuo == 0 ? 0 : 10 - $residuo;
return ($intVerificador == $intUltimo ? TRUE : FALSE);
}
function validarRUC($strRUC) {
if (strlen($strRUC) != 13)
return FALSE;
$suma = 0;
$strOriginal = $strRUC;
$intProvincia = substr($strRUC, 0, 2);
$intTercero = $strRUC[2];
if (!settype($strRUC, "float"))
return FALSE;
if ((int) $intProvincia < 1 || (int) $intProvincia > 23)
return FALSE;
if ((int) $intTercero != 6 && (int) $intTercero != 9) {
if (substr($strRUC, 10, 3) == '001')
return validarCI(substr($strRUC, 0, 10));
return FALSE;
}
if ((int) $intTercero == 6) {
$intUltimo = $strOriginal[8];
for ($indice = 0; $indice < 9; $indice++) {
//echo $strOriginal[$indice],'</br>';
switch ($indice) {
case 0:
$arrProducto[$indice] = $strOriginal[$indice] * 3;
break;
case 1:
$arrProducto[$indice] = $strOriginal[$indice] * 2;
break;
case 2:
$arrProducto[$indice] = $strOriginal[$indice] * 7;
break;
case 3:
$arrProducto[$indice] = $strOriginal[$indice] * 6;
break;
case 4:
$arrProducto[$indice] = $strOriginal[$indice] * 5;
break;
case 5:
$arrProducto[$indice] = $strOriginal[$indice] * 4;
break;
case 6:
$arrProducto[$indice] = $strOriginal[$indice] * 3;
break;
case 7:
$arrProducto[$indice] = $strOriginal[$indice] * 2;
break;
case 8:
$arrProducto[$indice] = 0;
break;
}
}
} else {
$intUltimo = $strOriginal[9];
for ($indice = 0; $indice < 9; $indice++) {
//echo $strOriginal[$indice],'</br>';
switch ($indice) {
case 0:
$arrProducto[$indice] = $strOriginal[$indice] * 4;
break;
case 1:
$arrProducto[$indice] = $strOriginal[$indice] * 3;
break;
case 2:
$arrProducto[$indice] = $strOriginal[$indice] * 2;
break;
case 3:
$arrProducto[$indice] = $strOriginal[$indice] * 7;
break;
case 4:
$arrProducto[$indice] = $strOriginal[$indice] * 6;
break;
case 5:
$arrProducto[$indice] = $strOriginal[$indice] * 5;
break;
case 6:
$arrProducto[$indice] = $strOriginal[$indice] * 4;
break;
case 7:
$arrProducto[$indice] = $strOriginal[$indice] * 3;
break;
case 8:
$arrProducto[$indice] = $strOriginal[$indice] * 2;
break;
}
}
}
foreach ($arrProducto as $indice => $producto)
$suma += $producto;
$residuo = $suma % 11;
$intVerificador = $residuo == 0 ? 0 : 11 - $residuo;
//echo "$intVerificador == $intUltimo";
return ($intVerificador == $intUltimo ? TRUE : FALSE);
}
function validarID($strId) {
switch (strlen($strId)) {
case 10:
return validarCI($strId);
break;
case 13:
return validarRUC($strId);
break;
default:
return FALSE;
}
}
public function beforeSave() {
echo $this->$CONT_CEDULA;
switch (strlen($this->$CONT_CEDULA)) {
case 10:
return validarCI($this->$CONT_CEDULA);
break;
case 13:
return validarRUC($this->$CONT_CEDULA);
break;
default:
echo "Numero de caracteres invalidos";
return FALSE;
}
//echo $op;
}
public function getSource() {
return 'SPM_CONTACTO';
}
public static function find($parameters = null) {
return parent::find($parameters);
}
public static function findFirst($parameters = null) {
return parent::findFirst($parameters);
}

By default Phalcon wont output any data you "echo" in your controllers or your models. The easy 'workaround' is to die('your output');
If you return a value in a switch, it is unnecessary to add a break; to the end of your case.
public function beforeSave()
{
// check the content of $this->$CONT_CEDULA
var_dump($this->$CONT_CEDULA);
die;
switch (strlen($this->$CONT_CEDULA)) {
case 10:
return validarCI($this->$CONT_CEDULA);
case 13:
return validarRUC($this->$CONT_CEDULA);
default:
// an example to test if your code enters this case.
die("Numero de caracteres invalidos");
return FALSE;
}
}

Related

PHP, switch case returned undefined variable

Hy,
I got switch case inside function when but when i call it, i got error Undefined Variable and i don't know why (i use PHP 8)
private function getIDFromBrand() {
switch ($this->brand) {
case "Niky":
$id = 1;
break;
case "Pumo":
$id = 4;
break;
case "Coke":
if ($this->typecoke== 0) {
$id = 2;
} else {
if ($this->typecoke== 1) {
$id = 3;
}
}
break;
case "Tomato":
$id = 5;
break;
case "Riles":
$id = 6;
break;
case "TEST":
$id = 7;
break;
}
return $id; // Error Undefined variable $id
}
When i declare $id at the top of my function, like
$id = null
or
$id = 0
The switch doesn't update it, so it will return null or 0, it will return the declared value.
Your switch statement has no default branch, so if $this->brand is, say, "Stack Overflow", it will not run any of the statements, and $id will never be set.
See the PHP manual for the switch statement:
A special case is the default case. This case matches anything that wasn't matched by the other cases.
Similarly, if $this->brand is "Coke", but $this->typecoke is, say, 42, it will not match either of the conditions in that branch.
switch ($this->brand) {
case "Niky":
$id = 1;
break;
case "Pumo":
$id = 4;
break;
case "Coke":
if ($this->typecoke== 0) {
$id = 2;
} elseif ($this->typecoke== 1) {
$id = 3;
} else {
$id = -1; // WAS PREVIOUSLY NOT SET
}
break;
case "Tomato":
$id = 5;
break;
case "Riles":
$id = 6;
break;
case "TEST":
$id = 7;
break;
default:
$id = -1; // WAS PREVIOUSLY NOT SET
break;
}

php object oriented calculator

Hello im trying to make an object as learning task which takes a number and calculate it three times and echos every step.
<?
// neues Objekt der Klasse erzeugen
$stringManager = new StringManager();
// output String initialisieren
$meinString = "";
$zahl = "100";
$stringManager->setMeinString($meinString);
$stringManager->setZahl($zahl);
// Schritte ausführen
for ($i=1; $i<=3; $i++) {
$stringManager->machSchritt($i,$zahl);
}
// String ausgeben
echo $stringManager->getMeinString();
// Klasse StringManager
class StringManager {
var $meinString;
var $zahl;
function StringManager() {
}
function machSchritt($welchenSchritt,$zahl) {
switch ($welchenSchritt) {
case 1:
$zahl + 50;
break;
case 2:
$zahl / 2;
break;
case 3:
$zahl * 5;
break;
default:
break;
}
$this->append("schritt".$welchenSchritt." fertig...");
$this->append("Zahl:".$zahl." ");
}
function append($what) {
$this->meinString .= $what;
}
//function append($what) {
//$this->zahl .= $what;
//}
function setMeinString($value) {
$this->meinString = $value;
}
function getMeinString() {
return $this->meinString;
}
function setZahl($value) {
$this->zahl = $value;
}
function getZahl() {
return $this->zahl;
}
}
?>
My output is: "schritt1 fertig...Zahl:100 schritt2 fertig...Zahl:100 schritt3 fertig...Zahl:100"
But I expect it to be "schritt1 fertig...Zahl:150 schritt2 fertig...Zahl:75 schritt3 fertig...Zahl:375
Please help me find what im doing wrong.
your problem is between this lines:
$zahl + 50;
break;
case 2:
$zahl / 2;
break;
case 3:
$zahl * 5;
if you want to increase/manipulate the variable $zahl so you have to use it:
$zahl += 50;
break;
case 2:
$zahl /= 2;
break;
case 3:
$zahl *= 5;
btw: your code is deprecated.
class StringManager {
var $meinString;
var $zahl;
function StringManager() {
}
}
should replace with
class StringManager {
private $meinString;
private $zahl;
public function __construct() {
}
}
update:
ah, now i understand, you need to work with your value.
so use this instead:
$this->zahl += 50;
break;
case 2:
$this->zahl /= 2;
break;
case 3:
$this->zahl *= 5;
$this->append("Zahl:".$this->zahl." ");
But it would be better, to use your setter (with typecasting) and getter methods.
warning
your code looks like php4 code. php4 is not supported since 2008 (http://php.net/eol.php).

Error when I try to post to database. I am trying to calculate GPA

I am getting this error "ErrorException in scoresheetController.php line 259:
Object of class Illuminate\Database\Eloquent\Collection could not be converted to int" when I want to post the following into the database. Kindly find the code below.
<?php
namespace App\Http\Controllers;
use App\Http\Requests\scoresheetRequest;
use App\Scoresheet;
use App\StudentCourse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use DB;
use Excel;
use Illuminate\Database\Eloquent\Collection;
class scoresheetController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$scoresheet = Scoresheet::select('id', 'code', 'stud_id', 'term', 'year', 'CA_Score', 'exam_score', 'total', 'grade')->get();
return view('admin.results')->with('scoresheet', $scoresheet);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(scoresheetRequest $request)
{
//dd($request ->all());
$scoresheet = new Scoresheet();
$crdthr = StudentCourse::select('student_courses')
->join('scoresheets', 'student_courses.stud_id', '=', 'scoresheets.stud_id')
->select('student_courses.credit_hrs')
->get();
//Calculate total
$total = $request['CA_Score'] + $request['exam_score'];
//Calculate the grade
switch ($grade = $total) {
case $total >=93 && $total==100:
$grade = "A+";
break;
case $total>=85:
$grade = "A";
break;
case $total >=77:
$grade = "B+";
break;
case $total >=70:
$grade = "B";
break;
case $total >=60:
$grade = "C";
break;
case $total >=55:
$grade = "D+";
break;
case $total >=50:
$grade = "D";
break;
case $total <50:
$grade = "F";
break;
}
//Check for grade equivalent
switch ($digit = $grade) {
case $grade == "A+":
$digit = "4.00";
break;
case $grade == "A":
$digit = "3.75";
break;
case $grade == "B+":
$digit = "3.50";
break;
case $grade == "B":
$digit = "3.00";
break;
case $grade == "C+":
$digit = "2.50";
break;
case $grade == "C":
$digit = "2.00";
break;
case $grade == "D+":
$digit = "1.50";
break;
case $grade == "D":
$digit = "1.00";
break;
case $grade == "F":
$digit = "0.00";
break;
}
//Calculate mini wgt
$gpa = $digit * $crdthr;
$scoresheet->code = $request['code'];
$scoresheet->stud_id = $request['stud_id'];
$scoresheet->term = $request['term'];
$scoresheet->year = $request['year'];
$scoresheet->CA_Score = $request['CA_Score'];
$scoresheet->exam_score = $request['exam_score'];
$scoresheet->total = $total;
$scoresheet->grade = $grade;
$scoresheet->grade_digit = $digit;
$scoresheet->mini_wgt = $gpa;
//dd($gpa);
if ($scoresheet->save()){
flash($request['name'].' successfully saved.')->success();
/*echo 'saved';*/
}else{
flash($request['name'].' not saved.')->error();
/*echo 'Not saved';*/
}
return redirect()->back();
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
$scoresheet =Scoresheet::findOrFail($id);
return view('admin.result_edit') ->with('scoresheet', $scoresheet);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$scoresheet = Scoresheet::findOrFail($id);
$crdthr = StudentCourse::select('student_courses')
->join('scoresheets', 'student_courses.stud_id', '=', 'scoresheets.stud_id')
->select('student_courses.credit_hrs')
->get();
$total = $request['CA_Score'] + $request['exam_score'];
//Calculate the grade
switch ($grade = $total) {
case $total >=93 && $total==100:
$grade = "A+";
break;
case $total>=85:
$grade = "A";
break;
case $total >=77:
$grade = "B+";
break;
case $total >=70:
$grade = "B";
break;
case $total >=60:
$grade = "C";
break;
case $total >=55:
$grade = "D+";
break;
case $total >=50:
$grade = "D";
break;
case $total <50:
$grade = "F";
break;
}
//Check for grade equivalent
switch ($digit = $grade) {
case $grade == "A+":
$digit = "4.00";
break;
case $grade == "A":
$digit = "3.75";
break;
case $grade == "B+":
$digit = "3.50";
break;
case $grade == "B":
$digit = "3.00";
break;
case $grade == "C+":
$digit = "2.50";
break;
case $grade == "C":
$digit = "2.00";
break;
case $grade == "D+":
$digit = "1.50";
break;
case $grade == "D":
$digit = "1.00";
break;
case $grade == "F":
$digit = "0.00";
break;
}
//Calculate mini wgt
$gpa = $digit * $crdthr;
$scoresheet->code = $request['code'];
$scoresheet->stud_id = $request['stud_id'];
$scoresheet->term = $request['term'];
$scoresheet->year = $request['year'];
$scoresheet->CA_Score = $request['CA_Score'];
$scoresheet->exam_score = $request['exam_score'];
$scoresheet->total = $total;
$scoresheet->grade = $grade;
$scoresheet->grade_digit = $digit;
$scoresheet->mini_wgt = $gpa;
if ($scoresheet->save()){
flash($request['name'].' successfully saved.')->success();
/*echo 'saved';*/
}else{
flash($request['name'].' not saved.')->error();
/*echo 'Not saved';*/
}
return redirect() ->to('/scoresheet');
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
$scoresheet = Scoresheet::findOrFail($id);
if (Scoresheet::destroy($id)){
flash ('deleted successfully')->success();
}else{
flash ('failed to delete')->warning();
}
return redirect()->back();
}
}
I would be glad if assistance can be given as soon as possible.
Since $crdthr is a Collection object, you can print it to see the data format in there. Usually, you can get the data you are looking for as $crdthr[0]-> credit_hrs
$gpa = $digit * $crdthr[0]->credit_hrs;
Looking quickly at your code I can say that your problem is in this bit of code :
$crdthr = StudentCourse::select('student_courses')
->join('scoresheets', 'student_courses.stud_id', '=', 'scoresheets.stud_id')
->select('student_courses.credit_hrs')
->get();
Since you are returning an Eloquent Collection from here later below in your code you are trying to make math operations over this Collection :
//Calculate mini wgt
$gpa = $digit * $crdthr;

php switch between range of numbers does not work

I have this PHP function for changing color between 2 numbers:
function color_switch($number){
switch (true){
case $number == range(1 , 3):
$color = "progress-bar-danger";
break;
case $number == range(3 , 5):
$color = "progress-bar-warning";
break;
case $number == range(5 , 6):
$color = "progress-bar-default";
break;
case $number == range(6 , 8):
$color = "progress-bar-success";
break;
case $number == range(8, 10):
$color = "progress-bar-success";
break;
}
return $color;
}
But in action this function does not work for me. How should I fix this ?
You are comparing range() which is an array, and $number is integer, which is invalid,
Change your function something like,
function color_switch($number) {
switch ($number) { // switching the function argument
case $number <= 3 : // if less than three, execute case
$color = "progress-bar-danger";
break;
case $number <= 5 :
$color = "progress-bar-warning";
break;
case $number <= 6 :
$color = "progress-bar-default";
break;
case $number <= 8 :
$color = "progress-bar-success";
break;
case $number <= 10 :
$color = "progress-bar-success";
break;
}
return $color;
}
Your utilization of switch is incorrect and your utilization of range() is too.
Your parameter of switch should be the variable you evaluate.
Range() will return an array containing the range.
So the correct code is better :
function color_switch($number) {
switch ($number){
case in_array($number, range(1 , 3)):
$color = "progress-bar-danger";
break;
case in_array($number, range(3 , 5)):
$color = "progress-bar-warning";
break;
case in_array($number, range(5 , 6)):
$color = "progress-bar-default";
break;
case in_array($number, range(6 , 8)):
$color = "progress-bar-success";
break;
case in_array($number, range(8 , 10)):
$color = "progress-bar-success";
break;
}
return $color;
}

How can this big method be refactored?

I wrote a class for badge activation and it should be refactored now.
Are there any good advices, how should I refactor it's trigger() method?
The source of the class is in github:
https://github.com/heal25/ced/blob/master/models/BadgeActivator.php
The problematic method:
public function trigger($id, $data = []) {
if (!$this->_uid) $this->setUid(Yii::app()->player->model->uid); //set default uid
$activate = false;
switch ($id) {
//case 'login_1': $activate = true; break;
case 'max_nrg_35': if ($data['energy_max'] >= 35) $activate = true; break;
case 'max_nrg_100': if ($data['energy_max'] >= 100) $activate = true; break;
case 'skill_35': if ($data['skill'] >= 35) $activate = true; break;
case 'skill_100': if ($data['skill'] >= 100) $activate = true; break;
case 'strength_35': if ($data['strength'] >= 35) $activate = true; break;
case 'strength_100': if ($data['strength'] >= 100) $activate = true; break;
case 'energy_drink': $activate = true; break;
case 'level_10': if ($data['level'] >= 10) $activate = true; break;
case 'level_100': if ($data['level'] >= 100) $activate = true; break;
case 'dollar_50': if ($data['dollar'] >= 50) $activate = true; break;
case 'dollar_5000': if ($data['dollar'] >= 5000) $activate = true; break;
case 'travel_loc3': if ($data['water_id'] == 3) $activate = true; break;
case 'travel_county2': if ($data['county_id'] == 2) $activate = true; break;
case 'travel_county9': if ($data['county_id'] == 9) $activate = true; break;
case 'routine_100': if ($data['routine'] >= 100) $activate = true; break;
case 'loc_routine_4b': if ($data['water_id']==4 and $data['routine'] > 0) $activate = true; break;
case 'loc_routine_13s': if ($data['water_id']==13 and $data['routine'] >= 3) $activate = true; break;
case 'loc_routine_28s': if ($data['water_id']==28 and $data['routine'] >= 3) $activate = true; break;
case 'loc_routine_37g': if ($data['water_id']==37 and $data['routine'] >= 9) $activate = true; break;
case 'loc_routine_52b': if ($data['water_id']==52 and $data['routine'] > 0) $activate = true; break;
case 'loc_routine_61s': if ($data['water_id']==61 and $data['routine'] >= 3) $activate = true; break;
case 'loc_routine_71g': if ($data['water_id']==71 and $data['routine'] >= 9) $activate = true; break;
case 'loc_routine_72e': if ($data['water_id']==72 and $data['routine'] >= 27) $activate = true; break;
case 'loc_routine_46d': if ($data['water_id']==46 and $data['routine'] >= 81) $activate = true; break;
case 'setpart_3': if ($data['cnt'] >= 3) $activate = true; break;
case 'setpart_10': if ($data['cnt'] >= 10) $activate = true; break;
case 'setpart_30': if ($data['cnt'] >= 30) $activate = true; break;
case 'first_duel_win': if ($data['role'] == 'caller' and $data['winner'] == 'caller') $activate = true; break;
case 'duel_success_100': if ($data['cnt'] >= 100) $activate = true; break;
case 'duel_fail_100': if ($data['cnt'] >= 100) $activate = true; break;
case 'duel_rate_40': if ($this->getSuccessRate(100, $data) <= 40) $activate = true; break;
case 'duel_rate_25': if ($this->getSuccessRate(300, $data) <= 25) $activate = true; break;
case 'duel_rate_10': if ($this->getSuccessRate(600, $data) <= 10) $activate = true; break;
case 'duel_rate_60': if ($this->getSuccessRate(100, $data) >= 60) $activate = true; break;
case 'duel_rate_75': if ($this->getSuccessRate(300, $data) >= 75) $activate = true; break;
case 'duel_rate_90': if ($this->getSuccessRate(900, $data) >= 90) $activate = true; break;
case 'duel_money_100': if ($data['dollar'] >= 100) $activate = true; break;
case 'duel_money_1000': if ($data['dollar'] >= 1000) $activate = true; break;
case 'duel_win_chance35': if ($data['winner'] and $data['chance'] <= 35) $activate = true; break;
case 'duel_win_chance20': if ($data['winner'] and $data['chance'] <= 20) $activate = true; break;
case 'duel_win_chance5': if ($data['winner'] and $data['chance'] <= 5) $activate = true; break;
case 'duel_lose_chance65': if (!$data['winner'] and $data['chance'] >= 65) $activate = true; break;
case 'duel_lose_chance80': if (!$data['winner'] and $data['chance'] >= 80) $activate = true; break;
case 'duel_lose_chance95': if (!$data['winner'] and $data['chance'] >= 95) $activate = true; break;
case 'duel_2h': if ($data['role'] == 'caller' and date('G')==2) $activate = true; break;
case 'shop_item10': if (Yii::app()->player->model->owned_items >= 10) $activate = true; break;
case 'shop_bait20': if (Yii::app()->player->model->owned_baits >= 20) $activate = true; break;
case 'set_b': if ($data['id']==1) $activate = true; break;
case 'set_s': if ($data['id']==2) $activate = true; break;
case 'set_g': if ($data['id']==3) $activate = true; break;
case 'set_sell_b': if ($data['id']==1) $activate = true; break;
case 'set_sell_s': if ($data['id']==2) $activate = true; break;
case 'set_sell_g': if ($data['id']==3) $activate = true; break;
case 'club_join': $activate = true; break;
case 'club_create': $activate = true; break;
case 'club_members_8': if ($data['cnt'] >= 8) $activate = true; break;
case 'login_days_7': if ($this->getLoginDays() >= 7) $activate = true; break;
case 'login_days_30': if ($this->getLoginDays() >= 30) $activate = true; break;
case 'login_days_60': if ($this->getLoginDays() >= 60) $activate = true; break;
case 'win_contest': $activate = true; break;
}
if ($activate) {
return $this->activate($id);
}
return false;
}
I can extract the activations for 'loc_routine_*' cases, but it isn't much.
I'm not familiar with Yii, but from glancing over their docs, you could probably refactor the trigger method to make use of Yii Validators and the DI container. Something along these lines:
class BadgeActivator
…
public function trigger($id, array $data)
{
$badgeValidator = $this->badgeValidators->findById($id);
if ($badgeValidator->validate($data)) {
$this->activate($id);
}
}
}
The BadgeValidators object is a simple collection of objects implementing the BadgeValidator interface. You need to inject this to your BadgeActivator.
class BadgeValidators
{
private $validators = [];
public function __construct(array $badgeValidators)
{
foreach ($badgeValidators as $badgeValidator) {
$this->addBadgeValidator($badgeValidator);
}
}
public function addBadgeValidator(BadgeValidator $badgeValidator)
{
$this->validators[$badgeValidator->getId()] = $badgeValidator;
}
public function findById($badgeId)
{
if (isset($this->validators[$badgeId])) {
return $this->validators[$badgeId];
}
throw new BadgeValidatorNotFoundException(
"No BadgeValidator found for badge id [$badgeId]"
);
}
}
The BadgeValidator interface is the contract all concrete validators need to obey. Their purpose is to map from $data to Yii's build in validators or to encapsulate additional/unique validation logic.:
interface BadgeValidator
{
public function getId();
public function validate($value = null);
}
A concrete Validator would then look like this:
class MaxEnergy35 implements BadgeValidator
{
public function getId()
{
return 'max_nrg_35';
}
public function validate($value = null)
{
$validator = new yii\validators\IntegerValidator();
$validator->min = 35;
return $validator->validate($value['max_energy']);
}
}
You could move the configuration for this class to the DI config as well, e.g. you could inject maxEnergy, validatorId and the Yii Validator. If you do that, you'll only have one class MaxEnergy instead of MaxEnergy35 and MaxEnergy100. For sake of simplicity, I'll keep it this way now.
Here is one with custom logic:
class DuelRate40 implements BadgeValidator
{
public function getId()
{
return 'duel_rate_40';
}
public function validate()
{
return $this->getSuccessRate(100, $data) <= 40;
}
private function getSuccessRate($limit, array $data)
{
// moved from BadgeActivator
}
}
As you can see, it's trivial to make your BadgeValidators with custom logic and without using the Yii validators. In this particular case, I just moved the getSuccessRate rate method to the validator. You could easily see that it's misplaced on the BadgeActivator because it didn't have any cohesion to any class properties. Obviously, if you need this code in multiple validations, you could make it configurable again, so you have only one validator of that kind, instead of duplicating that method in each concrete one.
Now, for each case in your switch/case, simply add another concrete BadgeValidator and inject it to the BadgeValidators in the DIConfig.
In your ced/config/main.php:
// more config …
components => [
'badgeValidator' => [
'class'=> 'application.components.BadgeValidator',
'badgeValidators' => [
['class'=>'MaxEnergy35'],
['class'=>'MaxEnergy100'],
['class'=>'DuelRate40'],
// more validators …
]
],
// other components …
]
Note: I have no clue if this is the correct way to use Yii's DI config. I am just assuming from your file on GitHub. But I guess, you'll know how to change it if necessary.
And whenever you need to add a new Badge, you simply write the Validator and wire it up in the config. You will never need to touch the BadgeActivator again. This will also significantly lower the Cyclomatic Complexity of the BadgeActivator. And it's trivial to add Unit Tests for each of the components above.

Categories