Completed
Pull Request — master (#49)
by
unknown
01:21
created

Pivot::getPivotModel()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.4222
c 0
b 0
f 0
cc 5
nc 4
nop 1
1
<?php
2
3
namespace Mtolhuys\LaravelSchematics\Services;
4
5
use ReflectionClass;
6
use Mtolhuys\LaravelSchematics\Http\Requests\CreateRelationRequest;
7
use Mtolhuys\LaravelSchematics\Exceptions\PivotException;
8
9
class Pivot
10
{
11
	/**
12
	 * Find pivot model class for BelongsToMany
13
	 * 
14
	 * @return object|null Returns instance of pivot model when found, null on failure
15
	 */
16
	public static function getPivotModel($method)
17
	{
18
		$pattern = '/(@schematics-pivot)([\s]*)([\S]*)/';
19
		preg_match_all($pattern, $method->getDocComment(), $matches);
20
		if (isset($matches[1][0]) && $matches[1][0] == "@schematics-pivot"){
21
			try{
22
				$pivotModelName = $matches[3][0];
23
			} catch (\Exception $e){
24
				throw new PivotException("Malformed @schematics-pivot tag");
25
			}
26
			if (class_exists($pivotModelName)){
27
				return App($pivotModelName);
28
			} 
29
		}
30
		return NULL;
31
	}
32
33
	/**
34
	 * Makes an attemp at finding pivot model class for BelongsToMany without @schematics-pivot tag
35
	 * 
36
	 * @return object|null Returns instance of pivot model when found, null on failure
37
	 */
38
	public static function getPivotModelFallback($srcModel, $invocation, $method, $models)
39
	{
40
41
		//Assumed name is ModeloneModeltwo or modeltwoModelone in same namespace, if not, we have to do dark magic
42
		$reflectionOne =  new ReflectionClass($srcModel);
43
		$reflectionTwo = new ReflectionClass($invocation->getRelated());
44
45
		$possibleNames = [];
46
		$assumedNamespace = $reflectionTwo->getNamespaceName();
47
		$possibleNames[] = $assumedNamespace . '\\' . $reflectionOne->getShortName() . $reflectionTwo->getShortName();
48
		$possibleNames[] = $assumedNamespace . '\\' . $reflectionTwo->getShortName() . $reflectionOne->getShortName();
49
50
		$obj = NULL;
51
		$i = 0;
0 ignored issues
show
Unused Code introduced by
$i is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
52
		for ($i = 0; $i < count($possibleNames); $i++){
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
53
			if (class_exists($possibleNames[$i])){
54
				$obj = app($possibleNames[$i]);
55
				break;
56
			}
57
		};
58
		if ($obj){
59
			return $obj;
60
		}
61
62
		//Did not find it the easy way, analyze code to see if we get better results in some sort of desperate attempt
63
		$source = file($method->getFileName());
64
		$startLine = $method->getStartLine();
65
		$endLine = $method->getEndLine();
66
		$nLines = $endLine - $startLine;
67
		$functionSrc = implode("", array_slice($source, $startLine, $nLines));
68
69
		//this only works for very simple setups, if database name is given ( $this->belongsToMany('App\A', a_b);)
70
		//TODO: deal more complex code ? ;_; simple regex wont help there, but is probably overkill anyway
71
		$pattern = '/(belongsToMany\()([\s\S]*)(,)([\s\S]*)(\))/';
72
		preg_match_all($pattern, $functionSrc, $matches);
73
		if (!isset($matches[4][0])){
74
			return NULL;
75
		}
76
	
77
		//Won't scale amazing with big databases
78
		foreach ($models as $model){
79
			$obj = app($model);
80
			if ("assumedSecondParam" == $obj->getTable()){
81
				break;
82
			}
83
		}
84
		return $obj;
85
	}
86
87
	/**
88
	 * @param CreateRelationRequest $request 
89
	 * @return string Name of pivot model
90
	 * @throws PivotException When pivot model does not exist.
91
	 */
92
	public static function GetPivotModelFromRequest(CreateRelationRequest $request)
93
	{
94
		if (!isset($request['pivot']) || !$request['pivot']){
95
			$name  = self::getDefaultPivotModelName($request['source'], $request['target']);
96
		} else {
97
			$name = $request['pivot'];
98
		}
99
		return $name;
100
	}
101
102
	/**
103
	 * Returns default modelName (including namespace) for a pivot model, based on name of target and source models.
104
	 * Throws exception if model with default name does not exist, so returned name is always valid class.
105
	 * 
106
	 * @param string $sourceModelName Name of source model including namespace
107
	 * @param string $targetModelName Name of target model including namespace
108
	 * @return string Name of pivot model
109
	 * @throws PivotException When model with default name does not exist.
110
	 */
111
	private static function getDefaultPivotModelName(string $sourceModelName,string $targetModelName)
112
	{
113
		$arr = explode('\\', $sourceModelName);
114
		$source = end($arr);
115
		$namespaceName = count($arr) > 1 ? $arr[0] : "";
116
117
		$arr = explode('\\', $targetModelName);
118
		$target = end($arr);
119
120
		$modelName = $namespaceName . '\\' . $target . $source;
121
122
		if (!class_exists($modelName)){
123
			$modelName = $namespaceName . '\\' . $source . $target;
124
			if (!class_exists($modelName)){
125
				throw new  PivotException("Pivot model with default name does not exist");
126
			}
127
		}	
128
		return $modelName;
129
	}
130
}
131